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