Coverage Report

Created: 2025-09-27 06:52

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