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