1 /*-------------------------------------------------------------------------
2 *
3 * execExpr.c
4 * Expression evaluation infrastructure.
5 *
6 * During executor startup, we compile each expression tree (which has
7 * previously been processed by the parser and planner) into an ExprState,
8 * using ExecInitExpr() et al. This converts the tree into a flat array
9 * of ExprEvalSteps, which may be thought of as instructions in a program.
10 * At runtime, we'll execute steps, starting with the first, until we reach
11 * an EEOP_DONE opcode.
12 *
13 * This file contains the "compilation" logic. It is independent of the
14 * specific execution technology we use (switch statement, computed goto,
15 * JIT compilation, etc).
16 *
17 * See src/backend/executor/README for some background, specifically the
18 * "Expression Trees and ExprState nodes", "Expression Initialization",
19 * and "Expression Evaluation" sections.
20 *
21 *
22 * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
23 * Portions Copyright (c) 1994, Regents of the University of California
24 *
25 *
26 * IDENTIFICATION
27 * src/backend/executor/execExpr.c
28 *
29 *-------------------------------------------------------------------------
30 */
31 #include "postgres.h"
32
33 #include "access/nbtree.h"
34 #include "catalog/objectaccess.h"
35 #include "catalog/pg_type.h"
36 #include "executor/execExpr.h"
37 #include "executor/nodeSubplan.h"
38 #include "funcapi.h"
39 #include "miscadmin.h"
40 #include "nodes/makefuncs.h"
41 #include "nodes/nodeFuncs.h"
42 #include "optimizer/clauses.h"
43 #include "optimizer/planner.h"
44 #include "pgstat.h"
45 #include "utils/builtins.h"
46 #include "utils/lsyscache.h"
47 #include "utils/typcache.h"
48
49
50 typedef struct LastAttnumInfo
51 {
52 AttrNumber last_inner;
53 AttrNumber last_outer;
54 AttrNumber last_scan;
55 } LastAttnumInfo;
56
57 static void ExecReadyExpr(ExprState *state);
58 static void ExecInitExprRec(Expr *node, PlanState *parent, ExprState *state,
59 Datum *resv, bool *resnull);
60 static void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s);
61 static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args,
62 Oid funcid, Oid inputcollid, PlanState *parent,
63 ExprState *state);
64 static void ExecInitExprSlots(ExprState *state, Node *node);
65 static bool get_last_attnums_walker(Node *node, LastAttnumInfo *info);
66 static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable,
67 PlanState *parent);
68 static void ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref,
69 PlanState *parent, ExprState *state,
70 Datum *resv, bool *resnull);
71 static bool isAssignmentIndirectionExpr(Expr *expr);
72 static void ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
73 PlanState *parent, ExprState *state,
74 Datum *resv, bool *resnull);
75
76
77 /*
78 * ExecInitExpr: prepare an expression tree for execution
79 *
80 * This function builds and returns an ExprState implementing the given
81 * Expr node tree. The return ExprState can then be handed to ExecEvalExpr
82 * for execution. Because the Expr tree itself is read-only as far as
83 * ExecInitExpr and ExecEvalExpr are concerned, several different executions
84 * of the same plan tree can occur concurrently. (But note that an ExprState
85 * does mutate at runtime, so it can't be re-used concurrently.)
86 *
87 * This must be called in a memory context that will last as long as repeated
88 * executions of the expression are needed. Typically the context will be
89 * the same as the per-query context of the associated ExprContext.
90 *
91 * Any Aggref, WindowFunc, or SubPlan nodes found in the tree are added to
92 * the lists of such nodes held by the parent PlanState (or more accurately,
93 * the AggrefExprState etc. nodes created for them are added).
94 *
95 * Note: there is no ExecEndExpr function; we assume that any resource
96 * cleanup needed will be handled by just releasing the memory context
97 * in which the state tree is built. Functions that require additional
98 * cleanup work can register a shutdown callback in the ExprContext.
99 *
100 * 'node' is the root of the expression tree to compile.
101 * 'parent' is the PlanState node that owns the expression.
102 *
103 * 'parent' may be NULL if we are preparing an expression that is not
104 * associated with a plan tree. (If so, it can't have aggs or subplans.)
105 * Such cases should usually come through ExecPrepareExpr, not directly here.
106 *
107 * Also, if 'node' is NULL, we just return NULL. This is convenient for some
108 * callers that may or may not have an expression that needs to be compiled.
109 * Note that a NULL ExprState pointer *cannot* be handed to ExecEvalExpr,
110 * although ExecQual and ExecCheck will accept one (and treat it as "true").
111 */
112 ExprState *
ExecInitExpr(Expr * node,PlanState * parent)113 ExecInitExpr(Expr *node, PlanState *parent)
114 {
115 ExprState *state;
116 ExprEvalStep scratch;
117
118 /* Special case: NULL expression produces a NULL ExprState pointer */
119 if (node == NULL)
120 return NULL;
121
122 /* Initialize ExprState with empty step list */
123 state = makeNode(ExprState);
124 state->expr = node;
125
126 /* Insert EEOP_*_FETCHSOME steps as needed */
127 ExecInitExprSlots(state, (Node *) node);
128
129 /* Compile the expression proper */
130 ExecInitExprRec(node, parent, state, &state->resvalue, &state->resnull);
131
132 /* Finally, append a DONE step */
133 scratch.opcode = EEOP_DONE;
134 ExprEvalPushStep(state, &scratch);
135
136 ExecReadyExpr(state);
137
138 return state;
139 }
140
141 /*
142 * ExecInitQual: prepare a qual for execution by ExecQual
143 *
144 * Prepares for the evaluation of a conjunctive boolean expression (qual list
145 * with implicit AND semantics) that returns true if none of the
146 * subexpressions are false.
147 *
148 * We must return true if the list is empty. Since that's a very common case,
149 * we optimize it a bit further by translating to a NULL ExprState pointer
150 * rather than setting up an ExprState that computes constant TRUE. (Some
151 * especially hot-spot callers of ExecQual detect this and avoid calling
152 * ExecQual at all.)
153 *
154 * If any of the subexpressions yield NULL, then the result of the conjunction
155 * is false. This makes ExecQual primarily useful for evaluating WHERE
156 * clauses, since SQL specifies that tuples with null WHERE results do not
157 * get selected.
158 */
159 ExprState *
ExecInitQual(List * qual,PlanState * parent)160 ExecInitQual(List *qual, PlanState *parent)
161 {
162 ExprState *state;
163 ExprEvalStep scratch;
164 List *adjust_jumps = NIL;
165 ListCell *lc;
166
167 /* short-circuit (here and in ExecQual) for empty restriction list */
168 if (qual == NIL)
169 return NULL;
170
171 Assert(IsA(qual, List));
172
173 state = makeNode(ExprState);
174 state->expr = (Expr *) qual;
175 /* mark expression as to be used with ExecQual() */
176 state->flags = EEO_FLAG_IS_QUAL;
177
178 /* Insert EEOP_*_FETCHSOME steps as needed */
179 ExecInitExprSlots(state, (Node *) qual);
180
181 /*
182 * ExecQual() needs to return false for an expression returning NULL. That
183 * allows us to short-circuit the evaluation the first time a NULL is
184 * encountered. As qual evaluation is a hot-path this warrants using a
185 * special opcode for qual evaluation that's simpler than BOOL_AND (which
186 * has more complex NULL handling).
187 */
188 scratch.opcode = EEOP_QUAL;
189
190 /*
191 * We can use ExprState's resvalue/resnull as target for each qual expr.
192 */
193 scratch.resvalue = &state->resvalue;
194 scratch.resnull = &state->resnull;
195
196 foreach(lc, qual)
197 {
198 Expr *node = (Expr *) lfirst(lc);
199
200 /* first evaluate expression */
201 ExecInitExprRec(node, parent, state, &state->resvalue, &state->resnull);
202
203 /* then emit EEOP_QUAL to detect if it's false (or null) */
204 scratch.d.qualexpr.jumpdone = -1;
205 ExprEvalPushStep(state, &scratch);
206 adjust_jumps = lappend_int(adjust_jumps,
207 state->steps_len - 1);
208 }
209
210 /* adjust jump targets */
211 foreach(lc, adjust_jumps)
212 {
213 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
214
215 Assert(as->opcode == EEOP_QUAL);
216 Assert(as->d.qualexpr.jumpdone == -1);
217 as->d.qualexpr.jumpdone = state->steps_len;
218 }
219
220 /*
221 * At the end, we don't need to do anything more. The last qual expr must
222 * have yielded TRUE, and since its result is stored in the desired output
223 * location, we're done.
224 */
225 scratch.opcode = EEOP_DONE;
226 ExprEvalPushStep(state, &scratch);
227
228 ExecReadyExpr(state);
229
230 return state;
231 }
232
233 /*
234 * ExecInitCheck: prepare a check constraint for execution by ExecCheck
235 *
236 * This is much like ExecInitQual/ExecQual, except that a null result from
237 * the conjunction is treated as TRUE. This behavior is appropriate for
238 * evaluating CHECK constraints, since SQL specifies that NULL constraint
239 * conditions are not failures.
240 *
241 * Note that like ExecInitQual, this expects input in implicit-AND format.
242 * Users of ExecCheck that have expressions in normal explicit-AND format
243 * can just apply ExecInitExpr to produce suitable input for ExecCheck.
244 */
245 ExprState *
ExecInitCheck(List * qual,PlanState * parent)246 ExecInitCheck(List *qual, PlanState *parent)
247 {
248 /* short-circuit (here and in ExecCheck) for empty restriction list */
249 if (qual == NIL)
250 return NULL;
251
252 Assert(IsA(qual, List));
253
254 /*
255 * Just convert the implicit-AND list to an explicit AND (if there's more
256 * than one entry), and compile normally. Unlike ExecQual, we can't
257 * short-circuit on NULL results, so the regular AND behavior is needed.
258 */
259 return ExecInitExpr(make_ands_explicit(qual), parent);
260 }
261
262 /*
263 * Call ExecInitExpr() on a list of expressions, return a list of ExprStates.
264 */
265 List *
ExecInitExprList(List * nodes,PlanState * parent)266 ExecInitExprList(List *nodes, PlanState *parent)
267 {
268 List *result = NIL;
269 ListCell *lc;
270
271 foreach(lc, nodes)
272 {
273 Expr *e = lfirst(lc);
274
275 result = lappend(result, ExecInitExpr(e, parent));
276 }
277
278 return result;
279 }
280
281 /*
282 * ExecBuildProjectionInfo
283 *
284 * Build a ProjectionInfo node for evaluating the given tlist in the given
285 * econtext, and storing the result into the tuple slot. (Caller must have
286 * ensured that tuple slot has a descriptor matching the tlist!)
287 *
288 * inputDesc can be NULL, but if it is not, we check to see whether simple
289 * Vars in the tlist match the descriptor. It is important to provide
290 * inputDesc for relation-scan plan nodes, as a cross check that the relation
291 * hasn't been changed since the plan was made. At higher levels of a plan,
292 * there is no need to recheck.
293 *
294 * This is implemented by internally building an ExprState that performs the
295 * whole projection in one go.
296 *
297 * Caution: before PG v10, the targetList was a list of ExprStates; now it
298 * should be the planner-created targetlist, since we do the compilation here.
299 */
300 ProjectionInfo *
ExecBuildProjectionInfo(List * targetList,ExprContext * econtext,TupleTableSlot * slot,PlanState * parent,TupleDesc inputDesc)301 ExecBuildProjectionInfo(List *targetList,
302 ExprContext *econtext,
303 TupleTableSlot *slot,
304 PlanState *parent,
305 TupleDesc inputDesc)
306 {
307 return ExecBuildProjectionInfoExt(targetList,
308 econtext,
309 slot,
310 true,
311 parent,
312 inputDesc);
313 }
314
315 /*
316 * ExecBuildProjectionInfoExt
317 *
318 * As above, with one additional option.
319 *
320 * If assignJunkEntries is true (the usual case), resjunk entries in the tlist
321 * are not handled specially: they are evaluated and assigned to the proper
322 * column of the result slot. If assignJunkEntries is false, resjunk entries
323 * are evaluated, but their result is discarded without assignment.
324 */
325 ProjectionInfo *
ExecBuildProjectionInfoExt(List * targetList,ExprContext * econtext,TupleTableSlot * slot,bool assignJunkEntries,PlanState * parent,TupleDesc inputDesc)326 ExecBuildProjectionInfoExt(List *targetList,
327 ExprContext *econtext,
328 TupleTableSlot *slot,
329 bool assignJunkEntries,
330 PlanState *parent,
331 TupleDesc inputDesc)
332 {
333 ProjectionInfo *projInfo = makeNode(ProjectionInfo);
334 ExprState *state;
335 ExprEvalStep scratch;
336 ListCell *lc;
337
338 projInfo->pi_exprContext = econtext;
339 /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
340 projInfo->pi_state.tag.type = T_ExprState;
341 state = &projInfo->pi_state;
342 state->expr = (Expr *) targetList;
343 state->resultslot = slot;
344
345 /* Insert EEOP_*_FETCHSOME steps as needed */
346 ExecInitExprSlots(state, (Node *) targetList);
347
348 /* Now compile each tlist column */
349 foreach(lc, targetList)
350 {
351 TargetEntry *tle = lfirst_node(TargetEntry, lc);
352 Var *variable = NULL;
353 AttrNumber attnum = 0;
354 bool isSafeVar = false;
355
356 /*
357 * If tlist expression is a safe non-system Var, use the fast-path
358 * ASSIGN_*_VAR opcodes. "Safe" means that we don't need to apply
359 * CheckVarSlotCompatibility() during plan startup. If a source slot
360 * was provided, we make the equivalent tests here; if a slot was not
361 * provided, we assume that no check is needed because we're dealing
362 * with a non-relation-scan-level expression.
363 */
364 if (tle->expr != NULL &&
365 IsA(tle->expr, Var) &&
366 ((Var *) tle->expr)->varattno > 0 &&
367 (assignJunkEntries || !tle->resjunk))
368 {
369 /* Non-system Var, but how safe is it? */
370 variable = (Var *) tle->expr;
371 attnum = variable->varattno;
372
373 if (inputDesc == NULL)
374 isSafeVar = true; /* can't check, just assume OK */
375 else if (attnum <= inputDesc->natts)
376 {
377 Form_pg_attribute attr = inputDesc->attrs[attnum - 1];
378
379 /*
380 * If user attribute is dropped or has a type mismatch, don't
381 * use ASSIGN_*_VAR. Instead let the normal expression
382 * machinery handle it (which'll possibly error out).
383 */
384 if (!attr->attisdropped && variable->vartype == attr->atttypid)
385 {
386 isSafeVar = true;
387 }
388 }
389 }
390
391 if (isSafeVar)
392 {
393 /* Fast-path: just generate an EEOP_ASSIGN_*_VAR step */
394 switch (variable->varno)
395 {
396 case INNER_VAR:
397 /* get the tuple from the inner node */
398 scratch.opcode = EEOP_ASSIGN_INNER_VAR;
399 break;
400
401 case OUTER_VAR:
402 /* get the tuple from the outer node */
403 scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
404 break;
405
406 /* INDEX_VAR is handled by default case */
407
408 default:
409 /* get the tuple from the relation being scanned */
410 scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
411 break;
412 }
413
414 scratch.d.assign_var.attnum = attnum - 1;
415 scratch.d.assign_var.resultnum = tle->resno - 1;
416 ExprEvalPushStep(state, &scratch);
417 }
418 else
419 {
420 /*
421 * Otherwise, compile the column expression normally.
422 *
423 * We can't tell the expression to evaluate directly into the
424 * result slot, as the result slot (and the exprstate for that
425 * matter) can change between executions. We instead evaluate
426 * into the ExprState's resvalue/resnull and then move.
427 */
428 ExecInitExprRec(tle->expr, parent, state,
429 &state->resvalue, &state->resnull);
430
431 /* This makes it easy to discard resjunk results when told to. */
432 if (!assignJunkEntries && tle->resjunk)
433 continue;
434
435 /*
436 * Column might be referenced multiple times in upper nodes, so
437 * force value to R/O - but only if it could be an expanded datum.
438 */
439 if (get_typlen(exprType((Node *) tle->expr)) == -1)
440 scratch.opcode = EEOP_ASSIGN_TMP_MAKE_RO;
441 else
442 scratch.opcode = EEOP_ASSIGN_TMP;
443 scratch.d.assign_tmp.resultnum = tle->resno - 1;
444 ExprEvalPushStep(state, &scratch);
445 }
446 }
447
448 scratch.opcode = EEOP_DONE;
449 ExprEvalPushStep(state, &scratch);
450
451 ExecReadyExpr(state);
452
453 return projInfo;
454 }
455
456 /*
457 * ExecPrepareExpr --- initialize for expression execution outside a normal
458 * Plan tree context.
459 *
460 * This differs from ExecInitExpr in that we don't assume the caller is
461 * already running in the EState's per-query context. Also, we run the
462 * passed expression tree through expression_planner() to prepare it for
463 * execution. (In ordinary Plan trees the regular planning process will have
464 * made the appropriate transformations on expressions, but for standalone
465 * expressions this won't have happened.)
466 */
467 ExprState *
ExecPrepareExpr(Expr * node,EState * estate)468 ExecPrepareExpr(Expr *node, EState *estate)
469 {
470 ExprState *result;
471 MemoryContext oldcontext;
472
473 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
474
475 node = expression_planner(node);
476
477 result = ExecInitExpr(node, NULL);
478
479 MemoryContextSwitchTo(oldcontext);
480
481 return result;
482 }
483
484 /*
485 * ExecPrepareQual --- initialize for qual execution outside a normal
486 * Plan tree context.
487 *
488 * This differs from ExecInitQual in that we don't assume the caller is
489 * already running in the EState's per-query context. Also, we run the
490 * passed expression tree through expression_planner() to prepare it for
491 * execution. (In ordinary Plan trees the regular planning process will have
492 * made the appropriate transformations on expressions, but for standalone
493 * expressions this won't have happened.)
494 */
495 ExprState *
ExecPrepareQual(List * qual,EState * estate)496 ExecPrepareQual(List *qual, EState *estate)
497 {
498 ExprState *result;
499 MemoryContext oldcontext;
500
501 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
502
503 qual = (List *) expression_planner((Expr *) qual);
504
505 result = ExecInitQual(qual, NULL);
506
507 MemoryContextSwitchTo(oldcontext);
508
509 return result;
510 }
511
512 /*
513 * ExecPrepareCheck -- initialize check constraint for execution outside a
514 * normal Plan tree context.
515 *
516 * See ExecPrepareExpr() and ExecInitCheck() for details.
517 */
518 ExprState *
ExecPrepareCheck(List * qual,EState * estate)519 ExecPrepareCheck(List *qual, EState *estate)
520 {
521 ExprState *result;
522 MemoryContext oldcontext;
523
524 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
525
526 qual = (List *) expression_planner((Expr *) qual);
527
528 result = ExecInitCheck(qual, NULL);
529
530 MemoryContextSwitchTo(oldcontext);
531
532 return result;
533 }
534
535 /*
536 * Call ExecPrepareExpr() on each member of a list of Exprs, and return
537 * a list of ExprStates.
538 *
539 * See ExecPrepareExpr() for details.
540 */
541 List *
ExecPrepareExprList(List * nodes,EState * estate)542 ExecPrepareExprList(List *nodes, EState *estate)
543 {
544 List *result = NIL;
545 MemoryContext oldcontext;
546 ListCell *lc;
547
548 /* Ensure that the list cell nodes are in the right context too */
549 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
550
551 foreach(lc, nodes)
552 {
553 Expr *e = (Expr *) lfirst(lc);
554
555 result = lappend(result, ExecPrepareExpr(e, estate));
556 }
557
558 MemoryContextSwitchTo(oldcontext);
559
560 return result;
561 }
562
563 /*
564 * ExecCheck - evaluate a check constraint
565 *
566 * For check constraints, a null result is taken as TRUE, ie the constraint
567 * passes.
568 *
569 * The check constraint may have been prepared with ExecInitCheck
570 * (possibly via ExecPrepareCheck) if the caller had it in implicit-AND
571 * format, but a regular boolean expression prepared with ExecInitExpr or
572 * ExecPrepareExpr works too.
573 */
574 bool
ExecCheck(ExprState * state,ExprContext * econtext)575 ExecCheck(ExprState *state, ExprContext *econtext)
576 {
577 Datum ret;
578 bool isnull;
579
580 /* short-circuit (here and in ExecInitCheck) for empty restriction list */
581 if (state == NULL)
582 return true;
583
584 /* verify that expression was not compiled using ExecInitQual */
585 Assert(!(state->flags & EEO_FLAG_IS_QUAL));
586
587 ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
588
589 if (isnull)
590 return true;
591
592 return DatumGetBool(ret);
593 }
594
595 /*
596 * Prepare a compiled expression for execution. This has to be called for
597 * every ExprState before it can be executed.
598 *
599 * NB: While this currently only calls ExecReadyInterpretedExpr(),
600 * this will likely get extended to further expression evaluation methods.
601 * Therefore this should be used instead of directly calling
602 * ExecReadyInterpretedExpr().
603 */
604 static void
ExecReadyExpr(ExprState * state)605 ExecReadyExpr(ExprState *state)
606 {
607 ExecReadyInterpretedExpr(state);
608 }
609
610 /*
611 * Append the steps necessary for the evaluation of node to ExprState->steps,
612 * possibly recursing into sub-expressions of node.
613 *
614 * node - expression to evaluate
615 * parent - parent executor node (or NULL if a standalone expression)
616 * state - ExprState to whose ->steps to append the necessary operations
617 * resv / resnull - where to store the result of the node into
618 */
619 static void
ExecInitExprRec(Expr * node,PlanState * parent,ExprState * state,Datum * resv,bool * resnull)620 ExecInitExprRec(Expr *node, PlanState *parent, ExprState *state,
621 Datum *resv, bool *resnull)
622 {
623 ExprEvalStep scratch;
624
625 /* Guard against stack overflow due to overly complex expressions */
626 check_stack_depth();
627
628 /* Step's output location is always what the caller gave us */
629 Assert(resv != NULL && resnull != NULL);
630 scratch.resvalue = resv;
631 scratch.resnull = resnull;
632
633 /* cases should be ordered as they are in enum NodeTag */
634 switch (nodeTag(node))
635 {
636 case T_Var:
637 {
638 Var *variable = (Var *) node;
639
640 if (variable->varattno == InvalidAttrNumber)
641 {
642 /* whole-row Var */
643 ExecInitWholeRowVar(&scratch, variable, parent);
644 }
645 else if (variable->varattno <= 0)
646 {
647 /* system column */
648 scratch.d.var.attnum = variable->varattno;
649 scratch.d.var.vartype = variable->vartype;
650 switch (variable->varno)
651 {
652 case INNER_VAR:
653 scratch.opcode = EEOP_INNER_SYSVAR;
654 break;
655 case OUTER_VAR:
656 scratch.opcode = EEOP_OUTER_SYSVAR;
657 break;
658
659 /* INDEX_VAR is handled by default case */
660
661 default:
662 scratch.opcode = EEOP_SCAN_SYSVAR;
663 break;
664 }
665 }
666 else
667 {
668 /* regular user column */
669 scratch.d.var.attnum = variable->varattno - 1;
670 scratch.d.var.vartype = variable->vartype;
671 /* select EEOP_*_FIRST opcode to force one-time checks */
672 switch (variable->varno)
673 {
674 case INNER_VAR:
675 scratch.opcode = EEOP_INNER_VAR_FIRST;
676 break;
677 case OUTER_VAR:
678 scratch.opcode = EEOP_OUTER_VAR_FIRST;
679 break;
680
681 /* INDEX_VAR is handled by default case */
682
683 default:
684 scratch.opcode = EEOP_SCAN_VAR_FIRST;
685 break;
686 }
687 }
688
689 ExprEvalPushStep(state, &scratch);
690 break;
691 }
692
693 case T_Const:
694 {
695 Const *con = (Const *) node;
696
697 scratch.opcode = EEOP_CONST;
698 scratch.d.constval.value = con->constvalue;
699 scratch.d.constval.isnull = con->constisnull;
700
701 ExprEvalPushStep(state, &scratch);
702 break;
703 }
704
705 case T_Param:
706 {
707 Param *param = (Param *) node;
708
709 switch (param->paramkind)
710 {
711 case PARAM_EXEC:
712 scratch.opcode = EEOP_PARAM_EXEC;
713 scratch.d.param.paramid = param->paramid;
714 scratch.d.param.paramtype = param->paramtype;
715 break;
716 case PARAM_EXTERN:
717 scratch.opcode = EEOP_PARAM_EXTERN;
718 scratch.d.param.paramid = param->paramid;
719 scratch.d.param.paramtype = param->paramtype;
720 break;
721 default:
722 elog(ERROR, "unrecognized paramkind: %d",
723 (int) param->paramkind);
724 break;
725 }
726
727 ExprEvalPushStep(state, &scratch);
728 break;
729 }
730
731 case T_Aggref:
732 {
733 Aggref *aggref = (Aggref *) node;
734 AggrefExprState *astate = makeNode(AggrefExprState);
735
736 scratch.opcode = EEOP_AGGREF;
737 scratch.d.aggref.astate = astate;
738 astate->aggref = aggref;
739
740 if (parent && IsA(parent, AggState))
741 {
742 AggState *aggstate = (AggState *) parent;
743
744 aggstate->aggs = lcons(astate, aggstate->aggs);
745 aggstate->numaggs++;
746 }
747 else
748 {
749 /* planner messed up */
750 elog(ERROR, "Aggref found in non-Agg plan node");
751 }
752
753 ExprEvalPushStep(state, &scratch);
754 break;
755 }
756
757 case T_GroupingFunc:
758 {
759 GroupingFunc *grp_node = (GroupingFunc *) node;
760 Agg *agg;
761
762 if (!parent || !IsA(parent, AggState) ||
763 !IsA(parent->plan, Agg))
764 elog(ERROR, "GroupingFunc found in non-Agg plan node");
765
766 scratch.opcode = EEOP_GROUPING_FUNC;
767 scratch.d.grouping_func.parent = (AggState *) parent;
768
769 agg = (Agg *) (parent->plan);
770
771 if (agg->groupingSets)
772 scratch.d.grouping_func.clauses = grp_node->cols;
773 else
774 scratch.d.grouping_func.clauses = NIL;
775
776 ExprEvalPushStep(state, &scratch);
777 break;
778 }
779
780 case T_WindowFunc:
781 {
782 WindowFunc *wfunc = (WindowFunc *) node;
783 WindowFuncExprState *wfstate = makeNode(WindowFuncExprState);
784
785 wfstate->wfunc = wfunc;
786
787 if (parent && IsA(parent, WindowAggState))
788 {
789 WindowAggState *winstate = (WindowAggState *) parent;
790 int nfuncs;
791
792 winstate->funcs = lcons(wfstate, winstate->funcs);
793 nfuncs = ++winstate->numfuncs;
794 if (wfunc->winagg)
795 winstate->numaggs++;
796
797 /* for now initialize agg using old style expressions */
798 wfstate->args = ExecInitExprList(wfunc->args, parent);
799 wfstate->aggfilter = ExecInitExpr(wfunc->aggfilter,
800 parent);
801
802 /*
803 * Complain if the windowfunc's arguments contain any
804 * windowfuncs; nested window functions are semantically
805 * nonsensical. (This should have been caught earlier,
806 * but we defend against it here anyway.)
807 */
808 if (nfuncs != winstate->numfuncs)
809 ereport(ERROR,
810 (errcode(ERRCODE_WINDOWING_ERROR),
811 errmsg("window function calls cannot be nested")));
812 }
813 else
814 {
815 /* planner messed up */
816 elog(ERROR, "WindowFunc found in non-WindowAgg plan node");
817 }
818
819 scratch.opcode = EEOP_WINDOW_FUNC;
820 scratch.d.window_func.wfstate = wfstate;
821 ExprEvalPushStep(state, &scratch);
822 break;
823 }
824
825 case T_ArrayRef:
826 {
827 ArrayRef *aref = (ArrayRef *) node;
828
829 ExecInitArrayRef(&scratch, aref, parent, state, resv, resnull);
830 break;
831 }
832
833 case T_FuncExpr:
834 {
835 FuncExpr *func = (FuncExpr *) node;
836
837 ExecInitFunc(&scratch, node,
838 func->args, func->funcid, func->inputcollid,
839 parent, state);
840 ExprEvalPushStep(state, &scratch);
841 break;
842 }
843
844 case T_OpExpr:
845 {
846 OpExpr *op = (OpExpr *) node;
847
848 ExecInitFunc(&scratch, node,
849 op->args, op->opfuncid, op->inputcollid,
850 parent, state);
851 ExprEvalPushStep(state, &scratch);
852 break;
853 }
854
855 case T_DistinctExpr:
856 {
857 DistinctExpr *op = (DistinctExpr *) node;
858
859 ExecInitFunc(&scratch, node,
860 op->args, op->opfuncid, op->inputcollid,
861 parent, state);
862
863 /*
864 * Change opcode of call instruction to EEOP_DISTINCT.
865 *
866 * XXX: historically we've not called the function usage
867 * pgstat infrastructure - that seems inconsistent given that
868 * we do so for normal function *and* operator evaluation. If
869 * we decided to do that here, we'd probably want separate
870 * opcodes for FUSAGE or not.
871 */
872 scratch.opcode = EEOP_DISTINCT;
873 ExprEvalPushStep(state, &scratch);
874 break;
875 }
876
877 case T_NullIfExpr:
878 {
879 NullIfExpr *op = (NullIfExpr *) node;
880
881 ExecInitFunc(&scratch, node,
882 op->args, op->opfuncid, op->inputcollid,
883 parent, state);
884
885 /*
886 * Change opcode of call instruction to EEOP_NULLIF.
887 *
888 * XXX: historically we've not called the function usage
889 * pgstat infrastructure - that seems inconsistent given that
890 * we do so for normal function *and* operator evaluation. If
891 * we decided to do that here, we'd probably want separate
892 * opcodes for FUSAGE or not.
893 */
894 scratch.opcode = EEOP_NULLIF;
895 ExprEvalPushStep(state, &scratch);
896 break;
897 }
898
899 case T_ScalarArrayOpExpr:
900 {
901 ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
902 Expr *scalararg;
903 Expr *arrayarg;
904 FmgrInfo *finfo;
905 FunctionCallInfo fcinfo;
906 AclResult aclresult;
907
908 Assert(list_length(opexpr->args) == 2);
909 scalararg = (Expr *) linitial(opexpr->args);
910 arrayarg = (Expr *) lsecond(opexpr->args);
911
912 /* Check permission to call function */
913 aclresult = pg_proc_aclcheck(opexpr->opfuncid,
914 GetUserId(),
915 ACL_EXECUTE);
916 if (aclresult != ACLCHECK_OK)
917 aclcheck_error(aclresult, ACL_KIND_PROC,
918 get_func_name(opexpr->opfuncid));
919 InvokeFunctionExecuteHook(opexpr->opfuncid);
920
921 /* Set up the primary fmgr lookup information */
922 finfo = palloc0(sizeof(FmgrInfo));
923 fcinfo = palloc0(sizeof(FunctionCallInfoData));
924 fmgr_info(opexpr->opfuncid, finfo);
925 fmgr_info_set_expr((Node *) node, finfo);
926 InitFunctionCallInfoData(*fcinfo, finfo, 2,
927 opexpr->inputcollid, NULL, NULL);
928
929 /* Evaluate scalar directly into left function argument */
930 ExecInitExprRec(scalararg, parent, state,
931 &fcinfo->arg[0], &fcinfo->argnull[0]);
932
933 /*
934 * Evaluate array argument into our return value. There's no
935 * danger in that, because the return value is guaranteed to
936 * be overwritten by EEOP_SCALARARRAYOP, and will not be
937 * passed to any other expression.
938 */
939 ExecInitExprRec(arrayarg, parent, state, resv, resnull);
940
941 /* And perform the operation */
942 scratch.opcode = EEOP_SCALARARRAYOP;
943 scratch.d.scalararrayop.element_type = InvalidOid;
944 scratch.d.scalararrayop.useOr = opexpr->useOr;
945 scratch.d.scalararrayop.finfo = finfo;
946 scratch.d.scalararrayop.fcinfo_data = fcinfo;
947 scratch.d.scalararrayop.fn_addr = finfo->fn_addr;
948 ExprEvalPushStep(state, &scratch);
949 break;
950 }
951
952 case T_BoolExpr:
953 {
954 BoolExpr *boolexpr = (BoolExpr *) node;
955 int nargs = list_length(boolexpr->args);
956 List *adjust_jumps = NIL;
957 int off;
958 ListCell *lc;
959
960 /* allocate scratch memory used by all steps of AND/OR */
961 if (boolexpr->boolop != NOT_EXPR)
962 scratch.d.boolexpr.anynull = (bool *) palloc(sizeof(bool));
963
964 /*
965 * For each argument evaluate the argument itself, then
966 * perform the bool operation's appropriate handling.
967 *
968 * We can evaluate each argument into our result area, since
969 * the short-circuiting logic means we only need to remember
970 * previous NULL values.
971 *
972 * AND/OR is split into separate STEP_FIRST (one) / STEP (zero
973 * or more) / STEP_LAST (one) steps, as each of those has to
974 * perform different work. The FIRST/LAST split is valid
975 * because AND/OR have at least two arguments.
976 */
977 off = 0;
978 foreach(lc, boolexpr->args)
979 {
980 Expr *arg = (Expr *) lfirst(lc);
981
982 /* Evaluate argument into our output variable */
983 ExecInitExprRec(arg, parent, state, resv, resnull);
984
985 /* Perform the appropriate step type */
986 switch (boolexpr->boolop)
987 {
988 case AND_EXPR:
989 Assert(nargs >= 2);
990
991 if (off == 0)
992 scratch.opcode = EEOP_BOOL_AND_STEP_FIRST;
993 else if (off + 1 == nargs)
994 scratch.opcode = EEOP_BOOL_AND_STEP_LAST;
995 else
996 scratch.opcode = EEOP_BOOL_AND_STEP;
997 break;
998 case OR_EXPR:
999 Assert(nargs >= 2);
1000
1001 if (off == 0)
1002 scratch.opcode = EEOP_BOOL_OR_STEP_FIRST;
1003 else if (off + 1 == nargs)
1004 scratch.opcode = EEOP_BOOL_OR_STEP_LAST;
1005 else
1006 scratch.opcode = EEOP_BOOL_OR_STEP;
1007 break;
1008 case NOT_EXPR:
1009 Assert(nargs == 1);
1010
1011 scratch.opcode = EEOP_BOOL_NOT_STEP;
1012 break;
1013 default:
1014 elog(ERROR, "unrecognized boolop: %d",
1015 (int) boolexpr->boolop);
1016 break;
1017 }
1018
1019 scratch.d.boolexpr.jumpdone = -1;
1020 ExprEvalPushStep(state, &scratch);
1021 adjust_jumps = lappend_int(adjust_jumps,
1022 state->steps_len - 1);
1023 off++;
1024 }
1025
1026 /* adjust jump targets */
1027 foreach(lc, adjust_jumps)
1028 {
1029 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1030
1031 Assert(as->d.boolexpr.jumpdone == -1);
1032 as->d.boolexpr.jumpdone = state->steps_len;
1033 }
1034
1035 break;
1036 }
1037
1038 case T_SubPlan:
1039 {
1040 SubPlan *subplan = (SubPlan *) node;
1041 SubPlanState *sstate;
1042
1043 if (!parent)
1044 elog(ERROR, "SubPlan found with no parent plan");
1045
1046 sstate = ExecInitSubPlan(subplan, parent);
1047
1048 /* add SubPlanState nodes to parent->subPlan */
1049 parent->subPlan = lappend(parent->subPlan, sstate);
1050
1051 scratch.opcode = EEOP_SUBPLAN;
1052 scratch.d.subplan.sstate = sstate;
1053
1054 ExprEvalPushStep(state, &scratch);
1055 break;
1056 }
1057
1058 case T_AlternativeSubPlan:
1059 {
1060 AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
1061 AlternativeSubPlanState *asstate;
1062
1063 if (!parent)
1064 elog(ERROR, "AlternativeSubPlan found with no parent plan");
1065
1066 asstate = ExecInitAlternativeSubPlan(asplan, parent);
1067
1068 scratch.opcode = EEOP_ALTERNATIVE_SUBPLAN;
1069 scratch.d.alternative_subplan.asstate = asstate;
1070
1071 ExprEvalPushStep(state, &scratch);
1072 break;
1073 }
1074
1075 case T_FieldSelect:
1076 {
1077 FieldSelect *fselect = (FieldSelect *) node;
1078
1079 /* evaluate row/record argument into result area */
1080 ExecInitExprRec(fselect->arg, parent, state, resv, resnull);
1081
1082 /* and extract field */
1083 scratch.opcode = EEOP_FIELDSELECT;
1084 scratch.d.fieldselect.fieldnum = fselect->fieldnum;
1085 scratch.d.fieldselect.resulttype = fselect->resulttype;
1086 scratch.d.fieldselect.argdesc = NULL;
1087
1088 ExprEvalPushStep(state, &scratch);
1089 break;
1090 }
1091
1092 case T_FieldStore:
1093 {
1094 FieldStore *fstore = (FieldStore *) node;
1095 TupleDesc tupDesc;
1096 TupleDesc *descp;
1097 Datum *values;
1098 bool *nulls;
1099 int ncolumns;
1100 ListCell *l1,
1101 *l2;
1102
1103 /* find out the number of columns in the composite type */
1104 tupDesc = lookup_rowtype_tupdesc(fstore->resulttype, -1);
1105 ncolumns = tupDesc->natts;
1106 DecrTupleDescRefCount(tupDesc);
1107
1108 /* create workspace for column values */
1109 values = (Datum *) palloc(sizeof(Datum) * ncolumns);
1110 nulls = (bool *) palloc(sizeof(bool) * ncolumns);
1111
1112 /* create workspace for runtime tupdesc cache */
1113 descp = (TupleDesc *) palloc(sizeof(TupleDesc));
1114 *descp = NULL;
1115
1116 /* emit code to evaluate the composite input value */
1117 ExecInitExprRec(fstore->arg, parent, state, resv, resnull);
1118
1119 /* next, deform the input tuple into our workspace */
1120 scratch.opcode = EEOP_FIELDSTORE_DEFORM;
1121 scratch.d.fieldstore.fstore = fstore;
1122 scratch.d.fieldstore.argdesc = descp;
1123 scratch.d.fieldstore.values = values;
1124 scratch.d.fieldstore.nulls = nulls;
1125 scratch.d.fieldstore.ncolumns = ncolumns;
1126 ExprEvalPushStep(state, &scratch);
1127
1128 /* evaluate new field values, store in workspace columns */
1129 forboth(l1, fstore->newvals, l2, fstore->fieldnums)
1130 {
1131 Expr *e = (Expr *) lfirst(l1);
1132 AttrNumber fieldnum = lfirst_int(l2);
1133 Datum *save_innermost_caseval;
1134 bool *save_innermost_casenull;
1135
1136 if (fieldnum <= 0 || fieldnum > ncolumns)
1137 elog(ERROR, "field number %d is out of range in FieldStore",
1138 fieldnum);
1139
1140 /*
1141 * Use the CaseTestExpr mechanism to pass down the old
1142 * value of the field being replaced; this is needed in
1143 * case the newval is itself a FieldStore or ArrayRef that
1144 * has to obtain and modify the old value. It's safe to
1145 * reuse the CASE mechanism because there cannot be a CASE
1146 * between here and where the value would be needed, and a
1147 * field assignment can't be within a CASE either. (So
1148 * saving and restoring innermost_caseval is just
1149 * paranoia, but let's do it anyway.)
1150 *
1151 * Another non-obvious point is that it's safe to use the
1152 * field's values[]/nulls[] entries as both the caseval
1153 * source and the result address for this subexpression.
1154 * That's okay only because (1) both FieldStore and
1155 * ArrayRef evaluate their arg or refexpr inputs first,
1156 * and (2) any such CaseTestExpr is directly the arg or
1157 * refexpr input. So any read of the caseval will occur
1158 * before there's a chance to overwrite it. Also, if
1159 * multiple entries in the newvals/fieldnums lists target
1160 * the same field, they'll effectively be applied
1161 * left-to-right which is what we want.
1162 */
1163 save_innermost_caseval = state->innermost_caseval;
1164 save_innermost_casenull = state->innermost_casenull;
1165 state->innermost_caseval = &values[fieldnum - 1];
1166 state->innermost_casenull = &nulls[fieldnum - 1];
1167
1168 ExecInitExprRec(e, parent, state,
1169 &values[fieldnum - 1],
1170 &nulls[fieldnum - 1]);
1171
1172 state->innermost_caseval = save_innermost_caseval;
1173 state->innermost_casenull = save_innermost_casenull;
1174 }
1175
1176 /* finally, form result tuple */
1177 scratch.opcode = EEOP_FIELDSTORE_FORM;
1178 scratch.d.fieldstore.fstore = fstore;
1179 scratch.d.fieldstore.argdesc = descp;
1180 scratch.d.fieldstore.values = values;
1181 scratch.d.fieldstore.nulls = nulls;
1182 scratch.d.fieldstore.ncolumns = ncolumns;
1183 ExprEvalPushStep(state, &scratch);
1184 break;
1185 }
1186
1187 case T_RelabelType:
1188 {
1189 /* relabel doesn't need to do anything at runtime */
1190 RelabelType *relabel = (RelabelType *) node;
1191
1192 ExecInitExprRec(relabel->arg, parent, state, resv, resnull);
1193 break;
1194 }
1195
1196 case T_CoerceViaIO:
1197 {
1198 CoerceViaIO *iocoerce = (CoerceViaIO *) node;
1199 Oid iofunc;
1200 bool typisvarlena;
1201 Oid typioparam;
1202 FunctionCallInfo fcinfo_in;
1203
1204 /* evaluate argument into step's result area */
1205 ExecInitExprRec(iocoerce->arg, parent, state, resv, resnull);
1206
1207 /*
1208 * Prepare both output and input function calls, to be
1209 * evaluated inside a single evaluation step for speed - this
1210 * can be a very common operation.
1211 *
1212 * We don't check permissions here as a type's input/output
1213 * function are assumed to be executable by everyone.
1214 */
1215 scratch.opcode = EEOP_IOCOERCE;
1216
1217 /* lookup the source type's output function */
1218 scratch.d.iocoerce.finfo_out = palloc0(sizeof(FmgrInfo));
1219 scratch.d.iocoerce.fcinfo_data_out = palloc0(sizeof(FunctionCallInfoData));
1220
1221 getTypeOutputInfo(exprType((Node *) iocoerce->arg),
1222 &iofunc, &typisvarlena);
1223 fmgr_info(iofunc, scratch.d.iocoerce.finfo_out);
1224 fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_out);
1225 InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_out,
1226 scratch.d.iocoerce.finfo_out,
1227 1, InvalidOid, NULL, NULL);
1228
1229 /* lookup the result type's input function */
1230 scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo));
1231 scratch.d.iocoerce.fcinfo_data_in = palloc0(sizeof(FunctionCallInfoData));
1232
1233 getTypeInputInfo(iocoerce->resulttype,
1234 &iofunc, &typioparam);
1235 fmgr_info(iofunc, scratch.d.iocoerce.finfo_in);
1236 fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_in);
1237 InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_in,
1238 scratch.d.iocoerce.finfo_in,
1239 3, InvalidOid, NULL, NULL);
1240
1241 /*
1242 * We can preload the second and third arguments for the input
1243 * function, since they're constants.
1244 */
1245 fcinfo_in = scratch.d.iocoerce.fcinfo_data_in;
1246 fcinfo_in->arg[1] = ObjectIdGetDatum(typioparam);
1247 fcinfo_in->argnull[1] = false;
1248 fcinfo_in->arg[2] = Int32GetDatum(-1);
1249 fcinfo_in->argnull[2] = false;
1250
1251 ExprEvalPushStep(state, &scratch);
1252 break;
1253 }
1254
1255 case T_ArrayCoerceExpr:
1256 {
1257 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
1258 Oid resultelemtype;
1259
1260 /* evaluate argument into step's result area */
1261 ExecInitExprRec(acoerce->arg, parent, state, resv, resnull);
1262
1263 resultelemtype = get_element_type(acoerce->resulttype);
1264 if (!OidIsValid(resultelemtype))
1265 ereport(ERROR,
1266 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1267 errmsg("target type is not an array")));
1268 /* Arrays over domains aren't supported yet */
1269 Assert(getBaseType(resultelemtype) == resultelemtype);
1270
1271 scratch.opcode = EEOP_ARRAYCOERCE;
1272 scratch.d.arraycoerce.coerceexpr = acoerce;
1273 scratch.d.arraycoerce.resultelemtype = resultelemtype;
1274
1275 if (OidIsValid(acoerce->elemfuncid))
1276 {
1277 AclResult aclresult;
1278
1279 /* Check permission to call function */
1280 aclresult = pg_proc_aclcheck(acoerce->elemfuncid,
1281 GetUserId(),
1282 ACL_EXECUTE);
1283 if (aclresult != ACLCHECK_OK)
1284 aclcheck_error(aclresult, ACL_KIND_PROC,
1285 get_func_name(acoerce->elemfuncid));
1286 InvokeFunctionExecuteHook(acoerce->elemfuncid);
1287
1288 /* Set up the primary fmgr lookup information */
1289 scratch.d.arraycoerce.elemfunc =
1290 (FmgrInfo *) palloc0(sizeof(FmgrInfo));
1291 fmgr_info(acoerce->elemfuncid,
1292 scratch.d.arraycoerce.elemfunc);
1293 fmgr_info_set_expr((Node *) acoerce,
1294 scratch.d.arraycoerce.elemfunc);
1295
1296 /* Set up workspace for array_map */
1297 scratch.d.arraycoerce.amstate =
1298 (ArrayMapState *) palloc0(sizeof(ArrayMapState));
1299 }
1300 else
1301 {
1302 /* Don't need workspace if there's no conversion func */
1303 scratch.d.arraycoerce.elemfunc = NULL;
1304 scratch.d.arraycoerce.amstate = NULL;
1305 }
1306
1307 ExprEvalPushStep(state, &scratch);
1308 break;
1309 }
1310
1311 case T_ConvertRowtypeExpr:
1312 {
1313 ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
1314
1315 /* evaluate argument into step's result area */
1316 ExecInitExprRec(convert->arg, parent, state, resv, resnull);
1317
1318 /* and push conversion step */
1319 scratch.opcode = EEOP_CONVERT_ROWTYPE;
1320 scratch.d.convert_rowtype.convert = convert;
1321 scratch.d.convert_rowtype.indesc = NULL;
1322 scratch.d.convert_rowtype.outdesc = NULL;
1323 scratch.d.convert_rowtype.map = NULL;
1324 scratch.d.convert_rowtype.initialized = false;
1325
1326 ExprEvalPushStep(state, &scratch);
1327 break;
1328 }
1329
1330 /* note that CaseWhen expressions are handled within this block */
1331 case T_CaseExpr:
1332 {
1333 CaseExpr *caseExpr = (CaseExpr *) node;
1334 List *adjust_jumps = NIL;
1335 Datum *caseval = NULL;
1336 bool *casenull = NULL;
1337 ListCell *lc;
1338
1339 /*
1340 * If there's a test expression, we have to evaluate it and
1341 * save the value where the CaseTestExpr placeholders can find
1342 * it.
1343 */
1344 if (caseExpr->arg != NULL)
1345 {
1346 /* Evaluate testexpr into caseval/casenull workspace */
1347 caseval = palloc(sizeof(Datum));
1348 casenull = palloc(sizeof(bool));
1349
1350 ExecInitExprRec(caseExpr->arg, parent, state,
1351 caseval, casenull);
1352
1353 /*
1354 * Since value might be read multiple times, force to R/O
1355 * - but only if it could be an expanded datum.
1356 */
1357 if (get_typlen(exprType((Node *) caseExpr->arg)) == -1)
1358 {
1359 /* change caseval in-place */
1360 scratch.opcode = EEOP_MAKE_READONLY;
1361 scratch.resvalue = caseval;
1362 scratch.resnull = casenull;
1363 scratch.d.make_readonly.value = caseval;
1364 scratch.d.make_readonly.isnull = casenull;
1365 ExprEvalPushStep(state, &scratch);
1366 /* restore normal settings of scratch fields */
1367 scratch.resvalue = resv;
1368 scratch.resnull = resnull;
1369 }
1370 }
1371
1372 /*
1373 * Prepare to evaluate each of the WHEN clauses in turn; as
1374 * soon as one is true we return the value of the
1375 * corresponding THEN clause. If none are true then we return
1376 * the value of the ELSE clause, or NULL if there is none.
1377 */
1378 foreach(lc, caseExpr->args)
1379 {
1380 CaseWhen *when = (CaseWhen *) lfirst(lc);
1381 Datum *save_innermost_caseval;
1382 bool *save_innermost_casenull;
1383 int whenstep;
1384
1385 /*
1386 * Make testexpr result available to CaseTestExpr nodes
1387 * within the condition. We must save and restore prior
1388 * setting of innermost_caseval fields, in case this node
1389 * is itself within a larger CASE.
1390 *
1391 * If there's no test expression, we don't actually need
1392 * to save and restore these fields; but it's less code to
1393 * just do so unconditionally.
1394 */
1395 save_innermost_caseval = state->innermost_caseval;
1396 save_innermost_casenull = state->innermost_casenull;
1397 state->innermost_caseval = caseval;
1398 state->innermost_casenull = casenull;
1399
1400 /* evaluate condition into CASE's result variables */
1401 ExecInitExprRec(when->expr, parent, state, resv, resnull);
1402
1403 state->innermost_caseval = save_innermost_caseval;
1404 state->innermost_casenull = save_innermost_casenull;
1405
1406 /* If WHEN result isn't true, jump to next CASE arm */
1407 scratch.opcode = EEOP_JUMP_IF_NOT_TRUE;
1408 scratch.d.jump.jumpdone = -1; /* computed later */
1409 ExprEvalPushStep(state, &scratch);
1410 whenstep = state->steps_len - 1;
1411
1412 /*
1413 * If WHEN result is true, evaluate THEN result, storing
1414 * it into the CASE's result variables.
1415 */
1416 ExecInitExprRec(when->result, parent, state, resv, resnull);
1417
1418 /* Emit JUMP step to jump to end of CASE's code */
1419 scratch.opcode = EEOP_JUMP;
1420 scratch.d.jump.jumpdone = -1; /* computed later */
1421 ExprEvalPushStep(state, &scratch);
1422
1423 /*
1424 * Don't know address for that jump yet, compute once the
1425 * whole CASE expression is built.
1426 */
1427 adjust_jumps = lappend_int(adjust_jumps,
1428 state->steps_len - 1);
1429
1430 /*
1431 * But we can set WHEN test's jump target now, to make it
1432 * jump to the next WHEN subexpression or the ELSE.
1433 */
1434 state->steps[whenstep].d.jump.jumpdone = state->steps_len;
1435 }
1436
1437 /* transformCaseExpr always adds a default */
1438 Assert(caseExpr->defresult);
1439
1440 /* evaluate ELSE expr into CASE's result variables */
1441 ExecInitExprRec(caseExpr->defresult, parent, state,
1442 resv, resnull);
1443
1444 /* adjust jump targets */
1445 foreach(lc, adjust_jumps)
1446 {
1447 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1448
1449 Assert(as->opcode == EEOP_JUMP);
1450 Assert(as->d.jump.jumpdone == -1);
1451 as->d.jump.jumpdone = state->steps_len;
1452 }
1453
1454 break;
1455 }
1456
1457 case T_CaseTestExpr:
1458 {
1459 /*
1460 * Read from location identified by innermost_caseval. Note
1461 * that innermost_caseval could be NULL, if this node isn't
1462 * actually within a CASE structure; some parts of the system
1463 * abuse CaseTestExpr to cause a read of a value externally
1464 * supplied in econtext->caseValue_datum. We'll take care of
1465 * that scenario at runtime.
1466 */
1467 scratch.opcode = EEOP_CASE_TESTVAL;
1468 scratch.d.casetest.value = state->innermost_caseval;
1469 scratch.d.casetest.isnull = state->innermost_casenull;
1470
1471 ExprEvalPushStep(state, &scratch);
1472 break;
1473 }
1474
1475 case T_ArrayExpr:
1476 {
1477 ArrayExpr *arrayexpr = (ArrayExpr *) node;
1478 int nelems = list_length(arrayexpr->elements);
1479 ListCell *lc;
1480 int elemoff;
1481
1482 /*
1483 * Evaluate by computing each element, and then forming the
1484 * array. Elements are computed into scratch arrays
1485 * associated with the ARRAYEXPR step.
1486 */
1487 scratch.opcode = EEOP_ARRAYEXPR;
1488 scratch.d.arrayexpr.elemvalues =
1489 (Datum *) palloc(sizeof(Datum) * nelems);
1490 scratch.d.arrayexpr.elemnulls =
1491 (bool *) palloc(sizeof(bool) * nelems);
1492 scratch.d.arrayexpr.nelems = nelems;
1493
1494 /* fill remaining fields of step */
1495 scratch.d.arrayexpr.multidims = arrayexpr->multidims;
1496 scratch.d.arrayexpr.elemtype = arrayexpr->element_typeid;
1497
1498 /* do one-time catalog lookup for type info */
1499 get_typlenbyvalalign(arrayexpr->element_typeid,
1500 &scratch.d.arrayexpr.elemlength,
1501 &scratch.d.arrayexpr.elembyval,
1502 &scratch.d.arrayexpr.elemalign);
1503
1504 /* prepare to evaluate all arguments */
1505 elemoff = 0;
1506 foreach(lc, arrayexpr->elements)
1507 {
1508 Expr *e = (Expr *) lfirst(lc);
1509
1510 ExecInitExprRec(e, parent, state,
1511 &scratch.d.arrayexpr.elemvalues[elemoff],
1512 &scratch.d.arrayexpr.elemnulls[elemoff]);
1513 elemoff++;
1514 }
1515
1516 /* and then collect all into an array */
1517 ExprEvalPushStep(state, &scratch);
1518 break;
1519 }
1520
1521 case T_RowExpr:
1522 {
1523 RowExpr *rowexpr = (RowExpr *) node;
1524 int nelems = list_length(rowexpr->args);
1525 TupleDesc tupdesc;
1526 Form_pg_attribute *attrs;
1527 int i;
1528 ListCell *l;
1529
1530 /* Build tupdesc to describe result tuples */
1531 if (rowexpr->row_typeid == RECORDOID)
1532 {
1533 /* generic record, use types of given expressions */
1534 tupdesc = ExecTypeFromExprList(rowexpr->args);
1535 }
1536 else
1537 {
1538 /* it's been cast to a named type, use that */
1539 tupdesc = lookup_rowtype_tupdesc_copy(rowexpr->row_typeid, -1);
1540 }
1541 /* In either case, adopt RowExpr's column aliases */
1542 ExecTypeSetColNames(tupdesc, rowexpr->colnames);
1543 /* Bless the tupdesc in case it's now of type RECORD */
1544 BlessTupleDesc(tupdesc);
1545
1546 /*
1547 * In the named-type case, the tupdesc could have more columns
1548 * than are in the args list, since the type might have had
1549 * columns added since the ROW() was parsed. We want those
1550 * extra columns to go to nulls, so we make sure that the
1551 * workspace arrays are large enough and then initialize any
1552 * extra columns to read as NULLs.
1553 */
1554 Assert(nelems <= tupdesc->natts);
1555 nelems = Max(nelems, tupdesc->natts);
1556
1557 /*
1558 * Evaluate by first building datums for each field, and then
1559 * a final step forming the composite datum.
1560 */
1561 scratch.opcode = EEOP_ROW;
1562 scratch.d.row.tupdesc = tupdesc;
1563
1564 /* space for the individual field datums */
1565 scratch.d.row.elemvalues =
1566 (Datum *) palloc(sizeof(Datum) * nelems);
1567 scratch.d.row.elemnulls =
1568 (bool *) palloc(sizeof(bool) * nelems);
1569 /* as explained above, make sure any extra columns are null */
1570 memset(scratch.d.row.elemnulls, true, sizeof(bool) * nelems);
1571
1572 /* Set up evaluation, skipping any deleted columns */
1573 attrs = tupdesc->attrs;
1574 i = 0;
1575 foreach(l, rowexpr->args)
1576 {
1577 Expr *e = (Expr *) lfirst(l);
1578
1579 if (!attrs[i]->attisdropped)
1580 {
1581 /*
1582 * Guard against ALTER COLUMN TYPE on rowtype since
1583 * the RowExpr was created. XXX should we check
1584 * typmod too? Not sure we can be sure it'll be the
1585 * same.
1586 */
1587 if (exprType((Node *) e) != attrs[i]->atttypid)
1588 ereport(ERROR,
1589 (errcode(ERRCODE_DATATYPE_MISMATCH),
1590 errmsg("ROW() column has type %s instead of type %s",
1591 format_type_be(exprType((Node *) e)),
1592 format_type_be(attrs[i]->atttypid))));
1593 }
1594 else
1595 {
1596 /*
1597 * Ignore original expression and insert a NULL. We
1598 * don't really care what type of NULL it is, so
1599 * always make an int4 NULL.
1600 */
1601 e = (Expr *) makeNullConst(INT4OID, -1, InvalidOid);
1602 }
1603
1604 /* Evaluate column expr into appropriate workspace slot */
1605 ExecInitExprRec(e, parent, state,
1606 &scratch.d.row.elemvalues[i],
1607 &scratch.d.row.elemnulls[i]);
1608 i++;
1609 }
1610
1611 /* And finally build the row value */
1612 ExprEvalPushStep(state, &scratch);
1613 break;
1614 }
1615
1616 case T_RowCompareExpr:
1617 {
1618 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
1619 int nopers = list_length(rcexpr->opnos);
1620 List *adjust_jumps = NIL;
1621 ListCell *l_left_expr,
1622 *l_right_expr,
1623 *l_opno,
1624 *l_opfamily,
1625 *l_inputcollid;
1626 ListCell *lc;
1627 int off;
1628
1629 /*
1630 * Iterate over each field, prepare comparisons. To handle
1631 * NULL results, prepare jumps to after the expression. If a
1632 * comparison yields a != 0 result, jump to the final step.
1633 */
1634 Assert(list_length(rcexpr->largs) == nopers);
1635 Assert(list_length(rcexpr->rargs) == nopers);
1636 Assert(list_length(rcexpr->opfamilies) == nopers);
1637 Assert(list_length(rcexpr->inputcollids) == nopers);
1638
1639 off = 0;
1640 for (off = 0,
1641 l_left_expr = list_head(rcexpr->largs),
1642 l_right_expr = list_head(rcexpr->rargs),
1643 l_opno = list_head(rcexpr->opnos),
1644 l_opfamily = list_head(rcexpr->opfamilies),
1645 l_inputcollid = list_head(rcexpr->inputcollids);
1646 off < nopers;
1647 off++,
1648 l_left_expr = lnext(l_left_expr),
1649 l_right_expr = lnext(l_right_expr),
1650 l_opno = lnext(l_opno),
1651 l_opfamily = lnext(l_opfamily),
1652 l_inputcollid = lnext(l_inputcollid))
1653 {
1654 Expr *left_expr = (Expr *) lfirst(l_left_expr);
1655 Expr *right_expr = (Expr *) lfirst(l_right_expr);
1656 Oid opno = lfirst_oid(l_opno);
1657 Oid opfamily = lfirst_oid(l_opfamily);
1658 Oid inputcollid = lfirst_oid(l_inputcollid);
1659 int strategy;
1660 Oid lefttype;
1661 Oid righttype;
1662 Oid proc;
1663 FmgrInfo *finfo;
1664 FunctionCallInfo fcinfo;
1665
1666 get_op_opfamily_properties(opno, opfamily, false,
1667 &strategy,
1668 &lefttype,
1669 &righttype);
1670 proc = get_opfamily_proc(opfamily,
1671 lefttype,
1672 righttype,
1673 BTORDER_PROC);
1674 if (!OidIsValid(proc))
1675 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
1676 BTORDER_PROC, lefttype, righttype, opfamily);
1677
1678 /* Set up the primary fmgr lookup information */
1679 finfo = palloc0(sizeof(FmgrInfo));
1680 fcinfo = palloc0(sizeof(FunctionCallInfoData));
1681 fmgr_info(proc, finfo);
1682 fmgr_info_set_expr((Node *) node, finfo);
1683 InitFunctionCallInfoData(*fcinfo, finfo, 2,
1684 inputcollid, NULL, NULL);
1685
1686 /*
1687 * If we enforced permissions checks on index support
1688 * functions, we'd need to make a check here. But the
1689 * index support machinery doesn't do that, and thus
1690 * neither does this code.
1691 */
1692
1693 /* evaluate left and right args directly into fcinfo */
1694 ExecInitExprRec(left_expr, parent, state,
1695 &fcinfo->arg[0], &fcinfo->argnull[0]);
1696 ExecInitExprRec(right_expr, parent, state,
1697 &fcinfo->arg[1], &fcinfo->argnull[1]);
1698
1699 scratch.opcode = EEOP_ROWCOMPARE_STEP;
1700 scratch.d.rowcompare_step.finfo = finfo;
1701 scratch.d.rowcompare_step.fcinfo_data = fcinfo;
1702 scratch.d.rowcompare_step.fn_addr = finfo->fn_addr;
1703 /* jump targets filled below */
1704 scratch.d.rowcompare_step.jumpnull = -1;
1705 scratch.d.rowcompare_step.jumpdone = -1;
1706
1707 ExprEvalPushStep(state, &scratch);
1708 adjust_jumps = lappend_int(adjust_jumps,
1709 state->steps_len - 1);
1710 }
1711
1712 /*
1713 * We could have a zero-column rowtype, in which case the rows
1714 * necessarily compare equal.
1715 */
1716 if (nopers == 0)
1717 {
1718 scratch.opcode = EEOP_CONST;
1719 scratch.d.constval.value = Int32GetDatum(0);
1720 scratch.d.constval.isnull = false;
1721 ExprEvalPushStep(state, &scratch);
1722 }
1723
1724 /* Finally, examine the last comparison result */
1725 scratch.opcode = EEOP_ROWCOMPARE_FINAL;
1726 scratch.d.rowcompare_final.rctype = rcexpr->rctype;
1727 ExprEvalPushStep(state, &scratch);
1728
1729 /* adjust jump targetss */
1730 foreach(lc, adjust_jumps)
1731 {
1732 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1733
1734 Assert(as->opcode == EEOP_ROWCOMPARE_STEP);
1735 Assert(as->d.rowcompare_step.jumpdone == -1);
1736 Assert(as->d.rowcompare_step.jumpnull == -1);
1737
1738 /* jump to comparison evaluation */
1739 as->d.rowcompare_step.jumpdone = state->steps_len - 1;
1740 /* jump to the following expression */
1741 as->d.rowcompare_step.jumpnull = state->steps_len;
1742 }
1743
1744 break;
1745 }
1746
1747 case T_CoalesceExpr:
1748 {
1749 CoalesceExpr *coalesce = (CoalesceExpr *) node;
1750 List *adjust_jumps = NIL;
1751 ListCell *lc;
1752
1753 /* We assume there's at least one arg */
1754 Assert(coalesce->args != NIL);
1755
1756 /*
1757 * Prepare evaluation of all coalesced arguments, after each
1758 * one push a step that short-circuits if not null.
1759 */
1760 foreach(lc, coalesce->args)
1761 {
1762 Expr *e = (Expr *) lfirst(lc);
1763
1764 /* evaluate argument, directly into result datum */
1765 ExecInitExprRec(e, parent, state, resv, resnull);
1766
1767 /* if it's not null, skip to end of COALESCE expr */
1768 scratch.opcode = EEOP_JUMP_IF_NOT_NULL;
1769 scratch.d.jump.jumpdone = -1; /* adjust later */
1770 ExprEvalPushStep(state, &scratch);
1771
1772 adjust_jumps = lappend_int(adjust_jumps,
1773 state->steps_len - 1);
1774 }
1775
1776 /*
1777 * No need to add a constant NULL return - we only can get to
1778 * the end of the expression if a NULL already is being
1779 * returned.
1780 */
1781
1782 /* adjust jump targets */
1783 foreach(lc, adjust_jumps)
1784 {
1785 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1786
1787 Assert(as->opcode == EEOP_JUMP_IF_NOT_NULL);
1788 Assert(as->d.jump.jumpdone == -1);
1789 as->d.jump.jumpdone = state->steps_len;
1790 }
1791
1792 break;
1793 }
1794
1795 case T_MinMaxExpr:
1796 {
1797 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
1798 int nelems = list_length(minmaxexpr->args);
1799 TypeCacheEntry *typentry;
1800 FmgrInfo *finfo;
1801 FunctionCallInfo fcinfo;
1802 ListCell *lc;
1803 int off;
1804
1805 /* Look up the btree comparison function for the datatype */
1806 typentry = lookup_type_cache(minmaxexpr->minmaxtype,
1807 TYPECACHE_CMP_PROC);
1808 if (!OidIsValid(typentry->cmp_proc))
1809 ereport(ERROR,
1810 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1811 errmsg("could not identify a comparison function for type %s",
1812 format_type_be(minmaxexpr->minmaxtype))));
1813
1814 /*
1815 * If we enforced permissions checks on index support
1816 * functions, we'd need to make a check here. But the index
1817 * support machinery doesn't do that, and thus neither does
1818 * this code.
1819 */
1820
1821 /* Perform function lookup */
1822 finfo = palloc0(sizeof(FmgrInfo));
1823 fcinfo = palloc0(sizeof(FunctionCallInfoData));
1824 fmgr_info(typentry->cmp_proc, finfo);
1825 fmgr_info_set_expr((Node *) node, finfo);
1826 InitFunctionCallInfoData(*fcinfo, finfo, 2,
1827 minmaxexpr->inputcollid, NULL, NULL);
1828
1829 scratch.opcode = EEOP_MINMAX;
1830 /* allocate space to store arguments */
1831 scratch.d.minmax.values =
1832 (Datum *) palloc(sizeof(Datum) * nelems);
1833 scratch.d.minmax.nulls =
1834 (bool *) palloc(sizeof(bool) * nelems);
1835 scratch.d.minmax.nelems = nelems;
1836
1837 scratch.d.minmax.op = minmaxexpr->op;
1838 scratch.d.minmax.finfo = finfo;
1839 scratch.d.minmax.fcinfo_data = fcinfo;
1840
1841 /* evaluate expressions into minmax->values/nulls */
1842 off = 0;
1843 foreach(lc, minmaxexpr->args)
1844 {
1845 Expr *e = (Expr *) lfirst(lc);
1846
1847 ExecInitExprRec(e, parent, state,
1848 &scratch.d.minmax.values[off],
1849 &scratch.d.minmax.nulls[off]);
1850 off++;
1851 }
1852
1853 /* and push the final comparison */
1854 ExprEvalPushStep(state, &scratch);
1855 break;
1856 }
1857
1858 case T_SQLValueFunction:
1859 {
1860 SQLValueFunction *svf = (SQLValueFunction *) node;
1861
1862 scratch.opcode = EEOP_SQLVALUEFUNCTION;
1863 scratch.d.sqlvaluefunction.svf = svf;
1864
1865 ExprEvalPushStep(state, &scratch);
1866 break;
1867 }
1868
1869 case T_XmlExpr:
1870 {
1871 XmlExpr *xexpr = (XmlExpr *) node;
1872 int nnamed = list_length(xexpr->named_args);
1873 int nargs = list_length(xexpr->args);
1874 int off;
1875 ListCell *arg;
1876
1877 scratch.opcode = EEOP_XMLEXPR;
1878 scratch.d.xmlexpr.xexpr = xexpr;
1879
1880 /* allocate space for storing all the arguments */
1881 if (nnamed)
1882 {
1883 scratch.d.xmlexpr.named_argvalue =
1884 (Datum *) palloc(sizeof(Datum) * nnamed);
1885 scratch.d.xmlexpr.named_argnull =
1886 (bool *) palloc(sizeof(bool) * nnamed);
1887 }
1888 else
1889 {
1890 scratch.d.xmlexpr.named_argvalue = NULL;
1891 scratch.d.xmlexpr.named_argnull = NULL;
1892 }
1893
1894 if (nargs)
1895 {
1896 scratch.d.xmlexpr.argvalue =
1897 (Datum *) palloc(sizeof(Datum) * nargs);
1898 scratch.d.xmlexpr.argnull =
1899 (bool *) palloc(sizeof(bool) * nargs);
1900 }
1901 else
1902 {
1903 scratch.d.xmlexpr.argvalue = NULL;
1904 scratch.d.xmlexpr.argnull = NULL;
1905 }
1906
1907 /* prepare argument execution */
1908 off = 0;
1909 foreach(arg, xexpr->named_args)
1910 {
1911 Expr *e = (Expr *) lfirst(arg);
1912
1913 ExecInitExprRec(e, parent, state,
1914 &scratch.d.xmlexpr.named_argvalue[off],
1915 &scratch.d.xmlexpr.named_argnull[off]);
1916 off++;
1917 }
1918
1919 off = 0;
1920 foreach(arg, xexpr->args)
1921 {
1922 Expr *e = (Expr *) lfirst(arg);
1923
1924 ExecInitExprRec(e, parent, state,
1925 &scratch.d.xmlexpr.argvalue[off],
1926 &scratch.d.xmlexpr.argnull[off]);
1927 off++;
1928 }
1929
1930 /* and evaluate the actual XML expression */
1931 ExprEvalPushStep(state, &scratch);
1932 break;
1933 }
1934
1935 case T_NullTest:
1936 {
1937 NullTest *ntest = (NullTest *) node;
1938
1939 if (ntest->nulltesttype == IS_NULL)
1940 {
1941 if (ntest->argisrow)
1942 scratch.opcode = EEOP_NULLTEST_ROWISNULL;
1943 else
1944 scratch.opcode = EEOP_NULLTEST_ISNULL;
1945 }
1946 else if (ntest->nulltesttype == IS_NOT_NULL)
1947 {
1948 if (ntest->argisrow)
1949 scratch.opcode = EEOP_NULLTEST_ROWISNOTNULL;
1950 else
1951 scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
1952 }
1953 else
1954 {
1955 elog(ERROR, "unrecognized nulltesttype: %d",
1956 (int) ntest->nulltesttype);
1957 }
1958 /* initialize cache in case it's a row test */
1959 scratch.d.nulltest_row.argdesc = NULL;
1960
1961 /* first evaluate argument into result variable */
1962 ExecInitExprRec(ntest->arg, parent, state,
1963 resv, resnull);
1964
1965 /* then push the test of that argument */
1966 ExprEvalPushStep(state, &scratch);
1967 break;
1968 }
1969
1970 case T_BooleanTest:
1971 {
1972 BooleanTest *btest = (BooleanTest *) node;
1973
1974 /*
1975 * Evaluate argument, directly into result datum. That's ok,
1976 * because resv/resnull is definitely not used anywhere else,
1977 * and will get overwritten by the below EEOP_BOOLTEST_IS_*
1978 * step.
1979 */
1980 ExecInitExprRec(btest->arg, parent, state, resv, resnull);
1981
1982 switch (btest->booltesttype)
1983 {
1984 case IS_TRUE:
1985 scratch.opcode = EEOP_BOOLTEST_IS_TRUE;
1986 break;
1987 case IS_NOT_TRUE:
1988 scratch.opcode = EEOP_BOOLTEST_IS_NOT_TRUE;
1989 break;
1990 case IS_FALSE:
1991 scratch.opcode = EEOP_BOOLTEST_IS_FALSE;
1992 break;
1993 case IS_NOT_FALSE:
1994 scratch.opcode = EEOP_BOOLTEST_IS_NOT_FALSE;
1995 break;
1996 case IS_UNKNOWN:
1997 /* Same as scalar IS NULL test */
1998 scratch.opcode = EEOP_NULLTEST_ISNULL;
1999 break;
2000 case IS_NOT_UNKNOWN:
2001 /* Same as scalar IS NOT NULL test */
2002 scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
2003 break;
2004 default:
2005 elog(ERROR, "unrecognized booltesttype: %d",
2006 (int) btest->booltesttype);
2007 }
2008
2009 ExprEvalPushStep(state, &scratch);
2010 break;
2011 }
2012
2013 case T_CoerceToDomain:
2014 {
2015 CoerceToDomain *ctest = (CoerceToDomain *) node;
2016
2017 ExecInitCoerceToDomain(&scratch, ctest, parent, state,
2018 resv, resnull);
2019 break;
2020 }
2021
2022 case T_CoerceToDomainValue:
2023 {
2024 /*
2025 * Read from location identified by innermost_domainval. Note
2026 * that innermost_domainval could be NULL, if we're compiling
2027 * a standalone domain check rather than one embedded in a
2028 * larger expression. In that case we must read from
2029 * econtext->domainValue_datum. We'll take care of that
2030 * scenario at runtime.
2031 */
2032 scratch.opcode = EEOP_DOMAIN_TESTVAL;
2033 /* we share instruction union variant with case testval */
2034 scratch.d.casetest.value = state->innermost_domainval;
2035 scratch.d.casetest.isnull = state->innermost_domainnull;
2036
2037 ExprEvalPushStep(state, &scratch);
2038 break;
2039 }
2040
2041 case T_CurrentOfExpr:
2042 {
2043 scratch.opcode = EEOP_CURRENTOFEXPR;
2044 ExprEvalPushStep(state, &scratch);
2045 break;
2046 }
2047
2048 case T_NextValueExpr:
2049 {
2050 NextValueExpr *nve = (NextValueExpr *) node;
2051
2052 scratch.opcode = EEOP_NEXTVALUEEXPR;
2053 scratch.d.nextvalueexpr.seqid = nve->seqid;
2054 scratch.d.nextvalueexpr.seqtypid = nve->typeId;
2055
2056 ExprEvalPushStep(state, &scratch);
2057 break;
2058 }
2059
2060 default:
2061 elog(ERROR, "unrecognized node type: %d",
2062 (int) nodeTag(node));
2063 break;
2064 }
2065 }
2066
2067 /*
2068 * Add another expression evaluation step to ExprState->steps.
2069 *
2070 * Note that this potentially re-allocates es->steps, therefore no pointer
2071 * into that array may be used while the expression is still being built.
2072 */
2073 static void
ExprEvalPushStep(ExprState * es,const ExprEvalStep * s)2074 ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
2075 {
2076 if (es->steps_alloc == 0)
2077 {
2078 es->steps_alloc = 16;
2079 es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc);
2080 }
2081 else if (es->steps_alloc == es->steps_len)
2082 {
2083 es->steps_alloc *= 2;
2084 es->steps = repalloc(es->steps,
2085 sizeof(ExprEvalStep) * es->steps_alloc);
2086 }
2087
2088 memcpy(&es->steps[es->steps_len++], s, sizeof(ExprEvalStep));
2089 }
2090
2091 /*
2092 * Perform setup necessary for the evaluation of a function-like expression,
2093 * appending argument evaluation steps to the steps list in *state, and
2094 * setting up *scratch so it is ready to be pushed.
2095 *
2096 * *scratch is not pushed here, so that callers may override the opcode,
2097 * which is useful for function-like cases like DISTINCT.
2098 */
2099 static void
ExecInitFunc(ExprEvalStep * scratch,Expr * node,List * args,Oid funcid,Oid inputcollid,PlanState * parent,ExprState * state)2100 ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
2101 Oid inputcollid, PlanState *parent, ExprState *state)
2102 {
2103 int nargs = list_length(args);
2104 AclResult aclresult;
2105 FmgrInfo *flinfo;
2106 FunctionCallInfo fcinfo;
2107 int argno;
2108 ListCell *lc;
2109
2110 /* Check permission to call function */
2111 aclresult = pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE);
2112 if (aclresult != ACLCHECK_OK)
2113 aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(funcid));
2114 InvokeFunctionExecuteHook(funcid);
2115
2116 /*
2117 * Safety check on nargs. Under normal circumstances this should never
2118 * fail, as parser should check sooner. But possibly it might fail if
2119 * server has been compiled with FUNC_MAX_ARGS smaller than some functions
2120 * declared in pg_proc?
2121 */
2122 if (nargs > FUNC_MAX_ARGS)
2123 ereport(ERROR,
2124 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2125 errmsg_plural("cannot pass more than %d argument to a function",
2126 "cannot pass more than %d arguments to a function",
2127 FUNC_MAX_ARGS,
2128 FUNC_MAX_ARGS)));
2129
2130 /* Allocate function lookup data and parameter workspace for this call */
2131 scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
2132 scratch->d.func.fcinfo_data = palloc0(sizeof(FunctionCallInfoData));
2133 flinfo = scratch->d.func.finfo;
2134 fcinfo = scratch->d.func.fcinfo_data;
2135
2136 /* Set up the primary fmgr lookup information */
2137 fmgr_info(funcid, flinfo);
2138 fmgr_info_set_expr((Node *) node, flinfo);
2139
2140 /* Initialize function call parameter structure too */
2141 InitFunctionCallInfoData(*fcinfo, flinfo,
2142 nargs, inputcollid, NULL, NULL);
2143
2144 /* Keep extra copies of this info to save an indirection at runtime */
2145 scratch->d.func.fn_addr = flinfo->fn_addr;
2146 scratch->d.func.nargs = nargs;
2147
2148 /* We only support non-set functions here */
2149 if (flinfo->fn_retset)
2150 ereport(ERROR,
2151 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2152 errmsg("set-valued function called in context that cannot accept a set"),
2153 parent ? executor_errposition(parent->state,
2154 exprLocation((Node *) node)) : 0));
2155
2156 /* Build code to evaluate arguments directly into the fcinfo struct */
2157 argno = 0;
2158 foreach(lc, args)
2159 {
2160 Expr *arg = (Expr *) lfirst(lc);
2161
2162 if (IsA(arg, Const))
2163 {
2164 /*
2165 * Don't evaluate const arguments every round; especially
2166 * interesting for constants in comparisons.
2167 */
2168 Const *con = (Const *) arg;
2169
2170 fcinfo->arg[argno] = con->constvalue;
2171 fcinfo->argnull[argno] = con->constisnull;
2172 }
2173 else
2174 {
2175 ExecInitExprRec(arg, parent, state,
2176 &fcinfo->arg[argno], &fcinfo->argnull[argno]);
2177 }
2178 argno++;
2179 }
2180
2181 /* Insert appropriate opcode depending on strictness and stats level */
2182 if (pgstat_track_functions <= flinfo->fn_stats)
2183 {
2184 if (flinfo->fn_strict && nargs > 0)
2185 scratch->opcode = EEOP_FUNCEXPR_STRICT;
2186 else
2187 scratch->opcode = EEOP_FUNCEXPR;
2188 }
2189 else
2190 {
2191 if (flinfo->fn_strict && nargs > 0)
2192 scratch->opcode = EEOP_FUNCEXPR_STRICT_FUSAGE;
2193 else
2194 scratch->opcode = EEOP_FUNCEXPR_FUSAGE;
2195 }
2196 }
2197
2198 /*
2199 * Add expression steps deforming the ExprState's inner/outer/scan slots
2200 * as much as required by the expression.
2201 */
2202 static void
ExecInitExprSlots(ExprState * state,Node * node)2203 ExecInitExprSlots(ExprState *state, Node *node)
2204 {
2205 LastAttnumInfo info = {0, 0, 0};
2206 ExprEvalStep scratch;
2207
2208 /*
2209 * Figure out which attributes we're going to need.
2210 */
2211 get_last_attnums_walker(node, &info);
2212
2213 /* Emit steps as needed */
2214 if (info.last_inner > 0)
2215 {
2216 scratch.opcode = EEOP_INNER_FETCHSOME;
2217 scratch.d.fetch.last_var = info.last_inner;
2218 ExprEvalPushStep(state, &scratch);
2219 }
2220 if (info.last_outer > 0)
2221 {
2222 scratch.opcode = EEOP_OUTER_FETCHSOME;
2223 scratch.d.fetch.last_var = info.last_outer;
2224 ExprEvalPushStep(state, &scratch);
2225 }
2226 if (info.last_scan > 0)
2227 {
2228 scratch.opcode = EEOP_SCAN_FETCHSOME;
2229 scratch.d.fetch.last_var = info.last_scan;
2230 ExprEvalPushStep(state, &scratch);
2231 }
2232 }
2233
2234 /*
2235 * get_last_attnums_walker: expression walker for ExecInitExprSlots
2236 */
2237 static bool
get_last_attnums_walker(Node * node,LastAttnumInfo * info)2238 get_last_attnums_walker(Node *node, LastAttnumInfo *info)
2239 {
2240 if (node == NULL)
2241 return false;
2242 if (IsA(node, Var))
2243 {
2244 Var *variable = (Var *) node;
2245 AttrNumber attnum = variable->varattno;
2246
2247 switch (variable->varno)
2248 {
2249 case INNER_VAR:
2250 info->last_inner = Max(info->last_inner, attnum);
2251 break;
2252
2253 case OUTER_VAR:
2254 info->last_outer = Max(info->last_outer, attnum);
2255 break;
2256
2257 /* INDEX_VAR is handled by default case */
2258
2259 default:
2260 info->last_scan = Max(info->last_scan, attnum);
2261 break;
2262 }
2263 return false;
2264 }
2265
2266 /*
2267 * Don't examine the arguments or filters of Aggrefs or WindowFuncs,
2268 * because those do not represent expressions to be evaluated within the
2269 * calling expression's econtext. GroupingFunc arguments are never
2270 * evaluated at all.
2271 */
2272 if (IsA(node, Aggref))
2273 return false;
2274 if (IsA(node, WindowFunc))
2275 return false;
2276 if (IsA(node, GroupingFunc))
2277 return false;
2278 return expression_tree_walker(node, get_last_attnums_walker,
2279 (void *) info);
2280 }
2281
2282 /*
2283 * Prepare step for the evaluation of a whole-row variable.
2284 * The caller still has to push the step.
2285 */
2286 static void
ExecInitWholeRowVar(ExprEvalStep * scratch,Var * variable,PlanState * parent)2287 ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, PlanState *parent)
2288 {
2289 /* fill in all but the target */
2290 scratch->opcode = EEOP_WHOLEROW;
2291 scratch->d.wholerow.var = variable;
2292 scratch->d.wholerow.first = true;
2293 scratch->d.wholerow.slow = false;
2294 scratch->d.wholerow.tupdesc = NULL; /* filled at runtime */
2295 scratch->d.wholerow.junkFilter = NULL;
2296
2297 /*
2298 * If the input tuple came from a subquery, it might contain "resjunk"
2299 * columns (such as GROUP BY or ORDER BY columns), which we don't want to
2300 * keep in the whole-row result. We can get rid of such columns by
2301 * passing the tuple through a JunkFilter --- but to make one, we have to
2302 * lay our hands on the subquery's targetlist. Fortunately, there are not
2303 * very many cases where this can happen, and we can identify all of them
2304 * by examining our parent PlanState. We assume this is not an issue in
2305 * standalone expressions that don't have parent plans. (Whole-row Vars
2306 * can occur in such expressions, but they will always be referencing
2307 * table rows.)
2308 */
2309 if (parent)
2310 {
2311 PlanState *subplan = NULL;
2312
2313 switch (nodeTag(parent))
2314 {
2315 case T_SubqueryScanState:
2316 subplan = ((SubqueryScanState *) parent)->subplan;
2317 break;
2318 case T_CteScanState:
2319 subplan = ((CteScanState *) parent)->cteplanstate;
2320 break;
2321 default:
2322 break;
2323 }
2324
2325 if (subplan)
2326 {
2327 bool junk_filter_needed = false;
2328 ListCell *tlist;
2329
2330 /* Detect whether subplan tlist actually has any junk columns */
2331 foreach(tlist, subplan->plan->targetlist)
2332 {
2333 TargetEntry *tle = (TargetEntry *) lfirst(tlist);
2334
2335 if (tle->resjunk)
2336 {
2337 junk_filter_needed = true;
2338 break;
2339 }
2340 }
2341
2342 /* If so, build the junkfilter now */
2343 if (junk_filter_needed)
2344 {
2345 scratch->d.wholerow.junkFilter =
2346 ExecInitJunkFilter(subplan->plan->targetlist,
2347 ExecGetResultType(subplan)->tdhasoid,
2348 ExecInitExtraTupleSlot(parent->state));
2349 }
2350 }
2351 }
2352 }
2353
2354 /*
2355 * Prepare evaluation of an ArrayRef expression.
2356 */
2357 static void
ExecInitArrayRef(ExprEvalStep * scratch,ArrayRef * aref,PlanState * parent,ExprState * state,Datum * resv,bool * resnull)2358 ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref, PlanState *parent,
2359 ExprState *state, Datum *resv, bool *resnull)
2360 {
2361 bool isAssignment = (aref->refassgnexpr != NULL);
2362 ArrayRefState *arefstate = palloc0(sizeof(ArrayRefState));
2363 List *adjust_jumps = NIL;
2364 ListCell *lc;
2365 int i;
2366
2367 /* Fill constant fields of ArrayRefState */
2368 arefstate->isassignment = isAssignment;
2369 arefstate->refelemtype = aref->refelemtype;
2370 arefstate->refattrlength = get_typlen(aref->refarraytype);
2371 get_typlenbyvalalign(aref->refelemtype,
2372 &arefstate->refelemlength,
2373 &arefstate->refelembyval,
2374 &arefstate->refelemalign);
2375
2376 /*
2377 * Evaluate array input. It's safe to do so into resv/resnull, because we
2378 * won't use that as target for any of the other subexpressions, and it'll
2379 * be overwritten by the final EEOP_ARRAYREF_FETCH/ASSIGN step, which is
2380 * pushed last.
2381 */
2382 ExecInitExprRec(aref->refexpr, parent, state, resv, resnull);
2383
2384 /*
2385 * If refexpr yields NULL, and it's a fetch, then result is NULL. We can
2386 * implement this with just JUMP_IF_NULL, since we evaluated the array
2387 * into the desired target location.
2388 */
2389 if (!isAssignment)
2390 {
2391 scratch->opcode = EEOP_JUMP_IF_NULL;
2392 scratch->d.jump.jumpdone = -1; /* adjust later */
2393 ExprEvalPushStep(state, scratch);
2394 adjust_jumps = lappend_int(adjust_jumps,
2395 state->steps_len - 1);
2396 }
2397
2398 /* Verify subscript list lengths are within limit */
2399 if (list_length(aref->refupperindexpr) > MAXDIM)
2400 ereport(ERROR,
2401 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2402 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
2403 list_length(aref->refupperindexpr), MAXDIM)));
2404
2405 if (list_length(aref->reflowerindexpr) > MAXDIM)
2406 ereport(ERROR,
2407 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2408 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
2409 list_length(aref->reflowerindexpr), MAXDIM)));
2410
2411 /* Evaluate upper subscripts */
2412 i = 0;
2413 foreach(lc, aref->refupperindexpr)
2414 {
2415 Expr *e = (Expr *) lfirst(lc);
2416
2417 /* When slicing, individual subscript bounds can be omitted */
2418 if (!e)
2419 {
2420 arefstate->upperprovided[i] = false;
2421 i++;
2422 continue;
2423 }
2424
2425 arefstate->upperprovided[i] = true;
2426
2427 /* Each subscript is evaluated into subscriptvalue/subscriptnull */
2428 ExecInitExprRec(e, parent, state,
2429 &arefstate->subscriptvalue, &arefstate->subscriptnull);
2430
2431 /* ... and then ARRAYREF_SUBSCRIPT saves it into step's workspace */
2432 scratch->opcode = EEOP_ARRAYREF_SUBSCRIPT;
2433 scratch->d.arrayref_subscript.state = arefstate;
2434 scratch->d.arrayref_subscript.off = i;
2435 scratch->d.arrayref_subscript.isupper = true;
2436 scratch->d.arrayref_subscript.jumpdone = -1; /* adjust later */
2437 ExprEvalPushStep(state, scratch);
2438 adjust_jumps = lappend_int(adjust_jumps,
2439 state->steps_len - 1);
2440 i++;
2441 }
2442 arefstate->numupper = i;
2443
2444 /* Evaluate lower subscripts similarly */
2445 i = 0;
2446 foreach(lc, aref->reflowerindexpr)
2447 {
2448 Expr *e = (Expr *) lfirst(lc);
2449
2450 /* When slicing, individual subscript bounds can be omitted */
2451 if (!e)
2452 {
2453 arefstate->lowerprovided[i] = false;
2454 i++;
2455 continue;
2456 }
2457
2458 arefstate->lowerprovided[i] = true;
2459
2460 /* Each subscript is evaluated into subscriptvalue/subscriptnull */
2461 ExecInitExprRec(e, parent, state,
2462 &arefstate->subscriptvalue, &arefstate->subscriptnull);
2463
2464 /* ... and then ARRAYREF_SUBSCRIPT saves it into step's workspace */
2465 scratch->opcode = EEOP_ARRAYREF_SUBSCRIPT;
2466 scratch->d.arrayref_subscript.state = arefstate;
2467 scratch->d.arrayref_subscript.off = i;
2468 scratch->d.arrayref_subscript.isupper = false;
2469 scratch->d.arrayref_subscript.jumpdone = -1; /* adjust later */
2470 ExprEvalPushStep(state, scratch);
2471 adjust_jumps = lappend_int(adjust_jumps,
2472 state->steps_len - 1);
2473 i++;
2474 }
2475 arefstate->numlower = i;
2476
2477 /* Should be impossible if parser is sane, but check anyway: */
2478 if (arefstate->numlower != 0 &&
2479 arefstate->numupper != arefstate->numlower)
2480 elog(ERROR, "upper and lower index lists are not same length");
2481
2482 if (isAssignment)
2483 {
2484 Datum *save_innermost_caseval;
2485 bool *save_innermost_casenull;
2486
2487 /*
2488 * We might have a nested-assignment situation, in which the
2489 * refassgnexpr is itself a FieldStore or ArrayRef that needs to
2490 * obtain and modify the previous value of the array element or slice
2491 * being replaced. If so, we have to extract that value from the
2492 * array and pass it down via the CaseTestExpr mechanism. It's safe
2493 * to reuse the CASE mechanism because there cannot be a CASE between
2494 * here and where the value would be needed, and an array assignment
2495 * can't be within a CASE either. (So saving and restoring
2496 * innermost_caseval is just paranoia, but let's do it anyway.)
2497 *
2498 * Since fetching the old element might be a nontrivial expense, do it
2499 * only if the argument actually needs it.
2500 */
2501 if (isAssignmentIndirectionExpr(aref->refassgnexpr))
2502 {
2503 scratch->opcode = EEOP_ARRAYREF_OLD;
2504 scratch->d.arrayref.state = arefstate;
2505 ExprEvalPushStep(state, scratch);
2506 }
2507
2508 /* ARRAYREF_OLD puts extracted value into prevvalue/prevnull */
2509 save_innermost_caseval = state->innermost_caseval;
2510 save_innermost_casenull = state->innermost_casenull;
2511 state->innermost_caseval = &arefstate->prevvalue;
2512 state->innermost_casenull = &arefstate->prevnull;
2513
2514 /* evaluate replacement value into replacevalue/replacenull */
2515 ExecInitExprRec(aref->refassgnexpr, parent, state,
2516 &arefstate->replacevalue, &arefstate->replacenull);
2517
2518 state->innermost_caseval = save_innermost_caseval;
2519 state->innermost_casenull = save_innermost_casenull;
2520
2521 /* and perform the assignment */
2522 scratch->opcode = EEOP_ARRAYREF_ASSIGN;
2523 scratch->d.arrayref.state = arefstate;
2524 ExprEvalPushStep(state, scratch);
2525 }
2526 else
2527 {
2528 /* array fetch is much simpler */
2529 scratch->opcode = EEOP_ARRAYREF_FETCH;
2530 scratch->d.arrayref.state = arefstate;
2531 ExprEvalPushStep(state, scratch);
2532 }
2533
2534 /* adjust jump targets */
2535 foreach(lc, adjust_jumps)
2536 {
2537 ExprEvalStep *as = &state->steps[lfirst_int(lc)];
2538
2539 if (as->opcode == EEOP_ARRAYREF_SUBSCRIPT)
2540 {
2541 Assert(as->d.arrayref_subscript.jumpdone == -1);
2542 as->d.arrayref_subscript.jumpdone = state->steps_len;
2543 }
2544 else
2545 {
2546 Assert(as->opcode == EEOP_JUMP_IF_NULL);
2547 Assert(as->d.jump.jumpdone == -1);
2548 as->d.jump.jumpdone = state->steps_len;
2549 }
2550 }
2551 }
2552
2553 /*
2554 * Helper for preparing ArrayRef expressions for evaluation: is expr a nested
2555 * FieldStore or ArrayRef that needs the old element value passed down?
2556 *
2557 * (We could use this in FieldStore too, but in that case passing the old
2558 * value is so cheap there's no need.)
2559 *
2560 * Note: it might seem that this needs to recurse, but it does not; the
2561 * CaseTestExpr, if any, will be directly the arg or refexpr of the top-level
2562 * node. Nested-assignment situations give rise to expression trees in which
2563 * each level of assignment has its own CaseTestExpr, and the recursive
2564 * structure appears within the newvals or refassgnexpr field.
2565 */
2566 static bool
isAssignmentIndirectionExpr(Expr * expr)2567 isAssignmentIndirectionExpr(Expr *expr)
2568 {
2569 if (expr == NULL)
2570 return false; /* just paranoia */
2571 if (IsA(expr, FieldStore))
2572 {
2573 FieldStore *fstore = (FieldStore *) expr;
2574
2575 if (fstore->arg && IsA(fstore->arg, CaseTestExpr))
2576 return true;
2577 }
2578 else if (IsA(expr, ArrayRef))
2579 {
2580 ArrayRef *arrayRef = (ArrayRef *) expr;
2581
2582 if (arrayRef->refexpr && IsA(arrayRef->refexpr, CaseTestExpr))
2583 return true;
2584 }
2585 return false;
2586 }
2587
2588 /*
2589 * Prepare evaluation of a CoerceToDomain expression.
2590 */
2591 static void
ExecInitCoerceToDomain(ExprEvalStep * scratch,CoerceToDomain * ctest,PlanState * parent,ExprState * state,Datum * resv,bool * resnull)2592 ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
2593 PlanState *parent, ExprState *state,
2594 Datum *resv, bool *resnull)
2595 {
2596 ExprEvalStep scratch2;
2597 DomainConstraintRef *constraint_ref;
2598 Datum *domainval = NULL;
2599 bool *domainnull = NULL;
2600 Datum *save_innermost_domainval;
2601 bool *save_innermost_domainnull;
2602 ListCell *l;
2603
2604 scratch->d.domaincheck.resulttype = ctest->resulttype;
2605 /* we'll allocate workspace only if needed */
2606 scratch->d.domaincheck.checkvalue = NULL;
2607 scratch->d.domaincheck.checknull = NULL;
2608
2609 /*
2610 * Evaluate argument - it's fine to directly store it into resv/resnull,
2611 * if there's constraint failures there'll be errors, otherwise it's what
2612 * needs to be returned.
2613 */
2614 ExecInitExprRec(ctest->arg, parent, state, resv, resnull);
2615
2616 /*
2617 * Note: if the argument is of varlena type, it could be a R/W expanded
2618 * object. We want to return the R/W pointer as the final result, but we
2619 * have to pass a R/O pointer as the value to be tested by any functions
2620 * in check expressions. We don't bother to emit a MAKE_READONLY step
2621 * unless there's actually at least one check expression, though. Until
2622 * we've tested that, domainval/domainnull are NULL.
2623 */
2624
2625 /*
2626 * Collect the constraints associated with the domain.
2627 *
2628 * Note: before PG v10 we'd recheck the set of constraints during each
2629 * evaluation of the expression. Now we bake them into the ExprState
2630 * during executor initialization. That means we don't need typcache.c to
2631 * provide compiled exprs.
2632 */
2633 constraint_ref = (DomainConstraintRef *)
2634 palloc(sizeof(DomainConstraintRef));
2635 InitDomainConstraintRef(ctest->resulttype,
2636 constraint_ref,
2637 CurrentMemoryContext,
2638 false);
2639
2640 /*
2641 * Compile code to check each domain constraint. NOTNULL constraints can
2642 * just be applied on the resv/resnull value, but for CHECK constraints we
2643 * need more pushups.
2644 */
2645 foreach(l, constraint_ref->constraints)
2646 {
2647 DomainConstraintState *con = (DomainConstraintState *) lfirst(l);
2648
2649 scratch->d.domaincheck.constraintname = con->name;
2650
2651 switch (con->constrainttype)
2652 {
2653 case DOM_CONSTRAINT_NOTNULL:
2654 scratch->opcode = EEOP_DOMAIN_NOTNULL;
2655 ExprEvalPushStep(state, scratch);
2656 break;
2657 case DOM_CONSTRAINT_CHECK:
2658 /* Allocate workspace for CHECK output if we didn't yet */
2659 if (scratch->d.domaincheck.checkvalue == NULL)
2660 {
2661 scratch->d.domaincheck.checkvalue =
2662 (Datum *) palloc(sizeof(Datum));
2663 scratch->d.domaincheck.checknull =
2664 (bool *) palloc(sizeof(bool));
2665 }
2666
2667 /*
2668 * If first time through, determine where CoerceToDomainValue
2669 * nodes should read from.
2670 */
2671 if (domainval == NULL)
2672 {
2673 /*
2674 * Since value might be read multiple times, force to R/O
2675 * - but only if it could be an expanded datum.
2676 */
2677 if (get_typlen(ctest->resulttype) == -1)
2678 {
2679 /* Yes, so make output workspace for MAKE_READONLY */
2680 domainval = (Datum *) palloc(sizeof(Datum));
2681 domainnull = (bool *) palloc(sizeof(bool));
2682
2683 /* Emit MAKE_READONLY */
2684 scratch2.opcode = EEOP_MAKE_READONLY;
2685 scratch2.resvalue = domainval;
2686 scratch2.resnull = domainnull;
2687 scratch2.d.make_readonly.value = resv;
2688 scratch2.d.make_readonly.isnull = resnull;
2689 ExprEvalPushStep(state, &scratch2);
2690 }
2691 else
2692 {
2693 /* No, so it's fine to read from resv/resnull */
2694 domainval = resv;
2695 domainnull = resnull;
2696 }
2697 }
2698
2699 /*
2700 * Set up value to be returned by CoerceToDomainValue nodes.
2701 * We must save and restore innermost_domainval/null fields,
2702 * in case this node is itself within a check expression for
2703 * another domain.
2704 */
2705 save_innermost_domainval = state->innermost_domainval;
2706 save_innermost_domainnull = state->innermost_domainnull;
2707 state->innermost_domainval = domainval;
2708 state->innermost_domainnull = domainnull;
2709
2710 /* evaluate check expression value */
2711 ExecInitExprRec(con->check_expr, parent, state,
2712 scratch->d.domaincheck.checkvalue,
2713 scratch->d.domaincheck.checknull);
2714
2715 state->innermost_domainval = save_innermost_domainval;
2716 state->innermost_domainnull = save_innermost_domainnull;
2717
2718 /* now test result */
2719 scratch->opcode = EEOP_DOMAIN_CHECK;
2720 ExprEvalPushStep(state, scratch);
2721
2722 break;
2723 default:
2724 elog(ERROR, "unrecognized constraint type: %d",
2725 (int) con->constrainttype);
2726 break;
2727 }
2728 }
2729 }
2730