| 16 | static OpBase *SkipClone(const ExecutionPlan *plan, const OpBase *opBase); |
| 17 | |
| 18 | static void _eval_skip(OpSkip *op, AR_ExpNode *skip_exp) { |
| 19 | /* Store a copy of the original expression. |
| 20 | * This is required in the case of a parameterized skip: "SKIP $L" |
| 21 | * Evaluating the expression will modify it, replacing the parameter with a constant. |
| 22 | * As a result, clones of this operation would invalidly resolve to an outdated constant. */ |
| 23 | op->skip_exp = AR_EXP_Clone(skip_exp); |
| 24 | |
| 25 | // Evaluate using the input expression, leaving the stored expression untouched. |
| 26 | SIValue s = AR_EXP_Evaluate(skip_exp, NULL); |
| 27 | |
| 28 | // Validate that the skip value is numeric and non-negative. |
| 29 | if(SI_TYPE(s) != T_INT64 || SI_GET_NUMERIC(s) < 0) { |
| 30 | ErrorCtx_SetError("Skip operates only on non-negative integers"); |
| 31 | } |
| 32 | |
| 33 | op->skip = SI_GET_NUMERIC(s); |
| 34 | |
| 35 | // Free the expression we've evaluated. |
| 36 | AR_EXP_Free(skip_exp); |
| 37 | } |
| 38 | |
| 39 | OpBase *NewSkipOp(const ExecutionPlan *plan, AR_ExpNode *skip_exp) { |
| 40 | OpSkip *op = rm_malloc(sizeof(OpSkip)); |
no test coverage detected