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