LCOV - code coverage report
Current view: top level - src/backend/executor - execExpr.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 929 982 94.6 %
Date: 2017-09-29 15:12:54 Functions: 20 20 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11