LCOV - differential code coverage report
Current view: top level - src/backend/executor - execExpr.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 96.9 % 1669 1617 33 12 7 9 844 81 683 35 893 1 8
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 28 28 28 28
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a