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-2019, 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_type.h"
36 #include "executor/execExpr.h"
37 #include "executor/nodeSubplan.h"
38 #include "funcapi.h"
39 #include "jit/jit.h"
40 #include "miscadmin.h"
41 #include "nodes/makefuncs.h"
42 #include "nodes/nodeFuncs.h"
43 #include "optimizer/optimizer.h"
44 #include "pgstat.h"
45 #include "utils/builtins.h"
46 #include "utils/datum.h"
47 #include "utils/lsyscache.h"
48 #include "utils/typcache.h"
49
50
51 typedef struct LastAttnumInfo
52 {
53 AttrNumber last_inner;
54 AttrNumber last_outer;
55 AttrNumber last_scan;
56 } LastAttnumInfo;
57
58 static void ExecReadyExpr(ExprState *state);
59 static void ExecInitExprRec(Expr *node, ExprState *state,
60 Datum *resv, bool *resnull);
61 static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args,
62 Oid funcid, Oid inputcollid,
63 ExprState *state);
64 static void ExecInitExprSlots(ExprState *state, Node *node);
65 static void ExecPushExprSlots(ExprState *state, LastAttnumInfo *info);
66 static bool get_last_attnums_walker(Node *node, LastAttnumInfo *info);
67 static void ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op);
68 static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable,
69 ExprState *state);
70 static void ExecInitSubscriptingRef(ExprEvalStep *scratch,
71 SubscriptingRef *sbsref,
72 ExprState *state,
73 Datum *resv, bool *resnull);
74 static bool isAssignmentIndirectionExpr(Expr *expr);
75 static void ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
76 ExprState *state,
77 Datum *resv, bool *resnull);
78 static void ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
79 ExprEvalStep *scratch,
80 FunctionCallInfo fcinfo, AggStatePerTrans pertrans,
81 int transno, int setno, int setoff, bool ishash);
82
83
84 /*
85 * ExecInitExpr: prepare an expression tree for execution
86 *
87 * This function builds and returns an ExprState implementing the given
88 * Expr node tree. The return ExprState can then be handed to ExecEvalExpr
89 * for execution. Because the Expr tree itself is read-only as far as
90 * ExecInitExpr and ExecEvalExpr are concerned, several different executions
91 * of the same plan tree can occur concurrently. (But note that an ExprState
92 * does mutate at runtime, so it can't be re-used concurrently.)
93 *
94 * This must be called in a memory context that will last as long as repeated
95 * executions of the expression are needed. Typically the context will be
96 * the same as the per-query context of the associated ExprContext.
97 *
98 * Any Aggref, WindowFunc, or SubPlan nodes found in the tree are added to
99 * the lists of such nodes held by the parent PlanState (or more accurately,
100 * the AggrefExprState etc. nodes created for them are added).
101 *
102 * Note: there is no ExecEndExpr function; we assume that any resource
103 * cleanup needed will be handled by just releasing the memory context
104 * in which the state tree is built. Functions that require additional
105 * cleanup work can register a shutdown callback in the ExprContext.
106 *
107 * 'node' is the root of the expression tree to compile.
108 * 'parent' is the PlanState node that owns the expression.
109 *
110 * 'parent' may be NULL if we are preparing an expression that is not
111 * associated with a plan tree. (If so, it can't have aggs or subplans.)
112 * Such cases should usually come through ExecPrepareExpr, not directly here.
113 *
114 * Also, if 'node' is NULL, we just return NULL. This is convenient for some
115 * callers that may or may not have an expression that needs to be compiled.
116 * Note that a NULL ExprState pointer *cannot* be handed to ExecEvalExpr,
117 * although ExecQual and ExecCheck will accept one (and treat it as "true").
118 */
119 ExprState *
ExecInitExpr(Expr * node,PlanState * parent)120 ExecInitExpr(Expr *node, PlanState *parent)
121 {
122 ExprState *state;
123 ExprEvalStep scratch = {0};
124
125 /* Special case: NULL expression produces a NULL ExprState pointer */
126 if (node == NULL)
127 return NULL;
128
129 /* Initialize ExprState with empty step list */
130 state = makeNode(ExprState);
131 state->expr = node;
132 state->parent = parent;
133 state->ext_params = NULL;
134
135 /* Insert EEOP_*_FETCHSOME steps as needed */
136 ExecInitExprSlots(state, (Node *) node);
137
138 /* Compile the expression proper */
139 ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
140
141 /* Finally, append a DONE step */
142 scratch.opcode = EEOP_DONE;
143 ExprEvalPushStep(state, &scratch);
144
145 ExecReadyExpr(state);
146
147 return state;
148 }
149
150 /*
151 * ExecInitExprWithParams: prepare a standalone expression tree for execution
152 *
153 * This is the same as ExecInitExpr, except that there is no parent PlanState,
154 * and instead we may have a ParamListInfo describing PARAM_EXTERN Params.
155 */
156 ExprState *
ExecInitExprWithParams(Expr * node,ParamListInfo ext_params)157 ExecInitExprWithParams(Expr *node, ParamListInfo ext_params)
158 {
159 ExprState *state;
160 ExprEvalStep scratch = {0};
161
162 /* Special case: NULL expression produces a NULL ExprState pointer */
163 if (node == NULL)
164 return NULL;
165
166 /* Initialize ExprState with empty step list */
167 state = makeNode(ExprState);
168 state->expr = node;
169 state->parent = NULL;
170 state->ext_params = ext_params;
171
172 /* Insert EEOP_*_FETCHSOME steps as needed */
173 ExecInitExprSlots(state, (Node *) node);
174
175 /* Compile the expression proper */
176 ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
177
178 /* Finally, append a DONE step */
179 scratch.opcode = EEOP_DONE;
180 ExprEvalPushStep(state, &scratch);
181
182 ExecReadyExpr(state);
183
184 return state;
185 }
186
187 /*
188 * ExecInitQual: prepare a qual for execution by ExecQual
189 *
190 * Prepares for the evaluation of a conjunctive boolean expression (qual list
191 * with implicit AND semantics) that returns true if none of the
192 * subexpressions are false.
193 *
194 * We must return true if the list is empty. Since that's a very common case,
195 * we optimize it a bit further by translating to a NULL ExprState pointer
196 * rather than setting up an ExprState that computes constant TRUE. (Some
197 * especially hot-spot callers of ExecQual detect this and avoid calling
198 * ExecQual at all.)
199 *
200 * If any of the subexpressions yield NULL, then the result of the conjunction
201 * is false. This makes ExecQual primarily useful for evaluating WHERE
202 * clauses, since SQL specifies that tuples with null WHERE results do not
203 * get selected.
204 */
205 ExprState *
ExecInitQual(List * qual,PlanState * parent)206 ExecInitQual(List *qual, PlanState *parent)
207 {
208 ExprState *state;
209 ExprEvalStep scratch = {0};
210 List *adjust_jumps = NIL;
211 ListCell *lc;
212
213 /* short-circuit (here and in ExecQual) for empty restriction list */
214 if (qual == NIL)
215 return NULL;
216
217 Assert(IsA(qual, List));
218
219 state = makeNode(ExprState);
220 state->expr = (Expr *) qual;
221 state->parent = parent;
222 state->ext_params = NULL;
223
224 /* mark expression as to be used with ExecQual() */
225 state->flags = EEO_FLAG_IS_QUAL;
226
227 /* Insert EEOP_*_FETCHSOME steps as needed */
228 ExecInitExprSlots(state, (Node *) qual);
229
230 /*
231 * ExecQual() needs to return false for an expression returning NULL. That
232 * allows us to short-circuit the evaluation the first time a NULL is
233 * encountered. As qual evaluation is a hot-path this warrants using a
234 * special opcode for qual evaluation that's simpler than BOOL_AND (which
235 * has more complex NULL handling).
236 */
237 scratch.opcode = EEOP_QUAL;
238
239 /*
240 * We can use ExprState's resvalue/resnull as target for each qual expr.
241 */
242 scratch.resvalue = &state->resvalue;
243 scratch.resnull = &state->resnull;
244
245 foreach(lc, qual)
246 {
247 Expr *node = (Expr *) lfirst(lc);
248
249 /* first evaluate expression */
250 ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
251
252 /* then emit EEOP_QUAL to detect if it's false (or null) */
253 scratch.d.qualexpr.jumpdone = -1;
254 ExprEvalPushStep(state, &scratch);
255 adjust_jumps = lappend_int(adjust_jumps,
256 state->steps_len - 1);
257 }
258
259 /* adjust jump targets */
260 foreach(lc, adjust_jumps)
261 {
262 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
263
264 Assert(as->opcode == EEOP_QUAL);
265 Assert(as->d.qualexpr.jumpdone == -1);
266 as->d.qualexpr.jumpdone = state->steps_len;
267 }
268
269 /*
270 * At the end, we don't need to do anything more. The last qual expr must
271 * have yielded TRUE, and since its result is stored in the desired output
272 * location, we're done.
273 */
274 scratch.opcode = EEOP_DONE;
275 ExprEvalPushStep(state, &scratch);
276
277 ExecReadyExpr(state);
278
279 return state;
280 }
281
282 /*
283 * ExecInitCheck: prepare a check constraint for execution by ExecCheck
284 *
285 * This is much like ExecInitQual/ExecQual, except that a null result from
286 * the conjunction is treated as TRUE. This behavior is appropriate for
287 * evaluating CHECK constraints, since SQL specifies that NULL constraint
288 * conditions are not failures.
289 *
290 * Note that like ExecInitQual, this expects input in implicit-AND format.
291 * Users of ExecCheck that have expressions in normal explicit-AND format
292 * can just apply ExecInitExpr to produce suitable input for ExecCheck.
293 */
294 ExprState *
ExecInitCheck(List * qual,PlanState * parent)295 ExecInitCheck(List *qual, PlanState *parent)
296 {
297 /* short-circuit (here and in ExecCheck) for empty restriction list */
298 if (qual == NIL)
299 return NULL;
300
301 Assert(IsA(qual, List));
302
303 /*
304 * Just convert the implicit-AND list to an explicit AND (if there's more
305 * than one entry), and compile normally. Unlike ExecQual, we can't
306 * short-circuit on NULL results, so the regular AND behavior is needed.
307 */
308 return ExecInitExpr(make_ands_explicit(qual), parent);
309 }
310
311 /*
312 * Call ExecInitExpr() on a list of expressions, return a list of ExprStates.
313 */
314 List *
ExecInitExprList(List * nodes,PlanState * parent)315 ExecInitExprList(List *nodes, PlanState *parent)
316 {
317 List *result = NIL;
318 ListCell *lc;
319
320 foreach(lc, nodes)
321 {
322 Expr *e = lfirst(lc);
323
324 result = lappend(result, ExecInitExpr(e, parent));
325 }
326
327 return result;
328 }
329
330 /*
331 * ExecBuildProjectionInfo
332 *
333 * Build a ProjectionInfo node for evaluating the given tlist in the given
334 * econtext, and storing the result into the tuple slot. (Caller must have
335 * ensured that tuple slot has a descriptor matching the tlist!)
336 *
337 * inputDesc can be NULL, but if it is not, we check to see whether simple
338 * Vars in the tlist match the descriptor. It is important to provide
339 * inputDesc for relation-scan plan nodes, as a cross check that the relation
340 * hasn't been changed since the plan was made. At higher levels of a plan,
341 * there is no need to recheck.
342 *
343 * This is implemented by internally building an ExprState that performs the
344 * whole projection in one go.
345 *
346 * Caution: before PG v10, the targetList was a list of ExprStates; now it
347 * should be the planner-created targetlist, since we do the compilation here.
348 */
349 ProjectionInfo *
ExecBuildProjectionInfo(List * targetList,ExprContext * econtext,TupleTableSlot * slot,PlanState * parent,TupleDesc inputDesc)350 ExecBuildProjectionInfo(List *targetList,
351 ExprContext *econtext,
352 TupleTableSlot *slot,
353 PlanState *parent,
354 TupleDesc inputDesc)
355 {
356 return ExecBuildProjectionInfoExt(targetList,
357 econtext,
358 slot,
359 true,
360 parent,
361 inputDesc);
362 }
363
364 /*
365 * ExecBuildProjectionInfoExt
366 *
367 * As above, with one additional option.
368 *
369 * If assignJunkEntries is true (the usual case), resjunk entries in the tlist
370 * are not handled specially: they are evaluated and assigned to the proper
371 * column of the result slot. If assignJunkEntries is false, resjunk entries
372 * are evaluated, but their result is discarded without assignment.
373 */
374 ProjectionInfo *
ExecBuildProjectionInfoExt(List * targetList,ExprContext * econtext,TupleTableSlot * slot,bool assignJunkEntries,PlanState * parent,TupleDesc inputDesc)375 ExecBuildProjectionInfoExt(List *targetList,
376 ExprContext *econtext,
377 TupleTableSlot *slot,
378 bool assignJunkEntries,
379 PlanState *parent,
380 TupleDesc inputDesc)
381 {
382 ProjectionInfo *projInfo = makeNode(ProjectionInfo);
383 ExprState *state;
384 ExprEvalStep scratch = {0};
385 ListCell *lc;
386
387 projInfo->pi_exprContext = econtext;
388 /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
389 projInfo->pi_state.tag.type = T_ExprState;
390 state = &projInfo->pi_state;
391 state->expr = (Expr *) targetList;
392 state->parent = parent;
393 state->ext_params = NULL;
394
395 state->resultslot = slot;
396
397 /* Insert EEOP_*_FETCHSOME steps as needed */
398 ExecInitExprSlots(state, (Node *) targetList);
399
400 /* Now compile each tlist column */
401 foreach(lc, targetList)
402 {
403 TargetEntry *tle = lfirst_node(TargetEntry, lc);
404 Var *variable = NULL;
405 AttrNumber attnum = 0;
406 bool isSafeVar = false;
407
408 /*
409 * If tlist expression is a safe non-system Var, use the fast-path
410 * ASSIGN_*_VAR opcodes. "Safe" means that we don't need to apply
411 * CheckVarSlotCompatibility() during plan startup. If a source slot
412 * was provided, we make the equivalent tests here; if a slot was not
413 * provided, we assume that no check is needed because we're dealing
414 * with a non-relation-scan-level expression.
415 */
416 if (tle->expr != NULL &&
417 IsA(tle->expr, Var) &&
418 ((Var *) tle->expr)->varattno > 0 &&
419 (assignJunkEntries || !tle->resjunk))
420 {
421 /* Non-system Var, but how safe is it? */
422 variable = (Var *) tle->expr;
423 attnum = variable->varattno;
424
425 if (inputDesc == NULL)
426 isSafeVar = true; /* can't check, just assume OK */
427 else if (attnum <= inputDesc->natts)
428 {
429 Form_pg_attribute attr = TupleDescAttr(inputDesc, attnum - 1);
430
431 /*
432 * If user attribute is dropped or has a type mismatch, don't
433 * use ASSIGN_*_VAR. Instead let the normal expression
434 * machinery handle it (which'll possibly error out).
435 */
436 if (!attr->attisdropped && variable->vartype == attr->atttypid)
437 {
438 isSafeVar = true;
439 }
440 }
441 }
442
443 if (isSafeVar)
444 {
445 /* Fast-path: just generate an EEOP_ASSIGN_*_VAR step */
446 switch (variable->varno)
447 {
448 case INNER_VAR:
449 /* get the tuple from the inner node */
450 scratch.opcode = EEOP_ASSIGN_INNER_VAR;
451 break;
452
453 case OUTER_VAR:
454 /* get the tuple from the outer node */
455 scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
456 break;
457
458 /* INDEX_VAR is handled by default case */
459
460 default:
461 /* get the tuple from the relation being scanned */
462 scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
463 break;
464 }
465
466 scratch.d.assign_var.attnum = attnum - 1;
467 scratch.d.assign_var.resultnum = tle->resno - 1;
468 ExprEvalPushStep(state, &scratch);
469 }
470 else
471 {
472 /*
473 * Otherwise, compile the column expression normally.
474 *
475 * We can't tell the expression to evaluate directly into the
476 * result slot, as the result slot (and the exprstate for that
477 * matter) can change between executions. We instead evaluate
478 * into the ExprState's resvalue/resnull and then move.
479 */
480 ExecInitExprRec(tle->expr, state,
481 &state->resvalue, &state->resnull);
482
483 /* This makes it easy to discard resjunk results when told to. */
484 if (!assignJunkEntries && tle->resjunk)
485 continue;
486
487 /*
488 * Column might be referenced multiple times in upper nodes, so
489 * force value to R/O - but only if it could be an expanded datum.
490 */
491 if (get_typlen(exprType((Node *) tle->expr)) == -1)
492 scratch.opcode = EEOP_ASSIGN_TMP_MAKE_RO;
493 else
494 scratch.opcode = EEOP_ASSIGN_TMP;
495 scratch.d.assign_tmp.resultnum = tle->resno - 1;
496 ExprEvalPushStep(state, &scratch);
497 }
498 }
499
500 scratch.opcode = EEOP_DONE;
501 ExprEvalPushStep(state, &scratch);
502
503 ExecReadyExpr(state);
504
505 return projInfo;
506 }
507
508 /*
509 * ExecPrepareExpr --- initialize for expression execution outside a normal
510 * Plan tree context.
511 *
512 * This differs from ExecInitExpr in that we don't assume the caller is
513 * already running in the EState's per-query context. Also, we run the
514 * passed expression tree through expression_planner() to prepare it for
515 * execution. (In ordinary Plan trees the regular planning process will have
516 * made the appropriate transformations on expressions, but for standalone
517 * expressions this won't have happened.)
518 */
519 ExprState *
ExecPrepareExpr(Expr * node,EState * estate)520 ExecPrepareExpr(Expr *node, EState *estate)
521 {
522 ExprState *result;
523 MemoryContext oldcontext;
524
525 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
526
527 node = expression_planner(node);
528
529 result = ExecInitExpr(node, NULL);
530
531 MemoryContextSwitchTo(oldcontext);
532
533 return result;
534 }
535
536 /*
537 * ExecPrepareQual --- initialize for qual execution outside a normal
538 * Plan tree context.
539 *
540 * This differs from ExecInitQual in that we don't assume the caller is
541 * already running in the EState's per-query context. Also, we run the
542 * passed expression tree through expression_planner() to prepare it for
543 * execution. (In ordinary Plan trees the regular planning process will have
544 * made the appropriate transformations on expressions, but for standalone
545 * expressions this won't have happened.)
546 */
547 ExprState *
ExecPrepareQual(List * qual,EState * estate)548 ExecPrepareQual(List *qual, EState *estate)
549 {
550 ExprState *result;
551 MemoryContext oldcontext;
552
553 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
554
555 qual = (List *) expression_planner((Expr *) qual);
556
557 result = ExecInitQual(qual, NULL);
558
559 MemoryContextSwitchTo(oldcontext);
560
561 return result;
562 }
563
564 /*
565 * ExecPrepareCheck -- initialize check constraint for execution outside a
566 * normal Plan tree context.
567 *
568 * See ExecPrepareExpr() and ExecInitCheck() for details.
569 */
570 ExprState *
ExecPrepareCheck(List * qual,EState * estate)571 ExecPrepareCheck(List *qual, EState *estate)
572 {
573 ExprState *result;
574 MemoryContext oldcontext;
575
576 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
577
578 qual = (List *) expression_planner((Expr *) qual);
579
580 result = ExecInitCheck(qual, NULL);
581
582 MemoryContextSwitchTo(oldcontext);
583
584 return result;
585 }
586
587 /*
588 * Call ExecPrepareExpr() on each member of a list of Exprs, and return
589 * a list of ExprStates.
590 *
591 * See ExecPrepareExpr() for details.
592 */
593 List *
ExecPrepareExprList(List * nodes,EState * estate)594 ExecPrepareExprList(List *nodes, EState *estate)
595 {
596 List *result = NIL;
597 MemoryContext oldcontext;
598 ListCell *lc;
599
600 /* Ensure that the list cell nodes are in the right context too */
601 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
602
603 foreach(lc, nodes)
604 {
605 Expr *e = (Expr *) lfirst(lc);
606
607 result = lappend(result, ExecPrepareExpr(e, estate));
608 }
609
610 MemoryContextSwitchTo(oldcontext);
611
612 return result;
613 }
614
615 /*
616 * ExecCheck - evaluate a check constraint
617 *
618 * For check constraints, a null result is taken as TRUE, ie the constraint
619 * passes.
620 *
621 * The check constraint may have been prepared with ExecInitCheck
622 * (possibly via ExecPrepareCheck) if the caller had it in implicit-AND
623 * format, but a regular boolean expression prepared with ExecInitExpr or
624 * ExecPrepareExpr works too.
625 */
626 bool
ExecCheck(ExprState * state,ExprContext * econtext)627 ExecCheck(ExprState *state, ExprContext *econtext)
628 {
629 Datum ret;
630 bool isnull;
631
632 /* short-circuit (here and in ExecInitCheck) for empty restriction list */
633 if (state == NULL)
634 return true;
635
636 /* verify that expression was not compiled using ExecInitQual */
637 Assert(!(state->flags & EEO_FLAG_IS_QUAL));
638
639 ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
640
641 if (isnull)
642 return true;
643
644 return DatumGetBool(ret);
645 }
646
647 /*
648 * Prepare a compiled expression for execution. This has to be called for
649 * every ExprState before it can be executed.
650 *
651 * NB: While this currently only calls ExecReadyInterpretedExpr(),
652 * this will likely get extended to further expression evaluation methods.
653 * Therefore this should be used instead of directly calling
654 * ExecReadyInterpretedExpr().
655 */
656 static void
ExecReadyExpr(ExprState * state)657 ExecReadyExpr(ExprState *state)
658 {
659 if (jit_compile_expr(state))
660 return;
661
662 ExecReadyInterpretedExpr(state);
663 }
664
665 /*
666 * Append the steps necessary for the evaluation of node to ExprState->steps,
667 * possibly recursing into sub-expressions of node.
668 *
669 * node - expression to evaluate
670 * state - ExprState to whose ->steps to append the necessary operations
671 * resv / resnull - where to store the result of the node into
672 */
673 static void
ExecInitExprRec(Expr * node,ExprState * state,Datum * resv,bool * resnull)674 ExecInitExprRec(Expr *node, ExprState *state,
675 Datum *resv, bool *resnull)
676 {
677 ExprEvalStep scratch = {0};
678
679 /* Guard against stack overflow due to overly complex expressions */
680 check_stack_depth();
681
682 /* Step's output location is always what the caller gave us */
683 Assert(resv != NULL && resnull != NULL);
684 scratch.resvalue = resv;
685 scratch.resnull = resnull;
686
687 /* cases should be ordered as they are in enum NodeTag */
688 switch (nodeTag(node))
689 {
690 case T_Var:
691 {
692 Var *variable = (Var *) node;
693
694 if (variable->varattno == InvalidAttrNumber)
695 {
696 /* whole-row Var */
697 ExecInitWholeRowVar(&scratch, variable, state);
698 }
699 else if (variable->varattno <= 0)
700 {
701 /* system column */
702 scratch.d.var.attnum = variable->varattno;
703 scratch.d.var.vartype = variable->vartype;
704 switch (variable->varno)
705 {
706 case INNER_VAR:
707 scratch.opcode = EEOP_INNER_SYSVAR;
708 break;
709 case OUTER_VAR:
710 scratch.opcode = EEOP_OUTER_SYSVAR;
711 break;
712
713 /* INDEX_VAR is handled by default case */
714
715 default:
716 scratch.opcode = EEOP_SCAN_SYSVAR;
717 break;
718 }
719 }
720 else
721 {
722 /* regular user column */
723 scratch.d.var.attnum = variable->varattno - 1;
724 scratch.d.var.vartype = variable->vartype;
725 switch (variable->varno)
726 {
727 case INNER_VAR:
728 scratch.opcode = EEOP_INNER_VAR;
729 break;
730 case OUTER_VAR:
731 scratch.opcode = EEOP_OUTER_VAR;
732 break;
733
734 /* INDEX_VAR is handled by default case */
735
736 default:
737 scratch.opcode = EEOP_SCAN_VAR;
738 break;
739 }
740 }
741
742 ExprEvalPushStep(state, &scratch);
743 break;
744 }
745
746 case T_Const:
747 {
748 Const *con = (Const *) node;
749
750 scratch.opcode = EEOP_CONST;
751 scratch.d.constval.value = con->constvalue;
752 scratch.d.constval.isnull = con->constisnull;
753
754 ExprEvalPushStep(state, &scratch);
755 break;
756 }
757
758 case T_Param:
759 {
760 Param *param = (Param *) node;
761 ParamListInfo params;
762
763 switch (param->paramkind)
764 {
765 case PARAM_EXEC:
766 scratch.opcode = EEOP_PARAM_EXEC;
767 scratch.d.param.paramid = param->paramid;
768 scratch.d.param.paramtype = param->paramtype;
769 ExprEvalPushStep(state, &scratch);
770 break;
771 case PARAM_EXTERN:
772
773 /*
774 * If we have a relevant ParamCompileHook, use it;
775 * otherwise compile a standard EEOP_PARAM_EXTERN
776 * step. ext_params, if supplied, takes precedence
777 * over info from the parent node's EState (if any).
778 */
779 if (state->ext_params)
780 params = state->ext_params;
781 else if (state->parent &&
782 state->parent->state)
783 params = state->parent->state->es_param_list_info;
784 else
785 params = NULL;
786 if (params && params->paramCompile)
787 {
788 params->paramCompile(params, param, state,
789 resv, resnull);
790 }
791 else
792 {
793 scratch.opcode = EEOP_PARAM_EXTERN;
794 scratch.d.param.paramid = param->paramid;
795 scratch.d.param.paramtype = param->paramtype;
796 ExprEvalPushStep(state, &scratch);
797 }
798 break;
799 default:
800 elog(ERROR, "unrecognized paramkind: %d",
801 (int) param->paramkind);
802 break;
803 }
804 break;
805 }
806
807 case T_Aggref:
808 {
809 Aggref *aggref = (Aggref *) node;
810 AggrefExprState *astate = makeNode(AggrefExprState);
811
812 scratch.opcode = EEOP_AGGREF;
813 scratch.d.aggref.astate = astate;
814 astate->aggref = aggref;
815
816 if (state->parent && IsA(state->parent, AggState))
817 {
818 AggState *aggstate = (AggState *) state->parent;
819
820 aggstate->aggs = lcons(astate, aggstate->aggs);
821 aggstate->numaggs++;
822 }
823 else
824 {
825 /* planner messed up */
826 elog(ERROR, "Aggref found in non-Agg plan node");
827 }
828
829 ExprEvalPushStep(state, &scratch);
830 break;
831 }
832
833 case T_GroupingFunc:
834 {
835 GroupingFunc *grp_node = (GroupingFunc *) node;
836 Agg *agg;
837
838 if (!state->parent || !IsA(state->parent, AggState) ||
839 !IsA(state->parent->plan, Agg))
840 elog(ERROR, "GroupingFunc found in non-Agg plan node");
841
842 scratch.opcode = EEOP_GROUPING_FUNC;
843 scratch.d.grouping_func.parent = (AggState *) state->parent;
844
845 agg = (Agg *) (state->parent->plan);
846
847 if (agg->groupingSets)
848 scratch.d.grouping_func.clauses = grp_node->cols;
849 else
850 scratch.d.grouping_func.clauses = NIL;
851
852 ExprEvalPushStep(state, &scratch);
853 break;
854 }
855
856 case T_WindowFunc:
857 {
858 WindowFunc *wfunc = (WindowFunc *) node;
859 WindowFuncExprState *wfstate = makeNode(WindowFuncExprState);
860
861 wfstate->wfunc = wfunc;
862
863 if (state->parent && IsA(state->parent, WindowAggState))
864 {
865 WindowAggState *winstate = (WindowAggState *) state->parent;
866 int nfuncs;
867
868 winstate->funcs = lcons(wfstate, winstate->funcs);
869 nfuncs = ++winstate->numfuncs;
870 if (wfunc->winagg)
871 winstate->numaggs++;
872
873 /* for now initialize agg using old style expressions */
874 wfstate->args = ExecInitExprList(wfunc->args,
875 state->parent);
876 wfstate->aggfilter = ExecInitExpr(wfunc->aggfilter,
877 state->parent);
878
879 /*
880 * Complain if the windowfunc's arguments contain any
881 * windowfuncs; nested window functions are semantically
882 * nonsensical. (This should have been caught earlier,
883 * but we defend against it here anyway.)
884 */
885 if (nfuncs != winstate->numfuncs)
886 ereport(ERROR,
887 (errcode(ERRCODE_WINDOWING_ERROR),
888 errmsg("window function calls cannot be nested")));
889 }
890 else
891 {
892 /* planner messed up */
893 elog(ERROR, "WindowFunc found in non-WindowAgg plan node");
894 }
895
896 scratch.opcode = EEOP_WINDOW_FUNC;
897 scratch.d.window_func.wfstate = wfstate;
898 ExprEvalPushStep(state, &scratch);
899 break;
900 }
901
902 case T_SubscriptingRef:
903 {
904 SubscriptingRef *sbsref = (SubscriptingRef *) node;
905
906 ExecInitSubscriptingRef(&scratch, sbsref, state, resv, resnull);
907 break;
908 }
909
910 case T_FuncExpr:
911 {
912 FuncExpr *func = (FuncExpr *) node;
913
914 ExecInitFunc(&scratch, node,
915 func->args, func->funcid, func->inputcollid,
916 state);
917 ExprEvalPushStep(state, &scratch);
918 break;
919 }
920
921 case T_OpExpr:
922 {
923 OpExpr *op = (OpExpr *) node;
924
925 ExecInitFunc(&scratch, node,
926 op->args, op->opfuncid, op->inputcollid,
927 state);
928 ExprEvalPushStep(state, &scratch);
929 break;
930 }
931
932 case T_DistinctExpr:
933 {
934 DistinctExpr *op = (DistinctExpr *) node;
935
936 ExecInitFunc(&scratch, node,
937 op->args, op->opfuncid, op->inputcollid,
938 state);
939
940 /*
941 * Change opcode of call instruction to EEOP_DISTINCT.
942 *
943 * XXX: historically we've not called the function usage
944 * pgstat infrastructure - that seems inconsistent given that
945 * we do so for normal function *and* operator evaluation. If
946 * we decided to do that here, we'd probably want separate
947 * opcodes for FUSAGE or not.
948 */
949 scratch.opcode = EEOP_DISTINCT;
950 ExprEvalPushStep(state, &scratch);
951 break;
952 }
953
954 case T_NullIfExpr:
955 {
956 NullIfExpr *op = (NullIfExpr *) node;
957
958 ExecInitFunc(&scratch, node,
959 op->args, op->opfuncid, op->inputcollid,
960 state);
961
962 /*
963 * Change opcode of call instruction to EEOP_NULLIF.
964 *
965 * XXX: historically we've not called the function usage
966 * pgstat infrastructure - that seems inconsistent given that
967 * we do so for normal function *and* operator evaluation. If
968 * we decided to do that here, we'd probably want separate
969 * opcodes for FUSAGE or not.
970 */
971 scratch.opcode = EEOP_NULLIF;
972 ExprEvalPushStep(state, &scratch);
973 break;
974 }
975
976 case T_ScalarArrayOpExpr:
977 {
978 ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
979 Expr *scalararg;
980 Expr *arrayarg;
981 FmgrInfo *finfo;
982 FunctionCallInfo fcinfo;
983 AclResult aclresult;
984
985 Assert(list_length(opexpr->args) == 2);
986 scalararg = (Expr *) linitial(opexpr->args);
987 arrayarg = (Expr *) lsecond(opexpr->args);
988
989 /* Check permission to call function */
990 aclresult = pg_proc_aclcheck(opexpr->opfuncid,
991 GetUserId(),
992 ACL_EXECUTE);
993 if (aclresult != ACLCHECK_OK)
994 aclcheck_error(aclresult, OBJECT_FUNCTION,
995 get_func_name(opexpr->opfuncid));
996 InvokeFunctionExecuteHook(opexpr->opfuncid);
997
998 /* Set up the primary fmgr lookup information */
999 finfo = palloc0(sizeof(FmgrInfo));
1000 fcinfo = palloc0(SizeForFunctionCallInfo(2));
1001 fmgr_info(opexpr->opfuncid, finfo);
1002 fmgr_info_set_expr((Node *) node, finfo);
1003 InitFunctionCallInfoData(*fcinfo, finfo, 2,
1004 opexpr->inputcollid, NULL, NULL);
1005
1006 /* Evaluate scalar directly into left function argument */
1007 ExecInitExprRec(scalararg, state,
1008 &fcinfo->args[0].value, &fcinfo->args[0].isnull);
1009
1010 /*
1011 * Evaluate array argument into our return value. There's no
1012 * danger in that, because the return value is guaranteed to
1013 * be overwritten by EEOP_SCALARARRAYOP, and will not be
1014 * passed to any other expression.
1015 */
1016 ExecInitExprRec(arrayarg, state, resv, resnull);
1017
1018 /* And perform the operation */
1019 scratch.opcode = EEOP_SCALARARRAYOP;
1020 scratch.d.scalararrayop.element_type = InvalidOid;
1021 scratch.d.scalararrayop.useOr = opexpr->useOr;
1022 scratch.d.scalararrayop.finfo = finfo;
1023 scratch.d.scalararrayop.fcinfo_data = fcinfo;
1024 scratch.d.scalararrayop.fn_addr = finfo->fn_addr;
1025 ExprEvalPushStep(state, &scratch);
1026 break;
1027 }
1028
1029 case T_BoolExpr:
1030 {
1031 BoolExpr *boolexpr = (BoolExpr *) node;
1032 int nargs = list_length(boolexpr->args);
1033 List *adjust_jumps = NIL;
1034 int off;
1035 ListCell *lc;
1036
1037 /* allocate scratch memory used by all steps of AND/OR */
1038 if (boolexpr->boolop != NOT_EXPR)
1039 scratch.d.boolexpr.anynull = (bool *) palloc(sizeof(bool));
1040
1041 /*
1042 * For each argument evaluate the argument itself, then
1043 * perform the bool operation's appropriate handling.
1044 *
1045 * We can evaluate each argument into our result area, since
1046 * the short-circuiting logic means we only need to remember
1047 * previous NULL values.
1048 *
1049 * AND/OR is split into separate STEP_FIRST (one) / STEP (zero
1050 * or more) / STEP_LAST (one) steps, as each of those has to
1051 * perform different work. The FIRST/LAST split is valid
1052 * because AND/OR have at least two arguments.
1053 */
1054 off = 0;
1055 foreach(lc, boolexpr->args)
1056 {
1057 Expr *arg = (Expr *) lfirst(lc);
1058
1059 /* Evaluate argument into our output variable */
1060 ExecInitExprRec(arg, state, resv, resnull);
1061
1062 /* Perform the appropriate step type */
1063 switch (boolexpr->boolop)
1064 {
1065 case AND_EXPR:
1066 Assert(nargs >= 2);
1067
1068 if (off == 0)
1069 scratch.opcode = EEOP_BOOL_AND_STEP_FIRST;
1070 else if (off + 1 == nargs)
1071 scratch.opcode = EEOP_BOOL_AND_STEP_LAST;
1072 else
1073 scratch.opcode = EEOP_BOOL_AND_STEP;
1074 break;
1075 case OR_EXPR:
1076 Assert(nargs >= 2);
1077
1078 if (off == 0)
1079 scratch.opcode = EEOP_BOOL_OR_STEP_FIRST;
1080 else if (off + 1 == nargs)
1081 scratch.opcode = EEOP_BOOL_OR_STEP_LAST;
1082 else
1083 scratch.opcode = EEOP_BOOL_OR_STEP;
1084 break;
1085 case NOT_EXPR:
1086 Assert(nargs == 1);
1087
1088 scratch.opcode = EEOP_BOOL_NOT_STEP;
1089 break;
1090 default:
1091 elog(ERROR, "unrecognized boolop: %d",
1092 (int) boolexpr->boolop);
1093 break;
1094 }
1095
1096 scratch.d.boolexpr.jumpdone = -1;
1097 ExprEvalPushStep(state, &scratch);
1098 adjust_jumps = lappend_int(adjust_jumps,
1099 state->steps_len - 1);
1100 off++;
1101 }
1102
1103 /* adjust jump targets */
1104 foreach(lc, adjust_jumps)
1105 {
1106 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1107
1108 Assert(as->d.boolexpr.jumpdone == -1);
1109 as->d.boolexpr.jumpdone = state->steps_len;
1110 }
1111
1112 break;
1113 }
1114
1115 case T_SubPlan:
1116 {
1117 SubPlan *subplan = (SubPlan *) node;
1118 SubPlanState *sstate;
1119
1120 if (!state->parent)
1121 elog(ERROR, "SubPlan found with no parent plan");
1122
1123 sstate = ExecInitSubPlan(subplan, state->parent);
1124
1125 /* add SubPlanState nodes to state->parent->subPlan */
1126 state->parent->subPlan = lappend(state->parent->subPlan,
1127 sstate);
1128
1129 scratch.opcode = EEOP_SUBPLAN;
1130 scratch.d.subplan.sstate = sstate;
1131
1132 ExprEvalPushStep(state, &scratch);
1133 break;
1134 }
1135
1136 case T_AlternativeSubPlan:
1137 {
1138 AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
1139 AlternativeSubPlanState *asstate;
1140
1141 if (!state->parent)
1142 elog(ERROR, "AlternativeSubPlan found with no parent plan");
1143
1144 asstate = ExecInitAlternativeSubPlan(asplan, state->parent);
1145
1146 scratch.opcode = EEOP_ALTERNATIVE_SUBPLAN;
1147 scratch.d.alternative_subplan.asstate = asstate;
1148
1149 ExprEvalPushStep(state, &scratch);
1150 break;
1151 }
1152
1153 case T_FieldSelect:
1154 {
1155 FieldSelect *fselect = (FieldSelect *) node;
1156
1157 /* evaluate row/record argument into result area */
1158 ExecInitExprRec(fselect->arg, state, resv, resnull);
1159
1160 /* and extract field */
1161 scratch.opcode = EEOP_FIELDSELECT;
1162 scratch.d.fieldselect.fieldnum = fselect->fieldnum;
1163 scratch.d.fieldselect.resulttype = fselect->resulttype;
1164 scratch.d.fieldselect.rowcache.cacheptr = NULL;
1165
1166 ExprEvalPushStep(state, &scratch);
1167 break;
1168 }
1169
1170 case T_FieldStore:
1171 {
1172 FieldStore *fstore = (FieldStore *) node;
1173 TupleDesc tupDesc;
1174 ExprEvalRowtypeCache *rowcachep;
1175 Datum *values;
1176 bool *nulls;
1177 int ncolumns;
1178 ListCell *l1,
1179 *l2;
1180
1181 /* find out the number of columns in the composite type */
1182 tupDesc = lookup_rowtype_tupdesc(fstore->resulttype, -1);
1183 ncolumns = tupDesc->natts;
1184 DecrTupleDescRefCount(tupDesc);
1185
1186 /* create workspace for column values */
1187 values = (Datum *) palloc(sizeof(Datum) * ncolumns);
1188 nulls = (bool *) palloc(sizeof(bool) * ncolumns);
1189
1190 /* create shared composite-type-lookup cache struct */
1191 rowcachep = palloc(sizeof(ExprEvalRowtypeCache));
1192 rowcachep->cacheptr = NULL;
1193
1194 /* emit code to evaluate the composite input value */
1195 ExecInitExprRec(fstore->arg, state, resv, resnull);
1196
1197 /* next, deform the input tuple into our workspace */
1198 scratch.opcode = EEOP_FIELDSTORE_DEFORM;
1199 scratch.d.fieldstore.fstore = fstore;
1200 scratch.d.fieldstore.rowcache = rowcachep;
1201 scratch.d.fieldstore.values = values;
1202 scratch.d.fieldstore.nulls = nulls;
1203 scratch.d.fieldstore.ncolumns = ncolumns;
1204 ExprEvalPushStep(state, &scratch);
1205
1206 /* evaluate new field values, store in workspace columns */
1207 forboth(l1, fstore->newvals, l2, fstore->fieldnums)
1208 {
1209 Expr *e = (Expr *) lfirst(l1);
1210 AttrNumber fieldnum = lfirst_int(l2);
1211 Datum *save_innermost_caseval;
1212 bool *save_innermost_casenull;
1213
1214 if (fieldnum <= 0 || fieldnum > ncolumns)
1215 elog(ERROR, "field number %d is out of range in FieldStore",
1216 fieldnum);
1217
1218 /*
1219 * Use the CaseTestExpr mechanism to pass down the old
1220 * value of the field being replaced; this is needed in
1221 * case the newval is itself a FieldStore or
1222 * SubscriptingRef that has to obtain and modify the old
1223 * value. It's safe to reuse the CASE mechanism because
1224 * there cannot be a CASE between here and where the value
1225 * would be needed, and a field assignment can't be within
1226 * a CASE either. (So saving and restoring
1227 * innermost_caseval is just paranoia, but let's do it
1228 * anyway.)
1229 *
1230 * Another non-obvious point is that it's safe to use the
1231 * field's values[]/nulls[] entries as both the caseval
1232 * source and the result address for this subexpression.
1233 * That's okay only because (1) both FieldStore and
1234 * SubscriptingRef evaluate their arg or refexpr inputs
1235 * first, and (2) any such CaseTestExpr is directly the
1236 * arg or refexpr input. So any read of the caseval will
1237 * occur before there's a chance to overwrite it. Also,
1238 * if multiple entries in the newvals/fieldnums lists
1239 * target the same field, they'll effectively be applied
1240 * left-to-right which is what we want.
1241 */
1242 save_innermost_caseval = state->innermost_caseval;
1243 save_innermost_casenull = state->innermost_casenull;
1244 state->innermost_caseval = &values[fieldnum - 1];
1245 state->innermost_casenull = &nulls[fieldnum - 1];
1246
1247 ExecInitExprRec(e, state,
1248 &values[fieldnum - 1],
1249 &nulls[fieldnum - 1]);
1250
1251 state->innermost_caseval = save_innermost_caseval;
1252 state->innermost_casenull = save_innermost_casenull;
1253 }
1254
1255 /* finally, form result tuple */
1256 scratch.opcode = EEOP_FIELDSTORE_FORM;
1257 scratch.d.fieldstore.fstore = fstore;
1258 scratch.d.fieldstore.rowcache = rowcachep;
1259 scratch.d.fieldstore.values = values;
1260 scratch.d.fieldstore.nulls = nulls;
1261 scratch.d.fieldstore.ncolumns = ncolumns;
1262 ExprEvalPushStep(state, &scratch);
1263 break;
1264 }
1265
1266 case T_RelabelType:
1267 {
1268 /* relabel doesn't need to do anything at runtime */
1269 RelabelType *relabel = (RelabelType *) node;
1270
1271 ExecInitExprRec(relabel->arg, state, resv, resnull);
1272 break;
1273 }
1274
1275 case T_CoerceViaIO:
1276 {
1277 CoerceViaIO *iocoerce = (CoerceViaIO *) node;
1278 Oid iofunc;
1279 bool typisvarlena;
1280 Oid typioparam;
1281 FunctionCallInfo fcinfo_in;
1282
1283 /* evaluate argument into step's result area */
1284 ExecInitExprRec(iocoerce->arg, state, resv, resnull);
1285
1286 /*
1287 * Prepare both output and input function calls, to be
1288 * evaluated inside a single evaluation step for speed - this
1289 * can be a very common operation.
1290 *
1291 * We don't check permissions here as a type's input/output
1292 * function are assumed to be executable by everyone.
1293 */
1294 scratch.opcode = EEOP_IOCOERCE;
1295
1296 /* lookup the source type's output function */
1297 scratch.d.iocoerce.finfo_out = palloc0(sizeof(FmgrInfo));
1298 scratch.d.iocoerce.fcinfo_data_out = palloc0(SizeForFunctionCallInfo(1));
1299
1300 getTypeOutputInfo(exprType((Node *) iocoerce->arg),
1301 &iofunc, &typisvarlena);
1302 fmgr_info(iofunc, scratch.d.iocoerce.finfo_out);
1303 fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_out);
1304 InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_out,
1305 scratch.d.iocoerce.finfo_out,
1306 1, InvalidOid, NULL, NULL);
1307
1308 /* lookup the result type's input function */
1309 scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo));
1310 scratch.d.iocoerce.fcinfo_data_in = palloc0(SizeForFunctionCallInfo(3));
1311
1312 getTypeInputInfo(iocoerce->resulttype,
1313 &iofunc, &typioparam);
1314 fmgr_info(iofunc, scratch.d.iocoerce.finfo_in);
1315 fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_in);
1316 InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_in,
1317 scratch.d.iocoerce.finfo_in,
1318 3, InvalidOid, NULL, NULL);
1319
1320 /*
1321 * We can preload the second and third arguments for the input
1322 * function, since they're constants.
1323 */
1324 fcinfo_in = scratch.d.iocoerce.fcinfo_data_in;
1325 fcinfo_in->args[1].value = ObjectIdGetDatum(typioparam);
1326 fcinfo_in->args[1].isnull = false;
1327 fcinfo_in->args[2].value = Int32GetDatum(-1);
1328 fcinfo_in->args[2].isnull = false;
1329
1330 ExprEvalPushStep(state, &scratch);
1331 break;
1332 }
1333
1334 case T_ArrayCoerceExpr:
1335 {
1336 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
1337 Oid resultelemtype;
1338 ExprState *elemstate;
1339
1340 /* evaluate argument into step's result area */
1341 ExecInitExprRec(acoerce->arg, state, resv, resnull);
1342
1343 resultelemtype = get_element_type(acoerce->resulttype);
1344 if (!OidIsValid(resultelemtype))
1345 ereport(ERROR,
1346 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1347 errmsg("target type is not an array")));
1348
1349 /*
1350 * Construct a sub-expression for the per-element expression;
1351 * but don't ready it until after we check it for triviality.
1352 * We assume it hasn't any Var references, but does have a
1353 * CaseTestExpr representing the source array element values.
1354 */
1355 elemstate = makeNode(ExprState);
1356 elemstate->expr = acoerce->elemexpr;
1357 elemstate->parent = state->parent;
1358 elemstate->ext_params = state->ext_params;
1359
1360 elemstate->innermost_caseval = (Datum *) palloc(sizeof(Datum));
1361 elemstate->innermost_casenull = (bool *) palloc(sizeof(bool));
1362
1363 ExecInitExprRec(acoerce->elemexpr, elemstate,
1364 &elemstate->resvalue, &elemstate->resnull);
1365
1366 if (elemstate->steps_len == 1 &&
1367 elemstate->steps[0].opcode == EEOP_CASE_TESTVAL)
1368 {
1369 /* Trivial, so we need no per-element work at runtime */
1370 elemstate = NULL;
1371 }
1372 else
1373 {
1374 /* Not trivial, so append a DONE step */
1375 scratch.opcode = EEOP_DONE;
1376 ExprEvalPushStep(elemstate, &scratch);
1377 /* and ready the subexpression */
1378 ExecReadyExpr(elemstate);
1379 }
1380
1381 scratch.opcode = EEOP_ARRAYCOERCE;
1382 scratch.d.arraycoerce.elemexprstate = elemstate;
1383 scratch.d.arraycoerce.resultelemtype = resultelemtype;
1384
1385 if (elemstate)
1386 {
1387 /* Set up workspace for array_map */
1388 scratch.d.arraycoerce.amstate =
1389 (ArrayMapState *) palloc0(sizeof(ArrayMapState));
1390 }
1391 else
1392 {
1393 /* Don't need workspace if there's no subexpression */
1394 scratch.d.arraycoerce.amstate = NULL;
1395 }
1396
1397 ExprEvalPushStep(state, &scratch);
1398 break;
1399 }
1400
1401 case T_ConvertRowtypeExpr:
1402 {
1403 ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
1404 ExprEvalRowtypeCache *rowcachep;
1405
1406 /* cache structs must be out-of-line for space reasons */
1407 rowcachep = palloc(2 * sizeof(ExprEvalRowtypeCache));
1408 rowcachep[0].cacheptr = NULL;
1409 rowcachep[1].cacheptr = NULL;
1410
1411 /* evaluate argument into step's result area */
1412 ExecInitExprRec(convert->arg, state, resv, resnull);
1413
1414 /* and push conversion step */
1415 scratch.opcode = EEOP_CONVERT_ROWTYPE;
1416 scratch.d.convert_rowtype.inputtype =
1417 exprType((Node *) convert->arg);
1418 scratch.d.convert_rowtype.outputtype = convert->resulttype;
1419 scratch.d.convert_rowtype.incache = &rowcachep[0];
1420 scratch.d.convert_rowtype.outcache = &rowcachep[1];
1421 scratch.d.convert_rowtype.map = NULL;
1422
1423 ExprEvalPushStep(state, &scratch);
1424 break;
1425 }
1426
1427 /* note that CaseWhen expressions are handled within this block */
1428 case T_CaseExpr:
1429 {
1430 CaseExpr *caseExpr = (CaseExpr *) node;
1431 List *adjust_jumps = NIL;
1432 Datum *caseval = NULL;
1433 bool *casenull = NULL;
1434 ListCell *lc;
1435
1436 /*
1437 * If there's a test expression, we have to evaluate it and
1438 * save the value where the CaseTestExpr placeholders can find
1439 * it.
1440 */
1441 if (caseExpr->arg != NULL)
1442 {
1443 /* Evaluate testexpr into caseval/casenull workspace */
1444 caseval = palloc(sizeof(Datum));
1445 casenull = palloc(sizeof(bool));
1446
1447 ExecInitExprRec(caseExpr->arg, state,
1448 caseval, casenull);
1449
1450 /*
1451 * Since value might be read multiple times, force to R/O
1452 * - but only if it could be an expanded datum.
1453 */
1454 if (get_typlen(exprType((Node *) caseExpr->arg)) == -1)
1455 {
1456 /* change caseval in-place */
1457 scratch.opcode = EEOP_MAKE_READONLY;
1458 scratch.resvalue = caseval;
1459 scratch.resnull = casenull;
1460 scratch.d.make_readonly.value = caseval;
1461 scratch.d.make_readonly.isnull = casenull;
1462 ExprEvalPushStep(state, &scratch);
1463 /* restore normal settings of scratch fields */
1464 scratch.resvalue = resv;
1465 scratch.resnull = resnull;
1466 }
1467 }
1468
1469 /*
1470 * Prepare to evaluate each of the WHEN clauses in turn; as
1471 * soon as one is true we return the value of the
1472 * corresponding THEN clause. If none are true then we return
1473 * the value of the ELSE clause, or NULL if there is none.
1474 */
1475 foreach(lc, caseExpr->args)
1476 {
1477 CaseWhen *when = (CaseWhen *) lfirst(lc);
1478 Datum *save_innermost_caseval;
1479 bool *save_innermost_casenull;
1480 int whenstep;
1481
1482 /*
1483 * Make testexpr result available to CaseTestExpr nodes
1484 * within the condition. We must save and restore prior
1485 * setting of innermost_caseval fields, in case this node
1486 * is itself within a larger CASE.
1487 *
1488 * If there's no test expression, we don't actually need
1489 * to save and restore these fields; but it's less code to
1490 * just do so unconditionally.
1491 */
1492 save_innermost_caseval = state->innermost_caseval;
1493 save_innermost_casenull = state->innermost_casenull;
1494 state->innermost_caseval = caseval;
1495 state->innermost_casenull = casenull;
1496
1497 /* evaluate condition into CASE's result variables */
1498 ExecInitExprRec(when->expr, state, resv, resnull);
1499
1500 state->innermost_caseval = save_innermost_caseval;
1501 state->innermost_casenull = save_innermost_casenull;
1502
1503 /* If WHEN result isn't true, jump to next CASE arm */
1504 scratch.opcode = EEOP_JUMP_IF_NOT_TRUE;
1505 scratch.d.jump.jumpdone = -1; /* computed later */
1506 ExprEvalPushStep(state, &scratch);
1507 whenstep = state->steps_len - 1;
1508
1509 /*
1510 * If WHEN result is true, evaluate THEN result, storing
1511 * it into the CASE's result variables.
1512 */
1513 ExecInitExprRec(when->result, state, resv, resnull);
1514
1515 /* Emit JUMP step to jump to end of CASE's code */
1516 scratch.opcode = EEOP_JUMP;
1517 scratch.d.jump.jumpdone = -1; /* computed later */
1518 ExprEvalPushStep(state, &scratch);
1519
1520 /*
1521 * Don't know address for that jump yet, compute once the
1522 * whole CASE expression is built.
1523 */
1524 adjust_jumps = lappend_int(adjust_jumps,
1525 state->steps_len - 1);
1526
1527 /*
1528 * But we can set WHEN test's jump target now, to make it
1529 * jump to the next WHEN subexpression or the ELSE.
1530 */
1531 state->steps[whenstep].d.jump.jumpdone = state->steps_len;
1532 }
1533
1534 /* transformCaseExpr always adds a default */
1535 Assert(caseExpr->defresult);
1536
1537 /* evaluate ELSE expr into CASE's result variables */
1538 ExecInitExprRec(caseExpr->defresult, state,
1539 resv, resnull);
1540
1541 /* adjust jump targets */
1542 foreach(lc, adjust_jumps)
1543 {
1544 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1545
1546 Assert(as->opcode == EEOP_JUMP);
1547 Assert(as->d.jump.jumpdone == -1);
1548 as->d.jump.jumpdone = state->steps_len;
1549 }
1550
1551 break;
1552 }
1553
1554 case T_CaseTestExpr:
1555 {
1556 /*
1557 * Read from location identified by innermost_caseval. Note
1558 * that innermost_caseval could be NULL, if this node isn't
1559 * actually within a CaseExpr, ArrayCoerceExpr, etc structure.
1560 * That can happen because some parts of the system abuse
1561 * CaseTestExpr to cause a read of a value externally supplied
1562 * in econtext->caseValue_datum. We'll take care of that
1563 * scenario at runtime.
1564 */
1565 scratch.opcode = EEOP_CASE_TESTVAL;
1566 scratch.d.casetest.value = state->innermost_caseval;
1567 scratch.d.casetest.isnull = state->innermost_casenull;
1568
1569 ExprEvalPushStep(state, &scratch);
1570 break;
1571 }
1572
1573 case T_ArrayExpr:
1574 {
1575 ArrayExpr *arrayexpr = (ArrayExpr *) node;
1576 int nelems = list_length(arrayexpr->elements);
1577 ListCell *lc;
1578 int elemoff;
1579
1580 /*
1581 * Evaluate by computing each element, and then forming the
1582 * array. Elements are computed into scratch arrays
1583 * associated with the ARRAYEXPR step.
1584 */
1585 scratch.opcode = EEOP_ARRAYEXPR;
1586 scratch.d.arrayexpr.elemvalues =
1587 (Datum *) palloc(sizeof(Datum) * nelems);
1588 scratch.d.arrayexpr.elemnulls =
1589 (bool *) palloc(sizeof(bool) * nelems);
1590 scratch.d.arrayexpr.nelems = nelems;
1591
1592 /* fill remaining fields of step */
1593 scratch.d.arrayexpr.multidims = arrayexpr->multidims;
1594 scratch.d.arrayexpr.elemtype = arrayexpr->element_typeid;
1595
1596 /* do one-time catalog lookup for type info */
1597 get_typlenbyvalalign(arrayexpr->element_typeid,
1598 &scratch.d.arrayexpr.elemlength,
1599 &scratch.d.arrayexpr.elembyval,
1600 &scratch.d.arrayexpr.elemalign);
1601
1602 /* prepare to evaluate all arguments */
1603 elemoff = 0;
1604 foreach(lc, arrayexpr->elements)
1605 {
1606 Expr *e = (Expr *) lfirst(lc);
1607
1608 ExecInitExprRec(e, state,
1609 &scratch.d.arrayexpr.elemvalues[elemoff],
1610 &scratch.d.arrayexpr.elemnulls[elemoff]);
1611 elemoff++;
1612 }
1613
1614 /* and then collect all into an array */
1615 ExprEvalPushStep(state, &scratch);
1616 break;
1617 }
1618
1619 case T_RowExpr:
1620 {
1621 RowExpr *rowexpr = (RowExpr *) node;
1622 int nelems = list_length(rowexpr->args);
1623 TupleDesc tupdesc;
1624 int i;
1625 ListCell *l;
1626
1627 /* Build tupdesc to describe result tuples */
1628 if (rowexpr->row_typeid == RECORDOID)
1629 {
1630 /* generic record, use types of given expressions */
1631 tupdesc = ExecTypeFromExprList(rowexpr->args);
1632 }
1633 else
1634 {
1635 /* it's been cast to a named type, use that */
1636 tupdesc = lookup_rowtype_tupdesc_copy(rowexpr->row_typeid, -1);
1637 }
1638 /* In either case, adopt RowExpr's column aliases */
1639 ExecTypeSetColNames(tupdesc, rowexpr->colnames);
1640 /* Bless the tupdesc in case it's now of type RECORD */
1641 BlessTupleDesc(tupdesc);
1642
1643 /*
1644 * In the named-type case, the tupdesc could have more columns
1645 * than are in the args list, since the type might have had
1646 * columns added since the ROW() was parsed. We want those
1647 * extra columns to go to nulls, so we make sure that the
1648 * workspace arrays are large enough and then initialize any
1649 * extra columns to read as NULLs.
1650 */
1651 Assert(nelems <= tupdesc->natts);
1652 nelems = Max(nelems, tupdesc->natts);
1653
1654 /*
1655 * Evaluate by first building datums for each field, and then
1656 * a final step forming the composite datum.
1657 */
1658 scratch.opcode = EEOP_ROW;
1659 scratch.d.row.tupdesc = tupdesc;
1660
1661 /* space for the individual field datums */
1662 scratch.d.row.elemvalues =
1663 (Datum *) palloc(sizeof(Datum) * nelems);
1664 scratch.d.row.elemnulls =
1665 (bool *) palloc(sizeof(bool) * nelems);
1666 /* as explained above, make sure any extra columns are null */
1667 memset(scratch.d.row.elemnulls, true, sizeof(bool) * nelems);
1668
1669 /* Set up evaluation, skipping any deleted columns */
1670 i = 0;
1671 foreach(l, rowexpr->args)
1672 {
1673 Form_pg_attribute att = TupleDescAttr(tupdesc, i);
1674 Expr *e = (Expr *) lfirst(l);
1675
1676 if (!att->attisdropped)
1677 {
1678 /*
1679 * Guard against ALTER COLUMN TYPE on rowtype since
1680 * the RowExpr was created. XXX should we check
1681 * typmod too? Not sure we can be sure it'll be the
1682 * same.
1683 */
1684 if (exprType((Node *) e) != att->atttypid)
1685 ereport(ERROR,
1686 (errcode(ERRCODE_DATATYPE_MISMATCH),
1687 errmsg("ROW() column has type %s instead of type %s",
1688 format_type_be(exprType((Node *) e)),
1689 format_type_be(att->atttypid))));
1690 }
1691 else
1692 {
1693 /*
1694 * Ignore original expression and insert a NULL. We
1695 * don't really care what type of NULL it is, so
1696 * always make an int4 NULL.
1697 */
1698 e = (Expr *) makeNullConst(INT4OID, -1, InvalidOid);
1699 }
1700
1701 /* Evaluate column expr into appropriate workspace slot */
1702 ExecInitExprRec(e, state,
1703 &scratch.d.row.elemvalues[i],
1704 &scratch.d.row.elemnulls[i]);
1705 i++;
1706 }
1707
1708 /* And finally build the row value */
1709 ExprEvalPushStep(state, &scratch);
1710 break;
1711 }
1712
1713 case T_RowCompareExpr:
1714 {
1715 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
1716 int nopers = list_length(rcexpr->opnos);
1717 List *adjust_jumps = NIL;
1718 ListCell *l_left_expr,
1719 *l_right_expr,
1720 *l_opno,
1721 *l_opfamily,
1722 *l_inputcollid;
1723 ListCell *lc;
1724
1725 /*
1726 * Iterate over each field, prepare comparisons. To handle
1727 * NULL results, prepare jumps to after the expression. If a
1728 * comparison yields a != 0 result, jump to the final step.
1729 */
1730 Assert(list_length(rcexpr->largs) == nopers);
1731 Assert(list_length(rcexpr->rargs) == nopers);
1732 Assert(list_length(rcexpr->opfamilies) == nopers);
1733 Assert(list_length(rcexpr->inputcollids) == nopers);
1734
1735 forfive(l_left_expr, rcexpr->largs,
1736 l_right_expr, rcexpr->rargs,
1737 l_opno, rcexpr->opnos,
1738 l_opfamily, rcexpr->opfamilies,
1739 l_inputcollid, rcexpr->inputcollids)
1740 {
1741 Expr *left_expr = (Expr *) lfirst(l_left_expr);
1742 Expr *right_expr = (Expr *) lfirst(l_right_expr);
1743 Oid opno = lfirst_oid(l_opno);
1744 Oid opfamily = lfirst_oid(l_opfamily);
1745 Oid inputcollid = lfirst_oid(l_inputcollid);
1746 int strategy;
1747 Oid lefttype;
1748 Oid righttype;
1749 Oid proc;
1750 FmgrInfo *finfo;
1751 FunctionCallInfo fcinfo;
1752
1753 get_op_opfamily_properties(opno, opfamily, false,
1754 &strategy,
1755 &lefttype,
1756 &righttype);
1757 proc = get_opfamily_proc(opfamily,
1758 lefttype,
1759 righttype,
1760 BTORDER_PROC);
1761 if (!OidIsValid(proc))
1762 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
1763 BTORDER_PROC, lefttype, righttype, opfamily);
1764
1765 /* Set up the primary fmgr lookup information */
1766 finfo = palloc0(sizeof(FmgrInfo));
1767 fcinfo = palloc0(SizeForFunctionCallInfo(2));
1768 fmgr_info(proc, finfo);
1769 fmgr_info_set_expr((Node *) node, finfo);
1770 InitFunctionCallInfoData(*fcinfo, finfo, 2,
1771 inputcollid, NULL, NULL);
1772
1773 /*
1774 * If we enforced permissions checks on index support
1775 * functions, we'd need to make a check here. But the
1776 * index support machinery doesn't do that, and thus
1777 * neither does this code.
1778 */
1779
1780 /* evaluate left and right args directly into fcinfo */
1781 ExecInitExprRec(left_expr, state,
1782 &fcinfo->args[0].value, &fcinfo->args[0].isnull);
1783 ExecInitExprRec(right_expr, state,
1784 &fcinfo->args[1].value, &fcinfo->args[1].isnull);
1785
1786 scratch.opcode = EEOP_ROWCOMPARE_STEP;
1787 scratch.d.rowcompare_step.finfo = finfo;
1788 scratch.d.rowcompare_step.fcinfo_data = fcinfo;
1789 scratch.d.rowcompare_step.fn_addr = finfo->fn_addr;
1790 /* jump targets filled below */
1791 scratch.d.rowcompare_step.jumpnull = -1;
1792 scratch.d.rowcompare_step.jumpdone = -1;
1793
1794 ExprEvalPushStep(state, &scratch);
1795 adjust_jumps = lappend_int(adjust_jumps,
1796 state->steps_len - 1);
1797 }
1798
1799 /*
1800 * We could have a zero-column rowtype, in which case the rows
1801 * necessarily compare equal.
1802 */
1803 if (nopers == 0)
1804 {
1805 scratch.opcode = EEOP_CONST;
1806 scratch.d.constval.value = Int32GetDatum(0);
1807 scratch.d.constval.isnull = false;
1808 ExprEvalPushStep(state, &scratch);
1809 }
1810
1811 /* Finally, examine the last comparison result */
1812 scratch.opcode = EEOP_ROWCOMPARE_FINAL;
1813 scratch.d.rowcompare_final.rctype = rcexpr->rctype;
1814 ExprEvalPushStep(state, &scratch);
1815
1816 /* adjust jump targetss */
1817 foreach(lc, adjust_jumps)
1818 {
1819 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1820
1821 Assert(as->opcode == EEOP_ROWCOMPARE_STEP);
1822 Assert(as->d.rowcompare_step.jumpdone == -1);
1823 Assert(as->d.rowcompare_step.jumpnull == -1);
1824
1825 /* jump to comparison evaluation */
1826 as->d.rowcompare_step.jumpdone = state->steps_len - 1;
1827 /* jump to the following expression */
1828 as->d.rowcompare_step.jumpnull = state->steps_len;
1829 }
1830
1831 break;
1832 }
1833
1834 case T_CoalesceExpr:
1835 {
1836 CoalesceExpr *coalesce = (CoalesceExpr *) node;
1837 List *adjust_jumps = NIL;
1838 ListCell *lc;
1839
1840 /* We assume there's at least one arg */
1841 Assert(coalesce->args != NIL);
1842
1843 /*
1844 * Prepare evaluation of all coalesced arguments, after each
1845 * one push a step that short-circuits if not null.
1846 */
1847 foreach(lc, coalesce->args)
1848 {
1849 Expr *e = (Expr *) lfirst(lc);
1850
1851 /* evaluate argument, directly into result datum */
1852 ExecInitExprRec(e, state, resv, resnull);
1853
1854 /* if it's not null, skip to end of COALESCE expr */
1855 scratch.opcode = EEOP_JUMP_IF_NOT_NULL;
1856 scratch.d.jump.jumpdone = -1; /* adjust later */
1857 ExprEvalPushStep(state, &scratch);
1858
1859 adjust_jumps = lappend_int(adjust_jumps,
1860 state->steps_len - 1);
1861 }
1862
1863 /*
1864 * No need to add a constant NULL return - we only can get to
1865 * the end of the expression if a NULL already is being
1866 * returned.
1867 */
1868
1869 /* adjust jump targets */
1870 foreach(lc, adjust_jumps)
1871 {
1872 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1873
1874 Assert(as->opcode == EEOP_JUMP_IF_NOT_NULL);
1875 Assert(as->d.jump.jumpdone == -1);
1876 as->d.jump.jumpdone = state->steps_len;
1877 }
1878
1879 break;
1880 }
1881
1882 case T_MinMaxExpr:
1883 {
1884 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
1885 int nelems = list_length(minmaxexpr->args);
1886 TypeCacheEntry *typentry;
1887 FmgrInfo *finfo;
1888 FunctionCallInfo fcinfo;
1889 ListCell *lc;
1890 int off;
1891
1892 /* Look up the btree comparison function for the datatype */
1893 typentry = lookup_type_cache(minmaxexpr->minmaxtype,
1894 TYPECACHE_CMP_PROC);
1895 if (!OidIsValid(typentry->cmp_proc))
1896 ereport(ERROR,
1897 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1898 errmsg("could not identify a comparison function for type %s",
1899 format_type_be(minmaxexpr->minmaxtype))));
1900
1901 /*
1902 * If we enforced permissions checks on index support
1903 * functions, we'd need to make a check here. But the index
1904 * support machinery doesn't do that, and thus neither does
1905 * this code.
1906 */
1907
1908 /* Perform function lookup */
1909 finfo = palloc0(sizeof(FmgrInfo));
1910 fcinfo = palloc0(SizeForFunctionCallInfo(2));
1911 fmgr_info(typentry->cmp_proc, finfo);
1912 fmgr_info_set_expr((Node *) node, finfo);
1913 InitFunctionCallInfoData(*fcinfo, finfo, 2,
1914 minmaxexpr->inputcollid, NULL, NULL);
1915
1916 scratch.opcode = EEOP_MINMAX;
1917 /* allocate space to store arguments */
1918 scratch.d.minmax.values =
1919 (Datum *) palloc(sizeof(Datum) * nelems);
1920 scratch.d.minmax.nulls =
1921 (bool *) palloc(sizeof(bool) * nelems);
1922 scratch.d.minmax.nelems = nelems;
1923
1924 scratch.d.minmax.op = minmaxexpr->op;
1925 scratch.d.minmax.finfo = finfo;
1926 scratch.d.minmax.fcinfo_data = fcinfo;
1927
1928 /* evaluate expressions into minmax->values/nulls */
1929 off = 0;
1930 foreach(lc, minmaxexpr->args)
1931 {
1932 Expr *e = (Expr *) lfirst(lc);
1933
1934 ExecInitExprRec(e, state,
1935 &scratch.d.minmax.values[off],
1936 &scratch.d.minmax.nulls[off]);
1937 off++;
1938 }
1939
1940 /* and push the final comparison */
1941 ExprEvalPushStep(state, &scratch);
1942 break;
1943 }
1944
1945 case T_SQLValueFunction:
1946 {
1947 SQLValueFunction *svf = (SQLValueFunction *) node;
1948
1949 scratch.opcode = EEOP_SQLVALUEFUNCTION;
1950 scratch.d.sqlvaluefunction.svf = svf;
1951
1952 ExprEvalPushStep(state, &scratch);
1953 break;
1954 }
1955
1956 case T_XmlExpr:
1957 {
1958 XmlExpr *xexpr = (XmlExpr *) node;
1959 int nnamed = list_length(xexpr->named_args);
1960 int nargs = list_length(xexpr->args);
1961 int off;
1962 ListCell *arg;
1963
1964 scratch.opcode = EEOP_XMLEXPR;
1965 scratch.d.xmlexpr.xexpr = xexpr;
1966
1967 /* allocate space for storing all the arguments */
1968 if (nnamed)
1969 {
1970 scratch.d.xmlexpr.named_argvalue =
1971 (Datum *) palloc(sizeof(Datum) * nnamed);
1972 scratch.d.xmlexpr.named_argnull =
1973 (bool *) palloc(sizeof(bool) * nnamed);
1974 }
1975 else
1976 {
1977 scratch.d.xmlexpr.named_argvalue = NULL;
1978 scratch.d.xmlexpr.named_argnull = NULL;
1979 }
1980
1981 if (nargs)
1982 {
1983 scratch.d.xmlexpr.argvalue =
1984 (Datum *) palloc(sizeof(Datum) * nargs);
1985 scratch.d.xmlexpr.argnull =
1986 (bool *) palloc(sizeof(bool) * nargs);
1987 }
1988 else
1989 {
1990 scratch.d.xmlexpr.argvalue = NULL;
1991 scratch.d.xmlexpr.argnull = NULL;
1992 }
1993
1994 /* prepare argument execution */
1995 off = 0;
1996 foreach(arg, xexpr->named_args)
1997 {
1998 Expr *e = (Expr *) lfirst(arg);
1999
2000 ExecInitExprRec(e, state,
2001 &scratch.d.xmlexpr.named_argvalue[off],
2002 &scratch.d.xmlexpr.named_argnull[off]);
2003 off++;
2004 }
2005
2006 off = 0;
2007 foreach(arg, xexpr->args)
2008 {
2009 Expr *e = (Expr *) lfirst(arg);
2010
2011 ExecInitExprRec(e, state,
2012 &scratch.d.xmlexpr.argvalue[off],
2013 &scratch.d.xmlexpr.argnull[off]);
2014 off++;
2015 }
2016
2017 /* and evaluate the actual XML expression */
2018 ExprEvalPushStep(state, &scratch);
2019 break;
2020 }
2021
2022 case T_NullTest:
2023 {
2024 NullTest *ntest = (NullTest *) node;
2025
2026 if (ntest->nulltesttype == IS_NULL)
2027 {
2028 if (ntest->argisrow)
2029 scratch.opcode = EEOP_NULLTEST_ROWISNULL;
2030 else
2031 scratch.opcode = EEOP_NULLTEST_ISNULL;
2032 }
2033 else if (ntest->nulltesttype == IS_NOT_NULL)
2034 {
2035 if (ntest->argisrow)
2036 scratch.opcode = EEOP_NULLTEST_ROWISNOTNULL;
2037 else
2038 scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
2039 }
2040 else
2041 {
2042 elog(ERROR, "unrecognized nulltesttype: %d",
2043 (int) ntest->nulltesttype);
2044 }
2045 /* initialize cache in case it's a row test */
2046 scratch.d.nulltest_row.rowcache.cacheptr = NULL;
2047
2048 /* first evaluate argument into result variable */
2049 ExecInitExprRec(ntest->arg, state,
2050 resv, resnull);
2051
2052 /* then push the test of that argument */
2053 ExprEvalPushStep(state, &scratch);
2054 break;
2055 }
2056
2057 case T_BooleanTest:
2058 {
2059 BooleanTest *btest = (BooleanTest *) node;
2060
2061 /*
2062 * Evaluate argument, directly into result datum. That's ok,
2063 * because resv/resnull is definitely not used anywhere else,
2064 * and will get overwritten by the below EEOP_BOOLTEST_IS_*
2065 * step.
2066 */
2067 ExecInitExprRec(btest->arg, state, resv, resnull);
2068
2069 switch (btest->booltesttype)
2070 {
2071 case IS_TRUE:
2072 scratch.opcode = EEOP_BOOLTEST_IS_TRUE;
2073 break;
2074 case IS_NOT_TRUE:
2075 scratch.opcode = EEOP_BOOLTEST_IS_NOT_TRUE;
2076 break;
2077 case IS_FALSE:
2078 scratch.opcode = EEOP_BOOLTEST_IS_FALSE;
2079 break;
2080 case IS_NOT_FALSE:
2081 scratch.opcode = EEOP_BOOLTEST_IS_NOT_FALSE;
2082 break;
2083 case IS_UNKNOWN:
2084 /* Same as scalar IS NULL test */
2085 scratch.opcode = EEOP_NULLTEST_ISNULL;
2086 break;
2087 case IS_NOT_UNKNOWN:
2088 /* Same as scalar IS NOT NULL test */
2089 scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
2090 break;
2091 default:
2092 elog(ERROR, "unrecognized booltesttype: %d",
2093 (int) btest->booltesttype);
2094 }
2095
2096 ExprEvalPushStep(state, &scratch);
2097 break;
2098 }
2099
2100 case T_CoerceToDomain:
2101 {
2102 CoerceToDomain *ctest = (CoerceToDomain *) node;
2103
2104 ExecInitCoerceToDomain(&scratch, ctest, state,
2105 resv, resnull);
2106 break;
2107 }
2108
2109 case T_CoerceToDomainValue:
2110 {
2111 /*
2112 * Read from location identified by innermost_domainval. Note
2113 * that innermost_domainval could be NULL, if we're compiling
2114 * a standalone domain check rather than one embedded in a
2115 * larger expression. In that case we must read from
2116 * econtext->domainValue_datum. We'll take care of that
2117 * scenario at runtime.
2118 */
2119 scratch.opcode = EEOP_DOMAIN_TESTVAL;
2120 /* we share instruction union variant with case testval */
2121 scratch.d.casetest.value = state->innermost_domainval;
2122 scratch.d.casetest.isnull = state->innermost_domainnull;
2123
2124 ExprEvalPushStep(state, &scratch);
2125 break;
2126 }
2127
2128 case T_CurrentOfExpr:
2129 {
2130 scratch.opcode = EEOP_CURRENTOFEXPR;
2131 ExprEvalPushStep(state, &scratch);
2132 break;
2133 }
2134
2135 case T_NextValueExpr:
2136 {
2137 NextValueExpr *nve = (NextValueExpr *) node;
2138
2139 scratch.opcode = EEOP_NEXTVALUEEXPR;
2140 scratch.d.nextvalueexpr.seqid = nve->seqid;
2141 scratch.d.nextvalueexpr.seqtypid = nve->typeId;
2142
2143 ExprEvalPushStep(state, &scratch);
2144 break;
2145 }
2146
2147 default:
2148 elog(ERROR, "unrecognized node type: %d",
2149 (int) nodeTag(node));
2150 break;
2151 }
2152 }
2153
2154 /*
2155 * Add another expression evaluation step to ExprState->steps.
2156 *
2157 * Note that this potentially re-allocates es->steps, therefore no pointer
2158 * into that array may be used while the expression is still being built.
2159 */
2160 void
ExprEvalPushStep(ExprState * es,const ExprEvalStep * s)2161 ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
2162 {
2163 if (es->steps_alloc == 0)
2164 {
2165 es->steps_alloc = 16;
2166 es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc);
2167 }
2168 else if (es->steps_alloc == es->steps_len)
2169 {
2170 es->steps_alloc *= 2;
2171 es->steps = repalloc(es->steps,
2172 sizeof(ExprEvalStep) * es->steps_alloc);
2173 }
2174
2175 memcpy(&es->steps[es->steps_len++], s, sizeof(ExprEvalStep));
2176 }
2177
2178 /*
2179 * Perform setup necessary for the evaluation of a function-like expression,
2180 * appending argument evaluation steps to the steps list in *state, and
2181 * setting up *scratch so it is ready to be pushed.
2182 *
2183 * *scratch is not pushed here, so that callers may override the opcode,
2184 * which is useful for function-like cases like DISTINCT.
2185 */
2186 static void
ExecInitFunc(ExprEvalStep * scratch,Expr * node,List * args,Oid funcid,Oid inputcollid,ExprState * state)2187 ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
2188 Oid inputcollid, ExprState *state)
2189 {
2190 int nargs = list_length(args);
2191 AclResult aclresult;
2192 FmgrInfo *flinfo;
2193 FunctionCallInfo fcinfo;
2194 int argno;
2195 ListCell *lc;
2196
2197 /* Check permission to call function */
2198 aclresult = pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE);
2199 if (aclresult != ACLCHECK_OK)
2200 aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(funcid));
2201 InvokeFunctionExecuteHook(funcid);
2202
2203 /*
2204 * Safety check on nargs. Under normal circumstances this should never
2205 * fail, as parser should check sooner. But possibly it might fail if
2206 * server has been compiled with FUNC_MAX_ARGS smaller than some functions
2207 * declared in pg_proc?
2208 */
2209 if (nargs > FUNC_MAX_ARGS)
2210 ereport(ERROR,
2211 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2212 errmsg_plural("cannot pass more than %d argument to a function",
2213 "cannot pass more than %d arguments to a function",
2214 FUNC_MAX_ARGS,
2215 FUNC_MAX_ARGS)));
2216
2217 /* Allocate function lookup data and parameter workspace for this call */
2218 scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
2219 scratch->d.func.fcinfo_data = palloc0(SizeForFunctionCallInfo(nargs));
2220 flinfo = scratch->d.func.finfo;
2221 fcinfo = scratch->d.func.fcinfo_data;
2222
2223 /* Set up the primary fmgr lookup information */
2224 fmgr_info(funcid, flinfo);
2225 fmgr_info_set_expr((Node *) node, flinfo);
2226
2227 /* Initialize function call parameter structure too */
2228 InitFunctionCallInfoData(*fcinfo, flinfo,
2229 nargs, inputcollid, NULL, NULL);
2230
2231 /* Keep extra copies of this info to save an indirection at runtime */
2232 scratch->d.func.fn_addr = flinfo->fn_addr;
2233 scratch->d.func.nargs = nargs;
2234
2235 /* We only support non-set functions here */
2236 if (flinfo->fn_retset)
2237 ereport(ERROR,
2238 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2239 errmsg("set-valued function called in context that cannot accept a set"),
2240 state->parent ?
2241 executor_errposition(state->parent->state,
2242 exprLocation((Node *) node)) : 0));
2243
2244 /* Build code to evaluate arguments directly into the fcinfo struct */
2245 argno = 0;
2246 foreach(lc, args)
2247 {
2248 Expr *arg = (Expr *) lfirst(lc);
2249
2250 if (IsA(arg, Const))
2251 {
2252 /*
2253 * Don't evaluate const arguments every round; especially
2254 * interesting for constants in comparisons.
2255 */
2256 Const *con = (Const *) arg;
2257
2258 fcinfo->args[argno].value = con->constvalue;
2259 fcinfo->args[argno].isnull = con->constisnull;
2260 }
2261 else
2262 {
2263 ExecInitExprRec(arg, state,
2264 &fcinfo->args[argno].value,
2265 &fcinfo->args[argno].isnull);
2266 }
2267 argno++;
2268 }
2269
2270 /* Insert appropriate opcode depending on strictness and stats level */
2271 if (pgstat_track_functions <= flinfo->fn_stats)
2272 {
2273 if (flinfo->fn_strict && nargs > 0)
2274 scratch->opcode = EEOP_FUNCEXPR_STRICT;
2275 else
2276 scratch->opcode = EEOP_FUNCEXPR;
2277 }
2278 else
2279 {
2280 if (flinfo->fn_strict && nargs > 0)
2281 scratch->opcode = EEOP_FUNCEXPR_STRICT_FUSAGE;
2282 else
2283 scratch->opcode = EEOP_FUNCEXPR_FUSAGE;
2284 }
2285 }
2286
2287 /*
2288 * Add expression steps deforming the ExprState's inner/outer/scan slots
2289 * as much as required by the expression.
2290 */
2291 static void
ExecInitExprSlots(ExprState * state,Node * node)2292 ExecInitExprSlots(ExprState *state, Node *node)
2293 {
2294 LastAttnumInfo info = {0, 0, 0};
2295
2296 /*
2297 * Figure out which attributes we're going to need.
2298 */
2299 get_last_attnums_walker(node, &info);
2300
2301 ExecPushExprSlots(state, &info);
2302 }
2303
2304 /*
2305 * Add steps deforming the ExprState's inner/out/scan slots as much as
2306 * indicated by info. This is useful when building an ExprState covering more
2307 * than one expression.
2308 */
2309 static void
ExecPushExprSlots(ExprState * state,LastAttnumInfo * info)2310 ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
2311 {
2312 ExprEvalStep scratch = {0};
2313
2314 scratch.resvalue = NULL;
2315 scratch.resnull = NULL;
2316
2317 /* Emit steps as needed */
2318 if (info->last_inner > 0)
2319 {
2320 scratch.opcode = EEOP_INNER_FETCHSOME;
2321 scratch.d.fetch.last_var = info->last_inner;
2322 scratch.d.fetch.fixed = false;
2323 scratch.d.fetch.kind = NULL;
2324 scratch.d.fetch.known_desc = NULL;
2325 ExecComputeSlotInfo(state, &scratch);
2326 ExprEvalPushStep(state, &scratch);
2327 }
2328 if (info->last_outer > 0)
2329 {
2330 scratch.opcode = EEOP_OUTER_FETCHSOME;
2331 scratch.d.fetch.last_var = info->last_outer;
2332 scratch.d.fetch.fixed = false;
2333 scratch.d.fetch.kind = NULL;
2334 scratch.d.fetch.known_desc = NULL;
2335 ExecComputeSlotInfo(state, &scratch);
2336 ExprEvalPushStep(state, &scratch);
2337 }
2338 if (info->last_scan > 0)
2339 {
2340 scratch.opcode = EEOP_SCAN_FETCHSOME;
2341 scratch.d.fetch.last_var = info->last_scan;
2342 scratch.d.fetch.fixed = false;
2343 scratch.d.fetch.kind = NULL;
2344 scratch.d.fetch.known_desc = NULL;
2345 ExecComputeSlotInfo(state, &scratch);
2346 ExprEvalPushStep(state, &scratch);
2347 }
2348 }
2349
2350 /*
2351 * get_last_attnums_walker: expression walker for ExecInitExprSlots
2352 */
2353 static bool
get_last_attnums_walker(Node * node,LastAttnumInfo * info)2354 get_last_attnums_walker(Node *node, LastAttnumInfo *info)
2355 {
2356 if (node == NULL)
2357 return false;
2358 if (IsA(node, Var))
2359 {
2360 Var *variable = (Var *) node;
2361 AttrNumber attnum = variable->varattno;
2362
2363 switch (variable->varno)
2364 {
2365 case INNER_VAR:
2366 info->last_inner = Max(info->last_inner, attnum);
2367 break;
2368
2369 case OUTER_VAR:
2370 info->last_outer = Max(info->last_outer, attnum);
2371 break;
2372
2373 /* INDEX_VAR is handled by default case */
2374
2375 default:
2376 info->last_scan = Max(info->last_scan, attnum);
2377 break;
2378 }
2379 return false;
2380 }
2381
2382 /*
2383 * Don't examine the arguments or filters of Aggrefs or WindowFuncs,
2384 * because those do not represent expressions to be evaluated within the
2385 * calling expression's econtext. GroupingFunc arguments are never
2386 * evaluated at all.
2387 */
2388 if (IsA(node, Aggref))
2389 return false;
2390 if (IsA(node, WindowFunc))
2391 return false;
2392 if (IsA(node, GroupingFunc))
2393 return false;
2394 return expression_tree_walker(node, get_last_attnums_walker,
2395 (void *) info);
2396 }
2397
2398 /*
2399 * Compute additional information for EEOP_*_FETCHSOME ops.
2400 *
2401 * The goal is to determine whether a slot is 'fixed', that is, every
2402 * evaluation of the expression will have the same type of slot, with an
2403 * equivalent descriptor.
2404 */
2405 static void
ExecComputeSlotInfo(ExprState * state,ExprEvalStep * op)2406 ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
2407 {
2408 PlanState *parent = state->parent;
2409 TupleDesc desc = NULL;
2410 const TupleTableSlotOps *tts_ops = NULL;
2411 bool isfixed = false;
2412
2413 if (op->d.fetch.known_desc != NULL)
2414 {
2415 desc = op->d.fetch.known_desc;
2416 tts_ops = op->d.fetch.kind;
2417 isfixed = op->d.fetch.kind != NULL;
2418 }
2419 else if (!parent)
2420 {
2421 isfixed = false;
2422 }
2423 else if (op->opcode == EEOP_INNER_FETCHSOME)
2424 {
2425 PlanState *is = innerPlanState(parent);
2426
2427 if (parent->inneropsset && !parent->inneropsfixed)
2428 {
2429 isfixed = false;
2430 }
2431 else if (parent->inneropsset && parent->innerops)
2432 {
2433 isfixed = true;
2434 tts_ops = parent->innerops;
2435 desc = ExecGetResultType(is);
2436 }
2437 else if (is)
2438 {
2439 tts_ops = ExecGetResultSlotOps(is, &isfixed);
2440 desc = ExecGetResultType(is);
2441 }
2442 }
2443 else if (op->opcode == EEOP_OUTER_FETCHSOME)
2444 {
2445 PlanState *os = outerPlanState(parent);
2446
2447 if (parent->outeropsset && !parent->outeropsfixed)
2448 {
2449 isfixed = false;
2450 }
2451 else if (parent->outeropsset && parent->outerops)
2452 {
2453 isfixed = true;
2454 tts_ops = parent->outerops;
2455 desc = ExecGetResultType(os);
2456 }
2457 else if (os)
2458 {
2459 tts_ops = ExecGetResultSlotOps(os, &isfixed);
2460 desc = ExecGetResultType(os);
2461 }
2462 }
2463 else if (op->opcode == EEOP_SCAN_FETCHSOME)
2464 {
2465 desc = parent->scandesc;
2466
2467 if (parent && parent->scanops)
2468 tts_ops = parent->scanops;
2469
2470 if (parent->scanopsset)
2471 isfixed = parent->scanopsfixed;
2472 }
2473
2474 if (isfixed && desc != NULL && tts_ops != NULL)
2475 {
2476 op->d.fetch.fixed = true;
2477 op->d.fetch.kind = tts_ops;
2478 op->d.fetch.known_desc = desc;
2479 }
2480 else
2481 {
2482 op->d.fetch.fixed = false;
2483 op->d.fetch.kind = NULL;
2484 op->d.fetch.known_desc = NULL;
2485 }
2486 }
2487
2488 /*
2489 * Prepare step for the evaluation of a whole-row variable.
2490 * The caller still has to push the step.
2491 */
2492 static void
ExecInitWholeRowVar(ExprEvalStep * scratch,Var * variable,ExprState * state)2493 ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state)
2494 {
2495 PlanState *parent = state->parent;
2496
2497 /* fill in all but the target */
2498 scratch->opcode = EEOP_WHOLEROW;
2499 scratch->d.wholerow.var = variable;
2500 scratch->d.wholerow.first = true;
2501 scratch->d.wholerow.slow = false;
2502 scratch->d.wholerow.tupdesc = NULL; /* filled at runtime */
2503 scratch->d.wholerow.junkFilter = NULL;
2504
2505 /*
2506 * If the input tuple came from a subquery, it might contain "resjunk"
2507 * columns (such as GROUP BY or ORDER BY columns), which we don't want to
2508 * keep in the whole-row result. We can get rid of such columns by
2509 * passing the tuple through a JunkFilter --- but to make one, we have to
2510 * lay our hands on the subquery's targetlist. Fortunately, there are not
2511 * very many cases where this can happen, and we can identify all of them
2512 * by examining our parent PlanState. We assume this is not an issue in
2513 * standalone expressions that don't have parent plans. (Whole-row Vars
2514 * can occur in such expressions, but they will always be referencing
2515 * table rows.)
2516 */
2517 if (parent)
2518 {
2519 PlanState *subplan = NULL;
2520
2521 switch (nodeTag(parent))
2522 {
2523 case T_SubqueryScanState:
2524 subplan = ((SubqueryScanState *) parent)->subplan;
2525 break;
2526 case T_CteScanState:
2527 subplan = ((CteScanState *) parent)->cteplanstate;
2528 break;
2529 default:
2530 break;
2531 }
2532
2533 if (subplan)
2534 {
2535 bool junk_filter_needed = false;
2536 ListCell *tlist;
2537
2538 /* Detect whether subplan tlist actually has any junk columns */
2539 foreach(tlist, subplan->plan->targetlist)
2540 {
2541 TargetEntry *tle = (TargetEntry *) lfirst(tlist);
2542
2543 if (tle->resjunk)
2544 {
2545 junk_filter_needed = true;
2546 break;
2547 }
2548 }
2549
2550 /* If so, build the junkfilter now */
2551 if (junk_filter_needed)
2552 {
2553 scratch->d.wholerow.junkFilter =
2554 ExecInitJunkFilter(subplan->plan->targetlist,
2555 ExecInitExtraTupleSlot(parent->state, NULL,
2556 &TTSOpsVirtual));
2557 }
2558 }
2559 }
2560 }
2561
2562 /*
2563 * Prepare evaluation of a SubscriptingRef expression.
2564 */
2565 static void
ExecInitSubscriptingRef(ExprEvalStep * scratch,SubscriptingRef * sbsref,ExprState * state,Datum * resv,bool * resnull)2566 ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref,
2567 ExprState *state, Datum *resv, bool *resnull)
2568 {
2569 bool isAssignment = (sbsref->refassgnexpr != NULL);
2570 SubscriptingRefState *sbsrefstate = palloc0(sizeof(SubscriptingRefState));
2571 List *adjust_jumps = NIL;
2572 ListCell *lc;
2573 int i;
2574
2575 /* Fill constant fields of SubscriptingRefState */
2576 sbsrefstate->isassignment = isAssignment;
2577 sbsrefstate->refelemtype = sbsref->refelemtype;
2578 sbsrefstate->refattrlength = get_typlen(sbsref->refcontainertype);
2579 get_typlenbyvalalign(sbsref->refelemtype,
2580 &sbsrefstate->refelemlength,
2581 &sbsrefstate->refelembyval,
2582 &sbsrefstate->refelemalign);
2583
2584 /*
2585 * Evaluate array input. It's safe to do so into resv/resnull, because we
2586 * won't use that as target for any of the other subexpressions, and it'll
2587 * be overwritten by the final EEOP_SBSREF_FETCH/ASSIGN step, which is
2588 * pushed last.
2589 */
2590 ExecInitExprRec(sbsref->refexpr, state, resv, resnull);
2591
2592 /*
2593 * If refexpr yields NULL, and it's a fetch, then result is NULL. We can
2594 * implement this with just JUMP_IF_NULL, since we evaluated the array
2595 * into the desired target location.
2596 */
2597 if (!isAssignment)
2598 {
2599 scratch->opcode = EEOP_JUMP_IF_NULL;
2600 scratch->d.jump.jumpdone = -1; /* adjust later */
2601 ExprEvalPushStep(state, scratch);
2602 adjust_jumps = lappend_int(adjust_jumps,
2603 state->steps_len - 1);
2604 }
2605
2606 /* Verify subscript list lengths are within limit */
2607 if (list_length(sbsref->refupperindexpr) > MAXDIM)
2608 ereport(ERROR,
2609 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2610 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
2611 list_length(sbsref->refupperindexpr), MAXDIM)));
2612
2613 if (list_length(sbsref->reflowerindexpr) > MAXDIM)
2614 ereport(ERROR,
2615 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2616 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
2617 list_length(sbsref->reflowerindexpr), MAXDIM)));
2618
2619 /* Evaluate upper subscripts */
2620 i = 0;
2621 foreach(lc, sbsref->refupperindexpr)
2622 {
2623 Expr *e = (Expr *) lfirst(lc);
2624
2625 /* When slicing, individual subscript bounds can be omitted */
2626 if (!e)
2627 {
2628 sbsrefstate->upperprovided[i] = false;
2629 i++;
2630 continue;
2631 }
2632
2633 sbsrefstate->upperprovided[i] = true;
2634
2635 /* Each subscript is evaluated into subscriptvalue/subscriptnull */
2636 ExecInitExprRec(e, state,
2637 &sbsrefstate->subscriptvalue, &sbsrefstate->subscriptnull);
2638
2639 /* ... and then SBSREF_SUBSCRIPT saves it into step's workspace */
2640 scratch->opcode = EEOP_SBSREF_SUBSCRIPT;
2641 scratch->d.sbsref_subscript.state = sbsrefstate;
2642 scratch->d.sbsref_subscript.off = i;
2643 scratch->d.sbsref_subscript.isupper = true;
2644 scratch->d.sbsref_subscript.jumpdone = -1; /* adjust later */
2645 ExprEvalPushStep(state, scratch);
2646 adjust_jumps = lappend_int(adjust_jumps,
2647 state->steps_len - 1);
2648 i++;
2649 }
2650 sbsrefstate->numupper = i;
2651
2652 /* Evaluate lower subscripts similarly */
2653 i = 0;
2654 foreach(lc, sbsref->reflowerindexpr)
2655 {
2656 Expr *e = (Expr *) lfirst(lc);
2657
2658 /* When slicing, individual subscript bounds can be omitted */
2659 if (!e)
2660 {
2661 sbsrefstate->lowerprovided[i] = false;
2662 i++;
2663 continue;
2664 }
2665
2666 sbsrefstate->lowerprovided[i] = true;
2667
2668 /* Each subscript is evaluated into subscriptvalue/subscriptnull */
2669 ExecInitExprRec(e, state,
2670 &sbsrefstate->subscriptvalue, &sbsrefstate->subscriptnull);
2671
2672 /* ... and then SBSREF_SUBSCRIPT saves it into step's workspace */
2673 scratch->opcode = EEOP_SBSREF_SUBSCRIPT;
2674 scratch->d.sbsref_subscript.state = sbsrefstate;
2675 scratch->d.sbsref_subscript.off = i;
2676 scratch->d.sbsref_subscript.isupper = false;
2677 scratch->d.sbsref_subscript.jumpdone = -1; /* adjust later */
2678 ExprEvalPushStep(state, scratch);
2679 adjust_jumps = lappend_int(adjust_jumps,
2680 state->steps_len - 1);
2681 i++;
2682 }
2683 sbsrefstate->numlower = i;
2684
2685 /* Should be impossible if parser is sane, but check anyway: */
2686 if (sbsrefstate->numlower != 0 &&
2687 sbsrefstate->numupper != sbsrefstate->numlower)
2688 elog(ERROR, "upper and lower index lists are not same length");
2689
2690 if (isAssignment)
2691 {
2692 Datum *save_innermost_caseval;
2693 bool *save_innermost_casenull;
2694
2695 /*
2696 * We might have a nested-assignment situation, in which the
2697 * refassgnexpr is itself a FieldStore or SubscriptingRef that needs
2698 * to obtain and modify the previous value of the array element or
2699 * slice being replaced. If so, we have to extract that value from
2700 * the array and pass it down via the CaseTestExpr mechanism. It's
2701 * safe to reuse the CASE mechanism because there cannot be a CASE
2702 * between here and where the value would be needed, and an array
2703 * assignment can't be within a CASE either. (So saving and restoring
2704 * innermost_caseval is just paranoia, but let's do it anyway.)
2705 *
2706 * Since fetching the old element might be a nontrivial expense, do it
2707 * only if the argument actually needs it.
2708 */
2709 if (isAssignmentIndirectionExpr(sbsref->refassgnexpr))
2710 {
2711 scratch->opcode = EEOP_SBSREF_OLD;
2712 scratch->d.sbsref.state = sbsrefstate;
2713 ExprEvalPushStep(state, scratch);
2714 }
2715
2716 /* SBSREF_OLD puts extracted value into prevvalue/prevnull */
2717 save_innermost_caseval = state->innermost_caseval;
2718 save_innermost_casenull = state->innermost_casenull;
2719 state->innermost_caseval = &sbsrefstate->prevvalue;
2720 state->innermost_casenull = &sbsrefstate->prevnull;
2721
2722 /* evaluate replacement value into replacevalue/replacenull */
2723 ExecInitExprRec(sbsref->refassgnexpr, state,
2724 &sbsrefstate->replacevalue, &sbsrefstate->replacenull);
2725
2726 state->innermost_caseval = save_innermost_caseval;
2727 state->innermost_casenull = save_innermost_casenull;
2728
2729 /* and perform the assignment */
2730 scratch->opcode = EEOP_SBSREF_ASSIGN;
2731 scratch->d.sbsref.state = sbsrefstate;
2732 ExprEvalPushStep(state, scratch);
2733
2734 }
2735 else
2736 {
2737 /* array fetch is much simpler */
2738 scratch->opcode = EEOP_SBSREF_FETCH;
2739 scratch->d.sbsref.state = sbsrefstate;
2740 ExprEvalPushStep(state, scratch);
2741
2742 }
2743
2744 /* adjust jump targets */
2745 foreach(lc, adjust_jumps)
2746 {
2747 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
2748
2749 if (as->opcode == EEOP_SBSREF_SUBSCRIPT)
2750 {
2751 Assert(as->d.sbsref_subscript.jumpdone == -1);
2752 as->d.sbsref_subscript.jumpdone = state->steps_len;
2753 }
2754 else
2755 {
2756 Assert(as->opcode == EEOP_JUMP_IF_NULL);
2757 Assert(as->d.jump.jumpdone == -1);
2758 as->d.jump.jumpdone = state->steps_len;
2759 }
2760 }
2761 }
2762
2763 /*
2764 * Helper for preparing SubscriptingRef expressions for evaluation: is expr
2765 * a nested FieldStore or SubscriptingRef that needs the old element value
2766 * passed down?
2767 *
2768 * (We could use this in FieldStore too, but in that case passing the old
2769 * value is so cheap there's no need.)
2770 *
2771 * Note: it might seem that this needs to recurse, but in most cases it does
2772 * not; the CaseTestExpr, if any, will be directly the arg or refexpr of the
2773 * top-level node. Nested-assignment situations give rise to expression
2774 * trees in which each level of assignment has its own CaseTestExpr, and the
2775 * recursive structure appears within the newvals or refassgnexpr field.
2776 * There is an exception, though: if the array is an array-of-domain, we will
2777 * have a CoerceToDomain as the refassgnexpr, and we need to be able to look
2778 * through that.
2779 */
2780 static bool
isAssignmentIndirectionExpr(Expr * expr)2781 isAssignmentIndirectionExpr(Expr *expr)
2782 {
2783 if (expr == NULL)
2784 return false; /* just paranoia */
2785 if (IsA(expr, FieldStore))
2786 {
2787 FieldStore *fstore = (FieldStore *) expr;
2788
2789 if (fstore->arg && IsA(fstore->arg, CaseTestExpr))
2790 return true;
2791 }
2792 else if (IsA(expr, SubscriptingRef))
2793 {
2794 SubscriptingRef *sbsRef = (SubscriptingRef *) expr;
2795
2796 if (sbsRef->refexpr && IsA(sbsRef->refexpr, CaseTestExpr))
2797 return true;
2798 }
2799 else if (IsA(expr, CoerceToDomain))
2800 {
2801 CoerceToDomain *cd = (CoerceToDomain *) expr;
2802
2803 return isAssignmentIndirectionExpr(cd->arg);
2804 }
2805 return false;
2806 }
2807
2808 /*
2809 * Prepare evaluation of a CoerceToDomain expression.
2810 */
2811 static void
ExecInitCoerceToDomain(ExprEvalStep * scratch,CoerceToDomain * ctest,ExprState * state,Datum * resv,bool * resnull)2812 ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
2813 ExprState *state, Datum *resv, bool *resnull)
2814 {
2815 ExprEvalStep scratch2 = {0};
2816 DomainConstraintRef *constraint_ref;
2817 Datum *domainval = NULL;
2818 bool *domainnull = NULL;
2819 Datum *save_innermost_domainval;
2820 bool *save_innermost_domainnull;
2821 ListCell *l;
2822
2823 scratch->d.domaincheck.resulttype = ctest->resulttype;
2824 /* we'll allocate workspace only if needed */
2825 scratch->d.domaincheck.checkvalue = NULL;
2826 scratch->d.domaincheck.checknull = NULL;
2827
2828 /*
2829 * Evaluate argument - it's fine to directly store it into resv/resnull,
2830 * if there's constraint failures there'll be errors, otherwise it's what
2831 * needs to be returned.
2832 */
2833 ExecInitExprRec(ctest->arg, state, resv, resnull);
2834
2835 /*
2836 * Note: if the argument is of varlena type, it could be a R/W expanded
2837 * object. We want to return the R/W pointer as the final result, but we
2838 * have to pass a R/O pointer as the value to be tested by any functions
2839 * in check expressions. We don't bother to emit a MAKE_READONLY step
2840 * unless there's actually at least one check expression, though. Until
2841 * we've tested that, domainval/domainnull are NULL.
2842 */
2843
2844 /*
2845 * Collect the constraints associated with the domain.
2846 *
2847 * Note: before PG v10 we'd recheck the set of constraints during each
2848 * evaluation of the expression. Now we bake them into the ExprState
2849 * during executor initialization. That means we don't need typcache.c to
2850 * provide compiled exprs.
2851 */
2852 constraint_ref = (DomainConstraintRef *)
2853 palloc(sizeof(DomainConstraintRef));
2854 InitDomainConstraintRef(ctest->resulttype,
2855 constraint_ref,
2856 CurrentMemoryContext,
2857 false);
2858
2859 /*
2860 * Compile code to check each domain constraint. NOTNULL constraints can
2861 * just be applied on the resv/resnull value, but for CHECK constraints we
2862 * need more pushups.
2863 */
2864 foreach(l, constraint_ref->constraints)
2865 {
2866 DomainConstraintState *con = (DomainConstraintState *) lfirst(l);
2867
2868 scratch->d.domaincheck.constraintname = con->name;
2869
2870 switch (con->constrainttype)
2871 {
2872 case DOM_CONSTRAINT_NOTNULL:
2873 scratch->opcode = EEOP_DOMAIN_NOTNULL;
2874 ExprEvalPushStep(state, scratch);
2875 break;
2876 case DOM_CONSTRAINT_CHECK:
2877 /* Allocate workspace for CHECK output if we didn't yet */
2878 if (scratch->d.domaincheck.checkvalue == NULL)
2879 {
2880 scratch->d.domaincheck.checkvalue =
2881 (Datum *) palloc(sizeof(Datum));
2882 scratch->d.domaincheck.checknull =
2883 (bool *) palloc(sizeof(bool));
2884 }
2885
2886 /*
2887 * If first time through, determine where CoerceToDomainValue
2888 * nodes should read from.
2889 */
2890 if (domainval == NULL)
2891 {
2892 /*
2893 * Since value might be read multiple times, force to R/O
2894 * - but only if it could be an expanded datum.
2895 */
2896 if (get_typlen(ctest->resulttype) == -1)
2897 {
2898 /* Yes, so make output workspace for MAKE_READONLY */
2899 domainval = (Datum *) palloc(sizeof(Datum));
2900 domainnull = (bool *) palloc(sizeof(bool));
2901
2902 /* Emit MAKE_READONLY */
2903 scratch2.opcode = EEOP_MAKE_READONLY;
2904 scratch2.resvalue = domainval;
2905 scratch2.resnull = domainnull;
2906 scratch2.d.make_readonly.value = resv;
2907 scratch2.d.make_readonly.isnull = resnull;
2908 ExprEvalPushStep(state, &scratch2);
2909 }
2910 else
2911 {
2912 /* No, so it's fine to read from resv/resnull */
2913 domainval = resv;
2914 domainnull = resnull;
2915 }
2916 }
2917
2918 /*
2919 * Set up value to be returned by CoerceToDomainValue nodes.
2920 * We must save and restore innermost_domainval/null fields,
2921 * in case this node is itself within a check expression for
2922 * another domain.
2923 */
2924 save_innermost_domainval = state->innermost_domainval;
2925 save_innermost_domainnull = state->innermost_domainnull;
2926 state->innermost_domainval = domainval;
2927 state->innermost_domainnull = domainnull;
2928
2929 /* evaluate check expression value */
2930 ExecInitExprRec(con->check_expr, state,
2931 scratch->d.domaincheck.checkvalue,
2932 scratch->d.domaincheck.checknull);
2933
2934 state->innermost_domainval = save_innermost_domainval;
2935 state->innermost_domainnull = save_innermost_domainnull;
2936
2937 /* now test result */
2938 scratch->opcode = EEOP_DOMAIN_CHECK;
2939 ExprEvalPushStep(state, scratch);
2940
2941 break;
2942 default:
2943 elog(ERROR, "unrecognized constraint type: %d",
2944 (int) con->constrainttype);
2945 break;
2946 }
2947 }
2948 }
2949
2950 /*
2951 * Build transition/combine function invocations for all aggregate transition
2952 * / combination function invocations in a grouping sets phase. This has to
2953 * invoke all sort based transitions in a phase (if doSort is true), all hash
2954 * based transitions (if doHash is true), or both (both true).
2955 *
2956 * The resulting expression will, for each set of transition values, first
2957 * check for filters, evaluate aggregate input, check that that input is not
2958 * NULL for a strict transition function, and then finally invoke the
2959 * transition for each of the concurrently computed grouping sets.
2960 */
2961 ExprState *
ExecBuildAggTrans(AggState * aggstate,AggStatePerPhase phase,bool doSort,bool doHash)2962 ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
2963 bool doSort, bool doHash)
2964 {
2965 ExprState *state = makeNode(ExprState);
2966 PlanState *parent = &aggstate->ss.ps;
2967 ExprEvalStep scratch = {0};
2968 int transno = 0;
2969 int setoff = 0;
2970 bool isCombine = DO_AGGSPLIT_COMBINE(aggstate->aggsplit);
2971 LastAttnumInfo deform = {0, 0, 0};
2972
2973 state->expr = (Expr *) aggstate;
2974 state->parent = parent;
2975
2976 scratch.resvalue = &state->resvalue;
2977 scratch.resnull = &state->resnull;
2978
2979 /*
2980 * First figure out which slots, and how many columns from each, we're
2981 * going to need.
2982 */
2983 for (transno = 0; transno < aggstate->numtrans; transno++)
2984 {
2985 AggStatePerTrans pertrans = &aggstate->pertrans[transno];
2986
2987 get_last_attnums_walker((Node *) pertrans->aggref->aggdirectargs,
2988 &deform);
2989 get_last_attnums_walker((Node *) pertrans->aggref->args,
2990 &deform);
2991 get_last_attnums_walker((Node *) pertrans->aggref->aggorder,
2992 &deform);
2993 get_last_attnums_walker((Node *) pertrans->aggref->aggdistinct,
2994 &deform);
2995 get_last_attnums_walker((Node *) pertrans->aggref->aggfilter,
2996 &deform);
2997 }
2998 ExecPushExprSlots(state, &deform);
2999
3000 /*
3001 * Emit instructions for each transition value / grouping set combination.
3002 */
3003 for (transno = 0; transno < aggstate->numtrans; transno++)
3004 {
3005 AggStatePerTrans pertrans = &aggstate->pertrans[transno];
3006 int argno;
3007 int setno;
3008 FunctionCallInfo trans_fcinfo = pertrans->transfn_fcinfo;
3009 ListCell *arg;
3010 ListCell *bail;
3011 List *adjust_bailout = NIL;
3012 NullableDatum *strictargs = NULL;
3013 bool *strictnulls = NULL;
3014
3015 /*
3016 * If filter present, emit. Do so before evaluating the input, to
3017 * avoid potentially unneeded computations, or even worse, unintended
3018 * side-effects. When combining, all the necessary filtering has
3019 * already been done.
3020 */
3021 if (pertrans->aggref->aggfilter && !isCombine)
3022 {
3023 /* evaluate filter expression */
3024 ExecInitExprRec(pertrans->aggref->aggfilter, state,
3025 &state->resvalue, &state->resnull);
3026 /* and jump out if false */
3027 scratch.opcode = EEOP_JUMP_IF_NOT_TRUE;
3028 scratch.d.jump.jumpdone = -1; /* adjust later */
3029 ExprEvalPushStep(state, &scratch);
3030 adjust_bailout = lappend_int(adjust_bailout,
3031 state->steps_len - 1);
3032 }
3033
3034 /*
3035 * Evaluate arguments to aggregate/combine function.
3036 */
3037 argno = 0;
3038 if (isCombine)
3039 {
3040 /*
3041 * Combining two aggregate transition values. Instead of directly
3042 * coming from a tuple the input is a, potentially deserialized,
3043 * transition value.
3044 */
3045 TargetEntry *source_tle;
3046
3047 Assert(pertrans->numSortCols == 0);
3048 Assert(list_length(pertrans->aggref->args) == 1);
3049
3050 strictargs = trans_fcinfo->args + 1;
3051 source_tle = (TargetEntry *) linitial(pertrans->aggref->args);
3052
3053 /*
3054 * deserialfn_oid will be set if we must deserialize the input
3055 * state before calling the combine function.
3056 */
3057 if (!OidIsValid(pertrans->deserialfn_oid))
3058 {
3059 /*
3060 * Start from 1, since the 0th arg will be the transition
3061 * value
3062 */
3063 ExecInitExprRec(source_tle->expr, state,
3064 &trans_fcinfo->args[argno + 1].value,
3065 &trans_fcinfo->args[argno + 1].isnull);
3066 }
3067 else
3068 {
3069 FunctionCallInfo ds_fcinfo = pertrans->deserialfn_fcinfo;
3070
3071 /* evaluate argument */
3072 ExecInitExprRec(source_tle->expr, state,
3073 &ds_fcinfo->args[0].value,
3074 &ds_fcinfo->args[0].isnull);
3075
3076 /* Dummy second argument for type-safety reasons */
3077 ds_fcinfo->args[1].value = PointerGetDatum(NULL);
3078 ds_fcinfo->args[1].isnull = false;
3079
3080 /*
3081 * Don't call a strict deserialization function with NULL
3082 * input
3083 */
3084 if (pertrans->deserialfn.fn_strict)
3085 scratch.opcode = EEOP_AGG_STRICT_DESERIALIZE;
3086 else
3087 scratch.opcode = EEOP_AGG_DESERIALIZE;
3088
3089 scratch.d.agg_deserialize.aggstate = aggstate;
3090 scratch.d.agg_deserialize.fcinfo_data = ds_fcinfo;
3091 scratch.d.agg_deserialize.jumpnull = -1; /* adjust later */
3092 scratch.resvalue = &trans_fcinfo->args[argno + 1].value;
3093 scratch.resnull = &trans_fcinfo->args[argno + 1].isnull;
3094
3095 ExprEvalPushStep(state, &scratch);
3096 /* don't add an adjustment unless the function is strict */
3097 if (pertrans->deserialfn.fn_strict)
3098 adjust_bailout = lappend_int(adjust_bailout,
3099 state->steps_len - 1);
3100
3101 /* restore normal settings of scratch fields */
3102 scratch.resvalue = &state->resvalue;
3103 scratch.resnull = &state->resnull;
3104 }
3105 argno++;
3106 }
3107 else if (pertrans->numSortCols == 0)
3108 {
3109 /*
3110 * Normal transition function without ORDER BY / DISTINCT.
3111 */
3112 strictargs = trans_fcinfo->args + 1;
3113
3114 foreach(arg, pertrans->aggref->args)
3115 {
3116 TargetEntry *source_tle = (TargetEntry *) lfirst(arg);
3117
3118 /*
3119 * Start from 1, since the 0th arg will be the transition
3120 * value
3121 */
3122 ExecInitExprRec(source_tle->expr, state,
3123 &trans_fcinfo->args[argno + 1].value,
3124 &trans_fcinfo->args[argno + 1].isnull);
3125 argno++;
3126 }
3127 }
3128 else if (pertrans->numInputs == 1)
3129 {
3130 /*
3131 * DISTINCT and/or ORDER BY case, with a single column sorted on.
3132 */
3133 TargetEntry *source_tle =
3134 (TargetEntry *) linitial(pertrans->aggref->args);
3135
3136 Assert(list_length(pertrans->aggref->args) == 1);
3137
3138 ExecInitExprRec(source_tle->expr, state,
3139 &state->resvalue,
3140 &state->resnull);
3141 strictnulls = &state->resnull;
3142 argno++;
3143 }
3144 else
3145 {
3146 /*
3147 * DISTINCT and/or ORDER BY case, with multiple columns sorted on.
3148 */
3149 Datum *values = pertrans->sortslot->tts_values;
3150 bool *nulls = pertrans->sortslot->tts_isnull;
3151
3152 strictnulls = nulls;
3153
3154 foreach(arg, pertrans->aggref->args)
3155 {
3156 TargetEntry *source_tle = (TargetEntry *) lfirst(arg);
3157
3158 ExecInitExprRec(source_tle->expr, state,
3159 &values[argno], &nulls[argno]);
3160 argno++;
3161 }
3162 }
3163 Assert(pertrans->numInputs == argno);
3164
3165 /*
3166 * For a strict transfn, nothing happens when there's a NULL input; we
3167 * just keep the prior transValue. This is true for both plain and
3168 * sorted/distinct aggregates.
3169 */
3170 if (trans_fcinfo->flinfo->fn_strict && pertrans->numTransInputs > 0)
3171 {
3172 if (strictnulls)
3173 scratch.opcode = EEOP_AGG_STRICT_INPUT_CHECK_NULLS;
3174 else
3175 scratch.opcode = EEOP_AGG_STRICT_INPUT_CHECK_ARGS;
3176 scratch.d.agg_strict_input_check.nulls = strictnulls;
3177 scratch.d.agg_strict_input_check.args = strictargs;
3178 scratch.d.agg_strict_input_check.jumpnull = -1; /* adjust later */
3179 scratch.d.agg_strict_input_check.nargs = pertrans->numTransInputs;
3180 ExprEvalPushStep(state, &scratch);
3181 adjust_bailout = lappend_int(adjust_bailout,
3182 state->steps_len - 1);
3183 }
3184
3185 /*
3186 * Call transition function (once for each concurrently evaluated
3187 * grouping set). Do so for both sort and hash based computations, as
3188 * applicable.
3189 */
3190 setoff = 0;
3191 if (doSort)
3192 {
3193 int processGroupingSets = Max(phase->numsets, 1);
3194
3195 for (setno = 0; setno < processGroupingSets; setno++)
3196 {
3197 ExecBuildAggTransCall(state, aggstate, &scratch, trans_fcinfo,
3198 pertrans, transno, setno, setoff, false);
3199 setoff++;
3200 }
3201 }
3202
3203 if (doHash)
3204 {
3205 int numHashes = aggstate->num_hashes;
3206
3207 /* in MIXED mode, there'll be preceding transition values */
3208 if (aggstate->aggstrategy != AGG_HASHED)
3209 setoff = aggstate->maxsets;
3210 else
3211 setoff = 0;
3212
3213 for (setno = 0; setno < numHashes; setno++)
3214 {
3215 ExecBuildAggTransCall(state, aggstate, &scratch, trans_fcinfo,
3216 pertrans, transno, setno, setoff, true);
3217 setoff++;
3218 }
3219 }
3220
3221 /* adjust early bail out jump target(s) */
3222 foreach(bail, adjust_bailout)
3223 {
3224 ExprEvalStep *as = &state->steps[lfirst_int(bail)];
3225
3226 if (as->opcode == EEOP_JUMP_IF_NOT_TRUE)
3227 {
3228 Assert(as->d.jump.jumpdone == -1);
3229 as->d.jump.jumpdone = state->steps_len;
3230 }
3231 else if (as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_ARGS ||
3232 as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
3233 {
3234 Assert(as->d.agg_strict_input_check.jumpnull == -1);
3235 as->d.agg_strict_input_check.jumpnull = state->steps_len;
3236 }
3237 else if (as->opcode == EEOP_AGG_STRICT_DESERIALIZE)
3238 {
3239 Assert(as->d.agg_deserialize.jumpnull == -1);
3240 as->d.agg_deserialize.jumpnull = state->steps_len;
3241 }
3242 }
3243 }
3244
3245 scratch.resvalue = NULL;
3246 scratch.resnull = NULL;
3247 scratch.opcode = EEOP_DONE;
3248 ExprEvalPushStep(state, &scratch);
3249
3250 ExecReadyExpr(state);
3251
3252 return state;
3253 }
3254
3255 /*
3256 * Build transition/combine function invocation for a single transition
3257 * value. This is separated from ExecBuildAggTrans() because there are
3258 * multiple callsites (hash and sort in some grouping set cases).
3259 */
3260 static void
ExecBuildAggTransCall(ExprState * state,AggState * aggstate,ExprEvalStep * scratch,FunctionCallInfo fcinfo,AggStatePerTrans pertrans,int transno,int setno,int setoff,bool ishash)3261 ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
3262 ExprEvalStep *scratch,
3263 FunctionCallInfo fcinfo, AggStatePerTrans pertrans,
3264 int transno, int setno, int setoff, bool ishash)
3265 {
3266 int adjust_init_jumpnull = -1;
3267 int adjust_strict_jumpnull = -1;
3268 ExprContext *aggcontext;
3269
3270 if (ishash)
3271 aggcontext = aggstate->hashcontext;
3272 else
3273 aggcontext = aggstate->aggcontexts[setno];
3274
3275 /*
3276 * If the initial value for the transition state doesn't exist in the
3277 * pg_aggregate table then we will let the first non-NULL value returned
3278 * from the outer procNode become the initial value. (This is useful for
3279 * aggregates like max() and min().) The noTransValue flag signals that we
3280 * still need to do this.
3281 */
3282 if (pertrans->numSortCols == 0 &&
3283 fcinfo->flinfo->fn_strict &&
3284 pertrans->initValueIsNull)
3285 {
3286 scratch->opcode = EEOP_AGG_INIT_TRANS;
3287 scratch->d.agg_init_trans.aggstate = aggstate;
3288 scratch->d.agg_init_trans.pertrans = pertrans;
3289 scratch->d.agg_init_trans.setno = setno;
3290 scratch->d.agg_init_trans.setoff = setoff;
3291 scratch->d.agg_init_trans.transno = transno;
3292 scratch->d.agg_init_trans.aggcontext = aggcontext;
3293 scratch->d.agg_init_trans.jumpnull = -1; /* adjust later */
3294 ExprEvalPushStep(state, scratch);
3295
3296 /* see comment about jumping out below */
3297 adjust_init_jumpnull = state->steps_len - 1;
3298 }
3299
3300 if (pertrans->numSortCols == 0 &&
3301 fcinfo->flinfo->fn_strict)
3302 {
3303 scratch->opcode = EEOP_AGG_STRICT_TRANS_CHECK;
3304 scratch->d.agg_strict_trans_check.aggstate = aggstate;
3305 scratch->d.agg_strict_trans_check.setno = setno;
3306 scratch->d.agg_strict_trans_check.setoff = setoff;
3307 scratch->d.agg_strict_trans_check.transno = transno;
3308 scratch->d.agg_strict_trans_check.jumpnull = -1; /* adjust later */
3309 ExprEvalPushStep(state, scratch);
3310
3311 /*
3312 * Note, we don't push into adjust_bailout here - those jump to the
3313 * end of all transition value computations. Here a single transition
3314 * value is NULL, so just skip processing the individual value.
3315 */
3316 adjust_strict_jumpnull = state->steps_len - 1;
3317 }
3318
3319 /* invoke appropriate transition implementation */
3320 if (pertrans->numSortCols == 0 && pertrans->transtypeByVal)
3321 scratch->opcode = EEOP_AGG_PLAIN_TRANS_BYVAL;
3322 else if (pertrans->numSortCols == 0)
3323 scratch->opcode = EEOP_AGG_PLAIN_TRANS;
3324 else if (pertrans->numInputs == 1)
3325 scratch->opcode = EEOP_AGG_ORDERED_TRANS_DATUM;
3326 else
3327 scratch->opcode = EEOP_AGG_ORDERED_TRANS_TUPLE;
3328
3329 scratch->d.agg_trans.aggstate = aggstate;
3330 scratch->d.agg_trans.pertrans = pertrans;
3331 scratch->d.agg_trans.setno = setno;
3332 scratch->d.agg_trans.setoff = setoff;
3333 scratch->d.agg_trans.transno = transno;
3334 scratch->d.agg_trans.aggcontext = aggcontext;
3335 ExprEvalPushStep(state, scratch);
3336
3337 /* adjust jumps so they jump till after transition invocation */
3338 if (adjust_init_jumpnull != -1)
3339 {
3340 ExprEvalStep *as = &state->steps[adjust_init_jumpnull];
3341
3342 Assert(as->d.agg_init_trans.jumpnull == -1);
3343 as->d.agg_init_trans.jumpnull = state->steps_len;
3344 }
3345 if (adjust_strict_jumpnull != -1)
3346 {
3347 ExprEvalStep *as = &state->steps[adjust_strict_jumpnull];
3348
3349 Assert(as->d.agg_strict_trans_check.jumpnull == -1);
3350 as->d.agg_strict_trans_check.jumpnull = state->steps_len;
3351 }
3352 }
3353
3354 /*
3355 * Build equality expression that can be evaluated using ExecQual(), returning
3356 * true if the expression context's inner/outer tuple are NOT DISTINCT. I.e
3357 * two nulls match, a null and a not-null don't match.
3358 *
3359 * desc: tuple descriptor of the to-be-compared tuples
3360 * numCols: the number of attributes to be examined
3361 * keyColIdx: array of attribute column numbers
3362 * eqFunctions: array of function oids of the equality functions to use
3363 * parent: parent executor node
3364 */
3365 ExprState *
ExecBuildGroupingEqual(TupleDesc ldesc,TupleDesc rdesc,const TupleTableSlotOps * lops,const TupleTableSlotOps * rops,int numCols,const AttrNumber * keyColIdx,const Oid * eqfunctions,const Oid * collations,PlanState * parent)3366 ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
3367 const TupleTableSlotOps *lops, const TupleTableSlotOps *rops,
3368 int numCols,
3369 const AttrNumber *keyColIdx,
3370 const Oid *eqfunctions,
3371 const Oid *collations,
3372 PlanState *parent)
3373 {
3374 ExprState *state = makeNode(ExprState);
3375 ExprEvalStep scratch = {0};
3376 int natt;
3377 int maxatt = -1;
3378 List *adjust_jumps = NIL;
3379 ListCell *lc;
3380
3381 /*
3382 * When no columns are actually compared, the result's always true. See
3383 * special case in ExecQual().
3384 */
3385 if (numCols == 0)
3386 return NULL;
3387
3388 state->expr = NULL;
3389 state->flags = EEO_FLAG_IS_QUAL;
3390 state->parent = parent;
3391
3392 scratch.resvalue = &state->resvalue;
3393 scratch.resnull = &state->resnull;
3394
3395 /* compute max needed attribute */
3396 for (natt = 0; natt < numCols; natt++)
3397 {
3398 int attno = keyColIdx[natt];
3399
3400 if (attno > maxatt)
3401 maxatt = attno;
3402 }
3403 Assert(maxatt >= 0);
3404
3405 /* push deform steps */
3406 scratch.opcode = EEOP_INNER_FETCHSOME;
3407 scratch.d.fetch.last_var = maxatt;
3408 scratch.d.fetch.fixed = false;
3409 scratch.d.fetch.known_desc = ldesc;
3410 scratch.d.fetch.kind = lops;
3411 ExecComputeSlotInfo(state, &scratch);
3412 ExprEvalPushStep(state, &scratch);
3413
3414 scratch.opcode = EEOP_OUTER_FETCHSOME;
3415 scratch.d.fetch.last_var = maxatt;
3416 scratch.d.fetch.fixed = false;
3417 scratch.d.fetch.known_desc = rdesc;
3418 scratch.d.fetch.kind = rops;
3419 ExecComputeSlotInfo(state, &scratch);
3420 ExprEvalPushStep(state, &scratch);
3421
3422 /*
3423 * Start comparing at the last field (least significant sort key). That's
3424 * the most likely to be different if we are dealing with sorted input.
3425 */
3426 for (natt = numCols; --natt >= 0;)
3427 {
3428 int attno = keyColIdx[natt];
3429 Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1);
3430 Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1);
3431 Oid foid = eqfunctions[natt];
3432 Oid collid = collations[natt];
3433 FmgrInfo *finfo;
3434 FunctionCallInfo fcinfo;
3435 AclResult aclresult;
3436
3437 /* Check permission to call function */
3438 aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
3439 if (aclresult != ACLCHECK_OK)
3440 aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
3441
3442 InvokeFunctionExecuteHook(foid);
3443
3444 /* Set up the primary fmgr lookup information */
3445 finfo = palloc0(sizeof(FmgrInfo));
3446 fcinfo = palloc0(SizeForFunctionCallInfo(2));
3447 fmgr_info(foid, finfo);
3448 fmgr_info_set_expr(NULL, finfo);
3449 InitFunctionCallInfoData(*fcinfo, finfo, 2,
3450 collid, NULL, NULL);
3451
3452 /* left arg */
3453 scratch.opcode = EEOP_INNER_VAR;
3454 scratch.d.var.attnum = attno - 1;
3455 scratch.d.var.vartype = latt->atttypid;
3456 scratch.resvalue = &fcinfo->args[0].value;
3457 scratch.resnull = &fcinfo->args[0].isnull;
3458 ExprEvalPushStep(state, &scratch);
3459
3460 /* right arg */
3461 scratch.opcode = EEOP_OUTER_VAR;
3462 scratch.d.var.attnum = attno - 1;
3463 scratch.d.var.vartype = ratt->atttypid;
3464 scratch.resvalue = &fcinfo->args[1].value;
3465 scratch.resnull = &fcinfo->args[1].isnull;
3466 ExprEvalPushStep(state, &scratch);
3467
3468 /* evaluate distinctness */
3469 scratch.opcode = EEOP_NOT_DISTINCT;
3470 scratch.d.func.finfo = finfo;
3471 scratch.d.func.fcinfo_data = fcinfo;
3472 scratch.d.func.fn_addr = finfo->fn_addr;
3473 scratch.d.func.nargs = 2;
3474 scratch.resvalue = &state->resvalue;
3475 scratch.resnull = &state->resnull;
3476 ExprEvalPushStep(state, &scratch);
3477
3478 /* then emit EEOP_QUAL to detect if result is false (or null) */
3479 scratch.opcode = EEOP_QUAL;
3480 scratch.d.qualexpr.jumpdone = -1;
3481 scratch.resvalue = &state->resvalue;
3482 scratch.resnull = &state->resnull;
3483 ExprEvalPushStep(state, &scratch);
3484 adjust_jumps = lappend_int(adjust_jumps,
3485 state->steps_len - 1);
3486 }
3487
3488 /* adjust jump targets */
3489 foreach(lc, adjust_jumps)
3490 {
3491 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
3492
3493 Assert(as->opcode == EEOP_QUAL);
3494 Assert(as->d.qualexpr.jumpdone == -1);
3495 as->d.qualexpr.jumpdone = state->steps_len;
3496 }
3497
3498 scratch.resvalue = NULL;
3499 scratch.resnull = NULL;
3500 scratch.opcode = EEOP_DONE;
3501 ExprEvalPushStep(state, &scratch);
3502
3503 ExecReadyExpr(state);
3504
3505 return state;
3506 }
3507