Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * execExpr.c
4 : * Expression evaluation infrastructure.
5 : *
6 : * During executor startup, we compile each expression tree (which has
7 : * previously been processed by the parser and planner) into an ExprState,
8 : * using ExecInitExpr() et al. This converts the tree into a flat array
9 : * of ExprEvalSteps, which may be thought of as instructions in a program.
10 : * At runtime, we'll execute steps, starting with the first, until we reach
11 : * an EEOP_DONE opcode.
12 : *
13 : * This file contains the "compilation" logic. It is independent of the
14 : * specific execution technology we use (switch statement, computed goto,
15 : * JIT compilation, etc).
16 : *
17 : * See src/backend/executor/README for some background, specifically the
18 : * "Expression Trees and ExprState nodes", "Expression Initialization",
19 : * and "Expression Evaluation" sections.
20 : *
21 : *
22 : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
23 : * Portions Copyright (c) 1994, Regents of the University of California
24 : *
25 : *
26 : * IDENTIFICATION
27 : * src/backend/executor/execExpr.c
28 : *
29 : *-------------------------------------------------------------------------
30 : */
31 : #include "postgres.h"
32 :
33 : #include "access/nbtree.h"
34 : #include "catalog/objectaccess.h"
35 : #include "catalog/pg_proc.h"
36 : #include "catalog/pg_type.h"
37 : #include "executor/execExpr.h"
38 : #include "executor/nodeSubplan.h"
39 : #include "funcapi.h"
40 : #include "jit/jit.h"
41 : #include "miscadmin.h"
42 : #include "nodes/makefuncs.h"
43 : #include "nodes/nodeFuncs.h"
44 : #include "nodes/subscripting.h"
45 : #include "optimizer/optimizer.h"
46 : #include "pgstat.h"
47 : #include "utils/acl.h"
48 : #include "utils/array.h"
49 : #include "utils/builtins.h"
50 : #include "utils/jsonfuncs.h"
51 : #include "utils/jsonpath.h"
52 : #include "utils/lsyscache.h"
53 : #include "utils/typcache.h"
54 :
55 :
56 : typedef struct ExprSetupInfo
57 : {
58 : /* Highest attribute numbers fetched from inner/outer/scan tuple slots: */
59 : AttrNumber last_inner;
60 : AttrNumber last_outer;
61 : AttrNumber last_scan;
62 : /* MULTIEXPR SubPlan nodes appearing in the expression: */
63 : List *multiexpr_subplans;
64 : } ExprSetupInfo;
65 :
66 : static void ExecReadyExpr(ExprState *state);
67 : static void ExecInitExprRec(Expr *node, ExprState *state,
68 : Datum *resv, bool *resnull);
69 : static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args,
70 : Oid funcid, Oid inputcollid,
71 : ExprState *state);
72 : static void ExecCreateExprSetupSteps(ExprState *state, Node *node);
73 : static void ExecPushExprSetupSteps(ExprState *state, ExprSetupInfo *info);
74 : static bool expr_setup_walker(Node *node, ExprSetupInfo *info);
75 : static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op);
76 : static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable,
77 : ExprState *state);
78 : static void ExecInitSubscriptingRef(ExprEvalStep *scratch,
79 : SubscriptingRef *sbsref,
80 : ExprState *state,
81 : Datum *resv, bool *resnull);
82 : static bool isAssignmentIndirectionExpr(Expr *expr);
83 : static void ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
84 : ExprState *state,
85 : Datum *resv, bool *resnull);
86 : static void ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
87 : ExprEvalStep *scratch,
88 : FunctionCallInfo fcinfo, AggStatePerTrans pertrans,
89 : int transno, int setno, int setoff, bool ishash,
90 : bool nullcheck);
91 : static void ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
92 : Datum *resv, bool *resnull,
93 : ExprEvalStep *scratch);
94 : static void ExecInitJsonCoercion(ExprState *state, JsonReturning *returning,
95 : ErrorSaveContext *escontext,
96 : Datum *resv, bool *resnull);
97 :
98 :
99 : /*
100 : * ExecInitExpr: prepare an expression tree for execution
101 : *
102 : * This function builds and returns an ExprState implementing the given
103 : * Expr node tree. The return ExprState can then be handed to ExecEvalExpr
104 : * for execution. Because the Expr tree itself is read-only as far as
105 : * ExecInitExpr and ExecEvalExpr are concerned, several different executions
106 : * of the same plan tree can occur concurrently. (But note that an ExprState
107 : * does mutate at runtime, so it can't be re-used concurrently.)
108 : *
109 : * This must be called in a memory context that will last as long as repeated
110 : * executions of the expression are needed. Typically the context will be
111 : * the same as the per-query context of the associated ExprContext.
112 : *
113 : * Any Aggref, WindowFunc, or SubPlan nodes found in the tree are added to
114 : * the lists of such nodes held by the parent PlanState.
115 : *
116 : * Note: there is no ExecEndExpr function; we assume that any resource
117 : * cleanup needed will be handled by just releasing the memory context
118 : * in which the state tree is built. Functions that require additional
119 : * cleanup work can register a shutdown callback in the ExprContext.
120 : *
121 : * 'node' is the root of the expression tree to compile.
122 : * 'parent' is the PlanState node that owns the expression.
123 : *
124 : * 'parent' may be NULL if we are preparing an expression that is not
125 : * associated with a plan tree. (If so, it can't have aggs or subplans.)
126 : * Such cases should usually come through ExecPrepareExpr, not directly here.
127 : *
128 : * Also, if 'node' is NULL, we just return NULL. This is convenient for some
129 : * callers that may or may not have an expression that needs to be compiled.
130 : * Note that a NULL ExprState pointer *cannot* be handed to ExecEvalExpr,
131 : * although ExecQual and ExecCheck will accept one (and treat it as "true").
132 : */
133 : ExprState *
134 1006612 : ExecInitExpr(Expr *node, PlanState *parent)
135 : {
136 : ExprState *state;
137 1006612 : ExprEvalStep scratch = {0};
138 :
139 : /* Special case: NULL expression produces a NULL ExprState pointer */
140 1006612 : if (node == NULL)
141 47540 : return NULL;
142 :
143 : /* Initialize ExprState with empty step list */
144 959072 : state = makeNode(ExprState);
145 959072 : state->expr = node;
146 959072 : state->parent = parent;
147 959072 : state->ext_params = NULL;
148 :
149 : /* Insert setup steps as needed */
150 959072 : ExecCreateExprSetupSteps(state, (Node *) node);
151 :
152 : /* Compile the expression proper */
153 959072 : ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
154 :
155 : /* Finally, append a DONE step */
156 959054 : scratch.opcode = EEOP_DONE;
157 959054 : ExprEvalPushStep(state, &scratch);
158 :
159 959054 : ExecReadyExpr(state);
160 :
161 959054 : return state;
162 : }
163 :
164 : /*
165 : * ExecInitExprWithParams: prepare a standalone expression tree for execution
166 : *
167 : * This is the same as ExecInitExpr, except that there is no parent PlanState,
168 : * and instead we may have a ParamListInfo describing PARAM_EXTERN Params.
169 : */
170 : ExprState *
171 75512 : ExecInitExprWithParams(Expr *node, ParamListInfo ext_params)
172 : {
173 : ExprState *state;
174 75512 : ExprEvalStep scratch = {0};
175 :
176 : /* Special case: NULL expression produces a NULL ExprState pointer */
177 75512 : if (node == NULL)
178 0 : return NULL;
179 :
180 : /* Initialize ExprState with empty step list */
181 75512 : state = makeNode(ExprState);
182 75512 : state->expr = node;
183 75512 : state->parent = NULL;
184 75512 : state->ext_params = ext_params;
185 :
186 : /* Insert setup steps as needed */
187 75512 : ExecCreateExprSetupSteps(state, (Node *) node);
188 :
189 : /* Compile the expression proper */
190 75512 : ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
191 :
192 : /* Finally, append a DONE step */
193 75512 : scratch.opcode = EEOP_DONE;
194 75512 : ExprEvalPushStep(state, &scratch);
195 :
196 75512 : ExecReadyExpr(state);
197 :
198 75512 : return state;
199 : }
200 :
201 : /*
202 : * ExecInitQual: prepare a qual for execution by ExecQual
203 : *
204 : * Prepares for the evaluation of a conjunctive boolean expression (qual list
205 : * with implicit AND semantics) that returns true if none of the
206 : * subexpressions are false.
207 : *
208 : * We must return true if the list is empty. Since that's a very common case,
209 : * we optimize it a bit further by translating to a NULL ExprState pointer
210 : * rather than setting up an ExprState that computes constant TRUE. (Some
211 : * especially hot-spot callers of ExecQual detect this and avoid calling
212 : * ExecQual at all.)
213 : *
214 : * If any of the subexpressions yield NULL, then the result of the conjunction
215 : * is false. This makes ExecQual primarily useful for evaluating WHERE
216 : * clauses, since SQL specifies that tuples with null WHERE results do not
217 : * get selected.
218 : */
219 : ExprState *
220 1715494 : ExecInitQual(List *qual, PlanState *parent)
221 : {
222 : ExprState *state;
223 1715494 : ExprEvalStep scratch = {0};
224 1715494 : List *adjust_jumps = NIL;
225 :
226 : /* short-circuit (here and in ExecQual) for empty restriction list */
227 1715494 : if (qual == NIL)
228 1306808 : return NULL;
229 :
230 : Assert(IsA(qual, List));
231 :
232 408686 : state = makeNode(ExprState);
233 408686 : state->expr = (Expr *) qual;
234 408686 : state->parent = parent;
235 408686 : state->ext_params = NULL;
236 :
237 : /* mark expression as to be used with ExecQual() */
238 408686 : state->flags = EEO_FLAG_IS_QUAL;
239 :
240 : /* Insert setup steps as needed */
241 408686 : ExecCreateExprSetupSteps(state, (Node *) qual);
242 :
243 : /*
244 : * ExecQual() needs to return false for an expression returning NULL. That
245 : * allows us to short-circuit the evaluation the first time a NULL is
246 : * encountered. As qual evaluation is a hot-path this warrants using a
247 : * special opcode for qual evaluation that's simpler than BOOL_AND (which
248 : * has more complex NULL handling).
249 : */
250 408686 : scratch.opcode = EEOP_QUAL;
251 :
252 : /*
253 : * We can use ExprState's resvalue/resnull as target for each qual expr.
254 : */
255 408686 : scratch.resvalue = &state->resvalue;
256 408686 : scratch.resnull = &state->resnull;
257 :
258 1311676 : foreach_ptr(Expr, node, qual)
259 : {
260 : /* first evaluate expression */
261 494304 : ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
262 :
263 : /* then emit EEOP_QUAL to detect if it's false (or null) */
264 494304 : scratch.d.qualexpr.jumpdone = -1;
265 494304 : ExprEvalPushStep(state, &scratch);
266 494304 : adjust_jumps = lappend_int(adjust_jumps,
267 494304 : state->steps_len - 1);
268 : }
269 :
270 : /* adjust jump targets */
271 1311676 : foreach_int(jump, adjust_jumps)
272 : {
273 494304 : ExprEvalStep *as = &state->steps[jump];
274 :
275 : Assert(as->opcode == EEOP_QUAL);
276 : Assert(as->d.qualexpr.jumpdone == -1);
277 494304 : as->d.qualexpr.jumpdone = state->steps_len;
278 : }
279 :
280 : /*
281 : * At the end, we don't need to do anything more. The last qual expr must
282 : * have yielded TRUE, and since its result is stored in the desired output
283 : * location, we're done.
284 : */
285 408686 : scratch.opcode = EEOP_DONE;
286 408686 : ExprEvalPushStep(state, &scratch);
287 :
288 408686 : ExecReadyExpr(state);
289 :
290 408686 : return state;
291 : }
292 :
293 : /*
294 : * ExecInitCheck: prepare a check constraint for execution by ExecCheck
295 : *
296 : * This is much like ExecInitQual/ExecQual, except that a null result from
297 : * the conjunction is treated as TRUE. This behavior is appropriate for
298 : * evaluating CHECK constraints, since SQL specifies that NULL constraint
299 : * conditions are not failures.
300 : *
301 : * Note that like ExecInitQual, this expects input in implicit-AND format.
302 : * Users of ExecCheck that have expressions in normal explicit-AND format
303 : * can just apply ExecInitExpr to produce suitable input for ExecCheck.
304 : */
305 : ExprState *
306 5660 : ExecInitCheck(List *qual, PlanState *parent)
307 : {
308 : /* short-circuit (here and in ExecCheck) for empty restriction list */
309 5660 : if (qual == NIL)
310 180 : return NULL;
311 :
312 : Assert(IsA(qual, List));
313 :
314 : /*
315 : * Just convert the implicit-AND list to an explicit AND (if there's more
316 : * than one entry), and compile normally. Unlike ExecQual, we can't
317 : * short-circuit on NULL results, so the regular AND behavior is needed.
318 : */
319 5480 : return ExecInitExpr(make_ands_explicit(qual), parent);
320 : }
321 :
322 : /*
323 : * Call ExecInitExpr() on a list of expressions, return a list of ExprStates.
324 : */
325 : List *
326 526756 : ExecInitExprList(List *nodes, PlanState *parent)
327 : {
328 526756 : List *result = NIL;
329 : ListCell *lc;
330 :
331 986156 : foreach(lc, nodes)
332 : {
333 459400 : Expr *e = lfirst(lc);
334 :
335 459400 : result = lappend(result, ExecInitExpr(e, parent));
336 : }
337 :
338 526756 : return result;
339 : }
340 :
341 : /*
342 : * ExecBuildProjectionInfo
343 : *
344 : * Build a ProjectionInfo node for evaluating the given tlist in the given
345 : * econtext, and storing the result into the tuple slot. (Caller must have
346 : * ensured that tuple slot has a descriptor matching the tlist!)
347 : *
348 : * inputDesc can be NULL, but if it is not, we check to see whether simple
349 : * Vars in the tlist match the descriptor. It is important to provide
350 : * inputDesc for relation-scan plan nodes, as a cross check that the relation
351 : * hasn't been changed since the plan was made. At higher levels of a plan,
352 : * there is no need to recheck.
353 : *
354 : * This is implemented by internally building an ExprState that performs the
355 : * whole projection in one go.
356 : *
357 : * Caution: before PG v10, the targetList was a list of ExprStates; now it
358 : * should be the planner-created targetlist, since we do the compilation here.
359 : */
360 : ProjectionInfo *
361 731368 : ExecBuildProjectionInfo(List *targetList,
362 : ExprContext *econtext,
363 : TupleTableSlot *slot,
364 : PlanState *parent,
365 : TupleDesc inputDesc)
366 : {
367 731368 : ProjectionInfo *projInfo = makeNode(ProjectionInfo);
368 : ExprState *state;
369 731368 : ExprEvalStep scratch = {0};
370 : ListCell *lc;
371 :
372 731368 : projInfo->pi_exprContext = econtext;
373 : /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
374 731368 : projInfo->pi_state.type = T_ExprState;
375 731368 : state = &projInfo->pi_state;
376 731368 : state->expr = (Expr *) targetList;
377 731368 : state->parent = parent;
378 731368 : state->ext_params = NULL;
379 :
380 731368 : state->resultslot = slot;
381 :
382 : /* Insert setup steps as needed */
383 731368 : ExecCreateExprSetupSteps(state, (Node *) targetList);
384 :
385 : /* Now compile each tlist column */
386 2484468 : foreach(lc, targetList)
387 : {
388 1753162 : TargetEntry *tle = lfirst_node(TargetEntry, lc);
389 1753162 : Var *variable = NULL;
390 1753162 : AttrNumber attnum = 0;
391 1753162 : bool isSafeVar = false;
392 :
393 : /*
394 : * If tlist expression is a safe non-system Var, use the fast-path
395 : * ASSIGN_*_VAR opcodes. "Safe" means that we don't need to apply
396 : * CheckVarSlotCompatibility() during plan startup. If a source slot
397 : * was provided, we make the equivalent tests here; if a slot was not
398 : * provided, we assume that no check is needed because we're dealing
399 : * with a non-relation-scan-level expression.
400 : */
401 1753162 : if (tle->expr != NULL &&
402 1753162 : IsA(tle->expr, Var) &&
403 1008348 : ((Var *) tle->expr)->varattno > 0)
404 : {
405 : /* Non-system Var, but how safe is it? */
406 934398 : variable = (Var *) tle->expr;
407 934398 : attnum = variable->varattno;
408 :
409 934398 : if (inputDesc == NULL)
410 565566 : isSafeVar = true; /* can't check, just assume OK */
411 368832 : else if (attnum <= inputDesc->natts)
412 : {
413 368242 : Form_pg_attribute attr = TupleDescAttr(inputDesc, attnum - 1);
414 :
415 : /*
416 : * If user attribute is dropped or has a type mismatch, don't
417 : * use ASSIGN_*_VAR. Instead let the normal expression
418 : * machinery handle it (which'll possibly error out).
419 : */
420 368242 : if (!attr->attisdropped && variable->vartype == attr->atttypid)
421 : {
422 367390 : isSafeVar = true;
423 : }
424 : }
425 : }
426 :
427 1753162 : if (isSafeVar)
428 : {
429 : /* Fast-path: just generate an EEOP_ASSIGN_*_VAR step */
430 932956 : switch (variable->varno)
431 : {
432 169936 : case INNER_VAR:
433 : /* get the tuple from the inner node */
434 169936 : scratch.opcode = EEOP_ASSIGN_INNER_VAR;
435 169936 : break;
436 :
437 394630 : case OUTER_VAR:
438 : /* get the tuple from the outer node */
439 394630 : scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
440 394630 : break;
441 :
442 : /* INDEX_VAR is handled by default case */
443 :
444 368390 : default:
445 : /* get the tuple from the relation being scanned */
446 368390 : scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
447 368390 : break;
448 : }
449 :
450 932956 : scratch.d.assign_var.attnum = attnum - 1;
451 932956 : scratch.d.assign_var.resultnum = tle->resno - 1;
452 932956 : ExprEvalPushStep(state, &scratch);
453 : }
454 : else
455 : {
456 : /*
457 : * Otherwise, compile the column expression normally.
458 : *
459 : * We can't tell the expression to evaluate directly into the
460 : * result slot, as the result slot (and the exprstate for that
461 : * matter) can change between executions. We instead evaluate
462 : * into the ExprState's resvalue/resnull and then move.
463 : */
464 820206 : ExecInitExprRec(tle->expr, state,
465 : &state->resvalue, &state->resnull);
466 :
467 : /*
468 : * Column might be referenced multiple times in upper nodes, so
469 : * force value to R/O - but only if it could be an expanded datum.
470 : */
471 820144 : if (get_typlen(exprType((Node *) tle->expr)) == -1)
472 262504 : scratch.opcode = EEOP_ASSIGN_TMP_MAKE_RO;
473 : else
474 557640 : scratch.opcode = EEOP_ASSIGN_TMP;
475 820144 : scratch.d.assign_tmp.resultnum = tle->resno - 1;
476 820144 : ExprEvalPushStep(state, &scratch);
477 : }
478 : }
479 :
480 731306 : scratch.opcode = EEOP_DONE;
481 731306 : ExprEvalPushStep(state, &scratch);
482 :
483 731306 : ExecReadyExpr(state);
484 :
485 731306 : return projInfo;
486 : }
487 :
488 : /*
489 : * ExecBuildUpdateProjection
490 : *
491 : * Build a ProjectionInfo node for constructing a new tuple during UPDATE.
492 : * The projection will be executed in the given econtext and the result will
493 : * be stored into the given tuple slot. (Caller must have ensured that tuple
494 : * slot has a descriptor matching the target rel!)
495 : *
496 : * When evalTargetList is false, targetList contains the UPDATE ... SET
497 : * expressions that have already been computed by a subplan node; the values
498 : * from this tlist are assumed to be available in the "outer" tuple slot.
499 : * When evalTargetList is true, targetList contains the UPDATE ... SET
500 : * expressions that must be computed (which could contain references to
501 : * the outer, inner, or scan tuple slots).
502 : *
503 : * In either case, targetColnos contains a list of the target column numbers
504 : * corresponding to the non-resjunk entries of targetList. The tlist values
505 : * are assigned into these columns of the result tuple slot. Target columns
506 : * not listed in targetColnos are filled from the UPDATE's old tuple, which
507 : * is assumed to be available in the "scan" tuple slot.
508 : *
509 : * targetList can also contain resjunk columns. These must be evaluated
510 : * if evalTargetList is true, but their values are discarded.
511 : *
512 : * relDesc must describe the relation we intend to update.
513 : *
514 : * This is basically a specialized variant of ExecBuildProjectionInfo.
515 : * However, it also performs sanity checks equivalent to ExecCheckPlanOutput.
516 : * Since we never make a normal tlist equivalent to the whole
517 : * tuple-to-be-assigned, there is no convenient way to apply
518 : * ExecCheckPlanOutput, so we must do our safety checks here.
519 : */
520 : ProjectionInfo *
521 15224 : ExecBuildUpdateProjection(List *targetList,
522 : bool evalTargetList,
523 : List *targetColnos,
524 : TupleDesc relDesc,
525 : ExprContext *econtext,
526 : TupleTableSlot *slot,
527 : PlanState *parent)
528 : {
529 15224 : ProjectionInfo *projInfo = makeNode(ProjectionInfo);
530 : ExprState *state;
531 : int nAssignableCols;
532 : bool sawJunk;
533 : Bitmapset *assignedCols;
534 15224 : ExprSetupInfo deform = {0, 0, 0, NIL};
535 15224 : ExprEvalStep scratch = {0};
536 : int outerattnum;
537 : ListCell *lc,
538 : *lc2;
539 :
540 15224 : projInfo->pi_exprContext = econtext;
541 : /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
542 15224 : projInfo->pi_state.type = T_ExprState;
543 15224 : state = &projInfo->pi_state;
544 15224 : if (evalTargetList)
545 2474 : state->expr = (Expr *) targetList;
546 : else
547 12750 : state->expr = NULL; /* not used */
548 15224 : state->parent = parent;
549 15224 : state->ext_params = NULL;
550 :
551 15224 : state->resultslot = slot;
552 :
553 : /*
554 : * Examine the targetList to see how many non-junk columns there are, and
555 : * to verify that the non-junk columns come before the junk ones.
556 : */
557 15224 : nAssignableCols = 0;
558 15224 : sawJunk = false;
559 50696 : foreach(lc, targetList)
560 : {
561 35472 : TargetEntry *tle = lfirst_node(TargetEntry, lc);
562 :
563 35472 : if (tle->resjunk)
564 15990 : sawJunk = true;
565 : else
566 : {
567 19482 : if (sawJunk)
568 0 : elog(ERROR, "subplan target list is out of order");
569 19482 : nAssignableCols++;
570 : }
571 : }
572 :
573 : /* We should have one targetColnos entry per non-junk column */
574 15224 : if (nAssignableCols != list_length(targetColnos))
575 0 : elog(ERROR, "targetColnos does not match subplan target list");
576 :
577 : /*
578 : * Build a bitmapset of the columns in targetColnos. (We could just use
579 : * list_member_int() tests, but that risks O(N^2) behavior with many
580 : * columns.)
581 : */
582 15224 : assignedCols = NULL;
583 34706 : foreach(lc, targetColnos)
584 : {
585 19482 : AttrNumber targetattnum = lfirst_int(lc);
586 :
587 19482 : assignedCols = bms_add_member(assignedCols, targetattnum);
588 : }
589 :
590 : /*
591 : * We need to insert EEOP_*_FETCHSOME steps to ensure the input tuples are
592 : * sufficiently deconstructed. The scan tuple must be deconstructed at
593 : * least as far as the last old column we need.
594 : */
595 25286 : for (int attnum = relDesc->natts; attnum > 0; attnum--)
596 : {
597 22966 : Form_pg_attribute attr = TupleDescAttr(relDesc, attnum - 1);
598 :
599 22966 : if (attr->attisdropped)
600 210 : continue;
601 22756 : if (bms_is_member(attnum, assignedCols))
602 9852 : continue;
603 12904 : deform.last_scan = attnum;
604 12904 : break;
605 : }
606 :
607 : /*
608 : * If we're actually evaluating the tlist, incorporate its input
609 : * requirements too; otherwise, we'll just need to fetch the appropriate
610 : * number of columns of the "outer" tuple.
611 : */
612 15224 : if (evalTargetList)
613 2474 : expr_setup_walker((Node *) targetList, &deform);
614 : else
615 12750 : deform.last_outer = nAssignableCols;
616 :
617 15224 : ExecPushExprSetupSteps(state, &deform);
618 :
619 : /*
620 : * Now generate code to evaluate the tlist's assignable expressions or
621 : * fetch them from the outer tuple, incidentally validating that they'll
622 : * be of the right data type. The checks above ensure that the forboth()
623 : * will iterate over exactly the non-junk columns. Note that we don't
624 : * bother evaluating any remaining resjunk columns.
625 : */
626 15224 : outerattnum = 0;
627 34706 : forboth(lc, targetList, lc2, targetColnos)
628 : {
629 19482 : TargetEntry *tle = lfirst_node(TargetEntry, lc);
630 19482 : AttrNumber targetattnum = lfirst_int(lc2);
631 : Form_pg_attribute attr;
632 :
633 : Assert(!tle->resjunk);
634 :
635 : /*
636 : * Apply sanity checks comparable to ExecCheckPlanOutput().
637 : */
638 19482 : if (targetattnum <= 0 || targetattnum > relDesc->natts)
639 0 : ereport(ERROR,
640 : (errcode(ERRCODE_DATATYPE_MISMATCH),
641 : errmsg("table row type and query-specified row type do not match"),
642 : errdetail("Query has too many columns.")));
643 19482 : attr = TupleDescAttr(relDesc, targetattnum - 1);
644 :
645 19482 : if (attr->attisdropped)
646 0 : ereport(ERROR,
647 : (errcode(ERRCODE_DATATYPE_MISMATCH),
648 : errmsg("table row type and query-specified row type do not match"),
649 : errdetail("Query provides a value for a dropped column at ordinal position %d.",
650 : targetattnum)));
651 19482 : if (exprType((Node *) tle->expr) != attr->atttypid)
652 0 : ereport(ERROR,
653 : (errcode(ERRCODE_DATATYPE_MISMATCH),
654 : errmsg("table row type and query-specified row type do not match"),
655 : errdetail("Table has type %s at ordinal position %d, but query expects %s.",
656 : format_type_be(attr->atttypid),
657 : targetattnum,
658 : format_type_be(exprType((Node *) tle->expr)))));
659 :
660 : /* OK, generate code to perform the assignment. */
661 19482 : if (evalTargetList)
662 : {
663 : /*
664 : * We must evaluate the TLE's expression and assign it. We do not
665 : * bother jumping through hoops for "safe" Vars like
666 : * ExecBuildProjectionInfo does; this is a relatively less-used
667 : * path and it doesn't seem worth expending code for that.
668 : */
669 3358 : ExecInitExprRec(tle->expr, state,
670 : &state->resvalue, &state->resnull);
671 : /* Needn't worry about read-only-ness here, either. */
672 3358 : scratch.opcode = EEOP_ASSIGN_TMP;
673 3358 : scratch.d.assign_tmp.resultnum = targetattnum - 1;
674 3358 : ExprEvalPushStep(state, &scratch);
675 : }
676 : else
677 : {
678 : /* Just assign from the outer tuple. */
679 16124 : scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
680 16124 : scratch.d.assign_var.attnum = outerattnum;
681 16124 : scratch.d.assign_var.resultnum = targetattnum - 1;
682 16124 : ExprEvalPushStep(state, &scratch);
683 : }
684 19482 : outerattnum++;
685 : }
686 :
687 : /*
688 : * Now generate code to copy over any old columns that were not assigned
689 : * to, and to ensure that dropped columns are set to NULL.
690 : */
691 148264 : for (int attnum = 1; attnum <= relDesc->natts; attnum++)
692 : {
693 133040 : Form_pg_attribute attr = TupleDescAttr(relDesc, attnum - 1);
694 :
695 133040 : if (attr->attisdropped)
696 : {
697 : /* Put a null into the ExprState's resvalue/resnull ... */
698 392 : scratch.opcode = EEOP_CONST;
699 392 : scratch.resvalue = &state->resvalue;
700 392 : scratch.resnull = &state->resnull;
701 392 : scratch.d.constval.value = (Datum) 0;
702 392 : scratch.d.constval.isnull = true;
703 392 : ExprEvalPushStep(state, &scratch);
704 : /* ... then assign it to the result slot */
705 392 : scratch.opcode = EEOP_ASSIGN_TMP;
706 392 : scratch.d.assign_tmp.resultnum = attnum - 1;
707 392 : ExprEvalPushStep(state, &scratch);
708 : }
709 132648 : else if (!bms_is_member(attnum, assignedCols))
710 : {
711 : /* Certainly the right type, so needn't check */
712 113166 : scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
713 113166 : scratch.d.assign_var.attnum = attnum - 1;
714 113166 : scratch.d.assign_var.resultnum = attnum - 1;
715 113166 : ExprEvalPushStep(state, &scratch);
716 : }
717 : }
718 :
719 15224 : scratch.opcode = EEOP_DONE;
720 15224 : ExprEvalPushStep(state, &scratch);
721 :
722 15224 : ExecReadyExpr(state);
723 :
724 15224 : return projInfo;
725 : }
726 :
727 : /*
728 : * ExecPrepareExpr --- initialize for expression execution outside a normal
729 : * Plan tree context.
730 : *
731 : * This differs from ExecInitExpr in that we don't assume the caller is
732 : * already running in the EState's per-query context. Also, we run the
733 : * passed expression tree through expression_planner() to prepare it for
734 : * execution. (In ordinary Plan trees the regular planning process will have
735 : * made the appropriate transformations on expressions, but for standalone
736 : * expressions this won't have happened.)
737 : */
738 : ExprState *
739 20360 : ExecPrepareExpr(Expr *node, EState *estate)
740 : {
741 : ExprState *result;
742 : MemoryContext oldcontext;
743 :
744 20360 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
745 :
746 20360 : node = expression_planner(node);
747 :
748 20354 : result = ExecInitExpr(node, NULL);
749 :
750 20354 : MemoryContextSwitchTo(oldcontext);
751 :
752 20354 : return result;
753 : }
754 :
755 : /*
756 : * ExecPrepareQual --- initialize for qual execution outside a normal
757 : * Plan tree context.
758 : *
759 : * This differs from ExecInitQual in that we don't assume the caller is
760 : * already running in the EState's per-query context. Also, we run the
761 : * passed expression tree through expression_planner() to prepare it for
762 : * execution. (In ordinary Plan trees the regular planning process will have
763 : * made the appropriate transformations on expressions, but for standalone
764 : * expressions this won't have happened.)
765 : */
766 : ExprState *
767 53112 : ExecPrepareQual(List *qual, EState *estate)
768 : {
769 : ExprState *result;
770 : MemoryContext oldcontext;
771 :
772 53112 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
773 :
774 53112 : qual = (List *) expression_planner((Expr *) qual);
775 :
776 53112 : result = ExecInitQual(qual, NULL);
777 :
778 53112 : MemoryContextSwitchTo(oldcontext);
779 :
780 53112 : return result;
781 : }
782 :
783 : /*
784 : * ExecPrepareCheck -- initialize check constraint for execution outside a
785 : * normal Plan tree context.
786 : *
787 : * See ExecPrepareExpr() and ExecInitCheck() for details.
788 : */
789 : ExprState *
790 5660 : ExecPrepareCheck(List *qual, EState *estate)
791 : {
792 : ExprState *result;
793 : MemoryContext oldcontext;
794 :
795 5660 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
796 :
797 5660 : qual = (List *) expression_planner((Expr *) qual);
798 :
799 5660 : result = ExecInitCheck(qual, NULL);
800 :
801 5660 : MemoryContextSwitchTo(oldcontext);
802 :
803 5660 : return result;
804 : }
805 :
806 : /*
807 : * Call ExecPrepareExpr() on each member of a list of Exprs, and return
808 : * a list of ExprStates.
809 : *
810 : * See ExecPrepareExpr() for details.
811 : */
812 : List *
813 12320 : ExecPrepareExprList(List *nodes, EState *estate)
814 : {
815 12320 : List *result = NIL;
816 : MemoryContext oldcontext;
817 : ListCell *lc;
818 :
819 : /* Ensure that the list cell nodes are in the right context too */
820 12320 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
821 :
822 24914 : foreach(lc, nodes)
823 : {
824 12594 : Expr *e = (Expr *) lfirst(lc);
825 :
826 12594 : result = lappend(result, ExecPrepareExpr(e, estate));
827 : }
828 :
829 12320 : MemoryContextSwitchTo(oldcontext);
830 :
831 12320 : return result;
832 : }
833 :
834 : /*
835 : * ExecCheck - evaluate a check constraint
836 : *
837 : * For check constraints, a null result is taken as TRUE, ie the constraint
838 : * passes.
839 : *
840 : * The check constraint may have been prepared with ExecInitCheck
841 : * (possibly via ExecPrepareCheck) if the caller had it in implicit-AND
842 : * format, but a regular boolean expression prepared with ExecInitExpr or
843 : * ExecPrepareExpr works too.
844 : */
845 : bool
846 96730 : ExecCheck(ExprState *state, ExprContext *econtext)
847 : {
848 : Datum ret;
849 : bool isnull;
850 :
851 : /* short-circuit (here and in ExecInitCheck) for empty restriction list */
852 96730 : if (state == NULL)
853 180 : return true;
854 :
855 : /* verify that expression was not compiled using ExecInitQual */
856 : Assert(!(state->flags & EEO_FLAG_IS_QUAL));
857 :
858 96550 : ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
859 :
860 96544 : if (isnull)
861 2806 : return true;
862 :
863 93738 : return DatumGetBool(ret);
864 : }
865 :
866 : /*
867 : * Prepare a compiled expression for execution. This has to be called for
868 : * every ExprState before it can be executed.
869 : *
870 : * NB: While this currently only calls ExecReadyInterpretedExpr(),
871 : * this will likely get extended to further expression evaluation methods.
872 : * Therefore this should be used instead of directly calling
873 : * ExecReadyInterpretedExpr().
874 : */
875 : static void
876 2250268 : ExecReadyExpr(ExprState *state)
877 : {
878 2250268 : if (jit_compile_expr(state))
879 11060 : return;
880 :
881 2239208 : ExecReadyInterpretedExpr(state);
882 : }
883 :
884 : /*
885 : * Append the steps necessary for the evaluation of node to ExprState->steps,
886 : * possibly recursing into sub-expressions of node.
887 : *
888 : * node - expression to evaluate
889 : * state - ExprState to whose ->steps to append the necessary operations
890 : * resv / resnull - where to store the result of the node into
891 : */
892 : static void
893 4767200 : ExecInitExprRec(Expr *node, ExprState *state,
894 : Datum *resv, bool *resnull)
895 : {
896 4767200 : ExprEvalStep scratch = {0};
897 :
898 : /* Guard against stack overflow due to overly complex expressions */
899 4767200 : check_stack_depth();
900 :
901 : /* Step's output location is always what the caller gave us */
902 : Assert(resv != NULL && resnull != NULL);
903 4767200 : scratch.resvalue = resv;
904 4767200 : scratch.resnull = resnull;
905 :
906 : /* cases should be ordered as they are in enum NodeTag */
907 4767200 : switch (nodeTag(node))
908 : {
909 1090468 : case T_Var:
910 : {
911 1090468 : Var *variable = (Var *) node;
912 :
913 1090468 : if (variable->varattno == InvalidAttrNumber)
914 : {
915 : /* whole-row Var */
916 3782 : ExecInitWholeRowVar(&scratch, variable, state);
917 : }
918 1086686 : else if (variable->varattno <= 0)
919 : {
920 : /* system column */
921 74336 : scratch.d.var.attnum = variable->varattno;
922 74336 : scratch.d.var.vartype = variable->vartype;
923 74336 : switch (variable->varno)
924 : {
925 6 : case INNER_VAR:
926 6 : scratch.opcode = EEOP_INNER_SYSVAR;
927 6 : break;
928 12 : case OUTER_VAR:
929 12 : scratch.opcode = EEOP_OUTER_SYSVAR;
930 12 : break;
931 :
932 : /* INDEX_VAR is handled by default case */
933 :
934 74318 : default:
935 74318 : scratch.opcode = EEOP_SCAN_SYSVAR;
936 74318 : break;
937 : }
938 : }
939 : else
940 : {
941 : /* regular user column */
942 1012350 : scratch.d.var.attnum = variable->varattno - 1;
943 1012350 : scratch.d.var.vartype = variable->vartype;
944 1012350 : switch (variable->varno)
945 : {
946 115276 : case INNER_VAR:
947 115276 : scratch.opcode = EEOP_INNER_VAR;
948 115276 : break;
949 286268 : case OUTER_VAR:
950 286268 : scratch.opcode = EEOP_OUTER_VAR;
951 286268 : break;
952 :
953 : /* INDEX_VAR is handled by default case */
954 :
955 610806 : default:
956 610806 : scratch.opcode = EEOP_SCAN_VAR;
957 610806 : break;
958 : }
959 : }
960 :
961 1090468 : ExprEvalPushStep(state, &scratch);
962 1090468 : break;
963 : }
964 :
965 992646 : case T_Const:
966 : {
967 992646 : Const *con = (Const *) node;
968 :
969 992646 : scratch.opcode = EEOP_CONST;
970 992646 : scratch.d.constval.value = con->constvalue;
971 992646 : scratch.d.constval.isnull = con->constisnull;
972 :
973 992646 : ExprEvalPushStep(state, &scratch);
974 992646 : break;
975 : }
976 :
977 745792 : case T_Param:
978 : {
979 745792 : Param *param = (Param *) node;
980 : ParamListInfo params;
981 :
982 745792 : switch (param->paramkind)
983 : {
984 222224 : case PARAM_EXEC:
985 222224 : scratch.opcode = EEOP_PARAM_EXEC;
986 222224 : scratch.d.param.paramid = param->paramid;
987 222224 : scratch.d.param.paramtype = param->paramtype;
988 222224 : ExprEvalPushStep(state, &scratch);
989 222224 : break;
990 523568 : case PARAM_EXTERN:
991 :
992 : /*
993 : * If we have a relevant ParamCompileHook, use it;
994 : * otherwise compile a standard EEOP_PARAM_EXTERN
995 : * step. ext_params, if supplied, takes precedence
996 : * over info from the parent node's EState (if any).
997 : */
998 523568 : if (state->ext_params)
999 68944 : params = state->ext_params;
1000 454624 : else if (state->parent &&
1001 454326 : state->parent->state)
1002 454326 : params = state->parent->state->es_param_list_info;
1003 : else
1004 298 : params = NULL;
1005 523568 : if (params && params->paramCompile)
1006 : {
1007 125754 : params->paramCompile(params, param, state,
1008 : resv, resnull);
1009 : }
1010 : else
1011 : {
1012 397814 : scratch.opcode = EEOP_PARAM_EXTERN;
1013 397814 : scratch.d.param.paramid = param->paramid;
1014 397814 : scratch.d.param.paramtype = param->paramtype;
1015 397814 : ExprEvalPushStep(state, &scratch);
1016 : }
1017 523568 : break;
1018 0 : default:
1019 0 : elog(ERROR, "unrecognized paramkind: %d",
1020 : (int) param->paramkind);
1021 : break;
1022 : }
1023 745792 : break;
1024 : }
1025 :
1026 46804 : case T_Aggref:
1027 : {
1028 46804 : Aggref *aggref = (Aggref *) node;
1029 :
1030 46804 : scratch.opcode = EEOP_AGGREF;
1031 46804 : scratch.d.aggref.aggno = aggref->aggno;
1032 :
1033 46804 : if (state->parent && IsA(state->parent, AggState))
1034 46804 : {
1035 46804 : AggState *aggstate = (AggState *) state->parent;
1036 :
1037 46804 : aggstate->aggs = lappend(aggstate->aggs, aggref);
1038 : }
1039 : else
1040 : {
1041 : /* planner messed up */
1042 0 : elog(ERROR, "Aggref found in non-Agg plan node");
1043 : }
1044 :
1045 46804 : ExprEvalPushStep(state, &scratch);
1046 46804 : break;
1047 : }
1048 :
1049 302 : case T_GroupingFunc:
1050 : {
1051 302 : GroupingFunc *grp_node = (GroupingFunc *) node;
1052 : Agg *agg;
1053 :
1054 302 : if (!state->parent || !IsA(state->parent, AggState) ||
1055 302 : !IsA(state->parent->plan, Agg))
1056 0 : elog(ERROR, "GroupingFunc found in non-Agg plan node");
1057 :
1058 302 : scratch.opcode = EEOP_GROUPING_FUNC;
1059 :
1060 302 : agg = (Agg *) (state->parent->plan);
1061 :
1062 302 : if (agg->groupingSets)
1063 212 : scratch.d.grouping_func.clauses = grp_node->cols;
1064 : else
1065 90 : scratch.d.grouping_func.clauses = NIL;
1066 :
1067 302 : ExprEvalPushStep(state, &scratch);
1068 302 : break;
1069 : }
1070 :
1071 3116 : case T_WindowFunc:
1072 : {
1073 3116 : WindowFunc *wfunc = (WindowFunc *) node;
1074 3116 : WindowFuncExprState *wfstate = makeNode(WindowFuncExprState);
1075 :
1076 3116 : wfstate->wfunc = wfunc;
1077 :
1078 3116 : if (state->parent && IsA(state->parent, WindowAggState))
1079 3116 : {
1080 3116 : WindowAggState *winstate = (WindowAggState *) state->parent;
1081 : int nfuncs;
1082 :
1083 3116 : winstate->funcs = lappend(winstate->funcs, wfstate);
1084 3116 : nfuncs = ++winstate->numfuncs;
1085 3116 : if (wfunc->winagg)
1086 1436 : winstate->numaggs++;
1087 :
1088 : /* for now initialize agg using old style expressions */
1089 6232 : wfstate->args = ExecInitExprList(wfunc->args,
1090 3116 : state->parent);
1091 6232 : wfstate->aggfilter = ExecInitExpr(wfunc->aggfilter,
1092 3116 : state->parent);
1093 :
1094 : /*
1095 : * Complain if the windowfunc's arguments contain any
1096 : * windowfuncs; nested window functions are semantically
1097 : * nonsensical. (This should have been caught earlier,
1098 : * but we defend against it here anyway.)
1099 : */
1100 3116 : if (nfuncs != winstate->numfuncs)
1101 0 : ereport(ERROR,
1102 : (errcode(ERRCODE_WINDOWING_ERROR),
1103 : errmsg("window function calls cannot be nested")));
1104 : }
1105 : else
1106 : {
1107 : /* planner messed up */
1108 0 : elog(ERROR, "WindowFunc found in non-WindowAgg plan node");
1109 : }
1110 :
1111 3116 : scratch.opcode = EEOP_WINDOW_FUNC;
1112 3116 : scratch.d.window_func.wfstate = wfstate;
1113 3116 : ExprEvalPushStep(state, &scratch);
1114 3116 : break;
1115 : }
1116 :
1117 186 : case T_MergeSupportFunc:
1118 : {
1119 : /* must be in a MERGE, else something messed up */
1120 186 : if (!state->parent ||
1121 186 : !IsA(state->parent, ModifyTableState) ||
1122 186 : ((ModifyTableState *) state->parent)->operation != CMD_MERGE)
1123 0 : elog(ERROR, "MergeSupportFunc found in non-merge plan node");
1124 :
1125 186 : scratch.opcode = EEOP_MERGE_SUPPORT_FUNC;
1126 186 : ExprEvalPushStep(state, &scratch);
1127 186 : break;
1128 : }
1129 :
1130 22376 : case T_SubscriptingRef:
1131 : {
1132 22376 : SubscriptingRef *sbsref = (SubscriptingRef *) node;
1133 :
1134 22376 : ExecInitSubscriptingRef(&scratch, sbsref, state, resv, resnull);
1135 22376 : break;
1136 : }
1137 :
1138 619666 : case T_FuncExpr:
1139 : {
1140 619666 : FuncExpr *func = (FuncExpr *) node;
1141 :
1142 619666 : ExecInitFunc(&scratch, node,
1143 : func->args, func->funcid, func->inputcollid,
1144 : state);
1145 619592 : ExprEvalPushStep(state, &scratch);
1146 619592 : break;
1147 : }
1148 :
1149 770460 : case T_OpExpr:
1150 : {
1151 770460 : OpExpr *op = (OpExpr *) node;
1152 :
1153 770460 : ExecInitFunc(&scratch, node,
1154 : op->args, op->opfuncid, op->inputcollid,
1155 : state);
1156 770460 : ExprEvalPushStep(state, &scratch);
1157 770460 : break;
1158 : }
1159 :
1160 930 : case T_DistinctExpr:
1161 : {
1162 930 : DistinctExpr *op = (DistinctExpr *) node;
1163 :
1164 930 : ExecInitFunc(&scratch, node,
1165 : op->args, op->opfuncid, op->inputcollid,
1166 : state);
1167 :
1168 : /*
1169 : * Change opcode of call instruction to EEOP_DISTINCT.
1170 : *
1171 : * XXX: historically we've not called the function usage
1172 : * pgstat infrastructure - that seems inconsistent given that
1173 : * we do so for normal function *and* operator evaluation. If
1174 : * we decided to do that here, we'd probably want separate
1175 : * opcodes for FUSAGE or not.
1176 : */
1177 930 : scratch.opcode = EEOP_DISTINCT;
1178 930 : ExprEvalPushStep(state, &scratch);
1179 930 : break;
1180 : }
1181 :
1182 168 : case T_NullIfExpr:
1183 : {
1184 168 : NullIfExpr *op = (NullIfExpr *) node;
1185 :
1186 168 : ExecInitFunc(&scratch, node,
1187 : op->args, op->opfuncid, op->inputcollid,
1188 : state);
1189 :
1190 : /*
1191 : * Change opcode of call instruction to EEOP_NULLIF.
1192 : *
1193 : * XXX: historically we've not called the function usage
1194 : * pgstat infrastructure - that seems inconsistent given that
1195 : * we do so for normal function *and* operator evaluation. If
1196 : * we decided to do that here, we'd probably want separate
1197 : * opcodes for FUSAGE or not.
1198 : */
1199 168 : scratch.opcode = EEOP_NULLIF;
1200 168 : ExprEvalPushStep(state, &scratch);
1201 168 : break;
1202 : }
1203 :
1204 33498 : case T_ScalarArrayOpExpr:
1205 : {
1206 33498 : ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
1207 : Expr *scalararg;
1208 : Expr *arrayarg;
1209 : FmgrInfo *finfo;
1210 : FunctionCallInfo fcinfo;
1211 : AclResult aclresult;
1212 : Oid cmpfuncid;
1213 :
1214 : /*
1215 : * Select the correct comparison function. When we do hashed
1216 : * NOT IN clauses, the opfuncid will be the inequality
1217 : * comparison function and negfuncid will be set to equality.
1218 : * We need to use the equality function for hash probes.
1219 : */
1220 33498 : if (OidIsValid(opexpr->negfuncid))
1221 : {
1222 : Assert(OidIsValid(opexpr->hashfuncid));
1223 70 : cmpfuncid = opexpr->negfuncid;
1224 : }
1225 : else
1226 33428 : cmpfuncid = opexpr->opfuncid;
1227 :
1228 : Assert(list_length(opexpr->args) == 2);
1229 33498 : scalararg = (Expr *) linitial(opexpr->args);
1230 33498 : arrayarg = (Expr *) lsecond(opexpr->args);
1231 :
1232 : /* Check permission to call function */
1233 33498 : aclresult = object_aclcheck(ProcedureRelationId, cmpfuncid,
1234 : GetUserId(),
1235 : ACL_EXECUTE);
1236 33498 : if (aclresult != ACLCHECK_OK)
1237 0 : aclcheck_error(aclresult, OBJECT_FUNCTION,
1238 0 : get_func_name(cmpfuncid));
1239 33498 : InvokeFunctionExecuteHook(cmpfuncid);
1240 :
1241 33498 : if (OidIsValid(opexpr->hashfuncid))
1242 : {
1243 266 : aclresult = object_aclcheck(ProcedureRelationId, opexpr->hashfuncid,
1244 : GetUserId(),
1245 : ACL_EXECUTE);
1246 266 : if (aclresult != ACLCHECK_OK)
1247 0 : aclcheck_error(aclresult, OBJECT_FUNCTION,
1248 0 : get_func_name(opexpr->hashfuncid));
1249 266 : InvokeFunctionExecuteHook(opexpr->hashfuncid);
1250 : }
1251 :
1252 : /* Set up the primary fmgr lookup information */
1253 33498 : finfo = palloc0(sizeof(FmgrInfo));
1254 33498 : fcinfo = palloc0(SizeForFunctionCallInfo(2));
1255 33498 : fmgr_info(cmpfuncid, finfo);
1256 33498 : fmgr_info_set_expr((Node *) node, finfo);
1257 33498 : InitFunctionCallInfoData(*fcinfo, finfo, 2,
1258 : opexpr->inputcollid, NULL, NULL);
1259 :
1260 : /*
1261 : * If hashfuncid is set, we create a EEOP_HASHED_SCALARARRAYOP
1262 : * step instead of a EEOP_SCALARARRAYOP. This provides much
1263 : * faster lookup performance than the normal linear search
1264 : * when the number of items in the array is anything but very
1265 : * small.
1266 : */
1267 33498 : if (OidIsValid(opexpr->hashfuncid))
1268 : {
1269 : /* Evaluate scalar directly into left function argument */
1270 266 : ExecInitExprRec(scalararg, state,
1271 : &fcinfo->args[0].value, &fcinfo->args[0].isnull);
1272 :
1273 : /*
1274 : * Evaluate array argument into our return value. There's
1275 : * no danger in that, because the return value is
1276 : * guaranteed to be overwritten by
1277 : * EEOP_HASHED_SCALARARRAYOP, and will not be passed to
1278 : * any other expression.
1279 : */
1280 266 : ExecInitExprRec(arrayarg, state, resv, resnull);
1281 :
1282 : /* And perform the operation */
1283 266 : scratch.opcode = EEOP_HASHED_SCALARARRAYOP;
1284 266 : scratch.d.hashedscalararrayop.inclause = opexpr->useOr;
1285 266 : scratch.d.hashedscalararrayop.finfo = finfo;
1286 266 : scratch.d.hashedscalararrayop.fcinfo_data = fcinfo;
1287 266 : scratch.d.hashedscalararrayop.saop = opexpr;
1288 :
1289 :
1290 266 : ExprEvalPushStep(state, &scratch);
1291 : }
1292 : else
1293 : {
1294 : /* Evaluate scalar directly into left function argument */
1295 33232 : ExecInitExprRec(scalararg, state,
1296 : &fcinfo->args[0].value,
1297 : &fcinfo->args[0].isnull);
1298 :
1299 : /*
1300 : * Evaluate array argument into our return value. There's
1301 : * no danger in that, because the return value is
1302 : * guaranteed to be overwritten by EEOP_SCALARARRAYOP, and
1303 : * will not be passed to any other expression.
1304 : */
1305 33232 : ExecInitExprRec(arrayarg, state, resv, resnull);
1306 :
1307 : /* And perform the operation */
1308 33232 : scratch.opcode = EEOP_SCALARARRAYOP;
1309 33232 : scratch.d.scalararrayop.element_type = InvalidOid;
1310 33232 : scratch.d.scalararrayop.useOr = opexpr->useOr;
1311 33232 : scratch.d.scalararrayop.finfo = finfo;
1312 33232 : scratch.d.scalararrayop.fcinfo_data = fcinfo;
1313 33232 : scratch.d.scalararrayop.fn_addr = finfo->fn_addr;
1314 33232 : ExprEvalPushStep(state, &scratch);
1315 : }
1316 33498 : break;
1317 : }
1318 :
1319 66046 : case T_BoolExpr:
1320 : {
1321 66046 : BoolExpr *boolexpr = (BoolExpr *) node;
1322 66046 : int nargs = list_length(boolexpr->args);
1323 66046 : List *adjust_jumps = NIL;
1324 : int off;
1325 : ListCell *lc;
1326 :
1327 : /* allocate scratch memory used by all steps of AND/OR */
1328 66046 : if (boolexpr->boolop != NOT_EXPR)
1329 54734 : scratch.d.boolexpr.anynull = (bool *) palloc(sizeof(bool));
1330 :
1331 : /*
1332 : * For each argument evaluate the argument itself, then
1333 : * perform the bool operation's appropriate handling.
1334 : *
1335 : * We can evaluate each argument into our result area, since
1336 : * the short-circuiting logic means we only need to remember
1337 : * previous NULL values.
1338 : *
1339 : * AND/OR is split into separate STEP_FIRST (one) / STEP (zero
1340 : * or more) / STEP_LAST (one) steps, as each of those has to
1341 : * perform different work. The FIRST/LAST split is valid
1342 : * because AND/OR have at least two arguments.
1343 : */
1344 66046 : off = 0;
1345 199664 : foreach(lc, boolexpr->args)
1346 : {
1347 133618 : Expr *arg = (Expr *) lfirst(lc);
1348 :
1349 : /* Evaluate argument into our output variable */
1350 133618 : ExecInitExprRec(arg, state, resv, resnull);
1351 :
1352 : /* Perform the appropriate step type */
1353 133618 : switch (boolexpr->boolop)
1354 : {
1355 85688 : case AND_EXPR:
1356 : Assert(nargs >= 2);
1357 :
1358 85688 : if (off == 0)
1359 38760 : scratch.opcode = EEOP_BOOL_AND_STEP_FIRST;
1360 46928 : else if (off + 1 == nargs)
1361 38760 : scratch.opcode = EEOP_BOOL_AND_STEP_LAST;
1362 : else
1363 8168 : scratch.opcode = EEOP_BOOL_AND_STEP;
1364 85688 : break;
1365 36618 : case OR_EXPR:
1366 : Assert(nargs >= 2);
1367 :
1368 36618 : if (off == 0)
1369 15974 : scratch.opcode = EEOP_BOOL_OR_STEP_FIRST;
1370 20644 : else if (off + 1 == nargs)
1371 15974 : scratch.opcode = EEOP_BOOL_OR_STEP_LAST;
1372 : else
1373 4670 : scratch.opcode = EEOP_BOOL_OR_STEP;
1374 36618 : break;
1375 11312 : case NOT_EXPR:
1376 : Assert(nargs == 1);
1377 :
1378 11312 : scratch.opcode = EEOP_BOOL_NOT_STEP;
1379 11312 : break;
1380 0 : default:
1381 0 : elog(ERROR, "unrecognized boolop: %d",
1382 : (int) boolexpr->boolop);
1383 : break;
1384 : }
1385 :
1386 133618 : scratch.d.boolexpr.jumpdone = -1;
1387 133618 : ExprEvalPushStep(state, &scratch);
1388 133618 : adjust_jumps = lappend_int(adjust_jumps,
1389 133618 : state->steps_len - 1);
1390 133618 : off++;
1391 : }
1392 :
1393 : /* adjust jump targets */
1394 199664 : foreach(lc, adjust_jumps)
1395 : {
1396 133618 : ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1397 :
1398 : Assert(as->d.boolexpr.jumpdone == -1);
1399 133618 : as->d.boolexpr.jumpdone = state->steps_len;
1400 : }
1401 :
1402 66046 : break;
1403 : }
1404 :
1405 23912 : case T_SubPlan:
1406 : {
1407 23912 : SubPlan *subplan = (SubPlan *) node;
1408 : SubPlanState *sstate;
1409 :
1410 : /*
1411 : * Real execution of a MULTIEXPR SubPlan has already been
1412 : * done. What we have to do here is return a dummy NULL record
1413 : * value in case this targetlist element is assigned
1414 : * someplace.
1415 : */
1416 23912 : if (subplan->subLinkType == MULTIEXPR_SUBLINK)
1417 : {
1418 60 : scratch.opcode = EEOP_CONST;
1419 60 : scratch.d.constval.value = (Datum) 0;
1420 60 : scratch.d.constval.isnull = true;
1421 60 : ExprEvalPushStep(state, &scratch);
1422 60 : break;
1423 : }
1424 :
1425 23852 : if (!state->parent)
1426 0 : elog(ERROR, "SubPlan found with no parent plan");
1427 :
1428 23852 : sstate = ExecInitSubPlan(subplan, state->parent);
1429 :
1430 : /* add SubPlanState nodes to state->parent->subPlan */
1431 23852 : state->parent->subPlan = lappend(state->parent->subPlan,
1432 : sstate);
1433 :
1434 23852 : scratch.opcode = EEOP_SUBPLAN;
1435 23852 : scratch.d.subplan.sstate = sstate;
1436 :
1437 23852 : ExprEvalPushStep(state, &scratch);
1438 23852 : break;
1439 : }
1440 :
1441 7716 : case T_FieldSelect:
1442 : {
1443 7716 : FieldSelect *fselect = (FieldSelect *) node;
1444 :
1445 : /* evaluate row/record argument into result area */
1446 7716 : ExecInitExprRec(fselect->arg, state, resv, resnull);
1447 :
1448 : /* and extract field */
1449 7716 : scratch.opcode = EEOP_FIELDSELECT;
1450 7716 : scratch.d.fieldselect.fieldnum = fselect->fieldnum;
1451 7716 : scratch.d.fieldselect.resulttype = fselect->resulttype;
1452 7716 : scratch.d.fieldselect.rowcache.cacheptr = NULL;
1453 :
1454 7716 : ExprEvalPushStep(state, &scratch);
1455 7716 : break;
1456 : }
1457 :
1458 382 : case T_FieldStore:
1459 : {
1460 382 : FieldStore *fstore = (FieldStore *) node;
1461 : TupleDesc tupDesc;
1462 : ExprEvalRowtypeCache *rowcachep;
1463 : Datum *values;
1464 : bool *nulls;
1465 : int ncolumns;
1466 : ListCell *l1,
1467 : *l2;
1468 :
1469 : /* find out the number of columns in the composite type */
1470 382 : tupDesc = lookup_rowtype_tupdesc(fstore->resulttype, -1);
1471 382 : ncolumns = tupDesc->natts;
1472 382 : ReleaseTupleDesc(tupDesc);
1473 :
1474 : /* create workspace for column values */
1475 382 : values = (Datum *) palloc(sizeof(Datum) * ncolumns);
1476 382 : nulls = (bool *) palloc(sizeof(bool) * ncolumns);
1477 :
1478 : /* create shared composite-type-lookup cache struct */
1479 382 : rowcachep = palloc(sizeof(ExprEvalRowtypeCache));
1480 382 : rowcachep->cacheptr = NULL;
1481 :
1482 : /* emit code to evaluate the composite input value */
1483 382 : ExecInitExprRec(fstore->arg, state, resv, resnull);
1484 :
1485 : /* next, deform the input tuple into our workspace */
1486 382 : scratch.opcode = EEOP_FIELDSTORE_DEFORM;
1487 382 : scratch.d.fieldstore.fstore = fstore;
1488 382 : scratch.d.fieldstore.rowcache = rowcachep;
1489 382 : scratch.d.fieldstore.values = values;
1490 382 : scratch.d.fieldstore.nulls = nulls;
1491 382 : scratch.d.fieldstore.ncolumns = ncolumns;
1492 382 : ExprEvalPushStep(state, &scratch);
1493 :
1494 : /* evaluate new field values, store in workspace columns */
1495 890 : forboth(l1, fstore->newvals, l2, fstore->fieldnums)
1496 : {
1497 508 : Expr *e = (Expr *) lfirst(l1);
1498 508 : AttrNumber fieldnum = lfirst_int(l2);
1499 : Datum *save_innermost_caseval;
1500 : bool *save_innermost_casenull;
1501 :
1502 508 : if (fieldnum <= 0 || fieldnum > ncolumns)
1503 0 : elog(ERROR, "field number %d is out of range in FieldStore",
1504 : fieldnum);
1505 :
1506 : /*
1507 : * Use the CaseTestExpr mechanism to pass down the old
1508 : * value of the field being replaced; this is needed in
1509 : * case the newval is itself a FieldStore or
1510 : * SubscriptingRef that has to obtain and modify the old
1511 : * value. It's safe to reuse the CASE mechanism because
1512 : * there cannot be a CASE between here and where the value
1513 : * would be needed, and a field assignment can't be within
1514 : * a CASE either. (So saving and restoring
1515 : * innermost_caseval is just paranoia, but let's do it
1516 : * anyway.)
1517 : *
1518 : * Another non-obvious point is that it's safe to use the
1519 : * field's values[]/nulls[] entries as both the caseval
1520 : * source and the result address for this subexpression.
1521 : * That's okay only because (1) both FieldStore and
1522 : * SubscriptingRef evaluate their arg or refexpr inputs
1523 : * first, and (2) any such CaseTestExpr is directly the
1524 : * arg or refexpr input. So any read of the caseval will
1525 : * occur before there's a chance to overwrite it. Also,
1526 : * if multiple entries in the newvals/fieldnums lists
1527 : * target the same field, they'll effectively be applied
1528 : * left-to-right which is what we want.
1529 : */
1530 508 : save_innermost_caseval = state->innermost_caseval;
1531 508 : save_innermost_casenull = state->innermost_casenull;
1532 508 : state->innermost_caseval = &values[fieldnum - 1];
1533 508 : state->innermost_casenull = &nulls[fieldnum - 1];
1534 :
1535 508 : ExecInitExprRec(e, state,
1536 508 : &values[fieldnum - 1],
1537 508 : &nulls[fieldnum - 1]);
1538 :
1539 508 : state->innermost_caseval = save_innermost_caseval;
1540 508 : state->innermost_casenull = save_innermost_casenull;
1541 : }
1542 :
1543 : /* finally, form result tuple */
1544 382 : scratch.opcode = EEOP_FIELDSTORE_FORM;
1545 382 : scratch.d.fieldstore.fstore = fstore;
1546 382 : scratch.d.fieldstore.rowcache = rowcachep;
1547 382 : scratch.d.fieldstore.values = values;
1548 382 : scratch.d.fieldstore.nulls = nulls;
1549 382 : scratch.d.fieldstore.ncolumns = ncolumns;
1550 382 : ExprEvalPushStep(state, &scratch);
1551 382 : break;
1552 : }
1553 :
1554 80974 : case T_RelabelType:
1555 : {
1556 : /* relabel doesn't need to do anything at runtime */
1557 80974 : RelabelType *relabel = (RelabelType *) node;
1558 :
1559 80974 : ExecInitExprRec(relabel->arg, state, resv, resnull);
1560 80974 : break;
1561 : }
1562 :
1563 37926 : case T_CoerceViaIO:
1564 : {
1565 37926 : CoerceViaIO *iocoerce = (CoerceViaIO *) node;
1566 : Oid iofunc;
1567 : bool typisvarlena;
1568 : Oid typioparam;
1569 : FunctionCallInfo fcinfo_in;
1570 :
1571 : /* evaluate argument into step's result area */
1572 37926 : ExecInitExprRec(iocoerce->arg, state, resv, resnull);
1573 :
1574 : /*
1575 : * Prepare both output and input function calls, to be
1576 : * evaluated inside a single evaluation step for speed - this
1577 : * can be a very common operation.
1578 : *
1579 : * We don't check permissions here as a type's input/output
1580 : * function are assumed to be executable by everyone.
1581 : */
1582 37926 : if (state->escontext == NULL)
1583 37662 : scratch.opcode = EEOP_IOCOERCE;
1584 : else
1585 264 : scratch.opcode = EEOP_IOCOERCE_SAFE;
1586 :
1587 : /* lookup the source type's output function */
1588 37926 : scratch.d.iocoerce.finfo_out = palloc0(sizeof(FmgrInfo));
1589 37926 : scratch.d.iocoerce.fcinfo_data_out = palloc0(SizeForFunctionCallInfo(1));
1590 :
1591 37926 : getTypeOutputInfo(exprType((Node *) iocoerce->arg),
1592 : &iofunc, &typisvarlena);
1593 37926 : fmgr_info(iofunc, scratch.d.iocoerce.finfo_out);
1594 37926 : fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_out);
1595 37926 : InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_out,
1596 : scratch.d.iocoerce.finfo_out,
1597 : 1, InvalidOid, NULL, NULL);
1598 :
1599 : /* lookup the result type's input function */
1600 37926 : scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo));
1601 37926 : scratch.d.iocoerce.fcinfo_data_in = palloc0(SizeForFunctionCallInfo(3));
1602 :
1603 37926 : getTypeInputInfo(iocoerce->resulttype,
1604 : &iofunc, &typioparam);
1605 37926 : fmgr_info(iofunc, scratch.d.iocoerce.finfo_in);
1606 37926 : fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_in);
1607 37926 : InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_in,
1608 : scratch.d.iocoerce.finfo_in,
1609 : 3, InvalidOid, NULL, NULL);
1610 :
1611 : /*
1612 : * We can preload the second and third arguments for the input
1613 : * function, since they're constants.
1614 : */
1615 37926 : fcinfo_in = scratch.d.iocoerce.fcinfo_data_in;
1616 37926 : fcinfo_in->args[1].value = ObjectIdGetDatum(typioparam);
1617 37926 : fcinfo_in->args[1].isnull = false;
1618 37926 : fcinfo_in->args[2].value = Int32GetDatum(-1);
1619 37926 : fcinfo_in->args[2].isnull = false;
1620 :
1621 37926 : fcinfo_in->context = (Node *) state->escontext;
1622 :
1623 37926 : ExprEvalPushStep(state, &scratch);
1624 37926 : break;
1625 : }
1626 :
1627 5100 : case T_ArrayCoerceExpr:
1628 : {
1629 5100 : ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
1630 : Oid resultelemtype;
1631 : ExprState *elemstate;
1632 :
1633 : /* evaluate argument into step's result area */
1634 5100 : ExecInitExprRec(acoerce->arg, state, resv, resnull);
1635 :
1636 5100 : resultelemtype = get_element_type(acoerce->resulttype);
1637 5100 : if (!OidIsValid(resultelemtype))
1638 0 : ereport(ERROR,
1639 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1640 : errmsg("target type is not an array")));
1641 :
1642 : /*
1643 : * Construct a sub-expression for the per-element expression;
1644 : * but don't ready it until after we check it for triviality.
1645 : * We assume it hasn't any Var references, but does have a
1646 : * CaseTestExpr representing the source array element values.
1647 : */
1648 5100 : elemstate = makeNode(ExprState);
1649 5100 : elemstate->expr = acoerce->elemexpr;
1650 5100 : elemstate->parent = state->parent;
1651 5100 : elemstate->ext_params = state->ext_params;
1652 :
1653 5100 : elemstate->innermost_caseval = (Datum *) palloc(sizeof(Datum));
1654 5100 : elemstate->innermost_casenull = (bool *) palloc(sizeof(bool));
1655 :
1656 5100 : ExecInitExprRec(acoerce->elemexpr, elemstate,
1657 : &elemstate->resvalue, &elemstate->resnull);
1658 :
1659 5094 : if (elemstate->steps_len == 1 &&
1660 4658 : elemstate->steps[0].opcode == EEOP_CASE_TESTVAL)
1661 : {
1662 : /* Trivial, so we need no per-element work at runtime */
1663 4658 : elemstate = NULL;
1664 : }
1665 : else
1666 : {
1667 : /* Not trivial, so append a DONE step */
1668 436 : scratch.opcode = EEOP_DONE;
1669 436 : ExprEvalPushStep(elemstate, &scratch);
1670 : /* and ready the subexpression */
1671 436 : ExecReadyExpr(elemstate);
1672 : }
1673 :
1674 5094 : scratch.opcode = EEOP_ARRAYCOERCE;
1675 5094 : scratch.d.arraycoerce.elemexprstate = elemstate;
1676 5094 : scratch.d.arraycoerce.resultelemtype = resultelemtype;
1677 :
1678 5094 : if (elemstate)
1679 : {
1680 : /* Set up workspace for array_map */
1681 436 : scratch.d.arraycoerce.amstate =
1682 436 : (ArrayMapState *) palloc0(sizeof(ArrayMapState));
1683 : }
1684 : else
1685 : {
1686 : /* Don't need workspace if there's no subexpression */
1687 4658 : scratch.d.arraycoerce.amstate = NULL;
1688 : }
1689 :
1690 5094 : ExprEvalPushStep(state, &scratch);
1691 5094 : break;
1692 : }
1693 :
1694 656 : case T_ConvertRowtypeExpr:
1695 : {
1696 656 : ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
1697 : ExprEvalRowtypeCache *rowcachep;
1698 :
1699 : /* cache structs must be out-of-line for space reasons */
1700 656 : rowcachep = palloc(2 * sizeof(ExprEvalRowtypeCache));
1701 656 : rowcachep[0].cacheptr = NULL;
1702 656 : rowcachep[1].cacheptr = NULL;
1703 :
1704 : /* evaluate argument into step's result area */
1705 656 : ExecInitExprRec(convert->arg, state, resv, resnull);
1706 :
1707 : /* and push conversion step */
1708 656 : scratch.opcode = EEOP_CONVERT_ROWTYPE;
1709 656 : scratch.d.convert_rowtype.inputtype =
1710 656 : exprType((Node *) convert->arg);
1711 656 : scratch.d.convert_rowtype.outputtype = convert->resulttype;
1712 656 : scratch.d.convert_rowtype.incache = &rowcachep[0];
1713 656 : scratch.d.convert_rowtype.outcache = &rowcachep[1];
1714 656 : scratch.d.convert_rowtype.map = NULL;
1715 :
1716 656 : ExprEvalPushStep(state, &scratch);
1717 656 : break;
1718 : }
1719 :
1720 : /* note that CaseWhen expressions are handled within this block */
1721 97396 : case T_CaseExpr:
1722 : {
1723 97396 : CaseExpr *caseExpr = (CaseExpr *) node;
1724 97396 : List *adjust_jumps = NIL;
1725 97396 : Datum *caseval = NULL;
1726 97396 : bool *casenull = NULL;
1727 : ListCell *lc;
1728 :
1729 : /*
1730 : * If there's a test expression, we have to evaluate it and
1731 : * save the value where the CaseTestExpr placeholders can find
1732 : * it.
1733 : */
1734 97396 : if (caseExpr->arg != NULL)
1735 : {
1736 : /* Evaluate testexpr into caseval/casenull workspace */
1737 3906 : caseval = palloc(sizeof(Datum));
1738 3906 : casenull = palloc(sizeof(bool));
1739 :
1740 3906 : ExecInitExprRec(caseExpr->arg, state,
1741 : caseval, casenull);
1742 :
1743 : /*
1744 : * Since value might be read multiple times, force to R/O
1745 : * - but only if it could be an expanded datum.
1746 : */
1747 3906 : if (get_typlen(exprType((Node *) caseExpr->arg)) == -1)
1748 : {
1749 : /* change caseval in-place */
1750 84 : scratch.opcode = EEOP_MAKE_READONLY;
1751 84 : scratch.resvalue = caseval;
1752 84 : scratch.resnull = casenull;
1753 84 : scratch.d.make_readonly.value = caseval;
1754 84 : scratch.d.make_readonly.isnull = casenull;
1755 84 : ExprEvalPushStep(state, &scratch);
1756 : /* restore normal settings of scratch fields */
1757 84 : scratch.resvalue = resv;
1758 84 : scratch.resnull = resnull;
1759 : }
1760 : }
1761 :
1762 : /*
1763 : * Prepare to evaluate each of the WHEN clauses in turn; as
1764 : * soon as one is true we return the value of the
1765 : * corresponding THEN clause. If none are true then we return
1766 : * the value of the ELSE clause, or NULL if there is none.
1767 : */
1768 262080 : foreach(lc, caseExpr->args)
1769 : {
1770 164684 : CaseWhen *when = (CaseWhen *) lfirst(lc);
1771 : Datum *save_innermost_caseval;
1772 : bool *save_innermost_casenull;
1773 : int whenstep;
1774 :
1775 : /*
1776 : * Make testexpr result available to CaseTestExpr nodes
1777 : * within the condition. We must save and restore prior
1778 : * setting of innermost_caseval fields, in case this node
1779 : * is itself within a larger CASE.
1780 : *
1781 : * If there's no test expression, we don't actually need
1782 : * to save and restore these fields; but it's less code to
1783 : * just do so unconditionally.
1784 : */
1785 164684 : save_innermost_caseval = state->innermost_caseval;
1786 164684 : save_innermost_casenull = state->innermost_casenull;
1787 164684 : state->innermost_caseval = caseval;
1788 164684 : state->innermost_casenull = casenull;
1789 :
1790 : /* evaluate condition into CASE's result variables */
1791 164684 : ExecInitExprRec(when->expr, state, resv, resnull);
1792 :
1793 164684 : state->innermost_caseval = save_innermost_caseval;
1794 164684 : state->innermost_casenull = save_innermost_casenull;
1795 :
1796 : /* If WHEN result isn't true, jump to next CASE arm */
1797 164684 : scratch.opcode = EEOP_JUMP_IF_NOT_TRUE;
1798 164684 : scratch.d.jump.jumpdone = -1; /* computed later */
1799 164684 : ExprEvalPushStep(state, &scratch);
1800 164684 : whenstep = state->steps_len - 1;
1801 :
1802 : /*
1803 : * If WHEN result is true, evaluate THEN result, storing
1804 : * it into the CASE's result variables.
1805 : */
1806 164684 : ExecInitExprRec(when->result, state, resv, resnull);
1807 :
1808 : /* Emit JUMP step to jump to end of CASE's code */
1809 164684 : scratch.opcode = EEOP_JUMP;
1810 164684 : scratch.d.jump.jumpdone = -1; /* computed later */
1811 164684 : ExprEvalPushStep(state, &scratch);
1812 :
1813 : /*
1814 : * Don't know address for that jump yet, compute once the
1815 : * whole CASE expression is built.
1816 : */
1817 164684 : adjust_jumps = lappend_int(adjust_jumps,
1818 164684 : state->steps_len - 1);
1819 :
1820 : /*
1821 : * But we can set WHEN test's jump target now, to make it
1822 : * jump to the next WHEN subexpression or the ELSE.
1823 : */
1824 164684 : state->steps[whenstep].d.jump.jumpdone = state->steps_len;
1825 : }
1826 :
1827 : /* transformCaseExpr always adds a default */
1828 : Assert(caseExpr->defresult);
1829 :
1830 : /* evaluate ELSE expr into CASE's result variables */
1831 97396 : ExecInitExprRec(caseExpr->defresult, state,
1832 : resv, resnull);
1833 :
1834 : /* adjust jump targets */
1835 262080 : foreach(lc, adjust_jumps)
1836 : {
1837 164684 : ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1838 :
1839 : Assert(as->opcode == EEOP_JUMP);
1840 : Assert(as->d.jump.jumpdone == -1);
1841 164684 : as->d.jump.jumpdone = state->steps_len;
1842 : }
1843 :
1844 97396 : break;
1845 : }
1846 :
1847 23070 : case T_CaseTestExpr:
1848 : {
1849 : /*
1850 : * Read from location identified by innermost_caseval. Note
1851 : * that innermost_caseval could be NULL, if this node isn't
1852 : * actually within a CaseExpr, ArrayCoerceExpr, etc structure.
1853 : * That can happen because some parts of the system abuse
1854 : * CaseTestExpr to cause a read of a value externally supplied
1855 : * in econtext->caseValue_datum. We'll take care of that
1856 : * scenario at runtime.
1857 : */
1858 23070 : scratch.opcode = EEOP_CASE_TESTVAL;
1859 23070 : scratch.d.casetest.value = state->innermost_caseval;
1860 23070 : scratch.d.casetest.isnull = state->innermost_casenull;
1861 :
1862 23070 : ExprEvalPushStep(state, &scratch);
1863 23070 : break;
1864 : }
1865 :
1866 27816 : case T_ArrayExpr:
1867 : {
1868 27816 : ArrayExpr *arrayexpr = (ArrayExpr *) node;
1869 27816 : int nelems = list_length(arrayexpr->elements);
1870 : ListCell *lc;
1871 : int elemoff;
1872 :
1873 : /*
1874 : * Evaluate by computing each element, and then forming the
1875 : * array. Elements are computed into scratch arrays
1876 : * associated with the ARRAYEXPR step.
1877 : */
1878 27816 : scratch.opcode = EEOP_ARRAYEXPR;
1879 27816 : scratch.d.arrayexpr.elemvalues =
1880 27816 : (Datum *) palloc(sizeof(Datum) * nelems);
1881 27816 : scratch.d.arrayexpr.elemnulls =
1882 27816 : (bool *) palloc(sizeof(bool) * nelems);
1883 27816 : scratch.d.arrayexpr.nelems = nelems;
1884 :
1885 : /* fill remaining fields of step */
1886 27816 : scratch.d.arrayexpr.multidims = arrayexpr->multidims;
1887 27816 : scratch.d.arrayexpr.elemtype = arrayexpr->element_typeid;
1888 :
1889 : /* do one-time catalog lookup for type info */
1890 27816 : get_typlenbyvalalign(arrayexpr->element_typeid,
1891 : &scratch.d.arrayexpr.elemlength,
1892 : &scratch.d.arrayexpr.elembyval,
1893 : &scratch.d.arrayexpr.elemalign);
1894 :
1895 : /* prepare to evaluate all arguments */
1896 27816 : elemoff = 0;
1897 100712 : foreach(lc, arrayexpr->elements)
1898 : {
1899 72896 : Expr *e = (Expr *) lfirst(lc);
1900 :
1901 72896 : ExecInitExprRec(e, state,
1902 72896 : &scratch.d.arrayexpr.elemvalues[elemoff],
1903 72896 : &scratch.d.arrayexpr.elemnulls[elemoff]);
1904 72896 : elemoff++;
1905 : }
1906 :
1907 : /* and then collect all into an array */
1908 27816 : ExprEvalPushStep(state, &scratch);
1909 27816 : break;
1910 : }
1911 :
1912 5202 : case T_RowExpr:
1913 : {
1914 5202 : RowExpr *rowexpr = (RowExpr *) node;
1915 5202 : int nelems = list_length(rowexpr->args);
1916 : TupleDesc tupdesc;
1917 : int i;
1918 : ListCell *l;
1919 :
1920 : /* Build tupdesc to describe result tuples */
1921 5202 : if (rowexpr->row_typeid == RECORDOID)
1922 : {
1923 : /* generic record, use types of given expressions */
1924 2730 : tupdesc = ExecTypeFromExprList(rowexpr->args);
1925 : /* ... but adopt RowExpr's column aliases */
1926 2730 : ExecTypeSetColNames(tupdesc, rowexpr->colnames);
1927 : /* Bless the tupdesc so it can be looked up later */
1928 2730 : BlessTupleDesc(tupdesc);
1929 : }
1930 : else
1931 : {
1932 : /* it's been cast to a named type, use that */
1933 2472 : tupdesc = lookup_rowtype_tupdesc_copy(rowexpr->row_typeid, -1);
1934 : }
1935 :
1936 : /*
1937 : * In the named-type case, the tupdesc could have more columns
1938 : * than are in the args list, since the type might have had
1939 : * columns added since the ROW() was parsed. We want those
1940 : * extra columns to go to nulls, so we make sure that the
1941 : * workspace arrays are large enough and then initialize any
1942 : * extra columns to read as NULLs.
1943 : */
1944 : Assert(nelems <= tupdesc->natts);
1945 5202 : nelems = Max(nelems, tupdesc->natts);
1946 :
1947 : /*
1948 : * Evaluate by first building datums for each field, and then
1949 : * a final step forming the composite datum.
1950 : */
1951 5202 : scratch.opcode = EEOP_ROW;
1952 5202 : scratch.d.row.tupdesc = tupdesc;
1953 :
1954 : /* space for the individual field datums */
1955 5202 : scratch.d.row.elemvalues =
1956 5202 : (Datum *) palloc(sizeof(Datum) * nelems);
1957 5202 : scratch.d.row.elemnulls =
1958 5202 : (bool *) palloc(sizeof(bool) * nelems);
1959 : /* as explained above, make sure any extra columns are null */
1960 5202 : memset(scratch.d.row.elemnulls, true, sizeof(bool) * nelems);
1961 :
1962 : /* Set up evaluation, skipping any deleted columns */
1963 5202 : i = 0;
1964 18306 : foreach(l, rowexpr->args)
1965 : {
1966 13110 : Form_pg_attribute att = TupleDescAttr(tupdesc, i);
1967 13110 : Expr *e = (Expr *) lfirst(l);
1968 :
1969 13110 : if (!att->attisdropped)
1970 : {
1971 : /*
1972 : * Guard against ALTER COLUMN TYPE on rowtype since
1973 : * the RowExpr was created. XXX should we check
1974 : * typmod too? Not sure we can be sure it'll be the
1975 : * same.
1976 : */
1977 13092 : if (exprType((Node *) e) != att->atttypid)
1978 6 : ereport(ERROR,
1979 : (errcode(ERRCODE_DATATYPE_MISMATCH),
1980 : errmsg("ROW() column has type %s instead of type %s",
1981 : format_type_be(exprType((Node *) e)),
1982 : format_type_be(att->atttypid))));
1983 : }
1984 : else
1985 : {
1986 : /*
1987 : * Ignore original expression and insert a NULL. We
1988 : * don't really care what type of NULL it is, so
1989 : * always make an int4 NULL.
1990 : */
1991 18 : e = (Expr *) makeNullConst(INT4OID, -1, InvalidOid);
1992 : }
1993 :
1994 : /* Evaluate column expr into appropriate workspace slot */
1995 13104 : ExecInitExprRec(e, state,
1996 13104 : &scratch.d.row.elemvalues[i],
1997 13104 : &scratch.d.row.elemnulls[i]);
1998 13104 : i++;
1999 : }
2000 :
2001 : /* And finally build the row value */
2002 5196 : ExprEvalPushStep(state, &scratch);
2003 5196 : break;
2004 : }
2005 :
2006 168 : case T_RowCompareExpr:
2007 : {
2008 168 : RowCompareExpr *rcexpr = (RowCompareExpr *) node;
2009 168 : int nopers = list_length(rcexpr->opnos);
2010 168 : List *adjust_jumps = NIL;
2011 : ListCell *l_left_expr,
2012 : *l_right_expr,
2013 : *l_opno,
2014 : *l_opfamily,
2015 : *l_inputcollid;
2016 : ListCell *lc;
2017 :
2018 : /*
2019 : * Iterate over each field, prepare comparisons. To handle
2020 : * NULL results, prepare jumps to after the expression. If a
2021 : * comparison yields a != 0 result, jump to the final step.
2022 : */
2023 : Assert(list_length(rcexpr->largs) == nopers);
2024 : Assert(list_length(rcexpr->rargs) == nopers);
2025 : Assert(list_length(rcexpr->opfamilies) == nopers);
2026 : Assert(list_length(rcexpr->inputcollids) == nopers);
2027 :
2028 558 : forfive(l_left_expr, rcexpr->largs,
2029 : l_right_expr, rcexpr->rargs,
2030 : l_opno, rcexpr->opnos,
2031 : l_opfamily, rcexpr->opfamilies,
2032 : l_inputcollid, rcexpr->inputcollids)
2033 : {
2034 390 : Expr *left_expr = (Expr *) lfirst(l_left_expr);
2035 390 : Expr *right_expr = (Expr *) lfirst(l_right_expr);
2036 390 : Oid opno = lfirst_oid(l_opno);
2037 390 : Oid opfamily = lfirst_oid(l_opfamily);
2038 390 : Oid inputcollid = lfirst_oid(l_inputcollid);
2039 : int strategy;
2040 : Oid lefttype;
2041 : Oid righttype;
2042 : Oid proc;
2043 : FmgrInfo *finfo;
2044 : FunctionCallInfo fcinfo;
2045 :
2046 390 : get_op_opfamily_properties(opno, opfamily, false,
2047 : &strategy,
2048 : &lefttype,
2049 : &righttype);
2050 390 : proc = get_opfamily_proc(opfamily,
2051 : lefttype,
2052 : righttype,
2053 : BTORDER_PROC);
2054 390 : if (!OidIsValid(proc))
2055 0 : elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
2056 : BTORDER_PROC, lefttype, righttype, opfamily);
2057 :
2058 : /* Set up the primary fmgr lookup information */
2059 390 : finfo = palloc0(sizeof(FmgrInfo));
2060 390 : fcinfo = palloc0(SizeForFunctionCallInfo(2));
2061 390 : fmgr_info(proc, finfo);
2062 390 : fmgr_info_set_expr((Node *) node, finfo);
2063 390 : InitFunctionCallInfoData(*fcinfo, finfo, 2,
2064 : inputcollid, NULL, NULL);
2065 :
2066 : /*
2067 : * If we enforced permissions checks on index support
2068 : * functions, we'd need to make a check here. But the
2069 : * index support machinery doesn't do that, and thus
2070 : * neither does this code.
2071 : */
2072 :
2073 : /* evaluate left and right args directly into fcinfo */
2074 390 : ExecInitExprRec(left_expr, state,
2075 : &fcinfo->args[0].value, &fcinfo->args[0].isnull);
2076 390 : ExecInitExprRec(right_expr, state,
2077 : &fcinfo->args[1].value, &fcinfo->args[1].isnull);
2078 :
2079 390 : scratch.opcode = EEOP_ROWCOMPARE_STEP;
2080 390 : scratch.d.rowcompare_step.finfo = finfo;
2081 390 : scratch.d.rowcompare_step.fcinfo_data = fcinfo;
2082 390 : scratch.d.rowcompare_step.fn_addr = finfo->fn_addr;
2083 : /* jump targets filled below */
2084 390 : scratch.d.rowcompare_step.jumpnull = -1;
2085 390 : scratch.d.rowcompare_step.jumpdone = -1;
2086 :
2087 390 : ExprEvalPushStep(state, &scratch);
2088 390 : adjust_jumps = lappend_int(adjust_jumps,
2089 390 : state->steps_len - 1);
2090 : }
2091 :
2092 : /*
2093 : * We could have a zero-column rowtype, in which case the rows
2094 : * necessarily compare equal.
2095 : */
2096 168 : if (nopers == 0)
2097 : {
2098 0 : scratch.opcode = EEOP_CONST;
2099 0 : scratch.d.constval.value = Int32GetDatum(0);
2100 0 : scratch.d.constval.isnull = false;
2101 0 : ExprEvalPushStep(state, &scratch);
2102 : }
2103 :
2104 : /* Finally, examine the last comparison result */
2105 168 : scratch.opcode = EEOP_ROWCOMPARE_FINAL;
2106 168 : scratch.d.rowcompare_final.rctype = rcexpr->rctype;
2107 168 : ExprEvalPushStep(state, &scratch);
2108 :
2109 : /* adjust jump targets */
2110 558 : foreach(lc, adjust_jumps)
2111 : {
2112 390 : ExprEvalStep *as = &state->steps[lfirst_int(lc)];
2113 :
2114 : Assert(as->opcode == EEOP_ROWCOMPARE_STEP);
2115 : Assert(as->d.rowcompare_step.jumpdone == -1);
2116 : Assert(as->d.rowcompare_step.jumpnull == -1);
2117 :
2118 : /* jump to comparison evaluation */
2119 390 : as->d.rowcompare_step.jumpdone = state->steps_len - 1;
2120 : /* jump to the following expression */
2121 390 : as->d.rowcompare_step.jumpnull = state->steps_len;
2122 : }
2123 :
2124 168 : break;
2125 : }
2126 :
2127 3588 : case T_CoalesceExpr:
2128 : {
2129 3588 : CoalesceExpr *coalesce = (CoalesceExpr *) node;
2130 3588 : List *adjust_jumps = NIL;
2131 : ListCell *lc;
2132 :
2133 : /* We assume there's at least one arg */
2134 : Assert(coalesce->args != NIL);
2135 :
2136 : /*
2137 : * Prepare evaluation of all coalesced arguments, after each
2138 : * one push a step that short-circuits if not null.
2139 : */
2140 10752 : foreach(lc, coalesce->args)
2141 : {
2142 7164 : Expr *e = (Expr *) lfirst(lc);
2143 :
2144 : /* evaluate argument, directly into result datum */
2145 7164 : ExecInitExprRec(e, state, resv, resnull);
2146 :
2147 : /* if it's not null, skip to end of COALESCE expr */
2148 7164 : scratch.opcode = EEOP_JUMP_IF_NOT_NULL;
2149 7164 : scratch.d.jump.jumpdone = -1; /* adjust later */
2150 7164 : ExprEvalPushStep(state, &scratch);
2151 :
2152 7164 : adjust_jumps = lappend_int(adjust_jumps,
2153 7164 : state->steps_len - 1);
2154 : }
2155 :
2156 : /*
2157 : * No need to add a constant NULL return - we only can get to
2158 : * the end of the expression if a NULL already is being
2159 : * returned.
2160 : */
2161 :
2162 : /* adjust jump targets */
2163 10752 : foreach(lc, adjust_jumps)
2164 : {
2165 7164 : ExprEvalStep *as = &state->steps[lfirst_int(lc)];
2166 :
2167 : Assert(as->opcode == EEOP_JUMP_IF_NOT_NULL);
2168 : Assert(as->d.jump.jumpdone == -1);
2169 7164 : as->d.jump.jumpdone = state->steps_len;
2170 : }
2171 :
2172 3588 : break;
2173 : }
2174 :
2175 2446 : case T_MinMaxExpr:
2176 : {
2177 2446 : MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
2178 2446 : int nelems = list_length(minmaxexpr->args);
2179 : TypeCacheEntry *typentry;
2180 : FmgrInfo *finfo;
2181 : FunctionCallInfo fcinfo;
2182 : ListCell *lc;
2183 : int off;
2184 :
2185 : /* Look up the btree comparison function for the datatype */
2186 2446 : typentry = lookup_type_cache(minmaxexpr->minmaxtype,
2187 : TYPECACHE_CMP_PROC);
2188 2446 : if (!OidIsValid(typentry->cmp_proc))
2189 0 : ereport(ERROR,
2190 : (errcode(ERRCODE_UNDEFINED_FUNCTION),
2191 : errmsg("could not identify a comparison function for type %s",
2192 : format_type_be(minmaxexpr->minmaxtype))));
2193 :
2194 : /*
2195 : * If we enforced permissions checks on index support
2196 : * functions, we'd need to make a check here. But the index
2197 : * support machinery doesn't do that, and thus neither does
2198 : * this code.
2199 : */
2200 :
2201 : /* Perform function lookup */
2202 2446 : finfo = palloc0(sizeof(FmgrInfo));
2203 2446 : fcinfo = palloc0(SizeForFunctionCallInfo(2));
2204 2446 : fmgr_info(typentry->cmp_proc, finfo);
2205 2446 : fmgr_info_set_expr((Node *) node, finfo);
2206 2446 : InitFunctionCallInfoData(*fcinfo, finfo, 2,
2207 : minmaxexpr->inputcollid, NULL, NULL);
2208 :
2209 2446 : scratch.opcode = EEOP_MINMAX;
2210 : /* allocate space to store arguments */
2211 2446 : scratch.d.minmax.values =
2212 2446 : (Datum *) palloc(sizeof(Datum) * nelems);
2213 2446 : scratch.d.minmax.nulls =
2214 2446 : (bool *) palloc(sizeof(bool) * nelems);
2215 2446 : scratch.d.minmax.nelems = nelems;
2216 :
2217 2446 : scratch.d.minmax.op = minmaxexpr->op;
2218 2446 : scratch.d.minmax.finfo = finfo;
2219 2446 : scratch.d.minmax.fcinfo_data = fcinfo;
2220 :
2221 : /* evaluate expressions into minmax->values/nulls */
2222 2446 : off = 0;
2223 7446 : foreach(lc, minmaxexpr->args)
2224 : {
2225 5000 : Expr *e = (Expr *) lfirst(lc);
2226 :
2227 5000 : ExecInitExprRec(e, state,
2228 5000 : &scratch.d.minmax.values[off],
2229 5000 : &scratch.d.minmax.nulls[off]);
2230 5000 : off++;
2231 : }
2232 :
2233 : /* and push the final comparison */
2234 2446 : ExprEvalPushStep(state, &scratch);
2235 2446 : break;
2236 : }
2237 :
2238 4862 : case T_SQLValueFunction:
2239 : {
2240 4862 : SQLValueFunction *svf = (SQLValueFunction *) node;
2241 :
2242 4862 : scratch.opcode = EEOP_SQLVALUEFUNCTION;
2243 4862 : scratch.d.sqlvaluefunction.svf = svf;
2244 :
2245 4862 : ExprEvalPushStep(state, &scratch);
2246 4862 : break;
2247 : }
2248 :
2249 690 : case T_XmlExpr:
2250 : {
2251 690 : XmlExpr *xexpr = (XmlExpr *) node;
2252 690 : int nnamed = list_length(xexpr->named_args);
2253 690 : int nargs = list_length(xexpr->args);
2254 : int off;
2255 : ListCell *arg;
2256 :
2257 690 : scratch.opcode = EEOP_XMLEXPR;
2258 690 : scratch.d.xmlexpr.xexpr = xexpr;
2259 :
2260 : /* allocate space for storing all the arguments */
2261 690 : if (nnamed)
2262 : {
2263 60 : scratch.d.xmlexpr.named_argvalue =
2264 60 : (Datum *) palloc(sizeof(Datum) * nnamed);
2265 60 : scratch.d.xmlexpr.named_argnull =
2266 60 : (bool *) palloc(sizeof(bool) * nnamed);
2267 : }
2268 : else
2269 : {
2270 630 : scratch.d.xmlexpr.named_argvalue = NULL;
2271 630 : scratch.d.xmlexpr.named_argnull = NULL;
2272 : }
2273 :
2274 690 : if (nargs)
2275 : {
2276 606 : scratch.d.xmlexpr.argvalue =
2277 606 : (Datum *) palloc(sizeof(Datum) * nargs);
2278 606 : scratch.d.xmlexpr.argnull =
2279 606 : (bool *) palloc(sizeof(bool) * nargs);
2280 : }
2281 : else
2282 : {
2283 84 : scratch.d.xmlexpr.argvalue = NULL;
2284 84 : scratch.d.xmlexpr.argnull = NULL;
2285 : }
2286 :
2287 : /* prepare argument execution */
2288 690 : off = 0;
2289 858 : foreach(arg, xexpr->named_args)
2290 : {
2291 168 : Expr *e = (Expr *) lfirst(arg);
2292 :
2293 168 : ExecInitExprRec(e, state,
2294 168 : &scratch.d.xmlexpr.named_argvalue[off],
2295 168 : &scratch.d.xmlexpr.named_argnull[off]);
2296 168 : off++;
2297 : }
2298 :
2299 690 : off = 0;
2300 1614 : foreach(arg, xexpr->args)
2301 : {
2302 924 : Expr *e = (Expr *) lfirst(arg);
2303 :
2304 924 : ExecInitExprRec(e, state,
2305 924 : &scratch.d.xmlexpr.argvalue[off],
2306 924 : &scratch.d.xmlexpr.argnull[off]);
2307 924 : off++;
2308 : }
2309 :
2310 : /* and evaluate the actual XML expression */
2311 690 : ExprEvalPushStep(state, &scratch);
2312 690 : break;
2313 : }
2314 :
2315 180 : case T_JsonValueExpr:
2316 : {
2317 180 : JsonValueExpr *jve = (JsonValueExpr *) node;
2318 :
2319 : Assert(jve->formatted_expr != NULL);
2320 180 : ExecInitExprRec(jve->formatted_expr, state, resv, resnull);
2321 180 : break;
2322 : }
2323 :
2324 1144 : case T_JsonConstructorExpr:
2325 : {
2326 1144 : JsonConstructorExpr *ctor = (JsonConstructorExpr *) node;
2327 1144 : List *args = ctor->args;
2328 : ListCell *lc;
2329 1144 : int nargs = list_length(args);
2330 1144 : int argno = 0;
2331 :
2332 1144 : if (ctor->func)
2333 : {
2334 324 : ExecInitExprRec(ctor->func, state, resv, resnull);
2335 : }
2336 820 : else if ((ctor->type == JSCTOR_JSON_PARSE && !ctor->unique) ||
2337 698 : ctor->type == JSCTOR_JSON_SERIALIZE)
2338 : {
2339 : /* Use the value of the first argument as result */
2340 202 : ExecInitExprRec(linitial(args), state, resv, resnull);
2341 : }
2342 : else
2343 : {
2344 : JsonConstructorExprState *jcstate;
2345 :
2346 618 : jcstate = palloc0(sizeof(JsonConstructorExprState));
2347 :
2348 618 : scratch.opcode = EEOP_JSON_CONSTRUCTOR;
2349 618 : scratch.d.json_constructor.jcstate = jcstate;
2350 :
2351 618 : jcstate->constructor = ctor;
2352 618 : jcstate->arg_values = (Datum *) palloc(sizeof(Datum) * nargs);
2353 618 : jcstate->arg_nulls = (bool *) palloc(sizeof(bool) * nargs);
2354 618 : jcstate->arg_types = (Oid *) palloc(sizeof(Oid) * nargs);
2355 618 : jcstate->nargs = nargs;
2356 :
2357 1924 : foreach(lc, args)
2358 : {
2359 1306 : Expr *arg = (Expr *) lfirst(lc);
2360 :
2361 1306 : jcstate->arg_types[argno] = exprType((Node *) arg);
2362 :
2363 1306 : if (IsA(arg, Const))
2364 : {
2365 : /* Don't evaluate const arguments every round */
2366 1240 : Const *con = (Const *) arg;
2367 :
2368 1240 : jcstate->arg_values[argno] = con->constvalue;
2369 1240 : jcstate->arg_nulls[argno] = con->constisnull;
2370 : }
2371 : else
2372 : {
2373 66 : ExecInitExprRec(arg, state,
2374 66 : &jcstate->arg_values[argno],
2375 66 : &jcstate->arg_nulls[argno]);
2376 : }
2377 1306 : argno++;
2378 : }
2379 :
2380 : /* prepare type cache for datum_to_json[b]() */
2381 618 : if (ctor->type == JSCTOR_JSON_SCALAR)
2382 : {
2383 112 : bool is_jsonb =
2384 112 : ctor->returning->format->format_type == JS_FORMAT_JSONB;
2385 :
2386 112 : jcstate->arg_type_cache =
2387 112 : palloc(sizeof(*jcstate->arg_type_cache) * nargs);
2388 :
2389 224 : for (int i = 0; i < nargs; i++)
2390 : {
2391 : JsonTypeCategory category;
2392 : Oid outfuncid;
2393 112 : Oid typid = jcstate->arg_types[i];
2394 :
2395 112 : json_categorize_type(typid, is_jsonb,
2396 : &category, &outfuncid);
2397 :
2398 112 : jcstate->arg_type_cache[i].outfuncid = outfuncid;
2399 112 : jcstate->arg_type_cache[i].category = (int) category;
2400 : }
2401 : }
2402 :
2403 618 : ExprEvalPushStep(state, &scratch);
2404 : }
2405 :
2406 1144 : if (ctor->coercion)
2407 : {
2408 236 : Datum *innermost_caseval = state->innermost_caseval;
2409 236 : bool *innermost_isnull = state->innermost_casenull;
2410 :
2411 236 : state->innermost_caseval = resv;
2412 236 : state->innermost_casenull = resnull;
2413 :
2414 236 : ExecInitExprRec(ctor->coercion, state, resv, resnull);
2415 :
2416 236 : state->innermost_caseval = innermost_caseval;
2417 236 : state->innermost_casenull = innermost_isnull;
2418 : }
2419 : }
2420 1144 : break;
2421 :
2422 356 : case T_JsonIsPredicate:
2423 : {
2424 356 : JsonIsPredicate *pred = (JsonIsPredicate *) node;
2425 :
2426 356 : ExecInitExprRec((Expr *) pred->expr, state, resv, resnull);
2427 :
2428 356 : scratch.opcode = EEOP_IS_JSON;
2429 356 : scratch.d.is_json.pred = pred;
2430 :
2431 356 : ExprEvalPushStep(state, &scratch);
2432 356 : break;
2433 : }
2434 :
2435 2410 : case T_JsonExpr:
2436 : {
2437 2410 : JsonExpr *jsexpr = castNode(JsonExpr, node);
2438 :
2439 : /*
2440 : * No need to initialize a full JsonExprState For
2441 : * JSON_TABLE(), because the upstream caller tfuncFetchRows()
2442 : * is only interested in the value of formatted_expr.
2443 : */
2444 2410 : if (jsexpr->op == JSON_TABLE_OP)
2445 326 : ExecInitExprRec((Expr *) jsexpr->formatted_expr, state,
2446 : resv, resnull);
2447 : else
2448 2084 : ExecInitJsonExpr(jsexpr, state, resv, resnull, &scratch);
2449 2410 : break;
2450 : }
2451 :
2452 26508 : case T_NullTest:
2453 : {
2454 26508 : NullTest *ntest = (NullTest *) node;
2455 :
2456 26508 : if (ntest->nulltesttype == IS_NULL)
2457 : {
2458 7900 : if (ntest->argisrow)
2459 228 : scratch.opcode = EEOP_NULLTEST_ROWISNULL;
2460 : else
2461 7672 : scratch.opcode = EEOP_NULLTEST_ISNULL;
2462 : }
2463 18608 : else if (ntest->nulltesttype == IS_NOT_NULL)
2464 : {
2465 18608 : if (ntest->argisrow)
2466 222 : scratch.opcode = EEOP_NULLTEST_ROWISNOTNULL;
2467 : else
2468 18386 : scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
2469 : }
2470 : else
2471 : {
2472 0 : elog(ERROR, "unrecognized nulltesttype: %d",
2473 : (int) ntest->nulltesttype);
2474 : }
2475 : /* initialize cache in case it's a row test */
2476 26508 : scratch.d.nulltest_row.rowcache.cacheptr = NULL;
2477 :
2478 : /* first evaluate argument into result variable */
2479 26508 : ExecInitExprRec(ntest->arg, state,
2480 : resv, resnull);
2481 :
2482 : /* then push the test of that argument */
2483 26508 : ExprEvalPushStep(state, &scratch);
2484 26508 : break;
2485 : }
2486 :
2487 1260 : case T_BooleanTest:
2488 : {
2489 1260 : BooleanTest *btest = (BooleanTest *) node;
2490 :
2491 : /*
2492 : * Evaluate argument, directly into result datum. That's ok,
2493 : * because resv/resnull is definitely not used anywhere else,
2494 : * and will get overwritten by the below EEOP_BOOLTEST_IS_*
2495 : * step.
2496 : */
2497 1260 : ExecInitExprRec(btest->arg, state, resv, resnull);
2498 :
2499 1260 : switch (btest->booltesttype)
2500 : {
2501 428 : case IS_TRUE:
2502 428 : scratch.opcode = EEOP_BOOLTEST_IS_TRUE;
2503 428 : break;
2504 396 : case IS_NOT_TRUE:
2505 396 : scratch.opcode = EEOP_BOOLTEST_IS_NOT_TRUE;
2506 396 : break;
2507 96 : case IS_FALSE:
2508 96 : scratch.opcode = EEOP_BOOLTEST_IS_FALSE;
2509 96 : break;
2510 168 : case IS_NOT_FALSE:
2511 168 : scratch.opcode = EEOP_BOOLTEST_IS_NOT_FALSE;
2512 168 : break;
2513 58 : case IS_UNKNOWN:
2514 : /* Same as scalar IS NULL test */
2515 58 : scratch.opcode = EEOP_NULLTEST_ISNULL;
2516 58 : break;
2517 114 : case IS_NOT_UNKNOWN:
2518 : /* Same as scalar IS NOT NULL test */
2519 114 : scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
2520 114 : break;
2521 0 : default:
2522 0 : elog(ERROR, "unrecognized booltesttype: %d",
2523 : (int) btest->booltesttype);
2524 : }
2525 :
2526 1260 : ExprEvalPushStep(state, &scratch);
2527 1260 : break;
2528 : }
2529 :
2530 8296 : case T_CoerceToDomain:
2531 : {
2532 8296 : CoerceToDomain *ctest = (CoerceToDomain *) node;
2533 :
2534 8296 : ExecInitCoerceToDomain(&scratch, ctest, state,
2535 : resv, resnull);
2536 8296 : break;
2537 : }
2538 :
2539 12080 : case T_CoerceToDomainValue:
2540 : {
2541 : /*
2542 : * Read from location identified by innermost_domainval. Note
2543 : * that innermost_domainval could be NULL, if we're compiling
2544 : * a standalone domain check rather than one embedded in a
2545 : * larger expression. In that case we must read from
2546 : * econtext->domainValue_datum. We'll take care of that
2547 : * scenario at runtime.
2548 : */
2549 12080 : scratch.opcode = EEOP_DOMAIN_TESTVAL;
2550 : /* we share instruction union variant with case testval */
2551 12080 : scratch.d.casetest.value = state->innermost_domainval;
2552 12080 : scratch.d.casetest.isnull = state->innermost_domainnull;
2553 :
2554 12080 : ExprEvalPushStep(state, &scratch);
2555 12080 : break;
2556 : }
2557 :
2558 2 : case T_CurrentOfExpr:
2559 : {
2560 2 : scratch.opcode = EEOP_CURRENTOFEXPR;
2561 2 : ExprEvalPushStep(state, &scratch);
2562 2 : break;
2563 : }
2564 :
2565 602 : case T_NextValueExpr:
2566 : {
2567 602 : NextValueExpr *nve = (NextValueExpr *) node;
2568 :
2569 602 : scratch.opcode = EEOP_NEXTVALUEEXPR;
2570 602 : scratch.d.nextvalueexpr.seqid = nve->seqid;
2571 602 : scratch.d.nextvalueexpr.seqtypid = nve->typeId;
2572 :
2573 602 : ExprEvalPushStep(state, &scratch);
2574 602 : break;
2575 : }
2576 :
2577 0 : default:
2578 0 : elog(ERROR, "unrecognized node type: %d",
2579 : (int) nodeTag(node));
2580 : break;
2581 : }
2582 4767114 : }
2583 :
2584 : /*
2585 : * Add another expression evaluation step to ExprState->steps.
2586 : *
2587 : * Note that this potentially re-allocates es->steps, therefore no pointer
2588 : * into that array may be used while the expression is still being built.
2589 : */
2590 : void
2591 10751730 : ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
2592 : {
2593 10751730 : if (es->steps_alloc == 0)
2594 : {
2595 2254938 : es->steps_alloc = 16;
2596 2254938 : es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc);
2597 : }
2598 8496792 : else if (es->steps_alloc == es->steps_len)
2599 : {
2600 72908 : es->steps_alloc *= 2;
2601 72908 : es->steps = repalloc(es->steps,
2602 72908 : sizeof(ExprEvalStep) * es->steps_alloc);
2603 : }
2604 :
2605 10751730 : memcpy(&es->steps[es->steps_len++], s, sizeof(ExprEvalStep));
2606 10751730 : }
2607 :
2608 : /*
2609 : * Perform setup necessary for the evaluation of a function-like expression,
2610 : * appending argument evaluation steps to the steps list in *state, and
2611 : * setting up *scratch so it is ready to be pushed.
2612 : *
2613 : * *scratch is not pushed here, so that callers may override the opcode,
2614 : * which is useful for function-like cases like DISTINCT.
2615 : */
2616 : static void
2617 1391224 : ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
2618 : Oid inputcollid, ExprState *state)
2619 : {
2620 1391224 : int nargs = list_length(args);
2621 : AclResult aclresult;
2622 : FmgrInfo *flinfo;
2623 : FunctionCallInfo fcinfo;
2624 : int argno;
2625 : ListCell *lc;
2626 :
2627 : /* Check permission to call function */
2628 1391224 : aclresult = object_aclcheck(ProcedureRelationId, funcid, GetUserId(), ACL_EXECUTE);
2629 1391224 : if (aclresult != ACLCHECK_OK)
2630 74 : aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(funcid));
2631 1391150 : InvokeFunctionExecuteHook(funcid);
2632 :
2633 : /*
2634 : * Safety check on nargs. Under normal circumstances this should never
2635 : * fail, as parser should check sooner. But possibly it might fail if
2636 : * server has been compiled with FUNC_MAX_ARGS smaller than some functions
2637 : * declared in pg_proc?
2638 : */
2639 1391150 : if (nargs > FUNC_MAX_ARGS)
2640 0 : ereport(ERROR,
2641 : (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2642 : errmsg_plural("cannot pass more than %d argument to a function",
2643 : "cannot pass more than %d arguments to a function",
2644 : FUNC_MAX_ARGS,
2645 : FUNC_MAX_ARGS)));
2646 :
2647 : /* Allocate function lookup data and parameter workspace for this call */
2648 1391150 : scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
2649 1391150 : scratch->d.func.fcinfo_data = palloc0(SizeForFunctionCallInfo(nargs));
2650 1391150 : flinfo = scratch->d.func.finfo;
2651 1391150 : fcinfo = scratch->d.func.fcinfo_data;
2652 :
2653 : /* Set up the primary fmgr lookup information */
2654 1391150 : fmgr_info(funcid, flinfo);
2655 1391150 : fmgr_info_set_expr((Node *) node, flinfo);
2656 :
2657 : /* Initialize function call parameter structure too */
2658 1391150 : InitFunctionCallInfoData(*fcinfo, flinfo,
2659 : nargs, inputcollid, NULL, NULL);
2660 :
2661 : /* Keep extra copies of this info to save an indirection at runtime */
2662 1391150 : scratch->d.func.fn_addr = flinfo->fn_addr;
2663 1391150 : scratch->d.func.nargs = nargs;
2664 :
2665 : /* We only support non-set functions here */
2666 1391150 : if (flinfo->fn_retset)
2667 0 : ereport(ERROR,
2668 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2669 : errmsg("set-valued function called in context that cannot accept a set"),
2670 : state->parent ?
2671 : executor_errposition(state->parent->state,
2672 : exprLocation((Node *) node)) : 0));
2673 :
2674 : /* Build code to evaluate arguments directly into the fcinfo struct */
2675 1391150 : argno = 0;
2676 3688506 : foreach(lc, args)
2677 : {
2678 2297356 : Expr *arg = (Expr *) lfirst(lc);
2679 :
2680 2297356 : if (IsA(arg, Const))
2681 : {
2682 : /*
2683 : * Don't evaluate const arguments every round; especially
2684 : * interesting for constants in comparisons.
2685 : */
2686 891514 : Const *con = (Const *) arg;
2687 :
2688 891514 : fcinfo->args[argno].value = con->constvalue;
2689 891514 : fcinfo->args[argno].isnull = con->constisnull;
2690 : }
2691 : else
2692 : {
2693 1405842 : ExecInitExprRec(arg, state,
2694 : &fcinfo->args[argno].value,
2695 : &fcinfo->args[argno].isnull);
2696 : }
2697 2297356 : argno++;
2698 : }
2699 :
2700 : /* Insert appropriate opcode depending on strictness and stats level */
2701 1391150 : if (pgstat_track_functions <= flinfo->fn_stats)
2702 : {
2703 1390936 : if (flinfo->fn_strict && nargs > 0)
2704 1245010 : scratch->opcode = EEOP_FUNCEXPR_STRICT;
2705 : else
2706 145926 : scratch->opcode = EEOP_FUNCEXPR;
2707 : }
2708 : else
2709 : {
2710 214 : if (flinfo->fn_strict && nargs > 0)
2711 6 : scratch->opcode = EEOP_FUNCEXPR_STRICT_FUSAGE;
2712 : else
2713 208 : scratch->opcode = EEOP_FUNCEXPR_FUSAGE;
2714 : }
2715 1391150 : }
2716 :
2717 : /*
2718 : * Add expression steps performing setup that's needed before any of the
2719 : * main execution of the expression.
2720 : */
2721 : static void
2722 2174638 : ExecCreateExprSetupSteps(ExprState *state, Node *node)
2723 : {
2724 2174638 : ExprSetupInfo info = {0, 0, 0, NIL};
2725 :
2726 : /* Prescan to find out what we need. */
2727 2174638 : expr_setup_walker(node, &info);
2728 :
2729 : /* And generate those steps. */
2730 2174638 : ExecPushExprSetupSteps(state, &info);
2731 2174638 : }
2732 :
2733 : /*
2734 : * Add steps performing expression setup as indicated by "info".
2735 : * This is useful when building an ExprState covering more than one expression.
2736 : */
2737 : static void
2738 2231342 : ExecPushExprSetupSteps(ExprState *state, ExprSetupInfo *info)
2739 : {
2740 2231342 : ExprEvalStep scratch = {0};
2741 : ListCell *lc;
2742 :
2743 2231342 : scratch.resvalue = NULL;
2744 2231342 : scratch.resnull = NULL;
2745 :
2746 : /*
2747 : * Add steps deforming the ExprState's inner/outer/scan slots as much as
2748 : * required by any Vars appearing in the expression.
2749 : */
2750 2231342 : if (info->last_inner > 0)
2751 : {
2752 159798 : scratch.opcode = EEOP_INNER_FETCHSOME;
2753 159798 : scratch.d.fetch.last_var = info->last_inner;
2754 159798 : scratch.d.fetch.fixed = false;
2755 159798 : scratch.d.fetch.kind = NULL;
2756 159798 : scratch.d.fetch.known_desc = NULL;
2757 159798 : if (ExecComputeSlotInfo(state, &scratch))
2758 151330 : ExprEvalPushStep(state, &scratch);
2759 : }
2760 2231342 : if (info->last_outer > 0)
2761 : {
2762 314480 : scratch.opcode = EEOP_OUTER_FETCHSOME;
2763 314480 : scratch.d.fetch.last_var = info->last_outer;
2764 314480 : scratch.d.fetch.fixed = false;
2765 314480 : scratch.d.fetch.kind = NULL;
2766 314480 : scratch.d.fetch.known_desc = NULL;
2767 314480 : if (ExecComputeSlotInfo(state, &scratch))
2768 168480 : ExprEvalPushStep(state, &scratch);
2769 : }
2770 2231342 : if (info->last_scan > 0)
2771 : {
2772 562688 : scratch.opcode = EEOP_SCAN_FETCHSOME;
2773 562688 : scratch.d.fetch.last_var = info->last_scan;
2774 562688 : scratch.d.fetch.fixed = false;
2775 562688 : scratch.d.fetch.kind = NULL;
2776 562688 : scratch.d.fetch.known_desc = NULL;
2777 562688 : if (ExecComputeSlotInfo(state, &scratch))
2778 533894 : ExprEvalPushStep(state, &scratch);
2779 : }
2780 :
2781 : /*
2782 : * Add steps to execute any MULTIEXPR SubPlans appearing in the
2783 : * expression. We need to evaluate these before any of the Params
2784 : * referencing their outputs are used, but after we've prepared for any
2785 : * Var references they may contain. (There cannot be cross-references
2786 : * between MULTIEXPR SubPlans, so we needn't worry about their order.)
2787 : */
2788 2231468 : foreach(lc, info->multiexpr_subplans)
2789 : {
2790 126 : SubPlan *subplan = (SubPlan *) lfirst(lc);
2791 : SubPlanState *sstate;
2792 :
2793 : Assert(subplan->subLinkType == MULTIEXPR_SUBLINK);
2794 :
2795 : /* This should match what ExecInitExprRec does for other SubPlans: */
2796 :
2797 126 : if (!state->parent)
2798 0 : elog(ERROR, "SubPlan found with no parent plan");
2799 :
2800 126 : sstate = ExecInitSubPlan(subplan, state->parent);
2801 :
2802 : /* add SubPlanState nodes to state->parent->subPlan */
2803 126 : state->parent->subPlan = lappend(state->parent->subPlan,
2804 : sstate);
2805 :
2806 126 : scratch.opcode = EEOP_SUBPLAN;
2807 126 : scratch.d.subplan.sstate = sstate;
2808 :
2809 : /* The result can be ignored, but we better put it somewhere */
2810 126 : scratch.resvalue = &state->resvalue;
2811 126 : scratch.resnull = &state->resnull;
2812 :
2813 126 : ExprEvalPushStep(state, &scratch);
2814 : }
2815 2231342 : }
2816 :
2817 : /*
2818 : * expr_setup_walker: expression walker for ExecCreateExprSetupSteps
2819 : */
2820 : static bool
2821 9967316 : expr_setup_walker(Node *node, ExprSetupInfo *info)
2822 : {
2823 9967316 : if (node == NULL)
2824 369256 : return false;
2825 9598060 : if (IsA(node, Var))
2826 : {
2827 2063014 : Var *variable = (Var *) node;
2828 2063014 : AttrNumber attnum = variable->varattno;
2829 :
2830 2063014 : switch (variable->varno)
2831 : {
2832 286562 : case INNER_VAR:
2833 286562 : info->last_inner = Max(info->last_inner, attnum);
2834 286562 : break;
2835 :
2836 695386 : case OUTER_VAR:
2837 695386 : info->last_outer = Max(info->last_outer, attnum);
2838 695386 : break;
2839 :
2840 : /* INDEX_VAR is handled by default case */
2841 :
2842 1081066 : default:
2843 1081066 : info->last_scan = Max(info->last_scan, attnum);
2844 1081066 : break;
2845 : }
2846 2063014 : return false;
2847 : }
2848 :
2849 : /* Collect all MULTIEXPR SubPlans, too */
2850 7535046 : if (IsA(node, SubPlan))
2851 : {
2852 23978 : SubPlan *subplan = (SubPlan *) node;
2853 :
2854 23978 : if (subplan->subLinkType == MULTIEXPR_SUBLINK)
2855 126 : info->multiexpr_subplans = lappend(info->multiexpr_subplans,
2856 : subplan);
2857 : }
2858 :
2859 : /*
2860 : * Don't examine the arguments or filters of Aggrefs or WindowFuncs,
2861 : * because those do not represent expressions to be evaluated within the
2862 : * calling expression's econtext. GroupingFunc arguments are never
2863 : * evaluated at all.
2864 : */
2865 7535046 : if (IsA(node, Aggref))
2866 46852 : return false;
2867 7488194 : if (IsA(node, WindowFunc))
2868 3116 : return false;
2869 7485078 : if (IsA(node, GroupingFunc))
2870 366 : return false;
2871 7484712 : return expression_tree_walker(node, expr_setup_walker,
2872 : (void *) info);
2873 : }
2874 :
2875 : /*
2876 : * Compute additional information for EEOP_*_FETCHSOME ops.
2877 : *
2878 : * The goal is to determine whether a slot is 'fixed', that is, every
2879 : * evaluation of the expression will have the same type of slot, with an
2880 : * equivalent descriptor.
2881 : *
2882 : * Returns true if the deforming step is required, false otherwise.
2883 : */
2884 : static bool
2885 1074106 : ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
2886 : {
2887 1074106 : PlanState *parent = state->parent;
2888 1074106 : TupleDesc desc = NULL;
2889 1074106 : const TupleTableSlotOps *tts_ops = NULL;
2890 1074106 : bool isfixed = false;
2891 1074106 : ExprEvalOp opcode = op->opcode;
2892 :
2893 : Assert(opcode == EEOP_INNER_FETCHSOME ||
2894 : opcode == EEOP_OUTER_FETCHSOME ||
2895 : opcode == EEOP_SCAN_FETCHSOME);
2896 :
2897 1074106 : if (op->d.fetch.known_desc != NULL)
2898 : {
2899 37140 : desc = op->d.fetch.known_desc;
2900 37140 : tts_ops = op->d.fetch.kind;
2901 37140 : isfixed = op->d.fetch.kind != NULL;
2902 : }
2903 1036966 : else if (!parent)
2904 : {
2905 15562 : isfixed = false;
2906 : }
2907 1021404 : else if (opcode == EEOP_INNER_FETCHSOME)
2908 : {
2909 159710 : PlanState *is = innerPlanState(parent);
2910 :
2911 159710 : if (parent->inneropsset && !parent->inneropsfixed)
2912 : {
2913 0 : isfixed = false;
2914 : }
2915 159710 : else if (parent->inneropsset && parent->innerops)
2916 : {
2917 0 : isfixed = true;
2918 0 : tts_ops = parent->innerops;
2919 0 : desc = ExecGetResultType(is);
2920 : }
2921 159710 : else if (is)
2922 : {
2923 157222 : tts_ops = ExecGetResultSlotOps(is, &isfixed);
2924 157222 : desc = ExecGetResultType(is);
2925 : }
2926 : }
2927 861694 : else if (opcode == EEOP_OUTER_FETCHSOME)
2928 : {
2929 314302 : PlanState *os = outerPlanState(parent);
2930 :
2931 314302 : if (parent->outeropsset && !parent->outeropsfixed)
2932 : {
2933 1976 : isfixed = false;
2934 : }
2935 312326 : else if (parent->outeropsset && parent->outerops)
2936 : {
2937 36898 : isfixed = true;
2938 36898 : tts_ops = parent->outerops;
2939 36898 : desc = ExecGetResultType(os);
2940 : }
2941 275428 : else if (os)
2942 : {
2943 275416 : tts_ops = ExecGetResultSlotOps(os, &isfixed);
2944 275416 : desc = ExecGetResultType(os);
2945 : }
2946 : }
2947 547392 : else if (opcode == EEOP_SCAN_FETCHSOME)
2948 : {
2949 547392 : desc = parent->scandesc;
2950 :
2951 547392 : if (parent->scanops)
2952 526136 : tts_ops = parent->scanops;
2953 :
2954 547392 : if (parent->scanopsset)
2955 526136 : isfixed = parent->scanopsfixed;
2956 : }
2957 :
2958 1074106 : if (isfixed && desc != NULL && tts_ops != NULL)
2959 : {
2960 1003954 : op->d.fetch.fixed = true;
2961 1003954 : op->d.fetch.kind = tts_ops;
2962 1003954 : op->d.fetch.known_desc = desc;
2963 : }
2964 : else
2965 : {
2966 70152 : op->d.fetch.fixed = false;
2967 70152 : op->d.fetch.kind = NULL;
2968 70152 : op->d.fetch.known_desc = NULL;
2969 : }
2970 :
2971 : /* if the slot is known to always virtual we never need to deform */
2972 1074106 : if (op->d.fetch.fixed && op->d.fetch.kind == &TTSOpsVirtual)
2973 185632 : return false;
2974 :
2975 888474 : return true;
2976 : }
2977 :
2978 : /*
2979 : * Prepare step for the evaluation of a whole-row variable.
2980 : * The caller still has to push the step.
2981 : */
2982 : static void
2983 3782 : ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state)
2984 : {
2985 3782 : PlanState *parent = state->parent;
2986 :
2987 : /* fill in all but the target */
2988 3782 : scratch->opcode = EEOP_WHOLEROW;
2989 3782 : scratch->d.wholerow.var = variable;
2990 3782 : scratch->d.wholerow.first = true;
2991 3782 : scratch->d.wholerow.slow = false;
2992 3782 : scratch->d.wholerow.tupdesc = NULL; /* filled at runtime */
2993 3782 : scratch->d.wholerow.junkFilter = NULL;
2994 :
2995 : /*
2996 : * If the input tuple came from a subquery, it might contain "resjunk"
2997 : * columns (such as GROUP BY or ORDER BY columns), which we don't want to
2998 : * keep in the whole-row result. We can get rid of such columns by
2999 : * passing the tuple through a JunkFilter --- but to make one, we have to
3000 : * lay our hands on the subquery's targetlist. Fortunately, there are not
3001 : * very many cases where this can happen, and we can identify all of them
3002 : * by examining our parent PlanState. We assume this is not an issue in
3003 : * standalone expressions that don't have parent plans. (Whole-row Vars
3004 : * can occur in such expressions, but they will always be referencing
3005 : * table rows.)
3006 : */
3007 3782 : if (parent)
3008 : {
3009 3750 : PlanState *subplan = NULL;
3010 :
3011 3750 : switch (nodeTag(parent))
3012 : {
3013 304 : case T_SubqueryScanState:
3014 304 : subplan = ((SubqueryScanState *) parent)->subplan;
3015 304 : break;
3016 172 : case T_CteScanState:
3017 172 : subplan = ((CteScanState *) parent)->cteplanstate;
3018 172 : break;
3019 3274 : default:
3020 3274 : break;
3021 : }
3022 :
3023 3750 : if (subplan)
3024 : {
3025 476 : bool junk_filter_needed = false;
3026 : ListCell *tlist;
3027 :
3028 : /* Detect whether subplan tlist actually has any junk columns */
3029 1344 : foreach(tlist, subplan->plan->targetlist)
3030 : {
3031 880 : TargetEntry *tle = (TargetEntry *) lfirst(tlist);
3032 :
3033 880 : if (tle->resjunk)
3034 : {
3035 12 : junk_filter_needed = true;
3036 12 : break;
3037 : }
3038 : }
3039 :
3040 : /* If so, build the junkfilter now */
3041 476 : if (junk_filter_needed)
3042 : {
3043 12 : scratch->d.wholerow.junkFilter =
3044 12 : ExecInitJunkFilter(subplan->plan->targetlist,
3045 : ExecInitExtraTupleSlot(parent->state, NULL,
3046 : &TTSOpsVirtual));
3047 : }
3048 : }
3049 : }
3050 3782 : }
3051 :
3052 : /*
3053 : * Prepare evaluation of a SubscriptingRef expression.
3054 : */
3055 : static void
3056 22376 : ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref,
3057 : ExprState *state, Datum *resv, bool *resnull)
3058 : {
3059 22376 : bool isAssignment = (sbsref->refassgnexpr != NULL);
3060 22376 : int nupper = list_length(sbsref->refupperindexpr);
3061 22376 : int nlower = list_length(sbsref->reflowerindexpr);
3062 : const SubscriptRoutines *sbsroutines;
3063 : SubscriptingRefState *sbsrefstate;
3064 : SubscriptExecSteps methods;
3065 : char *ptr;
3066 22376 : List *adjust_jumps = NIL;
3067 : ListCell *lc;
3068 : int i;
3069 :
3070 : /* Look up the subscripting support methods */
3071 22376 : sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype, NULL);
3072 22376 : if (!sbsroutines)
3073 0 : ereport(ERROR,
3074 : (errcode(ERRCODE_DATATYPE_MISMATCH),
3075 : errmsg("cannot subscript type %s because it does not support subscripting",
3076 : format_type_be(sbsref->refcontainertype)),
3077 : state->parent ?
3078 : executor_errposition(state->parent->state,
3079 : exprLocation((Node *) sbsref)) : 0));
3080 :
3081 : /* Allocate sbsrefstate, with enough space for per-subscript arrays too */
3082 22376 : sbsrefstate = palloc0(MAXALIGN(sizeof(SubscriptingRefState)) +
3083 22376 : (nupper + nlower) * (sizeof(Datum) +
3084 : 2 * sizeof(bool)));
3085 :
3086 : /* Fill constant fields of SubscriptingRefState */
3087 22376 : sbsrefstate->isassignment = isAssignment;
3088 22376 : sbsrefstate->numupper = nupper;
3089 22376 : sbsrefstate->numlower = nlower;
3090 : /* Set up per-subscript arrays */
3091 22376 : ptr = ((char *) sbsrefstate) + MAXALIGN(sizeof(SubscriptingRefState));
3092 22376 : sbsrefstate->upperindex = (Datum *) ptr;
3093 22376 : ptr += nupper * sizeof(Datum);
3094 22376 : sbsrefstate->lowerindex = (Datum *) ptr;
3095 22376 : ptr += nlower * sizeof(Datum);
3096 22376 : sbsrefstate->upperprovided = (bool *) ptr;
3097 22376 : ptr += nupper * sizeof(bool);
3098 22376 : sbsrefstate->lowerprovided = (bool *) ptr;
3099 22376 : ptr += nlower * sizeof(bool);
3100 22376 : sbsrefstate->upperindexnull = (bool *) ptr;
3101 22376 : ptr += nupper * sizeof(bool);
3102 22376 : sbsrefstate->lowerindexnull = (bool *) ptr;
3103 : /* ptr += nlower * sizeof(bool); */
3104 :
3105 : /*
3106 : * Let the container-type-specific code have a chance. It must fill the
3107 : * "methods" struct with function pointers for us to possibly use in
3108 : * execution steps below; and it can optionally set up some data pointed
3109 : * to by the workspace field.
3110 : */
3111 22376 : memset(&methods, 0, sizeof(methods));
3112 22376 : sbsroutines->exec_setup(sbsref, sbsrefstate, &methods);
3113 :
3114 : /*
3115 : * Evaluate array input. It's safe to do so into resv/resnull, because we
3116 : * won't use that as target for any of the other subexpressions, and it'll
3117 : * be overwritten by the final EEOP_SBSREF_FETCH/ASSIGN step, which is
3118 : * pushed last.
3119 : */
3120 22376 : ExecInitExprRec(sbsref->refexpr, state, resv, resnull);
3121 :
3122 : /*
3123 : * If refexpr yields NULL, and the operation should be strict, then result
3124 : * is NULL. We can implement this with just JUMP_IF_NULL, since we
3125 : * evaluated the array into the desired target location.
3126 : */
3127 22376 : if (!isAssignment && sbsroutines->fetch_strict)
3128 : {
3129 21068 : scratch->opcode = EEOP_JUMP_IF_NULL;
3130 21068 : scratch->d.jump.jumpdone = -1; /* adjust later */
3131 21068 : ExprEvalPushStep(state, scratch);
3132 21068 : adjust_jumps = lappend_int(adjust_jumps,
3133 21068 : state->steps_len - 1);
3134 : }
3135 :
3136 : /* Evaluate upper subscripts */
3137 22376 : i = 0;
3138 45336 : foreach(lc, sbsref->refupperindexpr)
3139 : {
3140 22960 : Expr *e = (Expr *) lfirst(lc);
3141 :
3142 : /* When slicing, individual subscript bounds can be omitted */
3143 22960 : if (!e)
3144 : {
3145 78 : sbsrefstate->upperprovided[i] = false;
3146 78 : sbsrefstate->upperindexnull[i] = true;
3147 : }
3148 : else
3149 : {
3150 22882 : sbsrefstate->upperprovided[i] = true;
3151 : /* Each subscript is evaluated into appropriate array entry */
3152 22882 : ExecInitExprRec(e, state,
3153 22882 : &sbsrefstate->upperindex[i],
3154 22882 : &sbsrefstate->upperindexnull[i]);
3155 : }
3156 22960 : i++;
3157 : }
3158 :
3159 : /* Evaluate lower subscripts similarly */
3160 22376 : i = 0;
3161 22940 : foreach(lc, sbsref->reflowerindexpr)
3162 : {
3163 564 : Expr *e = (Expr *) lfirst(lc);
3164 :
3165 : /* When slicing, individual subscript bounds can be omitted */
3166 564 : if (!e)
3167 : {
3168 78 : sbsrefstate->lowerprovided[i] = false;
3169 78 : sbsrefstate->lowerindexnull[i] = true;
3170 : }
3171 : else
3172 : {
3173 486 : sbsrefstate->lowerprovided[i] = true;
3174 : /* Each subscript is evaluated into appropriate array entry */
3175 486 : ExecInitExprRec(e, state,
3176 486 : &sbsrefstate->lowerindex[i],
3177 486 : &sbsrefstate->lowerindexnull[i]);
3178 : }
3179 564 : i++;
3180 : }
3181 :
3182 : /* SBSREF_SUBSCRIPTS checks and converts all the subscripts at once */
3183 22376 : if (methods.sbs_check_subscripts)
3184 : {
3185 22362 : scratch->opcode = EEOP_SBSREF_SUBSCRIPTS;
3186 22362 : scratch->d.sbsref_subscript.subscriptfunc = methods.sbs_check_subscripts;
3187 22362 : scratch->d.sbsref_subscript.state = sbsrefstate;
3188 22362 : scratch->d.sbsref_subscript.jumpdone = -1; /* adjust later */
3189 22362 : ExprEvalPushStep(state, scratch);
3190 22362 : adjust_jumps = lappend_int(adjust_jumps,
3191 22362 : state->steps_len - 1);
3192 : }
3193 :
3194 22376 : if (isAssignment)
3195 : {
3196 : Datum *save_innermost_caseval;
3197 : bool *save_innermost_casenull;
3198 :
3199 : /* Check for unimplemented methods */
3200 1308 : if (!methods.sbs_assign)
3201 0 : ereport(ERROR,
3202 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3203 : errmsg("type %s does not support subscripted assignment",
3204 : format_type_be(sbsref->refcontainertype))));
3205 :
3206 : /*
3207 : * We might have a nested-assignment situation, in which the
3208 : * refassgnexpr is itself a FieldStore or SubscriptingRef that needs
3209 : * to obtain and modify the previous value of the array element or
3210 : * slice being replaced. If so, we have to extract that value from
3211 : * the array and pass it down via the CaseTestExpr mechanism. It's
3212 : * safe to reuse the CASE mechanism because there cannot be a CASE
3213 : * between here and where the value would be needed, and an array
3214 : * assignment can't be within a CASE either. (So saving and restoring
3215 : * innermost_caseval is just paranoia, but let's do it anyway.)
3216 : *
3217 : * Since fetching the old element might be a nontrivial expense, do it
3218 : * only if the argument actually needs it.
3219 : */
3220 1308 : if (isAssignmentIndirectionExpr(sbsref->refassgnexpr))
3221 : {
3222 186 : if (!methods.sbs_fetch_old)
3223 0 : ereport(ERROR,
3224 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3225 : errmsg("type %s does not support subscripted assignment",
3226 : format_type_be(sbsref->refcontainertype))));
3227 186 : scratch->opcode = EEOP_SBSREF_OLD;
3228 186 : scratch->d.sbsref.subscriptfunc = methods.sbs_fetch_old;
3229 186 : scratch->d.sbsref.state = sbsrefstate;
3230 186 : ExprEvalPushStep(state, scratch);
3231 : }
3232 :
3233 : /* SBSREF_OLD puts extracted value into prevvalue/prevnull */
3234 1308 : save_innermost_caseval = state->innermost_caseval;
3235 1308 : save_innermost_casenull = state->innermost_casenull;
3236 1308 : state->innermost_caseval = &sbsrefstate->prevvalue;
3237 1308 : state->innermost_casenull = &sbsrefstate->prevnull;
3238 :
3239 : /* evaluate replacement value into replacevalue/replacenull */
3240 1308 : ExecInitExprRec(sbsref->refassgnexpr, state,
3241 : &sbsrefstate->replacevalue, &sbsrefstate->replacenull);
3242 :
3243 1308 : state->innermost_caseval = save_innermost_caseval;
3244 1308 : state->innermost_casenull = save_innermost_casenull;
3245 :
3246 : /* and perform the assignment */
3247 1308 : scratch->opcode = EEOP_SBSREF_ASSIGN;
3248 1308 : scratch->d.sbsref.subscriptfunc = methods.sbs_assign;
3249 1308 : scratch->d.sbsref.state = sbsrefstate;
3250 1308 : ExprEvalPushStep(state, scratch);
3251 : }
3252 : else
3253 : {
3254 : /* array fetch is much simpler */
3255 21068 : scratch->opcode = EEOP_SBSREF_FETCH;
3256 21068 : scratch->d.sbsref.subscriptfunc = methods.sbs_fetch;
3257 21068 : scratch->d.sbsref.state = sbsrefstate;
3258 21068 : ExprEvalPushStep(state, scratch);
3259 : }
3260 :
3261 : /* adjust jump targets */
3262 65806 : foreach(lc, adjust_jumps)
3263 : {
3264 43430 : ExprEvalStep *as = &state->steps[lfirst_int(lc)];
3265 :
3266 43430 : if (as->opcode == EEOP_SBSREF_SUBSCRIPTS)
3267 : {
3268 : Assert(as->d.sbsref_subscript.jumpdone == -1);
3269 22362 : as->d.sbsref_subscript.jumpdone = state->steps_len;
3270 : }
3271 : else
3272 : {
3273 : Assert(as->opcode == EEOP_JUMP_IF_NULL);
3274 : Assert(as->d.jump.jumpdone == -1);
3275 21068 : as->d.jump.jumpdone = state->steps_len;
3276 : }
3277 : }
3278 22376 : }
3279 :
3280 : /*
3281 : * Helper for preparing SubscriptingRef expressions for evaluation: is expr
3282 : * a nested FieldStore or SubscriptingRef that needs the old element value
3283 : * passed down?
3284 : *
3285 : * (We could use this in FieldStore too, but in that case passing the old
3286 : * value is so cheap there's no need.)
3287 : *
3288 : * Note: it might seem that this needs to recurse, but in most cases it does
3289 : * not; the CaseTestExpr, if any, will be directly the arg or refexpr of the
3290 : * top-level node. Nested-assignment situations give rise to expression
3291 : * trees in which each level of assignment has its own CaseTestExpr, and the
3292 : * recursive structure appears within the newvals or refassgnexpr field.
3293 : * There is an exception, though: if the array is an array-of-domain, we will
3294 : * have a CoerceToDomain or RelabelType as the refassgnexpr, and we need to
3295 : * be able to look through that.
3296 : */
3297 : static bool
3298 1392 : isAssignmentIndirectionExpr(Expr *expr)
3299 : {
3300 1392 : if (expr == NULL)
3301 0 : return false; /* just paranoia */
3302 1392 : if (IsA(expr, FieldStore))
3303 : {
3304 186 : FieldStore *fstore = (FieldStore *) expr;
3305 :
3306 186 : if (fstore->arg && IsA(fstore->arg, CaseTestExpr))
3307 186 : return true;
3308 : }
3309 1206 : else if (IsA(expr, SubscriptingRef))
3310 : {
3311 32 : SubscriptingRef *sbsRef = (SubscriptingRef *) expr;
3312 :
3313 32 : if (sbsRef->refexpr && IsA(sbsRef->refexpr, CaseTestExpr))
3314 0 : return true;
3315 : }
3316 1174 : else if (IsA(expr, CoerceToDomain))
3317 : {
3318 66 : CoerceToDomain *cd = (CoerceToDomain *) expr;
3319 :
3320 66 : return isAssignmentIndirectionExpr(cd->arg);
3321 : }
3322 1108 : else if (IsA(expr, RelabelType))
3323 : {
3324 18 : RelabelType *r = (RelabelType *) expr;
3325 :
3326 18 : return isAssignmentIndirectionExpr(r->arg);
3327 : }
3328 1122 : return false;
3329 : }
3330 :
3331 : /*
3332 : * Prepare evaluation of a CoerceToDomain expression.
3333 : */
3334 : static void
3335 8296 : ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
3336 : ExprState *state, Datum *resv, bool *resnull)
3337 : {
3338 : DomainConstraintRef *constraint_ref;
3339 8296 : Datum *domainval = NULL;
3340 8296 : bool *domainnull = NULL;
3341 : ListCell *l;
3342 :
3343 8296 : scratch->d.domaincheck.resulttype = ctest->resulttype;
3344 : /* we'll allocate workspace only if needed */
3345 8296 : scratch->d.domaincheck.checkvalue = NULL;
3346 8296 : scratch->d.domaincheck.checknull = NULL;
3347 8296 : scratch->d.domaincheck.escontext = state->escontext;
3348 :
3349 : /*
3350 : * Evaluate argument - it's fine to directly store it into resv/resnull,
3351 : * if there's constraint failures there'll be errors, otherwise it's what
3352 : * needs to be returned.
3353 : */
3354 8296 : ExecInitExprRec(ctest->arg, state, resv, resnull);
3355 :
3356 : /*
3357 : * Note: if the argument is of varlena type, it could be a R/W expanded
3358 : * object. We want to return the R/W pointer as the final result, but we
3359 : * have to pass a R/O pointer as the value to be tested by any functions
3360 : * in check expressions. We don't bother to emit a MAKE_READONLY step
3361 : * unless there's actually at least one check expression, though. Until
3362 : * we've tested that, domainval/domainnull are NULL.
3363 : */
3364 :
3365 : /*
3366 : * Collect the constraints associated with the domain.
3367 : *
3368 : * Note: before PG v10 we'd recheck the set of constraints during each
3369 : * evaluation of the expression. Now we bake them into the ExprState
3370 : * during executor initialization. That means we don't need typcache.c to
3371 : * provide compiled exprs.
3372 : */
3373 : constraint_ref = (DomainConstraintRef *)
3374 8296 : palloc(sizeof(DomainConstraintRef));
3375 8296 : InitDomainConstraintRef(ctest->resulttype,
3376 : constraint_ref,
3377 : CurrentMemoryContext,
3378 : false);
3379 :
3380 : /*
3381 : * Compile code to check each domain constraint. NOTNULL constraints can
3382 : * just be applied on the resv/resnull value, but for CHECK constraints we
3383 : * need more pushups.
3384 : */
3385 17542 : foreach(l, constraint_ref->constraints)
3386 : {
3387 9246 : DomainConstraintState *con = (DomainConstraintState *) lfirst(l);
3388 : Datum *save_innermost_domainval;
3389 : bool *save_innermost_domainnull;
3390 :
3391 9246 : scratch->d.domaincheck.constraintname = con->name;
3392 :
3393 9246 : switch (con->constrainttype)
3394 : {
3395 438 : case DOM_CONSTRAINT_NOTNULL:
3396 438 : scratch->opcode = EEOP_DOMAIN_NOTNULL;
3397 438 : ExprEvalPushStep(state, scratch);
3398 438 : break;
3399 8808 : case DOM_CONSTRAINT_CHECK:
3400 : /* Allocate workspace for CHECK output if we didn't yet */
3401 8808 : if (scratch->d.domaincheck.checkvalue == NULL)
3402 : {
3403 7948 : scratch->d.domaincheck.checkvalue =
3404 7948 : (Datum *) palloc(sizeof(Datum));
3405 7948 : scratch->d.domaincheck.checknull =
3406 7948 : (bool *) palloc(sizeof(bool));
3407 : }
3408 :
3409 : /*
3410 : * If first time through, determine where CoerceToDomainValue
3411 : * nodes should read from.
3412 : */
3413 8808 : if (domainval == NULL)
3414 : {
3415 : /*
3416 : * Since value might be read multiple times, force to R/O
3417 : * - but only if it could be an expanded datum.
3418 : */
3419 7948 : if (get_typlen(ctest->resulttype) == -1)
3420 : {
3421 2854 : ExprEvalStep scratch2 = {0};
3422 :
3423 : /* Yes, so make output workspace for MAKE_READONLY */
3424 2854 : domainval = (Datum *) palloc(sizeof(Datum));
3425 2854 : domainnull = (bool *) palloc(sizeof(bool));
3426 :
3427 : /* Emit MAKE_READONLY */
3428 2854 : scratch2.opcode = EEOP_MAKE_READONLY;
3429 2854 : scratch2.resvalue = domainval;
3430 2854 : scratch2.resnull = domainnull;
3431 2854 : scratch2.d.make_readonly.value = resv;
3432 2854 : scratch2.d.make_readonly.isnull = resnull;
3433 2854 : ExprEvalPushStep(state, &scratch2);
3434 : }
3435 : else
3436 : {
3437 : /* No, so it's fine to read from resv/resnull */
3438 5094 : domainval = resv;
3439 5094 : domainnull = resnull;
3440 : }
3441 : }
3442 :
3443 : /*
3444 : * Set up value to be returned by CoerceToDomainValue nodes.
3445 : * We must save and restore innermost_domainval/null fields,
3446 : * in case this node is itself within a check expression for
3447 : * another domain.
3448 : */
3449 8808 : save_innermost_domainval = state->innermost_domainval;
3450 8808 : save_innermost_domainnull = state->innermost_domainnull;
3451 8808 : state->innermost_domainval = domainval;
3452 8808 : state->innermost_domainnull = domainnull;
3453 :
3454 : /* evaluate check expression value */
3455 8808 : ExecInitExprRec(con->check_expr, state,
3456 : scratch->d.domaincheck.checkvalue,
3457 : scratch->d.domaincheck.checknull);
3458 :
3459 8808 : state->innermost_domainval = save_innermost_domainval;
3460 8808 : state->innermost_domainnull = save_innermost_domainnull;
3461 :
3462 : /* now test result */
3463 8808 : scratch->opcode = EEOP_DOMAIN_CHECK;
3464 8808 : ExprEvalPushStep(state, scratch);
3465 :
3466 8808 : break;
3467 0 : default:
3468 0 : elog(ERROR, "unrecognized constraint type: %d",
3469 : (int) con->constrainttype);
3470 : break;
3471 : }
3472 : }
3473 8296 : }
3474 :
3475 : /*
3476 : * Build transition/combine function invocations for all aggregate transition
3477 : * / combination function invocations in a grouping sets phase. This has to
3478 : * invoke all sort based transitions in a phase (if doSort is true), all hash
3479 : * based transitions (if doHash is true), or both (both true).
3480 : *
3481 : * The resulting expression will, for each set of transition values, first
3482 : * check for filters, evaluate aggregate input, check that that input is not
3483 : * NULL for a strict transition function, and then finally invoke the
3484 : * transition for each of the concurrently computed grouping sets.
3485 : *
3486 : * If nullcheck is true, the generated code will check for a NULL pointer to
3487 : * the array of AggStatePerGroup, and skip evaluation if so.
3488 : */
3489 : ExprState *
3490 41480 : ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
3491 : bool doSort, bool doHash, bool nullcheck)
3492 : {
3493 41480 : ExprState *state = makeNode(ExprState);
3494 41480 : PlanState *parent = &aggstate->ss.ps;
3495 41480 : ExprEvalStep scratch = {0};
3496 41480 : bool isCombine = DO_AGGSPLIT_COMBINE(aggstate->aggsplit);
3497 41480 : ExprSetupInfo deform = {0, 0, 0, NIL};
3498 :
3499 41480 : state->expr = (Expr *) aggstate;
3500 41480 : state->parent = parent;
3501 :
3502 41480 : scratch.resvalue = &state->resvalue;
3503 41480 : scratch.resnull = &state->resnull;
3504 :
3505 : /*
3506 : * First figure out which slots, and how many columns from each, we're
3507 : * going to need.
3508 : */
3509 88130 : for (int transno = 0; transno < aggstate->numtrans; transno++)
3510 : {
3511 46650 : AggStatePerTrans pertrans = &aggstate->pertrans[transno];
3512 :
3513 46650 : expr_setup_walker((Node *) pertrans->aggref->aggdirectargs,
3514 : &deform);
3515 46650 : expr_setup_walker((Node *) pertrans->aggref->args,
3516 : &deform);
3517 46650 : expr_setup_walker((Node *) pertrans->aggref->aggorder,
3518 : &deform);
3519 46650 : expr_setup_walker((Node *) pertrans->aggref->aggdistinct,
3520 : &deform);
3521 46650 : expr_setup_walker((Node *) pertrans->aggref->aggfilter,
3522 : &deform);
3523 : }
3524 41480 : ExecPushExprSetupSteps(state, &deform);
3525 :
3526 : /*
3527 : * Emit instructions for each transition value / grouping set combination.
3528 : */
3529 88130 : for (int transno = 0; transno < aggstate->numtrans; transno++)
3530 : {
3531 46650 : AggStatePerTrans pertrans = &aggstate->pertrans[transno];
3532 46650 : FunctionCallInfo trans_fcinfo = pertrans->transfn_fcinfo;
3533 46650 : List *adjust_bailout = NIL;
3534 46650 : NullableDatum *strictargs = NULL;
3535 46650 : bool *strictnulls = NULL;
3536 : int argno;
3537 : ListCell *bail;
3538 :
3539 : /*
3540 : * If filter present, emit. Do so before evaluating the input, to
3541 : * avoid potentially unneeded computations, or even worse, unintended
3542 : * side-effects. When combining, all the necessary filtering has
3543 : * already been done.
3544 : */
3545 46650 : if (pertrans->aggref->aggfilter && !isCombine)
3546 : {
3547 : /* evaluate filter expression */
3548 734 : ExecInitExprRec(pertrans->aggref->aggfilter, state,
3549 : &state->resvalue, &state->resnull);
3550 : /* and jump out if false */
3551 734 : scratch.opcode = EEOP_JUMP_IF_NOT_TRUE;
3552 734 : scratch.d.jump.jumpdone = -1; /* adjust later */
3553 734 : ExprEvalPushStep(state, &scratch);
3554 734 : adjust_bailout = lappend_int(adjust_bailout,
3555 734 : state->steps_len - 1);
3556 : }
3557 :
3558 : /*
3559 : * Evaluate arguments to aggregate/combine function.
3560 : */
3561 46650 : argno = 0;
3562 46650 : if (isCombine)
3563 : {
3564 : /*
3565 : * Combining two aggregate transition values. Instead of directly
3566 : * coming from a tuple the input is a, potentially deserialized,
3567 : * transition value.
3568 : */
3569 : TargetEntry *source_tle;
3570 :
3571 : Assert(pertrans->numSortCols == 0);
3572 : Assert(list_length(pertrans->aggref->args) == 1);
3573 :
3574 1358 : strictargs = trans_fcinfo->args + 1;
3575 1358 : source_tle = (TargetEntry *) linitial(pertrans->aggref->args);
3576 :
3577 : /*
3578 : * deserialfn_oid will be set if we must deserialize the input
3579 : * state before calling the combine function.
3580 : */
3581 1358 : if (!OidIsValid(pertrans->deserialfn_oid))
3582 : {
3583 : /*
3584 : * Start from 1, since the 0th arg will be the transition
3585 : * value
3586 : */
3587 1238 : ExecInitExprRec(source_tle->expr, state,
3588 1238 : &trans_fcinfo->args[argno + 1].value,
3589 1238 : &trans_fcinfo->args[argno + 1].isnull);
3590 : }
3591 : else
3592 : {
3593 120 : FunctionCallInfo ds_fcinfo = pertrans->deserialfn_fcinfo;
3594 :
3595 : /* evaluate argument */
3596 120 : ExecInitExprRec(source_tle->expr, state,
3597 : &ds_fcinfo->args[0].value,
3598 : &ds_fcinfo->args[0].isnull);
3599 :
3600 : /* Dummy second argument for type-safety reasons */
3601 120 : ds_fcinfo->args[1].value = PointerGetDatum(NULL);
3602 120 : ds_fcinfo->args[1].isnull = false;
3603 :
3604 : /*
3605 : * Don't call a strict deserialization function with NULL
3606 : * input
3607 : */
3608 120 : if (pertrans->deserialfn.fn_strict)
3609 120 : scratch.opcode = EEOP_AGG_STRICT_DESERIALIZE;
3610 : else
3611 0 : scratch.opcode = EEOP_AGG_DESERIALIZE;
3612 :
3613 120 : scratch.d.agg_deserialize.fcinfo_data = ds_fcinfo;
3614 120 : scratch.d.agg_deserialize.jumpnull = -1; /* adjust later */
3615 120 : scratch.resvalue = &trans_fcinfo->args[argno + 1].value;
3616 120 : scratch.resnull = &trans_fcinfo->args[argno + 1].isnull;
3617 :
3618 120 : ExprEvalPushStep(state, &scratch);
3619 : /* don't add an adjustment unless the function is strict */
3620 120 : if (pertrans->deserialfn.fn_strict)
3621 120 : adjust_bailout = lappend_int(adjust_bailout,
3622 120 : state->steps_len - 1);
3623 :
3624 : /* restore normal settings of scratch fields */
3625 120 : scratch.resvalue = &state->resvalue;
3626 120 : scratch.resnull = &state->resnull;
3627 : }
3628 1358 : argno++;
3629 :
3630 : Assert(pertrans->numInputs == argno);
3631 : }
3632 45292 : else if (!pertrans->aggsortrequired)
3633 : {
3634 : ListCell *arg;
3635 :
3636 : /*
3637 : * Normal transition function without ORDER BY / DISTINCT or with
3638 : * ORDER BY / DISTINCT but the planner has given us pre-sorted
3639 : * input.
3640 : */
3641 45016 : strictargs = trans_fcinfo->args + 1;
3642 :
3643 80674 : foreach(arg, pertrans->aggref->args)
3644 : {
3645 36704 : TargetEntry *source_tle = (TargetEntry *) lfirst(arg);
3646 :
3647 : /*
3648 : * Don't initialize args for any ORDER BY clause that might
3649 : * exist in a presorted aggregate.
3650 : */
3651 36704 : if (argno == pertrans->numTransInputs)
3652 1046 : break;
3653 :
3654 : /*
3655 : * Start from 1, since the 0th arg will be the transition
3656 : * value
3657 : */
3658 35658 : ExecInitExprRec(source_tle->expr, state,
3659 35658 : &trans_fcinfo->args[argno + 1].value,
3660 35658 : &trans_fcinfo->args[argno + 1].isnull);
3661 35658 : argno++;
3662 : }
3663 : Assert(pertrans->numTransInputs == argno);
3664 : }
3665 276 : else if (pertrans->numInputs == 1)
3666 : {
3667 : /*
3668 : * Non-presorted DISTINCT and/or ORDER BY case, with a single
3669 : * column sorted on.
3670 : */
3671 246 : TargetEntry *source_tle =
3672 246 : (TargetEntry *) linitial(pertrans->aggref->args);
3673 :
3674 : Assert(list_length(pertrans->aggref->args) == 1);
3675 :
3676 246 : ExecInitExprRec(source_tle->expr, state,
3677 : &state->resvalue,
3678 : &state->resnull);
3679 246 : strictnulls = &state->resnull;
3680 246 : argno++;
3681 :
3682 : Assert(pertrans->numInputs == argno);
3683 : }
3684 : else
3685 : {
3686 : /*
3687 : * Non-presorted DISTINCT and/or ORDER BY case, with multiple
3688 : * columns sorted on.
3689 : */
3690 30 : Datum *values = pertrans->sortslot->tts_values;
3691 30 : bool *nulls = pertrans->sortslot->tts_isnull;
3692 : ListCell *arg;
3693 :
3694 30 : strictnulls = nulls;
3695 :
3696 114 : foreach(arg, pertrans->aggref->args)
3697 : {
3698 84 : TargetEntry *source_tle = (TargetEntry *) lfirst(arg);
3699 :
3700 84 : ExecInitExprRec(source_tle->expr, state,
3701 84 : &values[argno], &nulls[argno]);
3702 84 : argno++;
3703 : }
3704 : Assert(pertrans->numInputs == argno);
3705 : }
3706 :
3707 : /*
3708 : * For a strict transfn, nothing happens when there's a NULL input; we
3709 : * just keep the prior transValue. This is true for both plain and
3710 : * sorted/distinct aggregates.
3711 : */
3712 46650 : if (trans_fcinfo->flinfo->fn_strict && pertrans->numTransInputs > 0)
3713 : {
3714 10544 : if (strictnulls)
3715 162 : scratch.opcode = EEOP_AGG_STRICT_INPUT_CHECK_NULLS;
3716 : else
3717 10382 : scratch.opcode = EEOP_AGG_STRICT_INPUT_CHECK_ARGS;
3718 10544 : scratch.d.agg_strict_input_check.nulls = strictnulls;
3719 10544 : scratch.d.agg_strict_input_check.args = strictargs;
3720 10544 : scratch.d.agg_strict_input_check.jumpnull = -1; /* adjust later */
3721 10544 : scratch.d.agg_strict_input_check.nargs = pertrans->numTransInputs;
3722 10544 : ExprEvalPushStep(state, &scratch);
3723 10544 : adjust_bailout = lappend_int(adjust_bailout,
3724 10544 : state->steps_len - 1);
3725 : }
3726 :
3727 : /* Handle DISTINCT aggregates which have pre-sorted input */
3728 46650 : if (pertrans->numDistinctCols > 0 && !pertrans->aggsortrequired)
3729 : {
3730 414 : if (pertrans->numDistinctCols > 1)
3731 96 : scratch.opcode = EEOP_AGG_PRESORTED_DISTINCT_MULTI;
3732 : else
3733 318 : scratch.opcode = EEOP_AGG_PRESORTED_DISTINCT_SINGLE;
3734 :
3735 414 : scratch.d.agg_presorted_distinctcheck.pertrans = pertrans;
3736 414 : scratch.d.agg_presorted_distinctcheck.jumpdistinct = -1; /* adjust later */
3737 414 : ExprEvalPushStep(state, &scratch);
3738 414 : adjust_bailout = lappend_int(adjust_bailout,
3739 414 : state->steps_len - 1);
3740 : }
3741 :
3742 : /*
3743 : * Call transition function (once for each concurrently evaluated
3744 : * grouping set). Do so for both sort and hash based computations, as
3745 : * applicable.
3746 : */
3747 46650 : if (doSort)
3748 : {
3749 40550 : int processGroupingSets = Max(phase->numsets, 1);
3750 40550 : int setoff = 0;
3751 :
3752 82210 : for (int setno = 0; setno < processGroupingSets; setno++)
3753 : {
3754 41660 : ExecBuildAggTransCall(state, aggstate, &scratch, trans_fcinfo,
3755 : pertrans, transno, setno, setoff, false,
3756 : nullcheck);
3757 41660 : setoff++;
3758 : }
3759 : }
3760 :
3761 46650 : if (doHash)
3762 : {
3763 6474 : int numHashes = aggstate->num_hashes;
3764 : int setoff;
3765 :
3766 : /* in MIXED mode, there'll be preceding transition values */
3767 6474 : if (aggstate->aggstrategy != AGG_HASHED)
3768 398 : setoff = aggstate->maxsets;
3769 : else
3770 6076 : setoff = 0;
3771 :
3772 14158 : for (int setno = 0; setno < numHashes; setno++)
3773 : {
3774 7684 : ExecBuildAggTransCall(state, aggstate, &scratch, trans_fcinfo,
3775 : pertrans, transno, setno, setoff, true,
3776 : nullcheck);
3777 7684 : setoff++;
3778 : }
3779 : }
3780 :
3781 : /* adjust early bail out jump target(s) */
3782 58462 : foreach(bail, adjust_bailout)
3783 : {
3784 11812 : ExprEvalStep *as = &state->steps[lfirst_int(bail)];
3785 :
3786 11812 : if (as->opcode == EEOP_JUMP_IF_NOT_TRUE)
3787 : {
3788 : Assert(as->d.jump.jumpdone == -1);
3789 734 : as->d.jump.jumpdone = state->steps_len;
3790 : }
3791 11078 : else if (as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_ARGS ||
3792 696 : as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
3793 : {
3794 : Assert(as->d.agg_strict_input_check.jumpnull == -1);
3795 10544 : as->d.agg_strict_input_check.jumpnull = state->steps_len;
3796 : }
3797 534 : else if (as->opcode == EEOP_AGG_STRICT_DESERIALIZE)
3798 : {
3799 : Assert(as->d.agg_deserialize.jumpnull == -1);
3800 120 : as->d.agg_deserialize.jumpnull = state->steps_len;
3801 : }
3802 414 : else if (as->opcode == EEOP_AGG_PRESORTED_DISTINCT_SINGLE ||
3803 96 : as->opcode == EEOP_AGG_PRESORTED_DISTINCT_MULTI)
3804 : {
3805 : Assert(as->d.agg_presorted_distinctcheck.jumpdistinct == -1);
3806 414 : as->d.agg_presorted_distinctcheck.jumpdistinct = state->steps_len;
3807 : }
3808 : else
3809 : Assert(false);
3810 : }
3811 : }
3812 :
3813 41480 : scratch.resvalue = NULL;
3814 41480 : scratch.resnull = NULL;
3815 41480 : scratch.opcode = EEOP_DONE;
3816 41480 : ExprEvalPushStep(state, &scratch);
3817 :
3818 41480 : ExecReadyExpr(state);
3819 :
3820 41480 : return state;
3821 : }
3822 :
3823 : /*
3824 : * Build transition/combine function invocation for a single transition
3825 : * value. This is separated from ExecBuildAggTrans() because there are
3826 : * multiple callsites (hash and sort in some grouping set cases).
3827 : */
3828 : static void
3829 49344 : ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
3830 : ExprEvalStep *scratch,
3831 : FunctionCallInfo fcinfo, AggStatePerTrans pertrans,
3832 : int transno, int setno, int setoff, bool ishash,
3833 : bool nullcheck)
3834 : {
3835 : ExprContext *aggcontext;
3836 49344 : int adjust_jumpnull = -1;
3837 :
3838 49344 : if (ishash)
3839 7684 : aggcontext = aggstate->hashcontext;
3840 : else
3841 41660 : aggcontext = aggstate->aggcontexts[setno];
3842 :
3843 : /* add check for NULL pointer? */
3844 49344 : if (nullcheck)
3845 : {
3846 408 : scratch->opcode = EEOP_AGG_PLAIN_PERGROUP_NULLCHECK;
3847 408 : scratch->d.agg_plain_pergroup_nullcheck.setoff = setoff;
3848 : /* adjust later */
3849 408 : scratch->d.agg_plain_pergroup_nullcheck.jumpnull = -1;
3850 408 : ExprEvalPushStep(state, scratch);
3851 408 : adjust_jumpnull = state->steps_len - 1;
3852 : }
3853 :
3854 : /*
3855 : * Determine appropriate transition implementation.
3856 : *
3857 : * For non-ordered aggregates and ORDER BY / DISTINCT aggregates with
3858 : * presorted input:
3859 : *
3860 : * If the initial value for the transition state doesn't exist in the
3861 : * pg_aggregate table then we will let the first non-NULL value returned
3862 : * from the outer procNode become the initial value. (This is useful for
3863 : * aggregates like max() and min().) The noTransValue flag signals that we
3864 : * need to do so. If true, generate a
3865 : * EEOP_AGG_INIT_STRICT_PLAIN_TRANS{,_BYVAL} step. This step also needs to
3866 : * do the work described next:
3867 : *
3868 : * If the function is strict, but does have an initial value, choose
3869 : * EEOP_AGG_STRICT_PLAIN_TRANS{,_BYVAL}, which skips the transition
3870 : * function if the transition value has become NULL (because a previous
3871 : * transition function returned NULL). This step also needs to do the work
3872 : * described next:
3873 : *
3874 : * Otherwise we call EEOP_AGG_PLAIN_TRANS{,_BYVAL}, which does not have to
3875 : * perform either of the above checks.
3876 : *
3877 : * Having steps with overlapping responsibilities is not nice, but
3878 : * aggregations are very performance sensitive, making this worthwhile.
3879 : *
3880 : * For ordered aggregates:
3881 : *
3882 : * Only need to choose between the faster path for a single ordered
3883 : * column, and the one between multiple columns. Checking strictness etc
3884 : * is done when finalizing the aggregate. See
3885 : * process_ordered_aggregate_{single, multi} and
3886 : * advance_transition_function.
3887 : */
3888 49344 : if (!pertrans->aggsortrequired)
3889 : {
3890 49020 : if (pertrans->transtypeByVal)
3891 : {
3892 45310 : if (fcinfo->flinfo->fn_strict &&
3893 22666 : pertrans->initValueIsNull)
3894 4696 : scratch->opcode = EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL;
3895 40614 : else if (fcinfo->flinfo->fn_strict)
3896 17970 : scratch->opcode = EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL;
3897 : else
3898 22644 : scratch->opcode = EEOP_AGG_PLAIN_TRANS_BYVAL;
3899 : }
3900 : else
3901 : {
3902 3710 : if (fcinfo->flinfo->fn_strict &&
3903 3338 : pertrans->initValueIsNull)
3904 954 : scratch->opcode = EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF;
3905 2756 : else if (fcinfo->flinfo->fn_strict)
3906 2384 : scratch->opcode = EEOP_AGG_PLAIN_TRANS_STRICT_BYREF;
3907 : else
3908 372 : scratch->opcode = EEOP_AGG_PLAIN_TRANS_BYREF;
3909 : }
3910 : }
3911 324 : else if (pertrans->numInputs == 1)
3912 282 : scratch->opcode = EEOP_AGG_ORDERED_TRANS_DATUM;
3913 : else
3914 42 : scratch->opcode = EEOP_AGG_ORDERED_TRANS_TUPLE;
3915 :
3916 49344 : scratch->d.agg_trans.pertrans = pertrans;
3917 49344 : scratch->d.agg_trans.setno = setno;
3918 49344 : scratch->d.agg_trans.setoff = setoff;
3919 49344 : scratch->d.agg_trans.transno = transno;
3920 49344 : scratch->d.agg_trans.aggcontext = aggcontext;
3921 49344 : ExprEvalPushStep(state, scratch);
3922 :
3923 : /* fix up jumpnull */
3924 49344 : if (adjust_jumpnull != -1)
3925 : {
3926 408 : ExprEvalStep *as = &state->steps[adjust_jumpnull];
3927 :
3928 : Assert(as->opcode == EEOP_AGG_PLAIN_PERGROUP_NULLCHECK);
3929 : Assert(as->d.agg_plain_pergroup_nullcheck.jumpnull == -1);
3930 408 : as->d.agg_plain_pergroup_nullcheck.jumpnull = state->steps_len;
3931 : }
3932 49344 : }
3933 :
3934 : /*
3935 : * Build equality expression that can be evaluated using ExecQual(), returning
3936 : * true if the expression context's inner/outer tuple are NOT DISTINCT. I.e
3937 : * two nulls match, a null and a not-null don't match.
3938 : *
3939 : * desc: tuple descriptor of the to-be-compared tuples
3940 : * numCols: the number of attributes to be examined
3941 : * keyColIdx: array of attribute column numbers
3942 : * eqFunctions: array of function oids of the equality functions to use
3943 : * parent: parent executor node
3944 : */
3945 : ExprState *
3946 17244 : ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
3947 : const TupleTableSlotOps *lops, const TupleTableSlotOps *rops,
3948 : int numCols,
3949 : const AttrNumber *keyColIdx,
3950 : const Oid *eqfunctions,
3951 : const Oid *collations,
3952 : PlanState *parent)
3953 : {
3954 17244 : ExprState *state = makeNode(ExprState);
3955 17244 : ExprEvalStep scratch = {0};
3956 17244 : int maxatt = -1;
3957 17244 : List *adjust_jumps = NIL;
3958 : ListCell *lc;
3959 :
3960 : /*
3961 : * When no columns are actually compared, the result's always true. See
3962 : * special case in ExecQual().
3963 : */
3964 17244 : if (numCols == 0)
3965 42 : return NULL;
3966 :
3967 17202 : state->expr = NULL;
3968 17202 : state->flags = EEO_FLAG_IS_QUAL;
3969 17202 : state->parent = parent;
3970 :
3971 17202 : scratch.resvalue = &state->resvalue;
3972 17202 : scratch.resnull = &state->resnull;
3973 :
3974 : /* compute max needed attribute */
3975 45986 : for (int natt = 0; natt < numCols; natt++)
3976 : {
3977 28784 : int attno = keyColIdx[natt];
3978 :
3979 28784 : if (attno > maxatt)
3980 28494 : maxatt = attno;
3981 : }
3982 : Assert(maxatt >= 0);
3983 :
3984 : /* push deform steps */
3985 17202 : scratch.opcode = EEOP_INNER_FETCHSOME;
3986 17202 : scratch.d.fetch.last_var = maxatt;
3987 17202 : scratch.d.fetch.fixed = false;
3988 17202 : scratch.d.fetch.known_desc = ldesc;
3989 17202 : scratch.d.fetch.kind = lops;
3990 17202 : if (ExecComputeSlotInfo(state, &scratch))
3991 16200 : ExprEvalPushStep(state, &scratch);
3992 :
3993 17202 : scratch.opcode = EEOP_OUTER_FETCHSOME;
3994 17202 : scratch.d.fetch.last_var = maxatt;
3995 17202 : scratch.d.fetch.fixed = false;
3996 17202 : scratch.d.fetch.known_desc = rdesc;
3997 17202 : scratch.d.fetch.kind = rops;
3998 17202 : if (ExecComputeSlotInfo(state, &scratch))
3999 17202 : ExprEvalPushStep(state, &scratch);
4000 :
4001 : /*
4002 : * Start comparing at the last field (least significant sort key). That's
4003 : * the most likely to be different if we are dealing with sorted input.
4004 : */
4005 45986 : for (int natt = numCols; --natt >= 0;)
4006 : {
4007 28784 : int attno = keyColIdx[natt];
4008 28784 : Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1);
4009 28784 : Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1);
4010 28784 : Oid foid = eqfunctions[natt];
4011 28784 : Oid collid = collations[natt];
4012 : FmgrInfo *finfo;
4013 : FunctionCallInfo fcinfo;
4014 : AclResult aclresult;
4015 :
4016 : /* Check permission to call function */
4017 28784 : aclresult = object_aclcheck(ProcedureRelationId, foid, GetUserId(), ACL_EXECUTE);
4018 28784 : if (aclresult != ACLCHECK_OK)
4019 0 : aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
4020 :
4021 28784 : InvokeFunctionExecuteHook(foid);
4022 :
4023 : /* Set up the primary fmgr lookup information */
4024 28784 : finfo = palloc0(sizeof(FmgrInfo));
4025 28784 : fcinfo = palloc0(SizeForFunctionCallInfo(2));
4026 28784 : fmgr_info(foid, finfo);
4027 28784 : fmgr_info_set_expr(NULL, finfo);
4028 28784 : InitFunctionCallInfoData(*fcinfo, finfo, 2,
4029 : collid, NULL, NULL);
4030 :
4031 : /* left arg */
4032 28784 : scratch.opcode = EEOP_INNER_VAR;
4033 28784 : scratch.d.var.attnum = attno - 1;
4034 28784 : scratch.d.var.vartype = latt->atttypid;
4035 28784 : scratch.resvalue = &fcinfo->args[0].value;
4036 28784 : scratch.resnull = &fcinfo->args[0].isnull;
4037 28784 : ExprEvalPushStep(state, &scratch);
4038 :
4039 : /* right arg */
4040 28784 : scratch.opcode = EEOP_OUTER_VAR;
4041 28784 : scratch.d.var.attnum = attno - 1;
4042 28784 : scratch.d.var.vartype = ratt->atttypid;
4043 28784 : scratch.resvalue = &fcinfo->args[1].value;
4044 28784 : scratch.resnull = &fcinfo->args[1].isnull;
4045 28784 : ExprEvalPushStep(state, &scratch);
4046 :
4047 : /* evaluate distinctness */
4048 28784 : scratch.opcode = EEOP_NOT_DISTINCT;
4049 28784 : scratch.d.func.finfo = finfo;
4050 28784 : scratch.d.func.fcinfo_data = fcinfo;
4051 28784 : scratch.d.func.fn_addr = finfo->fn_addr;
4052 28784 : scratch.d.func.nargs = 2;
4053 28784 : scratch.resvalue = &state->resvalue;
4054 28784 : scratch.resnull = &state->resnull;
4055 28784 : ExprEvalPushStep(state, &scratch);
4056 :
4057 : /* then emit EEOP_QUAL to detect if result is false (or null) */
4058 28784 : scratch.opcode = EEOP_QUAL;
4059 28784 : scratch.d.qualexpr.jumpdone = -1;
4060 28784 : scratch.resvalue = &state->resvalue;
4061 28784 : scratch.resnull = &state->resnull;
4062 28784 : ExprEvalPushStep(state, &scratch);
4063 28784 : adjust_jumps = lappend_int(adjust_jumps,
4064 28784 : state->steps_len - 1);
4065 : }
4066 :
4067 : /* adjust jump targets */
4068 45986 : foreach(lc, adjust_jumps)
4069 : {
4070 28784 : ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4071 :
4072 : Assert(as->opcode == EEOP_QUAL);
4073 : Assert(as->d.qualexpr.jumpdone == -1);
4074 28784 : as->d.qualexpr.jumpdone = state->steps_len;
4075 : }
4076 :
4077 17202 : scratch.resvalue = NULL;
4078 17202 : scratch.resnull = NULL;
4079 17202 : scratch.opcode = EEOP_DONE;
4080 17202 : ExprEvalPushStep(state, &scratch);
4081 :
4082 17202 : ExecReadyExpr(state);
4083 :
4084 17202 : return state;
4085 : }
4086 :
4087 : /*
4088 : * Build equality expression that can be evaluated using ExecQual(), returning
4089 : * true if the expression context's inner/outer tuples are equal. Datums in
4090 : * the inner/outer slots are assumed to be in the same order and quantity as
4091 : * the 'eqfunctions' parameter. NULLs are treated as equal.
4092 : *
4093 : * desc: tuple descriptor of the to-be-compared tuples
4094 : * lops: the slot ops for the inner tuple slots
4095 : * rops: the slot ops for the outer tuple slots
4096 : * eqFunctions: array of function oids of the equality functions to use
4097 : * this must be the same length as the 'param_exprs' list.
4098 : * collations: collation Oids to use for equality comparison. Must be the
4099 : * same length as the 'param_exprs' list.
4100 : * parent: parent executor node
4101 : */
4102 : ExprState *
4103 1368 : ExecBuildParamSetEqual(TupleDesc desc,
4104 : const TupleTableSlotOps *lops,
4105 : const TupleTableSlotOps *rops,
4106 : const Oid *eqfunctions,
4107 : const Oid *collations,
4108 : const List *param_exprs,
4109 : PlanState *parent)
4110 : {
4111 1368 : ExprState *state = makeNode(ExprState);
4112 1368 : ExprEvalStep scratch = {0};
4113 1368 : int maxatt = list_length(param_exprs);
4114 1368 : List *adjust_jumps = NIL;
4115 : ListCell *lc;
4116 :
4117 1368 : state->expr = NULL;
4118 1368 : state->flags = EEO_FLAG_IS_QUAL;
4119 1368 : state->parent = parent;
4120 :
4121 1368 : scratch.resvalue = &state->resvalue;
4122 1368 : scratch.resnull = &state->resnull;
4123 :
4124 : /* push deform steps */
4125 1368 : scratch.opcode = EEOP_INNER_FETCHSOME;
4126 1368 : scratch.d.fetch.last_var = maxatt;
4127 1368 : scratch.d.fetch.fixed = false;
4128 1368 : scratch.d.fetch.known_desc = desc;
4129 1368 : scratch.d.fetch.kind = lops;
4130 1368 : if (ExecComputeSlotInfo(state, &scratch))
4131 1368 : ExprEvalPushStep(state, &scratch);
4132 :
4133 1368 : scratch.opcode = EEOP_OUTER_FETCHSOME;
4134 1368 : scratch.d.fetch.last_var = maxatt;
4135 1368 : scratch.d.fetch.fixed = false;
4136 1368 : scratch.d.fetch.known_desc = desc;
4137 1368 : scratch.d.fetch.kind = rops;
4138 1368 : if (ExecComputeSlotInfo(state, &scratch))
4139 0 : ExprEvalPushStep(state, &scratch);
4140 :
4141 2766 : for (int attno = 0; attno < maxatt; attno++)
4142 : {
4143 1398 : Form_pg_attribute att = TupleDescAttr(desc, attno);
4144 1398 : Oid foid = eqfunctions[attno];
4145 1398 : Oid collid = collations[attno];
4146 : FmgrInfo *finfo;
4147 : FunctionCallInfo fcinfo;
4148 : AclResult aclresult;
4149 :
4150 : /* Check permission to call function */
4151 1398 : aclresult = object_aclcheck(ProcedureRelationId, foid, GetUserId(), ACL_EXECUTE);
4152 1398 : if (aclresult != ACLCHECK_OK)
4153 0 : aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
4154 :
4155 1398 : InvokeFunctionExecuteHook(foid);
4156 :
4157 : /* Set up the primary fmgr lookup information */
4158 1398 : finfo = palloc0(sizeof(FmgrInfo));
4159 1398 : fcinfo = palloc0(SizeForFunctionCallInfo(2));
4160 1398 : fmgr_info(foid, finfo);
4161 1398 : fmgr_info_set_expr(NULL, finfo);
4162 1398 : InitFunctionCallInfoData(*fcinfo, finfo, 2,
4163 : collid, NULL, NULL);
4164 :
4165 : /* left arg */
4166 1398 : scratch.opcode = EEOP_INNER_VAR;
4167 1398 : scratch.d.var.attnum = attno;
4168 1398 : scratch.d.var.vartype = att->atttypid;
4169 1398 : scratch.resvalue = &fcinfo->args[0].value;
4170 1398 : scratch.resnull = &fcinfo->args[0].isnull;
4171 1398 : ExprEvalPushStep(state, &scratch);
4172 :
4173 : /* right arg */
4174 1398 : scratch.opcode = EEOP_OUTER_VAR;
4175 1398 : scratch.d.var.attnum = attno;
4176 1398 : scratch.d.var.vartype = att->atttypid;
4177 1398 : scratch.resvalue = &fcinfo->args[1].value;
4178 1398 : scratch.resnull = &fcinfo->args[1].isnull;
4179 1398 : ExprEvalPushStep(state, &scratch);
4180 :
4181 : /* evaluate distinctness */
4182 1398 : scratch.opcode = EEOP_NOT_DISTINCT;
4183 1398 : scratch.d.func.finfo = finfo;
4184 1398 : scratch.d.func.fcinfo_data = fcinfo;
4185 1398 : scratch.d.func.fn_addr = finfo->fn_addr;
4186 1398 : scratch.d.func.nargs = 2;
4187 1398 : scratch.resvalue = &state->resvalue;
4188 1398 : scratch.resnull = &state->resnull;
4189 1398 : ExprEvalPushStep(state, &scratch);
4190 :
4191 : /* then emit EEOP_QUAL to detect if result is false (or null) */
4192 1398 : scratch.opcode = EEOP_QUAL;
4193 1398 : scratch.d.qualexpr.jumpdone = -1;
4194 1398 : scratch.resvalue = &state->resvalue;
4195 1398 : scratch.resnull = &state->resnull;
4196 1398 : ExprEvalPushStep(state, &scratch);
4197 1398 : adjust_jumps = lappend_int(adjust_jumps,
4198 1398 : state->steps_len - 1);
4199 : }
4200 :
4201 : /* adjust jump targets */
4202 2766 : foreach(lc, adjust_jumps)
4203 : {
4204 1398 : ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4205 :
4206 : Assert(as->opcode == EEOP_QUAL);
4207 : Assert(as->d.qualexpr.jumpdone == -1);
4208 1398 : as->d.qualexpr.jumpdone = state->steps_len;
4209 : }
4210 :
4211 1368 : scratch.resvalue = NULL;
4212 1368 : scratch.resnull = NULL;
4213 1368 : scratch.opcode = EEOP_DONE;
4214 1368 : ExprEvalPushStep(state, &scratch);
4215 :
4216 1368 : ExecReadyExpr(state);
4217 :
4218 1368 : return state;
4219 : }
4220 :
4221 : /*
4222 : * Push steps to evaluate a JsonExpr and its various subsidiary expressions.
4223 : */
4224 : static void
4225 2084 : ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
4226 : Datum *resv, bool *resnull,
4227 : ExprEvalStep *scratch)
4228 : {
4229 2084 : JsonExprState *jsestate = palloc0(sizeof(JsonExprState));
4230 : ListCell *argexprlc;
4231 : ListCell *argnamelc;
4232 2084 : List *jumps_return_null = NIL;
4233 2084 : List *jumps_to_end = NIL;
4234 : ListCell *lc;
4235 2084 : ErrorSaveContext *escontext =
4236 2084 : jsexpr->on_error->btype != JSON_BEHAVIOR_ERROR ?
4237 2084 : &jsestate->escontext : NULL;
4238 :
4239 2084 : jsestate->jsexpr = jsexpr;
4240 :
4241 : /*
4242 : * Evaluate formatted_expr storing the result into
4243 : * jsestate->formatted_expr.
4244 : */
4245 2084 : ExecInitExprRec((Expr *) jsexpr->formatted_expr, state,
4246 : &jsestate->formatted_expr.value,
4247 : &jsestate->formatted_expr.isnull);
4248 :
4249 : /* JUMP to return NULL if formatted_expr evaluates to NULL */
4250 2084 : jumps_return_null = lappend_int(jumps_return_null, state->steps_len);
4251 2084 : scratch->opcode = EEOP_JUMP_IF_NULL;
4252 2084 : scratch->resnull = &jsestate->formatted_expr.isnull;
4253 2084 : scratch->d.jump.jumpdone = -1; /* set below */
4254 2084 : ExprEvalPushStep(state, scratch);
4255 :
4256 : /*
4257 : * Evaluate pathspec expression storing the result into
4258 : * jsestate->pathspec.
4259 : */
4260 2084 : ExecInitExprRec((Expr *) jsexpr->path_spec, state,
4261 : &jsestate->pathspec.value,
4262 : &jsestate->pathspec.isnull);
4263 :
4264 : /* JUMP to return NULL if path_spec evaluates to NULL */
4265 2084 : jumps_return_null = lappend_int(jumps_return_null, state->steps_len);
4266 2084 : scratch->opcode = EEOP_JUMP_IF_NULL;
4267 2084 : scratch->resnull = &jsestate->pathspec.isnull;
4268 2084 : scratch->d.jump.jumpdone = -1; /* set below */
4269 2084 : ExprEvalPushStep(state, scratch);
4270 :
4271 : /* Steps to compute PASSING args. */
4272 2084 : jsestate->args = NIL;
4273 2972 : forboth(argexprlc, jsexpr->passing_values,
4274 : argnamelc, jsexpr->passing_names)
4275 : {
4276 888 : Expr *argexpr = (Expr *) lfirst(argexprlc);
4277 888 : String *argname = lfirst_node(String, argnamelc);
4278 888 : JsonPathVariable *var = palloc(sizeof(*var));
4279 :
4280 888 : var->name = argname->sval;
4281 888 : var->typid = exprType((Node *) argexpr);
4282 888 : var->typmod = exprTypmod((Node *) argexpr);
4283 :
4284 888 : ExecInitExprRec((Expr *) argexpr, state, &var->value, &var->isnull);
4285 :
4286 888 : jsestate->args = lappend(jsestate->args, var);
4287 : }
4288 :
4289 : /* Step for jsonpath evaluation; see ExecEvalJsonExprPath(). */
4290 2084 : scratch->opcode = EEOP_JSONEXPR_PATH;
4291 2084 : scratch->resvalue = resv;
4292 2084 : scratch->resnull = resnull;
4293 2084 : scratch->d.jsonexpr.jsestate = jsestate;
4294 2084 : ExprEvalPushStep(state, scratch);
4295 :
4296 : /*
4297 : * Step to return NULL after jumping to skip the EEOP_JSONEXPR_PATH step
4298 : * when either formatted_expr or pathspec is NULL. Adjust jump target
4299 : * addresses of JUMPs that we added above.
4300 : */
4301 6252 : foreach(lc, jumps_return_null)
4302 : {
4303 4168 : ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4304 :
4305 4168 : as->d.jump.jumpdone = state->steps_len;
4306 : }
4307 2084 : scratch->opcode = EEOP_CONST;
4308 2084 : scratch->resvalue = resv;
4309 2084 : scratch->resnull = resnull;
4310 2084 : scratch->d.constval.value = (Datum) 0;
4311 2084 : scratch->d.constval.isnull = true;
4312 2084 : ExprEvalPushStep(state, scratch);
4313 :
4314 : /*
4315 : * Jump to coerce the NULL using coercion_expr if present. Coercing NULL
4316 : * is only interesting when the RETURNING type is a domain whose
4317 : * constraints must be checked. jsexpr->coercion_expr containing a
4318 : * CoerceToDomain node must have been set in that case.
4319 : */
4320 2084 : if (jsexpr->coercion_expr)
4321 : {
4322 522 : scratch->opcode = EEOP_JUMP;
4323 522 : scratch->d.jump.jumpdone = state->steps_len + 1;
4324 522 : ExprEvalPushStep(state, scratch);
4325 : }
4326 :
4327 : /*
4328 : * To handle coercion errors softly, use the following ErrorSaveContext to
4329 : * pass to ExecInitExprRec() when initializing the coercion expressions
4330 : * and in the EEOP_JSONEXPR_COERCION step.
4331 : */
4332 2084 : jsestate->escontext.type = T_ErrorSaveContext;
4333 :
4334 : /*
4335 : * Steps to coerce the result value computed by EEOP_JSONEXPR_PATH or the
4336 : * NULL returned on NULL input as described above.
4337 : */
4338 2084 : jsestate->jump_eval_coercion = -1;
4339 2084 : if (jsexpr->coercion_expr)
4340 : {
4341 : Datum *save_innermost_caseval;
4342 : bool *save_innermost_casenull;
4343 : ErrorSaveContext *save_escontext;
4344 :
4345 522 : jsestate->jump_eval_coercion = state->steps_len;
4346 :
4347 522 : save_innermost_caseval = state->innermost_caseval;
4348 522 : save_innermost_casenull = state->innermost_casenull;
4349 522 : save_escontext = state->escontext;
4350 :
4351 522 : state->innermost_caseval = resv;
4352 522 : state->innermost_casenull = resnull;
4353 522 : state->escontext = escontext;
4354 :
4355 522 : ExecInitExprRec((Expr *) jsexpr->coercion_expr, state, resv, resnull);
4356 :
4357 522 : state->innermost_caseval = save_innermost_caseval;
4358 522 : state->innermost_casenull = save_innermost_casenull;
4359 522 : state->escontext = save_escontext;
4360 : }
4361 1562 : else if (jsexpr->use_json_coercion)
4362 : {
4363 534 : jsestate->jump_eval_coercion = state->steps_len;
4364 :
4365 534 : ExecInitJsonCoercion(state, jsexpr->returning, escontext, resv, resnull);
4366 : }
4367 1028 : else if (jsexpr->use_io_coercion)
4368 : {
4369 : /*
4370 : * Here we only need to initialize the FunctionCallInfo for the target
4371 : * type's input function, which is called by ExecEvalJsonExprPath()
4372 : * itself, so no additional step is necessary.
4373 : */
4374 : Oid typinput;
4375 : Oid typioparam;
4376 : FmgrInfo *finfo;
4377 : FunctionCallInfo fcinfo;
4378 :
4379 818 : getTypeInputInfo(jsexpr->returning->typid, &typinput, &typioparam);
4380 818 : finfo = palloc0(sizeof(FmgrInfo));
4381 818 : fcinfo = palloc0(SizeForFunctionCallInfo(3));
4382 818 : fmgr_info(typinput, finfo);
4383 818 : fmgr_info_set_expr((Node *) jsexpr->returning, finfo);
4384 818 : InitFunctionCallInfoData(*fcinfo, finfo, 3, InvalidOid, NULL, NULL);
4385 :
4386 : /*
4387 : * We can preload the second and third arguments for the input
4388 : * function, since they're constants.
4389 : */
4390 818 : fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
4391 818 : fcinfo->args[1].isnull = false;
4392 818 : fcinfo->args[2].value = Int32GetDatum(jsexpr->returning->typmod);
4393 818 : fcinfo->args[2].isnull = false;
4394 818 : fcinfo->context = (Node *) escontext;
4395 :
4396 818 : jsestate->input_fcinfo = fcinfo;
4397 : }
4398 :
4399 : /*
4400 : * Add a special step, if needed, to check if the coercion evaluation ran
4401 : * into an error but was not thrown because the ON ERROR behavior is not
4402 : * ERROR. It will set jsestate->error if an error did occur.
4403 : */
4404 2084 : if (jsestate->jump_eval_coercion >= 0 && escontext != NULL)
4405 : {
4406 900 : scratch->opcode = EEOP_JSONEXPR_COERCION_FINISH;
4407 900 : scratch->d.jsonexpr.jsestate = jsestate;
4408 900 : ExprEvalPushStep(state, scratch);
4409 : }
4410 :
4411 2084 : jsestate->jump_empty = jsestate->jump_error = -1;
4412 :
4413 : /*
4414 : * Step to check jsestate->error and return the ON ERROR expression if
4415 : * there is one. This handles both the errors that occur during jsonpath
4416 : * evaluation in EEOP_JSONEXPR_PATH and subsequent coercion evaluation.
4417 : */
4418 2084 : if (jsexpr->on_error &&
4419 2084 : jsexpr->on_error->btype != JSON_BEHAVIOR_ERROR)
4420 : {
4421 1748 : jsestate->jump_error = state->steps_len;
4422 :
4423 : /* JUMP to end if false, that is, skip the ON ERROR expression. */
4424 1748 : jumps_to_end = lappend_int(jumps_to_end, state->steps_len);
4425 1748 : scratch->opcode = EEOP_JUMP_IF_NOT_TRUE;
4426 1748 : scratch->resvalue = &jsestate->error.value;
4427 1748 : scratch->resnull = &jsestate->error.isnull;
4428 1748 : scratch->d.jump.jumpdone = -1; /* set below */
4429 1748 : ExprEvalPushStep(state, scratch);
4430 :
4431 : /* Steps to evaluate the ON ERROR expression */
4432 1748 : ExecInitExprRec((Expr *) jsexpr->on_error->expr,
4433 : state, resv, resnull);
4434 :
4435 : /* Step to coerce the ON ERROR expression if needed */
4436 1748 : if (jsexpr->on_error->coerce)
4437 1304 : ExecInitJsonCoercion(state, jsexpr->returning, escontext, resv,
4438 : resnull);
4439 :
4440 : /* JUMP to end to skip the ON EMPTY steps added below. */
4441 1748 : jumps_to_end = lappend_int(jumps_to_end, state->steps_len);
4442 1748 : scratch->opcode = EEOP_JUMP;
4443 1748 : scratch->d.jump.jumpdone = -1;
4444 1748 : ExprEvalPushStep(state, scratch);
4445 : }
4446 :
4447 : /*
4448 : * Step to check jsestate->empty and return the ON EMPTY expression if
4449 : * there is one.
4450 : */
4451 2084 : if (jsexpr->on_empty != NULL &&
4452 264 : jsexpr->on_empty->btype != JSON_BEHAVIOR_ERROR)
4453 : {
4454 204 : jsestate->jump_empty = state->steps_len;
4455 :
4456 : /* JUMP to end if false, that is, skip the ON EMPTY expression. */
4457 204 : jumps_to_end = lappend_int(jumps_to_end, state->steps_len);
4458 204 : scratch->opcode = EEOP_JUMP_IF_NOT_TRUE;
4459 204 : scratch->resvalue = &jsestate->empty.value;
4460 204 : scratch->resnull = &jsestate->empty.isnull;
4461 204 : scratch->d.jump.jumpdone = -1; /* set below */
4462 204 : ExprEvalPushStep(state, scratch);
4463 :
4464 : /* Steps to evaluate the ON EMPTY expression */
4465 204 : ExecInitExprRec((Expr *) jsexpr->on_empty->expr,
4466 : state, resv, resnull);
4467 :
4468 : /* Step to coerce the ON EMPTY expression if needed */
4469 204 : if (jsexpr->on_empty->coerce)
4470 18 : ExecInitJsonCoercion(state, jsexpr->returning, escontext, resv,
4471 : resnull);
4472 : }
4473 :
4474 5784 : foreach(lc, jumps_to_end)
4475 : {
4476 3700 : ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4477 :
4478 3700 : as->d.jump.jumpdone = state->steps_len;
4479 : }
4480 :
4481 2084 : jsestate->jump_end = state->steps_len;
4482 2084 : }
4483 :
4484 : /*
4485 : * Initialize a EEOP_JSONEXPR_COERCION step to coerce the value given in resv
4486 : * to the given RETURNING type.
4487 : */
4488 : static void
4489 1856 : ExecInitJsonCoercion(ExprState *state, JsonReturning *returning,
4490 : ErrorSaveContext *escontext,
4491 : Datum *resv, bool *resnull)
4492 : {
4493 1856 : ExprEvalStep scratch = {0};
4494 :
4495 : /* For json_populate_type() */
4496 1856 : scratch.opcode = EEOP_JSONEXPR_COERCION;
4497 1856 : scratch.resvalue = resv;
4498 1856 : scratch.resnull = resnull;
4499 1856 : scratch.d.jsonexpr_coercion.targettype = returning->typid;
4500 1856 : scratch.d.jsonexpr_coercion.targettypmod = returning->typmod;
4501 1856 : scratch.d.jsonexpr_coercion.json_populate_type_cache = NULL;
4502 1856 : scratch.d.jsonexpr_coercion.escontext = escontext;
4503 1856 : ExprEvalPushStep(state, &scratch);
4504 1856 : }
|