LCOV - code coverage report
Current view: top level - src/backend/executor - execExprInterp.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 1224 1310 93.4 %
Date: 2019-11-22 06:06:53 Functions: 62 64 96.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * execExprInterp.c
       4             :  *    Interpreted evaluation of an expression step list.
       5             :  *
       6             :  * This file provides either a "direct threaded" (for gcc, clang and
       7             :  * compatible) or a "switch threaded" (for all compilers) implementation of
       8             :  * expression evaluation.  The former is amongst the fastest known methods
       9             :  * of interpreting programs without resorting to assembly level work, or
      10             :  * just-in-time compilation, but it requires support for computed gotos.
      11             :  * The latter is amongst the fastest approaches doable in standard C.
      12             :  *
      13             :  * In either case we use ExprEvalStep->opcode to dispatch to the code block
      14             :  * within ExecInterpExpr() that implements the specific opcode type.
      15             :  *
      16             :  * Switch-threading uses a plain switch() statement to perform the
      17             :  * dispatch.  This has the advantages of being plain C and allowing the
      18             :  * compiler to warn if implementation of a specific opcode has been forgotten.
      19             :  * The disadvantage is that dispatches will, as commonly implemented by
      20             :  * compilers, happen from a single location, requiring more jumps and causing
      21             :  * bad branch prediction.
      22             :  *
      23             :  * In direct threading, we use gcc's label-as-values extension - also adopted
      24             :  * by some other compilers - to replace ExprEvalStep->opcode with the address
      25             :  * of the block implementing the instruction. Dispatch to the next instruction
      26             :  * is done by a "computed goto".  This allows for better branch prediction
      27             :  * (as the jumps are happening from different locations) and fewer jumps
      28             :  * (as no preparatory jump to a common dispatch location is needed).
      29             :  *
      30             :  * When using direct threading, ExecReadyInterpretedExpr will replace
      31             :  * each step's opcode field with the address of the relevant code block and
      32             :  * ExprState->flags will contain EEO_FLAG_DIRECT_THREADED to remember that
      33             :  * that's been done.
      34             :  *
      35             :  * For very simple instructions the overhead of the full interpreter
      36             :  * "startup", as minimal as it is, is noticeable.  Therefore
      37             :  * ExecReadyInterpretedExpr will choose to implement certain simple
      38             :  * opcode patterns using special fast-path routines (ExecJust*).
      39             :  *
      40             :  * Complex or uncommon instructions are not implemented in-line in
      41             :  * ExecInterpExpr(), rather we call out to a helper function appearing later
      42             :  * in this file.  For one reason, there'd not be a noticeable performance
      43             :  * benefit, but more importantly those complex routines are intended to be
      44             :  * shared between different expression evaluation approaches.  For instance
      45             :  * a JIT compiler would generate calls to them.  (This is why they are
      46             :  * exported rather than being "static" in this file.)
      47             :  *
      48             :  *
      49             :  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
      50             :  * Portions Copyright (c) 1994, Regents of the University of California
      51             :  *
      52             :  * IDENTIFICATION
      53             :  *    src/backend/executor/execExprInterp.c
      54             :  *
      55             :  *-------------------------------------------------------------------------
      56             :  */
      57             : #include "postgres.h"
      58             : 
      59             : #include "access/heaptoast.h"
      60             : #include "catalog/pg_type.h"
      61             : #include "commands/sequence.h"
      62             : #include "executor/execExpr.h"
      63             : #include "executor/nodeSubplan.h"
      64             : #include "funcapi.h"
      65             : #include "miscadmin.h"
      66             : #include "nodes/nodeFuncs.h"
      67             : #include "parser/parsetree.h"
      68             : #include "pgstat.h"
      69             : #include "utils/array.h"
      70             : #include "utils/builtins.h"
      71             : #include "utils/date.h"
      72             : #include "utils/datum.h"
      73             : #include "utils/expandedrecord.h"
      74             : #include "utils/lsyscache.h"
      75             : #include "utils/memutils.h"
      76             : #include "utils/timestamp.h"
      77             : #include "utils/typcache.h"
      78             : #include "utils/xml.h"
      79             : 
      80             : /*
      81             :  * Use computed-goto-based opcode dispatch when computed gotos are available.
      82             :  * But use a separate symbol so that it's easy to adjust locally in this file
      83             :  * for development and testing.
      84             :  */
      85             : #ifdef HAVE_COMPUTED_GOTO
      86             : #define EEO_USE_COMPUTED_GOTO
      87             : #endif                          /* HAVE_COMPUTED_GOTO */
      88             : 
      89             : /*
      90             :  * Macros for opcode dispatch.
      91             :  *
      92             :  * EEO_SWITCH - just hides the switch if not in use.
      93             :  * EEO_CASE - labels the implementation of named expression step type.
      94             :  * EEO_DISPATCH - jump to the implementation of the step type for 'op'.
      95             :  * EEO_OPCODE - compute opcode required by used expression evaluation method.
      96             :  * EEO_NEXT - increment 'op' and jump to correct next step type.
      97             :  * EEO_JUMP - jump to the specified step number within the current expression.
      98             :  */
      99             : #if defined(EEO_USE_COMPUTED_GOTO)
     100             : 
     101             : /* struct for jump target -> opcode lookup table */
     102             : typedef struct ExprEvalOpLookup
     103             : {
     104             :     const void *opcode;
     105             :     ExprEvalOp  op;
     106             : } ExprEvalOpLookup;
     107             : 
     108             : /* to make dispatch_table accessible outside ExecInterpExpr() */
     109             : static const void **dispatch_table = NULL;
     110             : 
     111             : /* jump target -> opcode lookup table */
     112             : static ExprEvalOpLookup reverse_dispatch_table[EEOP_LAST];
     113             : 
     114             : #define EEO_SWITCH()
     115             : #define EEO_CASE(name)      CASE_##name:
     116             : #define EEO_DISPATCH()      goto *((void *) op->opcode)
     117             : #define EEO_OPCODE(opcode)  ((intptr_t) dispatch_table[opcode])
     118             : 
     119             : #else                           /* !EEO_USE_COMPUTED_GOTO */
     120             : 
     121             : #define EEO_SWITCH()        starteval: switch ((ExprEvalOp) op->opcode)
     122             : #define EEO_CASE(name)      case name:
     123             : #define EEO_DISPATCH()      goto starteval
     124             : #define EEO_OPCODE(opcode)  (opcode)
     125             : 
     126             : #endif                          /* EEO_USE_COMPUTED_GOTO */
     127             : 
     128             : #define EEO_NEXT() \
     129             :     do { \
     130             :         op++; \
     131             :         EEO_DISPATCH(); \
     132             :     } while (0)
     133             : 
     134             : #define EEO_JUMP(stepno) \
     135             :     do { \
     136             :         op = &state->steps[stepno]; \
     137             :         EEO_DISPATCH(); \
     138             :     } while (0)
     139             : 
     140             : 
     141             : static Datum ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull);
     142             : static void ExecInitInterpreter(void);
     143             : 
     144             : /* support functions */
     145             : static void CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype);
     146             : static void CheckOpSlotCompatibility(ExprEvalStep *op, TupleTableSlot *slot);
     147             : static TupleDesc get_cached_rowtype(Oid type_id, int32 typmod,
     148             :                                     TupleDesc *cache_field, ExprContext *econtext);
     149             : static void ShutdownTupleDescRef(Datum arg);
     150             : static void ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op,
     151             :                                ExprContext *econtext, bool checkisnull);
     152             : 
     153             : /* fast-path evaluation functions */
     154             : static Datum ExecJustInnerVar(ExprState *state, ExprContext *econtext, bool *isnull);
     155             : static Datum ExecJustOuterVar(ExprState *state, ExprContext *econtext, bool *isnull);
     156             : static Datum ExecJustScanVar(ExprState *state, ExprContext *econtext, bool *isnull);
     157             : static Datum ExecJustAssignInnerVar(ExprState *state, ExprContext *econtext, bool *isnull);
     158             : static Datum ExecJustAssignOuterVar(ExprState *state, ExprContext *econtext, bool *isnull);
     159             : static Datum ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool *isnull);
     160             : static Datum ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull);
     161             : static Datum ExecJustConst(ExprState *state, ExprContext *econtext, bool *isnull);
     162             : static Datum ExecJustInnerVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
     163             : static Datum ExecJustOuterVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
     164             : static Datum ExecJustScanVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
     165             : static Datum ExecJustAssignInnerVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
     166             : static Datum ExecJustAssignOuterVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
     167             : static Datum ExecJustAssignScanVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
     168             : 
     169             : 
     170             : /*
     171             :  * Prepare ExprState for interpreted execution.
     172             :  */
     173             : void
     174     1184220 : ExecReadyInterpretedExpr(ExprState *state)
     175             : {
     176             :     /* Ensure one-time interpreter setup has been done */
     177     1184220 :     ExecInitInterpreter();
     178             : 
     179             :     /* Simple validity checks on expression */
     180             :     Assert(state->steps_len >= 1);
     181             :     Assert(state->steps[state->steps_len - 1].opcode == EEOP_DONE);
     182             : 
     183             :     /*
     184             :      * Don't perform redundant initialization. This is unreachable in current
     185             :      * cases, but might be hit if there's additional expression evaluation
     186             :      * methods that rely on interpreted execution to work.
     187             :      */
     188     1184220 :     if (state->flags & EEO_FLAG_INTERPRETER_INITIALIZED)
     189           0 :         return;
     190             : 
     191             :     /*
     192             :      * First time through, check whether attribute matches Var.  Might not be
     193             :      * ok anymore, due to schema changes. We do that by setting up a callback
     194             :      * that does checking on the first call, which then sets the evalfunc
     195             :      * callback to the actual method of execution.
     196             :      */
     197     1184220 :     state->evalfunc = ExecInterpExprStillValid;
     198             : 
     199             :     /* DIRECT_THREADED should not already be set */
     200             :     Assert((state->flags & EEO_FLAG_DIRECT_THREADED) == 0);
     201             : 
     202             :     /*
     203             :      * There shouldn't be any errors before the expression is fully
     204             :      * initialized, and even if so, it'd lead to the expression being
     205             :      * abandoned.  So we can set the flag now and save some code.
     206             :      */
     207     1184220 :     state->flags |= EEO_FLAG_INTERPRETER_INITIALIZED;
     208             : 
     209             :     /*
     210             :      * Select fast-path evalfuncs for very simple expressions.  "Starting up"
     211             :      * the full interpreter is a measurable overhead for these, and these
     212             :      * patterns occur often enough to be worth optimizing.
     213             :      */
     214     1184220 :     if (state->steps_len == 3)
     215             :     {
     216      281166 :         ExprEvalOp  step0 = state->steps[0].opcode;
     217      281166 :         ExprEvalOp  step1 = state->steps[1].opcode;
     218             : 
     219      281166 :         if (step0 == EEOP_INNER_FETCHSOME &&
     220             :             step1 == EEOP_INNER_VAR)
     221             :         {
     222        9536 :             state->evalfunc_private = (void *) ExecJustInnerVar;
     223        9536 :             return;
     224             :         }
     225      271630 :         else if (step0 == EEOP_OUTER_FETCHSOME &&
     226             :                  step1 == EEOP_OUTER_VAR)
     227             :         {
     228       42372 :             state->evalfunc_private = (void *) ExecJustOuterVar;
     229       42372 :             return;
     230             :         }
     231      229258 :         else if (step0 == EEOP_SCAN_FETCHSOME &&
     232             :                  step1 == EEOP_SCAN_VAR)
     233             :         {
     234       20550 :             state->evalfunc_private = (void *) ExecJustScanVar;
     235       20550 :             return;
     236             :         }
     237      208708 :         else if (step0 == EEOP_INNER_FETCHSOME &&
     238             :                  step1 == EEOP_ASSIGN_INNER_VAR)
     239             :         {
     240         498 :             state->evalfunc_private = (void *) ExecJustAssignInnerVar;
     241         498 :             return;
     242             :         }
     243      208210 :         else if (step0 == EEOP_OUTER_FETCHSOME &&
     244             :                  step1 == EEOP_ASSIGN_OUTER_VAR)
     245             :         {
     246        6594 :             state->evalfunc_private = (void *) ExecJustAssignOuterVar;
     247        6594 :             return;
     248             :         }
     249      201616 :         else if (step0 == EEOP_SCAN_FETCHSOME &&
     250             :                  step1 == EEOP_ASSIGN_SCAN_VAR)
     251             :         {
     252       32810 :             state->evalfunc_private = (void *) ExecJustAssignScanVar;
     253       32810 :             return;
     254             :         }
     255      168806 :         else if (step0 == EEOP_CASE_TESTVAL &&
     256         984 :                  step1 == EEOP_FUNCEXPR_STRICT &&
     257         984 :                  state->steps[0].d.casetest.value)
     258             :         {
     259         198 :             state->evalfunc_private = (void *) ExecJustApplyFuncToCase;
     260         198 :             return;
     261             :         }
     262             :     }
     263      903054 :     else if (state->steps_len == 2)
     264             :     {
     265      332428 :         ExprEvalOp  step0 = state->steps[0].opcode;
     266             : 
     267      332428 :         if (step0 == EEOP_CONST)
     268             :         {
     269      116026 :             state->evalfunc_private = (void *) ExecJustConst;
     270      116026 :             return;
     271             :         }
     272      216402 :         else if (step0 == EEOP_INNER_VAR)
     273             :         {
     274         262 :             state->evalfunc_private = (void *) ExecJustInnerVarVirt;
     275         262 :             return;
     276             :         }
     277      216140 :         else if (step0 == EEOP_OUTER_VAR)
     278             :         {
     279       42138 :             state->evalfunc_private = (void *) ExecJustOuterVarVirt;
     280       42138 :             return;
     281             :         }
     282      174002 :         else if (step0 == EEOP_SCAN_VAR)
     283             :         {
     284          48 :             state->evalfunc_private = (void *) ExecJustScanVarVirt;
     285          48 :             return;
     286             :         }
     287      173954 :         else if (step0 == EEOP_ASSIGN_INNER_VAR)
     288             :         {
     289          44 :             state->evalfunc_private = (void *) ExecJustAssignInnerVarVirt;
     290          44 :             return;
     291             :         }
     292      173910 :         else if (step0 == EEOP_ASSIGN_OUTER_VAR)
     293             :         {
     294         582 :             state->evalfunc_private = (void *) ExecJustAssignOuterVarVirt;
     295         582 :             return;
     296             :         }
     297      173328 :         else if (step0 == EEOP_ASSIGN_SCAN_VAR)
     298             :         {
     299        3348 :             state->evalfunc_private = (void *) ExecJustAssignScanVarVirt;
     300        3348 :             return;
     301             :         }
     302             :     }
     303             : 
     304             : #if defined(EEO_USE_COMPUTED_GOTO)
     305             : 
     306             :     /*
     307             :      * In the direct-threaded implementation, replace each opcode with the
     308             :      * address to jump to.  (Use ExecEvalStepOp() to get back the opcode.)
     309             :      */
     310             :     {
     311             :         int         off;
     312             : 
     313     6321452 :         for (off = 0; off < state->steps_len; off++)
     314             :         {
     315     5412238 :             ExprEvalStep *op = &state->steps[off];
     316             : 
     317     5412238 :             op->opcode = EEO_OPCODE(op->opcode);
     318             :         }
     319             : 
     320      909214 :         state->flags |= EEO_FLAG_DIRECT_THREADED;
     321             :     }
     322             : #endif                          /* EEO_USE_COMPUTED_GOTO */
     323             : 
     324      909214 :     state->evalfunc_private = (void *) ExecInterpExpr;
     325             : }
     326             : 
     327             : 
     328             : /*
     329             :  * Evaluate expression identified by "state" in the execution context
     330             :  * given by "econtext".  *isnull is set to the is-null flag for the result,
     331             :  * and the Datum value is the function result.
     332             :  *
     333             :  * As a special case, return the dispatch table's address if state is NULL.
     334             :  * This is used by ExecInitInterpreter to set up the dispatch_table global.
     335             :  * (Only applies when EEO_USE_COMPUTED_GOTO is defined.)
     336             :  */
     337             : static Datum
     338    98285686 : ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
     339             : {
     340             :     ExprEvalStep *op;
     341             :     TupleTableSlot *resultslot;
     342             :     TupleTableSlot *innerslot;
     343             :     TupleTableSlot *outerslot;
     344             :     TupleTableSlot *scanslot;
     345             : 
     346             :     /*
     347             :      * This array has to be in the same order as enum ExprEvalOp.
     348             :      */
     349             : #if defined(EEO_USE_COMPUTED_GOTO)
     350             :     static const void *const dispatch_table[] = {
     351             :         &&CASE_EEOP_DONE,
     352             :         &&CASE_EEOP_INNER_FETCHSOME,
     353             :         &&CASE_EEOP_OUTER_FETCHSOME,
     354             :         &&CASE_EEOP_SCAN_FETCHSOME,
     355             :         &&CASE_EEOP_INNER_VAR,
     356             :         &&CASE_EEOP_OUTER_VAR,
     357             :         &&CASE_EEOP_SCAN_VAR,
     358             :         &&CASE_EEOP_INNER_SYSVAR,
     359             :         &&CASE_EEOP_OUTER_SYSVAR,
     360             :         &&CASE_EEOP_SCAN_SYSVAR,
     361             :         &&CASE_EEOP_WHOLEROW,
     362             :         &&CASE_EEOP_ASSIGN_INNER_VAR,
     363             :         &&CASE_EEOP_ASSIGN_OUTER_VAR,
     364             :         &&CASE_EEOP_ASSIGN_SCAN_VAR,
     365             :         &&CASE_EEOP_ASSIGN_TMP,
     366             :         &&CASE_EEOP_ASSIGN_TMP_MAKE_RO,
     367             :         &&CASE_EEOP_CONST,
     368             :         &&CASE_EEOP_FUNCEXPR,
     369             :         &&CASE_EEOP_FUNCEXPR_STRICT,
     370             :         &&CASE_EEOP_FUNCEXPR_FUSAGE,
     371             :         &&CASE_EEOP_FUNCEXPR_STRICT_FUSAGE,
     372             :         &&CASE_EEOP_BOOL_AND_STEP_FIRST,
     373             :         &&CASE_EEOP_BOOL_AND_STEP,
     374             :         &&CASE_EEOP_BOOL_AND_STEP_LAST,
     375             :         &&CASE_EEOP_BOOL_OR_STEP_FIRST,
     376             :         &&CASE_EEOP_BOOL_OR_STEP,
     377             :         &&CASE_EEOP_BOOL_OR_STEP_LAST,
     378             :         &&CASE_EEOP_BOOL_NOT_STEP,
     379             :         &&CASE_EEOP_QUAL,
     380             :         &&CASE_EEOP_JUMP,
     381             :         &&CASE_EEOP_JUMP_IF_NULL,
     382             :         &&CASE_EEOP_JUMP_IF_NOT_NULL,
     383             :         &&CASE_EEOP_JUMP_IF_NOT_TRUE,
     384             :         &&CASE_EEOP_NULLTEST_ISNULL,
     385             :         &&CASE_EEOP_NULLTEST_ISNOTNULL,
     386             :         &&CASE_EEOP_NULLTEST_ROWISNULL,
     387             :         &&CASE_EEOP_NULLTEST_ROWISNOTNULL,
     388             :         &&CASE_EEOP_BOOLTEST_IS_TRUE,
     389             :         &&CASE_EEOP_BOOLTEST_IS_NOT_TRUE,
     390             :         &&CASE_EEOP_BOOLTEST_IS_FALSE,
     391             :         &&CASE_EEOP_BOOLTEST_IS_NOT_FALSE,
     392             :         &&CASE_EEOP_PARAM_EXEC,
     393             :         &&CASE_EEOP_PARAM_EXTERN,
     394             :         &&CASE_EEOP_PARAM_CALLBACK,
     395             :         &&CASE_EEOP_CASE_TESTVAL,
     396             :         &&CASE_EEOP_MAKE_READONLY,
     397             :         &&CASE_EEOP_IOCOERCE,
     398             :         &&CASE_EEOP_DISTINCT,
     399             :         &&CASE_EEOP_NOT_DISTINCT,
     400             :         &&CASE_EEOP_NULLIF,
     401             :         &&CASE_EEOP_SQLVALUEFUNCTION,
     402             :         &&CASE_EEOP_CURRENTOFEXPR,
     403             :         &&CASE_EEOP_NEXTVALUEEXPR,
     404             :         &&CASE_EEOP_ARRAYEXPR,
     405             :         &&CASE_EEOP_ARRAYCOERCE,
     406             :         &&CASE_EEOP_ROW,
     407             :         &&CASE_EEOP_ROWCOMPARE_STEP,
     408             :         &&CASE_EEOP_ROWCOMPARE_FINAL,
     409             :         &&CASE_EEOP_MINMAX,
     410             :         &&CASE_EEOP_FIELDSELECT,
     411             :         &&CASE_EEOP_FIELDSTORE_DEFORM,
     412             :         &&CASE_EEOP_FIELDSTORE_FORM,
     413             :         &&CASE_EEOP_SBSREF_SUBSCRIPT,
     414             :         &&CASE_EEOP_SBSREF_OLD,
     415             :         &&CASE_EEOP_SBSREF_ASSIGN,
     416             :         &&CASE_EEOP_SBSREF_FETCH,
     417             :         &&CASE_EEOP_DOMAIN_TESTVAL,
     418             :         &&CASE_EEOP_DOMAIN_NOTNULL,
     419             :         &&CASE_EEOP_DOMAIN_CHECK,
     420             :         &&CASE_EEOP_CONVERT_ROWTYPE,
     421             :         &&CASE_EEOP_SCALARARRAYOP,
     422             :         &&CASE_EEOP_XMLEXPR,
     423             :         &&CASE_EEOP_AGGREF,
     424             :         &&CASE_EEOP_GROUPING_FUNC,
     425             :         &&CASE_EEOP_WINDOW_FUNC,
     426             :         &&CASE_EEOP_SUBPLAN,
     427             :         &&CASE_EEOP_ALTERNATIVE_SUBPLAN,
     428             :         &&CASE_EEOP_AGG_STRICT_DESERIALIZE,
     429             :         &&CASE_EEOP_AGG_DESERIALIZE,
     430             :         &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
     431             :         &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_NULLS,
     432             :         &&CASE_EEOP_AGG_INIT_TRANS,
     433             :         &&CASE_EEOP_AGG_STRICT_TRANS_CHECK,
     434             :         &&CASE_EEOP_AGG_PLAIN_TRANS_BYVAL,
     435             :         &&CASE_EEOP_AGG_PLAIN_TRANS,
     436             :         &&CASE_EEOP_AGG_ORDERED_TRANS_DATUM,
     437             :         &&CASE_EEOP_AGG_ORDERED_TRANS_TUPLE,
     438             :         &&CASE_EEOP_LAST
     439             :     };
     440             : 
     441             :     StaticAssertStmt(EEOP_LAST + 1 == lengthof(dispatch_table),
     442             :                      "dispatch_table out of whack with ExprEvalOp");
     443             : 
     444    98285686 :     if (unlikely(state == NULL))
     445        6160 :         return PointerGetDatum(dispatch_table);
     446             : #else
     447             :     Assert(state != NULL);
     448             : #endif                          /* EEO_USE_COMPUTED_GOTO */
     449             : 
     450             :     /* setup state */
     451    98279526 :     op = state->steps;
     452    98279526 :     resultslot = state->resultslot;
     453    98279526 :     innerslot = econtext->ecxt_innertuple;
     454    98279526 :     outerslot = econtext->ecxt_outertuple;
     455    98279526 :     scanslot = econtext->ecxt_scantuple;
     456             : 
     457             : #if defined(EEO_USE_COMPUTED_GOTO)
     458    98279526 :     EEO_DISPATCH();
     459             : #endif
     460             : 
     461             :     EEO_SWITCH()
     462             :     {
     463             :         EEO_CASE(EEOP_DONE)
     464             :         {
     465    98268966 :             goto out;
     466             :         }
     467             : 
     468             :         EEO_CASE(EEOP_INNER_FETCHSOME)
     469             :         {
     470    25242444 :             CheckOpSlotCompatibility(op, innerslot);
     471             : 
     472    25242444 :             slot_getsomeattrs(innerslot, op->d.fetch.last_var);
     473             : 
     474    25242444 :             EEO_NEXT();
     475             :         }
     476             : 
     477             :         EEO_CASE(EEOP_OUTER_FETCHSOME)
     478             :         {
     479    20208498 :             CheckOpSlotCompatibility(op, outerslot);
     480             : 
     481    20208498 :             slot_getsomeattrs(outerslot, op->d.fetch.last_var);
     482             : 
     483    20208498 :             EEO_NEXT();
     484             :         }
     485             : 
     486             :         EEO_CASE(EEOP_SCAN_FETCHSOME)
     487             :         {
     488    45730388 :             CheckOpSlotCompatibility(op, scanslot);
     489             : 
     490    45730388 :             slot_getsomeattrs(scanslot, op->d.fetch.last_var);
     491             : 
     492    45730388 :             EEO_NEXT();
     493             :         }
     494             : 
     495             :         EEO_CASE(EEOP_INNER_VAR)
     496             :         {
     497    20794628 :             int         attnum = op->d.var.attnum;
     498             : 
     499             :             /*
     500             :              * Since we already extracted all referenced columns from the
     501             :              * tuple with a FETCHSOME step, we can just grab the value
     502             :              * directly out of the slot's decomposed-data arrays.  But let's
     503             :              * have an Assert to check that that did happen.
     504             :              */
     505             :             Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
     506    20794628 :             *op->resvalue = innerslot->tts_values[attnum];
     507    20794628 :             *op->resnull = innerslot->tts_isnull[attnum];
     508             : 
     509    20794628 :             EEO_NEXT();
     510             :         }
     511             : 
     512             :         EEO_CASE(EEOP_OUTER_VAR)
     513             :         {
     514    30054422 :             int         attnum = op->d.var.attnum;
     515             : 
     516             :             /* See EEOP_INNER_VAR comments */
     517             : 
     518             :             Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
     519    30054422 :             *op->resvalue = outerslot->tts_values[attnum];
     520    30054422 :             *op->resnull = outerslot->tts_isnull[attnum];
     521             : 
     522    30054422 :             EEO_NEXT();
     523             :         }
     524             : 
     525             :         EEO_CASE(EEOP_SCAN_VAR)
     526             :         {
     527    42388194 :             int         attnum = op->d.var.attnum;
     528             : 
     529             :             /* See EEOP_INNER_VAR comments */
     530             : 
     531             :             Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
     532    42388194 :             *op->resvalue = scanslot->tts_values[attnum];
     533    42388194 :             *op->resnull = scanslot->tts_isnull[attnum];
     534             : 
     535    42388194 :             EEO_NEXT();
     536             :         }
     537             : 
     538             :         EEO_CASE(EEOP_INNER_SYSVAR)
     539             :         {
     540           4 :             ExecEvalSysVar(state, op, econtext, innerslot);
     541           4 :             EEO_NEXT();
     542             :         }
     543             : 
     544             :         EEO_CASE(EEOP_OUTER_SYSVAR)
     545             :         {
     546           8 :             ExecEvalSysVar(state, op, econtext, outerslot);
     547           8 :             EEO_NEXT();
     548             :         }
     549             : 
     550             :         EEO_CASE(EEOP_SCAN_SYSVAR)
     551             :         {
     552     4999918 :             ExecEvalSysVar(state, op, econtext, scanslot);
     553     4999918 :             EEO_NEXT();
     554             :         }
     555             : 
     556             :         EEO_CASE(EEOP_WHOLEROW)
     557             :         {
     558             :             /* too complex for an inline implementation */
     559       31154 :             ExecEvalWholeRowVar(state, op, econtext);
     560             : 
     561       31154 :             EEO_NEXT();
     562             :         }
     563             : 
     564             :         EEO_CASE(EEOP_ASSIGN_INNER_VAR)
     565             :         {
     566     7397664 :             int         resultnum = op->d.assign_var.resultnum;
     567     7397664 :             int         attnum = op->d.assign_var.attnum;
     568             : 
     569             :             /*
     570             :              * We do not need CheckVarSlotCompatibility here; that was taken
     571             :              * care of at compilation time.  But see EEOP_INNER_VAR comments.
     572             :              */
     573             :             Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
     574     7397664 :             resultslot->tts_values[resultnum] = innerslot->tts_values[attnum];
     575     7397664 :             resultslot->tts_isnull[resultnum] = innerslot->tts_isnull[attnum];
     576             : 
     577     7397664 :             EEO_NEXT();
     578             :         }
     579             : 
     580             :         EEO_CASE(EEOP_ASSIGN_OUTER_VAR)
     581             :         {
     582    16029444 :             int         resultnum = op->d.assign_var.resultnum;
     583    16029444 :             int         attnum = op->d.assign_var.attnum;
     584             : 
     585             :             /*
     586             :              * We do not need CheckVarSlotCompatibility here; that was taken
     587             :              * care of at compilation time.  But see EEOP_INNER_VAR comments.
     588             :              */
     589             :             Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
     590    16029444 :             resultslot->tts_values[resultnum] = outerslot->tts_values[attnum];
     591    16029444 :             resultslot->tts_isnull[resultnum] = outerslot->tts_isnull[attnum];
     592             : 
     593    16029444 :             EEO_NEXT();
     594             :         }
     595             : 
     596             :         EEO_CASE(EEOP_ASSIGN_SCAN_VAR)
     597             :         {
     598    32844524 :             int         resultnum = op->d.assign_var.resultnum;
     599    32844524 :             int         attnum = op->d.assign_var.attnum;
     600             : 
     601             :             /*
     602             :              * We do not need CheckVarSlotCompatibility here; that was taken
     603             :              * care of at compilation time.  But see EEOP_INNER_VAR comments.
     604             :              */
     605             :             Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
     606    32844524 :             resultslot->tts_values[resultnum] = scanslot->tts_values[attnum];
     607    32844524 :             resultslot->tts_isnull[resultnum] = scanslot->tts_isnull[attnum];
     608             : 
     609    32844524 :             EEO_NEXT();
     610             :         }
     611             : 
     612             :         EEO_CASE(EEOP_ASSIGN_TMP)
     613             :         {
     614    27225712 :             int         resultnum = op->d.assign_tmp.resultnum;
     615             : 
     616    27225712 :             resultslot->tts_values[resultnum] = state->resvalue;
     617    27225712 :             resultslot->tts_isnull[resultnum] = state->resnull;
     618             : 
     619    27225712 :             EEO_NEXT();
     620             :         }
     621             : 
     622             :         EEO_CASE(EEOP_ASSIGN_TMP_MAKE_RO)
     623             :         {
     624     8571522 :             int         resultnum = op->d.assign_tmp.resultnum;
     625             : 
     626     8571522 :             resultslot->tts_isnull[resultnum] = state->resnull;
     627     8571522 :             if (!resultslot->tts_isnull[resultnum])
     628     8805408 :                 resultslot->tts_values[resultnum] =
     629     4402704 :                     MakeExpandedObjectReadOnlyInternal(state->resvalue);
     630             :             else
     631     4168818 :                 resultslot->tts_values[resultnum] = state->resvalue;
     632             : 
     633     8571522 :             EEO_NEXT();
     634             :         }
     635             : 
     636             :         EEO_CASE(EEOP_CONST)
     637             :         {
     638    23442078 :             *op->resnull = op->d.constval.isnull;
     639    23442078 :             *op->resvalue = op->d.constval.value;
     640             : 
     641    23442078 :             EEO_NEXT();
     642             :         }
     643             : 
     644             :         /*
     645             :          * Function-call implementations. Arguments have previously been
     646             :          * evaluated directly into fcinfo->args.
     647             :          *
     648             :          * As both STRICT checks and function-usage are noticeable performance
     649             :          * wise, and function calls are a very hot-path (they also back
     650             :          * operators!), it's worth having so many separate opcodes.
     651             :          *
     652             :          * Note: the reason for using a temporary variable "d", here and in
     653             :          * other places, is that some compilers think "*op->resvalue = f();"
     654             :          * requires them to evaluate op->resvalue into a register before
     655             :          * calling f(), just in case f() is able to modify op->resvalue
     656             :          * somehow.  The extra line of code can save a useless register spill
     657             :          * and reload across the function call.
     658             :          */
     659             :         EEO_CASE(EEOP_FUNCEXPR)
     660             :         {
     661      902518 :             FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
     662             :             Datum       d;
     663             : 
     664      902518 :             fcinfo->isnull = false;
     665      902518 :             d = op->d.func.fn_addr(fcinfo);
     666      895440 :             *op->resvalue = d;
     667      895440 :             *op->resnull = fcinfo->isnull;
     668             : 
     669      895440 :             EEO_NEXT();
     670             :         }
     671             : 
     672             :         EEO_CASE(EEOP_FUNCEXPR_STRICT)
     673             :         {
     674    62984424 :             FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
     675    62984424 :             NullableDatum *args = fcinfo->args;
     676             :             int         argno;
     677             :             Datum       d;
     678             : 
     679             :             /* strict function, so check for NULL args */
     680   181019396 :             for (argno = 0; argno < op->d.func.nargs; argno++)
     681             :             {
     682   118638004 :                 if (args[argno].isnull)
     683             :                 {
     684      603032 :                     *op->resnull = true;
     685      603032 :                     goto strictfail;
     686             :                 }
     687             :             }
     688    62381392 :             fcinfo->isnull = false;
     689    62381392 :             d = op->d.func.fn_addr(fcinfo);
     690    62378414 :             *op->resvalue = d;
     691    62378414 :             *op->resnull = fcinfo->isnull;
     692             : 
     693             :     strictfail:
     694    62981446 :             EEO_NEXT();
     695             :         }
     696             : 
     697             :         EEO_CASE(EEOP_FUNCEXPR_FUSAGE)
     698             :         {
     699             :             /* not common enough to inline */
     700           0 :             ExecEvalFuncExprFusage(state, op, econtext);
     701             : 
     702           0 :             EEO_NEXT();
     703             :         }
     704             : 
     705             :         EEO_CASE(EEOP_FUNCEXPR_STRICT_FUSAGE)
     706             :         {
     707             :             /* not common enough to inline */
     708           0 :             ExecEvalFuncExprStrictFusage(state, op, econtext);
     709             : 
     710           0 :             EEO_NEXT();
     711             :         }
     712             : 
     713             :         /*
     714             :          * If any of its clauses is FALSE, an AND's result is FALSE regardless
     715             :          * of the states of the rest of the clauses, so we can stop evaluating
     716             :          * and return FALSE immediately.  If none are FALSE and one or more is
     717             :          * NULL, we return NULL; otherwise we return TRUE.  This makes sense
     718             :          * when you interpret NULL as "don't know": perhaps one of the "don't
     719             :          * knows" would have been FALSE if we'd known its value.  Only when
     720             :          * all the inputs are known to be TRUE can we state confidently that
     721             :          * the AND's result is TRUE.
     722             :          */
     723             :         EEO_CASE(EEOP_BOOL_AND_STEP_FIRST)
     724             :         {
     725      297652 :             *op->d.boolexpr.anynull = false;
     726             : 
     727             :             /*
     728             :              * EEOP_BOOL_AND_STEP_FIRST resets anynull, otherwise it's the
     729             :              * same as EEOP_BOOL_AND_STEP - so fall through to that.
     730             :              */
     731             : 
     732             :             /* FALL THROUGH */
     733             :         }
     734             : 
     735             :         EEO_CASE(EEOP_BOOL_AND_STEP)
     736             :         {
     737      325156 :             if (*op->resnull)
     738             :             {
     739        1202 :                 *op->d.boolexpr.anynull = true;
     740             :             }
     741      323954 :             else if (!DatumGetBool(*op->resvalue))
     742             :             {
     743             :                 /* result is already set to FALSE, need not change it */
     744             :                 /* bail out early */
     745      205750 :                 EEO_JUMP(op->d.boolexpr.jumpdone);
     746             :             }
     747             : 
     748      119406 :             EEO_NEXT();
     749             :         }
     750             : 
     751             :         EEO_CASE(EEOP_BOOL_AND_STEP_LAST)
     752             :         {
     753       91902 :             if (*op->resnull)
     754             :             {
     755             :                 /* result is already set to NULL, need not change it */
     756             :             }
     757       91056 :             else if (!DatumGetBool(*op->resvalue))
     758             :             {
     759             :                 /* result is already set to FALSE, need not change it */
     760             : 
     761             :                 /*
     762             :                  * No point jumping early to jumpdone - would be same target
     763             :                  * (as this is the last argument to the AND expression),
     764             :                  * except more expensive.
     765             :                  */
     766             :             }
     767       30370 :             else if (*op->d.boolexpr.anynull)
     768             :             {
     769         370 :                 *op->resvalue = (Datum) 0;
     770         370 :                 *op->resnull = true;
     771             :             }
     772             :             else
     773             :             {
     774             :                 /* result is already set to TRUE, need not change it */
     775             :             }
     776             : 
     777       91902 :             EEO_NEXT();
     778             :         }
     779             : 
     780             :         /*
     781             :          * If any of its clauses is TRUE, an OR's result is TRUE regardless of
     782             :          * the states of the rest of the clauses, so we can stop evaluating
     783             :          * and return TRUE immediately.  If none are TRUE and one or more is
     784             :          * NULL, we return NULL; otherwise we return FALSE.  This makes sense
     785             :          * when you interpret NULL as "don't know": perhaps one of the "don't
     786             :          * knows" would have been TRUE if we'd known its value.  Only when all
     787             :          * the inputs are known to be FALSE can we state confidently that the
     788             :          * OR's result is FALSE.
     789             :          */
     790             :         EEO_CASE(EEOP_BOOL_OR_STEP_FIRST)
     791             :         {
     792     1847880 :             *op->d.boolexpr.anynull = false;
     793             : 
     794             :             /*
     795             :              * EEOP_BOOL_OR_STEP_FIRST resets anynull, otherwise it's the same
     796             :              * as EEOP_BOOL_OR_STEP - so fall through to that.
     797             :              */
     798             : 
     799             :             /* FALL THROUGH */
     800             :         }
     801             : 
     802             :         EEO_CASE(EEOP_BOOL_OR_STEP)
     803             :         {
     804     3375308 :             if (*op->resnull)
     805             :             {
     806       22196 :                 *op->d.boolexpr.anynull = true;
     807             :             }
     808     3353112 :             else if (DatumGetBool(*op->resvalue))
     809             :             {
     810             :                 /* result is already set to TRUE, need not change it */
     811             :                 /* bail out early */
     812      251112 :                 EEO_JUMP(op->d.boolexpr.jumpdone);
     813             :             }
     814             : 
     815     3124196 :             EEO_NEXT();
     816             :         }
     817             : 
     818             :         EEO_CASE(EEOP_BOOL_OR_STEP_LAST)
     819             :         {
     820     1596768 :             if (*op->resnull)
     821             :             {
     822             :                 /* result is already set to NULL, need not change it */
     823             :             }
     824     1574632 :             else if (DatumGetBool(*op->resvalue))
     825             :             {
     826             :                 /* result is already set to TRUE, need not change it */
     827             : 
     828             :                 /*
     829             :                  * No point jumping to jumpdone - would be same target (as
     830             :                  * this is the last argument to the AND expression), except
     831             :                  * more expensive.
     832             :                  */
     833             :             }
     834     1559126 :             else if (*op->d.boolexpr.anynull)
     835             :             {
     836         950 :                 *op->resvalue = (Datum) 0;
     837         950 :                 *op->resnull = true;
     838             :             }
     839             :             else
     840             :             {
     841             :                 /* result is already set to FALSE, need not change it */
     842             :             }
     843             : 
     844     1596768 :             EEO_NEXT();
     845             :         }
     846             : 
     847             :         EEO_CASE(EEOP_BOOL_NOT_STEP)
     848             :         {
     849             :             /*
     850             :              * Evaluation of 'not' is simple... if expr is false, then return
     851             :              * 'true' and vice versa.  It's safe to do this even on a
     852             :              * nominally null value, so we ignore resnull; that means that
     853             :              * NULL in produces NULL out, which is what we want.
     854             :              */
     855      535434 :             *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
     856             : 
     857      535434 :             EEO_NEXT();
     858             :         }
     859             : 
     860             :         EEO_CASE(EEOP_QUAL)
     861             :         {
     862             :             /* simplified version of BOOL_AND_STEP for use by ExecQual() */
     863             : 
     864             :             /* If argument (also result) is false or null ... */
     865   103693418 :             if (*op->resnull ||
     866    51689340 :                 !DatumGetBool(*op->resvalue))
     867             :             {
     868             :                 /* ... bail out early, returning FALSE */
     869    31392916 :                 *op->resnull = false;
     870    31392916 :                 *op->resvalue = BoolGetDatum(false);
     871    31392916 :                 EEO_JUMP(op->d.qualexpr.jumpdone);
     872             :             }
     873             : 
     874             :             /*
     875             :              * Otherwise, leave the TRUE value in place, in case this is the
     876             :              * last qual.  Then, TRUE is the correct answer.
     877             :              */
     878             : 
     879    20611162 :             EEO_NEXT();
     880             :         }
     881             : 
     882             :         EEO_CASE(EEOP_JUMP)
     883             :         {
     884             :             /* Unconditionally jump to target step */
     885      117470 :             EEO_JUMP(op->d.jump.jumpdone);
     886             :         }
     887             : 
     888             :         EEO_CASE(EEOP_JUMP_IF_NULL)
     889             :         {
     890             :             /* Transfer control if current result is null */
     891      439584 :             if (*op->resnull)
     892        2214 :                 EEO_JUMP(op->d.jump.jumpdone);
     893             : 
     894      437370 :             EEO_NEXT();
     895             :         }
     896             : 
     897             :         EEO_CASE(EEOP_JUMP_IF_NOT_NULL)
     898             :         {
     899             :             /* Transfer control if current result is non-null */
     900     2565838 :             if (!*op->resnull)
     901     1341364 :                 EEO_JUMP(op->d.jump.jumpdone);
     902             : 
     903     1224474 :             EEO_NEXT();
     904             :         }
     905             : 
     906             :         EEO_CASE(EEOP_JUMP_IF_NOT_TRUE)
     907             :         {
     908             :             /* Transfer control if current result is null or false */
     909     1018370 :             if (*op->resnull || !DatumGetBool(*op->resvalue))
     910      824178 :                 EEO_JUMP(op->d.jump.jumpdone);
     911             : 
     912      194192 :             EEO_NEXT();
     913             :         }
     914             : 
     915             :         EEO_CASE(EEOP_NULLTEST_ISNULL)
     916             :         {
     917      271434 :             *op->resvalue = BoolGetDatum(*op->resnull);
     918      271434 :             *op->resnull = false;
     919             : 
     920      271434 :             EEO_NEXT();
     921             :         }
     922             : 
     923             :         EEO_CASE(EEOP_NULLTEST_ISNOTNULL)
     924             :         {
     925     3762534 :             *op->resvalue = BoolGetDatum(!*op->resnull);
     926     3762534 :             *op->resnull = false;
     927             : 
     928     3762534 :             EEO_NEXT();
     929             :         }
     930             : 
     931             :         EEO_CASE(EEOP_NULLTEST_ROWISNULL)
     932             :         {
     933             :             /* out of line implementation: too large */
     934         388 :             ExecEvalRowNull(state, op, econtext);
     935             : 
     936         388 :             EEO_NEXT();
     937             :         }
     938             : 
     939             :         EEO_CASE(EEOP_NULLTEST_ROWISNOTNULL)
     940             :         {
     941             :             /* out of line implementation: too large */
     942         216 :             ExecEvalRowNotNull(state, op, econtext);
     943             : 
     944         216 :             EEO_NEXT();
     945             :         }
     946             : 
     947             :         /* BooleanTest implementations for all booltesttypes */
     948             : 
     949             :         EEO_CASE(EEOP_BOOLTEST_IS_TRUE)
     950             :         {
     951          86 :             if (*op->resnull)
     952             :             {
     953           8 :                 *op->resvalue = BoolGetDatum(false);
     954           8 :                 *op->resnull = false;
     955             :             }
     956             :             /* else, input value is the correct output as well */
     957             : 
     958          86 :             EEO_NEXT();
     959             :         }
     960             : 
     961             :         EEO_CASE(EEOP_BOOLTEST_IS_NOT_TRUE)
     962             :         {
     963        1566 :             if (*op->resnull)
     964             :             {
     965         112 :                 *op->resvalue = BoolGetDatum(true);
     966         112 :                 *op->resnull = false;
     967             :             }
     968             :             else
     969        1454 :                 *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
     970             : 
     971        1566 :             EEO_NEXT();
     972             :         }
     973             : 
     974             :         EEO_CASE(EEOP_BOOLTEST_IS_FALSE)
     975             :         {
     976         780 :             if (*op->resnull)
     977             :             {
     978         158 :                 *op->resvalue = BoolGetDatum(false);
     979         158 :                 *op->resnull = false;
     980             :             }
     981             :             else
     982         622 :                 *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
     983             : 
     984         780 :             EEO_NEXT();
     985             :         }
     986             : 
     987             :         EEO_CASE(EEOP_BOOLTEST_IS_NOT_FALSE)
     988             :         {
     989         200 :             if (*op->resnull)
     990             :             {
     991           4 :                 *op->resvalue = BoolGetDatum(true);
     992           4 :                 *op->resnull = false;
     993             :             }
     994             :             /* else, input value is the correct output as well */
     995             : 
     996         200 :             EEO_NEXT();
     997             :         }
     998             : 
     999             :         EEO_CASE(EEOP_PARAM_EXEC)
    1000             :         {
    1001             :             /* out of line implementation: too large */
    1002    13634456 :             ExecEvalParamExec(state, op, econtext);
    1003             : 
    1004    13634446 :             EEO_NEXT();
    1005             :         }
    1006             : 
    1007             :         EEO_CASE(EEOP_PARAM_EXTERN)
    1008             :         {
    1009             :             /* out of line implementation: too large */
    1010      140520 :             ExecEvalParamExtern(state, op, econtext);
    1011      140520 :             EEO_NEXT();
    1012             :         }
    1013             : 
    1014             :         EEO_CASE(EEOP_PARAM_CALLBACK)
    1015             :         {
    1016             :             /* allow an extension module to supply a PARAM_EXTERN value */
    1017      765798 :             op->d.cparam.paramfunc(state, op, econtext);
    1018      765790 :             EEO_NEXT();
    1019             :         }
    1020             : 
    1021             :         EEO_CASE(EEOP_CASE_TESTVAL)
    1022             :         {
    1023             :             /*
    1024             :              * Normally upper parts of the expression tree have setup the
    1025             :              * values to be returned here, but some parts of the system
    1026             :              * currently misuse {caseValue,domainValue}_{datum,isNull} to set
    1027             :              * run-time data.  So if no values have been set-up, use
    1028             :              * ExprContext's.  This isn't pretty, but also not *that* ugly,
    1029             :              * and this is unlikely to be performance sensitive enough to
    1030             :              * worry about an extra branch.
    1031             :              */
    1032        8158 :             if (op->d.casetest.value)
    1033             :             {
    1034        3624 :                 *op->resvalue = *op->d.casetest.value;
    1035        3624 :                 *op->resnull = *op->d.casetest.isnull;
    1036             :             }
    1037             :             else
    1038             :             {
    1039        4534 :                 *op->resvalue = econtext->caseValue_datum;
    1040        4534 :                 *op->resnull = econtext->caseValue_isNull;
    1041             :             }
    1042             : 
    1043        8158 :             EEO_NEXT();
    1044             :         }
    1045             : 
    1046             :         EEO_CASE(EEOP_DOMAIN_TESTVAL)
    1047             :         {
    1048             :             /*
    1049             :              * See EEOP_CASE_TESTVAL comment.
    1050             :              */
    1051      260672 :             if (op->d.casetest.value)
    1052             :             {
    1053       28910 :                 *op->resvalue = *op->d.casetest.value;
    1054       28910 :                 *op->resnull = *op->d.casetest.isnull;
    1055             :             }
    1056             :             else
    1057             :             {
    1058      231762 :                 *op->resvalue = econtext->domainValue_datum;
    1059      231762 :                 *op->resnull = econtext->domainValue_isNull;
    1060             :             }
    1061             : 
    1062      260672 :             EEO_NEXT();
    1063             :         }
    1064             : 
    1065             :         EEO_CASE(EEOP_MAKE_READONLY)
    1066             :         {
    1067             :             /*
    1068             :              * Force a varlena value that might be read multiple times to R/O
    1069             :              */
    1070        5162 :             if (!*op->d.make_readonly.isnull)
    1071       10248 :                 *op->resvalue =
    1072        5124 :                     MakeExpandedObjectReadOnlyInternal(*op->d.make_readonly.value);
    1073        5162 :             *op->resnull = *op->d.make_readonly.isnull;
    1074             : 
    1075        5162 :             EEO_NEXT();
    1076             :         }
    1077             : 
    1078             :         EEO_CASE(EEOP_IOCOERCE)
    1079             :         {
    1080             :             /*
    1081             :              * Evaluate a CoerceViaIO node.  This can be quite a hot path, so
    1082             :              * inline as much work as possible.  The source value is in our
    1083             :              * result variable.
    1084             :              */
    1085             :             char       *str;
    1086             : 
    1087             :             /* call output function (similar to OutputFunctionCall) */
    1088     2242032 :             if (*op->resnull)
    1089             :             {
    1090             :                 /* output functions are not called on nulls */
    1091         792 :                 str = NULL;
    1092             :             }
    1093             :             else
    1094             :             {
    1095             :                 FunctionCallInfo fcinfo_out;
    1096             : 
    1097     2241240 :                 fcinfo_out = op->d.iocoerce.fcinfo_data_out;
    1098     2241240 :                 fcinfo_out->args[0].value = *op->resvalue;
    1099     2241240 :                 fcinfo_out->args[0].isnull = false;
    1100             : 
    1101     2241240 :                 fcinfo_out->isnull = false;
    1102     2241240 :                 str = DatumGetCString(FunctionCallInvoke(fcinfo_out));
    1103             : 
    1104             :                 /* OutputFunctionCall assumes result isn't null */
    1105             :                 Assert(!fcinfo_out->isnull);
    1106             :             }
    1107             : 
    1108             :             /* call input function (similar to InputFunctionCall) */
    1109     2242032 :             if (!op->d.iocoerce.finfo_in->fn_strict || str != NULL)
    1110             :             {
    1111             :                 FunctionCallInfo fcinfo_in;
    1112             :                 Datum       d;
    1113             : 
    1114     2241318 :                 fcinfo_in = op->d.iocoerce.fcinfo_data_in;
    1115     2241318 :                 fcinfo_in->args[0].value = PointerGetDatum(str);
    1116     2241318 :                 fcinfo_in->args[0].isnull = *op->resnull;
    1117             :                 /* second and third arguments are already set up */
    1118             : 
    1119     2241318 :                 fcinfo_in->isnull = false;
    1120     2241318 :                 d = FunctionCallInvoke(fcinfo_in);
    1121     2241286 :                 *op->resvalue = d;
    1122             : 
    1123             :                 /* Should get null result if and only if str is NULL */
    1124             :                 if (str == NULL)
    1125             :                 {
    1126             :                     Assert(*op->resnull);
    1127             :                     Assert(fcinfo_in->isnull);
    1128             :                 }
    1129             :                 else
    1130             :                 {
    1131             :                     Assert(!*op->resnull);
    1132             :                     Assert(!fcinfo_in->isnull);
    1133             :                 }
    1134             :             }
    1135             : 
    1136     2242000 :             EEO_NEXT();
    1137             :         }
    1138             : 
    1139             :         EEO_CASE(EEOP_DISTINCT)
    1140             :         {
    1141             :             /*
    1142             :              * IS DISTINCT FROM must evaluate arguments (already done into
    1143             :              * fcinfo->args) to determine whether they are NULL; if either is
    1144             :              * NULL then the result is determined.  If neither is NULL, then
    1145             :              * proceed to evaluate the comparison function, which is just the
    1146             :              * type's standard equality operator.  We need not care whether
    1147             :              * that function is strict.  Because the handling of nulls is
    1148             :              * different, we can't just reuse EEOP_FUNCEXPR.
    1149             :              */
    1150      488306 :             FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
    1151             : 
    1152             :             /* check function arguments for NULLness */
    1153      488306 :             if (fcinfo->args[0].isnull && fcinfo->args[1].isnull)
    1154             :             {
    1155             :                 /* Both NULL? Then is not distinct... */
    1156      456672 :                 *op->resvalue = BoolGetDatum(false);
    1157      456672 :                 *op->resnull = false;
    1158             :             }
    1159       31634 :             else if (fcinfo->args[0].isnull || fcinfo->args[1].isnull)
    1160             :             {
    1161             :                 /* Only one is NULL? Then is distinct... */
    1162         142 :                 *op->resvalue = BoolGetDatum(true);
    1163         142 :                 *op->resnull = false;
    1164             :             }
    1165             :             else
    1166             :             {
    1167             :                 /* Neither null, so apply the equality function */
    1168             :                 Datum       eqresult;
    1169             : 
    1170       31492 :                 fcinfo->isnull = false;
    1171       31492 :                 eqresult = op->d.func.fn_addr(fcinfo);
    1172             :                 /* Must invert result of "="; safe to do even if null */
    1173       31492 :                 *op->resvalue = BoolGetDatum(!DatumGetBool(eqresult));
    1174       31492 :                 *op->resnull = fcinfo->isnull;
    1175             :             }
    1176             : 
    1177      488306 :             EEO_NEXT();
    1178             :         }
    1179             : 
    1180             :         /* see EEOP_DISTINCT for comments, this is just inverted */
    1181             :         EEO_CASE(EEOP_NOT_DISTINCT)
    1182             :         {
    1183     6409170 :             FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
    1184             : 
    1185     6409170 :             if (fcinfo->args[0].isnull && fcinfo->args[1].isnull)
    1186             :             {
    1187       98830 :                 *op->resvalue = BoolGetDatum(true);
    1188       98830 :                 *op->resnull = false;
    1189             :             }
    1190     6310340 :             else if (fcinfo->args[0].isnull || fcinfo->args[1].isnull)
    1191             :             {
    1192         194 :                 *op->resvalue = BoolGetDatum(false);
    1193         194 :                 *op->resnull = false;
    1194             :             }
    1195             :             else
    1196             :             {
    1197             :                 Datum       eqresult;
    1198             : 
    1199     6310146 :                 fcinfo->isnull = false;
    1200     6310146 :                 eqresult = op->d.func.fn_addr(fcinfo);
    1201     6310146 :                 *op->resvalue = eqresult;
    1202     6310146 :                 *op->resnull = fcinfo->isnull;
    1203             :             }
    1204             : 
    1205     6409170 :             EEO_NEXT();
    1206             :         }
    1207             : 
    1208             :         EEO_CASE(EEOP_NULLIF)
    1209             :         {
    1210             :             /*
    1211             :              * The arguments are already evaluated into fcinfo->args.
    1212             :              */
    1213        4392 :             FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
    1214             : 
    1215             :             /* if either argument is NULL they can't be equal */
    1216        4392 :             if (!fcinfo->args[0].isnull && !fcinfo->args[1].isnull)
    1217             :             {
    1218             :                 Datum       result;
    1219             : 
    1220        4356 :                 fcinfo->isnull = false;
    1221        4356 :                 result = op->d.func.fn_addr(fcinfo);
    1222             : 
    1223             :                 /* if the arguments are equal return null */
    1224        4356 :                 if (!fcinfo->isnull && DatumGetBool(result))
    1225             :                 {
    1226          60 :                     *op->resvalue = (Datum) 0;
    1227          60 :                     *op->resnull = true;
    1228             : 
    1229          60 :                     EEO_NEXT();
    1230             :                 }
    1231             :             }
    1232             : 
    1233             :             /* Arguments aren't equal, so return the first one */
    1234        4332 :             *op->resvalue = fcinfo->args[0].value;
    1235        4332 :             *op->resnull = fcinfo->args[0].isnull;
    1236             : 
    1237        4332 :             EEO_NEXT();
    1238             :         }
    1239             : 
    1240             :         EEO_CASE(EEOP_SQLVALUEFUNCTION)
    1241             :         {
    1242             :             /*
    1243             :              * Doesn't seem worthwhile to have an inline implementation
    1244             :              * efficiency-wise.
    1245             :              */
    1246        4356 :             ExecEvalSQLValueFunction(state, op);
    1247             : 
    1248        4356 :             EEO_NEXT();
    1249             :         }
    1250             : 
    1251             :         EEO_CASE(EEOP_CURRENTOFEXPR)
    1252             :         {
    1253             :             /* error invocation uses space, and shouldn't ever occur */
    1254           0 :             ExecEvalCurrentOfExpr(state, op);
    1255             : 
    1256           0 :             EEO_NEXT();
    1257             :         }
    1258             : 
    1259             :         EEO_CASE(EEOP_NEXTVALUEEXPR)
    1260             :         {
    1261             :             /*
    1262             :              * Doesn't seem worthwhile to have an inline implementation
    1263             :              * efficiency-wise.
    1264             :              */
    1265         196 :             ExecEvalNextValueExpr(state, op);
    1266             : 
    1267         196 :             EEO_NEXT();
    1268             :         }
    1269             : 
    1270             :         EEO_CASE(EEOP_ARRAYEXPR)
    1271             :         {
    1272             :             /* too complex for an inline implementation */
    1273      261762 :             ExecEvalArrayExpr(state, op);
    1274             : 
    1275      261762 :             EEO_NEXT();
    1276             :         }
    1277             : 
    1278             :         EEO_CASE(EEOP_ARRAYCOERCE)
    1279             :         {
    1280             :             /* too complex for an inline implementation */
    1281       38458 :             ExecEvalArrayCoerce(state, op, econtext);
    1282             : 
    1283       38440 :             EEO_NEXT();
    1284             :         }
    1285             : 
    1286             :         EEO_CASE(EEOP_ROW)
    1287             :         {
    1288             :             /* too complex for an inline implementation */
    1289       20568 :             ExecEvalRow(state, op);
    1290             : 
    1291       20568 :             EEO_NEXT();
    1292             :         }
    1293             : 
    1294             :         EEO_CASE(EEOP_ROWCOMPARE_STEP)
    1295             :         {
    1296      139128 :             FunctionCallInfo fcinfo = op->d.rowcompare_step.fcinfo_data;
    1297             :             Datum       d;
    1298             : 
    1299             :             /* force NULL result if strict fn and NULL input */
    1300      278256 :             if (op->d.rowcompare_step.finfo->fn_strict &&
    1301      278256 :                 (fcinfo->args[0].isnull || fcinfo->args[1].isnull))
    1302             :             {
    1303          12 :                 *op->resnull = true;
    1304          12 :                 EEO_JUMP(op->d.rowcompare_step.jumpnull);
    1305             :             }
    1306             : 
    1307             :             /* Apply comparison function */
    1308      139116 :             fcinfo->isnull = false;
    1309      139116 :             d = op->d.rowcompare_step.fn_addr(fcinfo);
    1310      139116 :             *op->resvalue = d;
    1311             : 
    1312             :             /* force NULL result if NULL function result */
    1313      139116 :             if (fcinfo->isnull)
    1314             :             {
    1315           0 :                 *op->resnull = true;
    1316           0 :                 EEO_JUMP(op->d.rowcompare_step.jumpnull);
    1317             :             }
    1318      139116 :             *op->resnull = false;
    1319             : 
    1320             :             /* If unequal, no need to compare remaining columns */
    1321      139116 :             if (DatumGetInt32(*op->resvalue) != 0)
    1322             :             {
    1323       63008 :                 EEO_JUMP(op->d.rowcompare_step.jumpdone);
    1324             :             }
    1325             : 
    1326       76108 :             EEO_NEXT();
    1327             :         }
    1328             : 
    1329             :         EEO_CASE(EEOP_ROWCOMPARE_FINAL)
    1330             :         {
    1331       63008 :             int32       cmpresult = DatumGetInt32(*op->resvalue);
    1332       63008 :             RowCompareType rctype = op->d.rowcompare_final.rctype;
    1333             : 
    1334       63008 :             *op->resnull = false;
    1335       63008 :             switch (rctype)
    1336             :             {
    1337             :                     /* EQ and NE cases aren't allowed here */
    1338             :                 case ROWCOMPARE_LT:
    1339       22936 :                     *op->resvalue = BoolGetDatum(cmpresult < 0);
    1340       22936 :                     break;
    1341             :                 case ROWCOMPARE_LE:
    1342       40000 :                     *op->resvalue = BoolGetDatum(cmpresult <= 0);
    1343       40000 :                     break;
    1344             :                 case ROWCOMPARE_GE:
    1345           4 :                     *op->resvalue = BoolGetDatum(cmpresult >= 0);
    1346           4 :                     break;
    1347             :                 case ROWCOMPARE_GT:
    1348          68 :                     *op->resvalue = BoolGetDatum(cmpresult > 0);
    1349          68 :                     break;
    1350             :                 default:
    1351             :                     Assert(false);
    1352           0 :                     break;
    1353             :             }
    1354             : 
    1355       63008 :             EEO_NEXT();
    1356             :         }
    1357             : 
    1358             :         EEO_CASE(EEOP_MINMAX)
    1359             :         {
    1360             :             /* too complex for an inline implementation */
    1361        2578 :             ExecEvalMinMax(state, op);
    1362             : 
    1363        2578 :             EEO_NEXT();
    1364             :         }
    1365             : 
    1366             :         EEO_CASE(EEOP_FIELDSELECT)
    1367             :         {
    1368             :             /* too complex for an inline implementation */
    1369       53852 :             ExecEvalFieldSelect(state, op, econtext);
    1370             : 
    1371       53852 :             EEO_NEXT();
    1372             :         }
    1373             : 
    1374             :         EEO_CASE(EEOP_FIELDSTORE_DEFORM)
    1375             :         {
    1376             :             /* too complex for an inline implementation */
    1377         224 :             ExecEvalFieldStoreDeForm(state, op, econtext);
    1378             : 
    1379         224 :             EEO_NEXT();
    1380             :         }
    1381             : 
    1382             :         EEO_CASE(EEOP_FIELDSTORE_FORM)
    1383             :         {
    1384             :             /* too complex for an inline implementation */
    1385         224 :             ExecEvalFieldStoreForm(state, op, econtext);
    1386             : 
    1387         224 :             EEO_NEXT();
    1388             :         }
    1389             : 
    1390             :         EEO_CASE(EEOP_SBSREF_SUBSCRIPT)
    1391             :         {
    1392             :             /* Process an array subscript */
    1393             : 
    1394             :             /* too complex for an inline implementation */
    1395      438712 :             if (ExecEvalSubscriptingRef(state, op))
    1396             :             {
    1397      438688 :                 EEO_NEXT();
    1398             :             }
    1399             :             else
    1400             :             {
    1401             :                 /* Subscript is null, short-circuit SubscriptingRef to NULL */
    1402          12 :                 EEO_JUMP(op->d.sbsref_subscript.jumpdone);
    1403             :             }
    1404             :         }
    1405             : 
    1406             :         EEO_CASE(EEOP_SBSREF_OLD)
    1407             :         {
    1408             :             /*
    1409             :              * Fetch the old value in an sbsref assignment, in case it's
    1410             :              * referenced (via a CaseTestExpr) inside the assignment
    1411             :              * expression.
    1412             :              */
    1413             : 
    1414             :             /* too complex for an inline implementation */
    1415         132 :             ExecEvalSubscriptingRefOld(state, op);
    1416             : 
    1417         132 :             EEO_NEXT();
    1418             :         }
    1419             : 
    1420             :         /*
    1421             :          * Perform SubscriptingRef assignment
    1422             :          */
    1423             :         EEO_CASE(EEOP_SBSREF_ASSIGN)
    1424             :         {
    1425             :             /* too complex for an inline implementation */
    1426         618 :             ExecEvalSubscriptingRefAssign(state, op);
    1427             : 
    1428         602 :             EEO_NEXT();
    1429             :         }
    1430             : 
    1431             :         /*
    1432             :          * Fetch subset of an array.
    1433             :          */
    1434             :         EEO_CASE(EEOP_SBSREF_FETCH)
    1435             :         {
    1436             :             /* too complex for an inline implementation */
    1437      437358 :             ExecEvalSubscriptingRefFetch(state, op);
    1438             : 
    1439      437342 :             EEO_NEXT();
    1440             :         }
    1441             : 
    1442             :         EEO_CASE(EEOP_CONVERT_ROWTYPE)
    1443             :         {
    1444             :             /* too complex for an inline implementation */
    1445       10054 :             ExecEvalConvertRowtype(state, op, econtext);
    1446             : 
    1447       10054 :             EEO_NEXT();
    1448             :         }
    1449             : 
    1450             :         EEO_CASE(EEOP_SCALARARRAYOP)
    1451             :         {
    1452             :             /* too complex for an inline implementation */
    1453     2286442 :             ExecEvalScalarArrayOp(state, op);
    1454             : 
    1455     2286442 :             EEO_NEXT();
    1456             :         }
    1457             : 
    1458             :         EEO_CASE(EEOP_DOMAIN_NOTNULL)
    1459             :         {
    1460             :             /* too complex for an inline implementation */
    1461         250 :             ExecEvalConstraintNotNull(state, op);
    1462             : 
    1463         186 :             EEO_NEXT();
    1464             :         }
    1465             : 
    1466             :         EEO_CASE(EEOP_DOMAIN_CHECK)
    1467             :         {
    1468             :             /* too complex for an inline implementation */
    1469       28566 :             ExecEvalConstraintCheck(state, op);
    1470             : 
    1471       28322 :             EEO_NEXT();
    1472             :         }
    1473             : 
    1474             :         EEO_CASE(EEOP_XMLEXPR)
    1475             :         {
    1476             :             /* too complex for an inline implementation */
    1477       26140 :             ExecEvalXmlExpr(state, op);
    1478             : 
    1479       26088 :             EEO_NEXT();
    1480             :         }
    1481             : 
    1482             :         EEO_CASE(EEOP_AGGREF)
    1483             :         {
    1484             :             /*
    1485             :              * Returns a Datum whose value is the precomputed aggregate value
    1486             :              * found in the given expression context.
    1487             :              */
    1488     1351446 :             AggrefExprState *aggref = op->d.aggref.astate;
    1489             : 
    1490             :             Assert(econtext->ecxt_aggvalues != NULL);
    1491             : 
    1492     1351446 :             *op->resvalue = econtext->ecxt_aggvalues[aggref->aggno];
    1493     1351446 :             *op->resnull = econtext->ecxt_aggnulls[aggref->aggno];
    1494             : 
    1495     1351446 :             EEO_NEXT();
    1496             :         }
    1497             : 
    1498             :         EEO_CASE(EEOP_GROUPING_FUNC)
    1499             :         {
    1500             :             /* too complex/uncommon for an inline implementation */
    1501        1094 :             ExecEvalGroupingFunc(state, op);
    1502             : 
    1503        1094 :             EEO_NEXT();
    1504             :         }
    1505             : 
    1506             :         EEO_CASE(EEOP_WINDOW_FUNC)
    1507             :         {
    1508             :             /*
    1509             :              * Like Aggref, just return a precomputed value from the econtext.
    1510             :              */
    1511      638644 :             WindowFuncExprState *wfunc = op->d.window_func.wfstate;
    1512             : 
    1513             :             Assert(econtext->ecxt_aggvalues != NULL);
    1514             : 
    1515      638644 :             *op->resvalue = econtext->ecxt_aggvalues[wfunc->wfuncno];
    1516      638644 :             *op->resnull = econtext->ecxt_aggnulls[wfunc->wfuncno];
    1517             : 
    1518      638644 :             EEO_NEXT();
    1519             :         }
    1520             : 
    1521             :         EEO_CASE(EEOP_SUBPLAN)
    1522             :         {
    1523             :             /* too complex for an inline implementation */
    1524     2290458 :             ExecEvalSubPlan(state, op, econtext);
    1525             : 
    1526     2290454 :             EEO_NEXT();
    1527             :         }
    1528             : 
    1529             :         EEO_CASE(EEOP_ALTERNATIVE_SUBPLAN)
    1530             :         {
    1531             :             /* too complex for an inline implementation */
    1532      489886 :             ExecEvalAlternativeSubPlan(state, op, econtext);
    1533             : 
    1534      489886 :             EEO_NEXT();
    1535             :         }
    1536             : 
    1537             :         /* evaluate a strict aggregate deserialization function */
    1538             :         EEO_CASE(EEOP_AGG_STRICT_DESERIALIZE)
    1539             :         {
    1540             :             /* Don't call a strict deserialization function with NULL input */
    1541          60 :             if (op->d.agg_deserialize.fcinfo_data->args[0].isnull)
    1542          48 :                 EEO_JUMP(op->d.agg_deserialize.jumpnull);
    1543             : 
    1544             :             /* fallthrough */
    1545             :         }
    1546             : 
    1547             :         /* evaluate aggregate deserialization function (non-strict portion) */
    1548             :         EEO_CASE(EEOP_AGG_DESERIALIZE)
    1549             :         {
    1550          12 :             FunctionCallInfo fcinfo = op->d.agg_deserialize.fcinfo_data;
    1551          12 :             AggState   *aggstate = op->d.agg_deserialize.aggstate;
    1552             :             MemoryContext oldContext;
    1553             : 
    1554             :             /*
    1555             :              * We run the deserialization functions in per-input-tuple memory
    1556             :              * context.
    1557             :              */
    1558          12 :             oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
    1559          12 :             fcinfo->isnull = false;
    1560          12 :             *op->resvalue = FunctionCallInvoke(fcinfo);
    1561          12 :             *op->resnull = fcinfo->isnull;
    1562          12 :             MemoryContextSwitchTo(oldContext);
    1563             : 
    1564          12 :             EEO_NEXT();
    1565             :         }
    1566             : 
    1567             :         /*
    1568             :          * Check that a strict aggregate transition / combination function's
    1569             :          * input is not NULL.
    1570             :          */
    1571             :         EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
    1572             :         {
    1573             :             int         argno;
    1574      188544 :             bool       *nulls = op->d.agg_strict_input_check.nulls;
    1575      188544 :             int         nargs = op->d.agg_strict_input_check.nargs;
    1576             : 
    1577      377232 :             for (argno = 0; argno < nargs; argno++)
    1578             :             {
    1579      188712 :                 if (nulls[argno])
    1580          24 :                     EEO_JUMP(op->d.agg_strict_input_check.jumpnull);
    1581             :             }
    1582      188520 :             EEO_NEXT();
    1583             :         }
    1584             : 
    1585             :         EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_ARGS)
    1586             :         {
    1587             :             int         argno;
    1588     2558910 :             NullableDatum *args = op->d.agg_strict_input_check.args;
    1589     2558910 :             int         nargs = op->d.agg_strict_input_check.nargs;
    1590             : 
    1591     5157358 :             for (argno = 0; argno < nargs; argno++)
    1592             :             {
    1593     2599190 :                 if (args[argno].isnull)
    1594         742 :                     EEO_JUMP(op->d.agg_strict_input_check.jumpnull);
    1595             :             }
    1596     2558168 :             EEO_NEXT();
    1597             :         }
    1598             : 
    1599             :         /*
    1600             :          * Initialize an aggregate's first value if necessary.
    1601             :          */
    1602             :         EEO_CASE(EEOP_AGG_INIT_TRANS)
    1603             :         {
    1604             :             AggState   *aggstate;
    1605             :             AggStatePerGroup pergroup;
    1606             : 
    1607      344098 :             aggstate = op->d.agg_init_trans.aggstate;
    1608      688196 :             pergroup = &aggstate->all_pergroups
    1609      344098 :                 [op->d.agg_init_trans.setoff]
    1610      344098 :                 [op->d.agg_init_trans.transno];
    1611             : 
    1612             :             /* If transValue has not yet been initialized, do so now. */
    1613      344098 :             if (pergroup->noTransValue)
    1614             :             {
    1615        5912 :                 AggStatePerTrans pertrans = op->d.agg_init_trans.pertrans;
    1616             : 
    1617        5912 :                 aggstate->curaggcontext = op->d.agg_init_trans.aggcontext;
    1618        5912 :                 aggstate->current_set = op->d.agg_init_trans.setno;
    1619             : 
    1620        5912 :                 ExecAggInitGroup(aggstate, pertrans, pergroup);
    1621             : 
    1622             :                 /* copied trans value from input, done this round */
    1623        5912 :                 EEO_JUMP(op->d.agg_init_trans.jumpnull);
    1624             :             }
    1625             : 
    1626      338186 :             EEO_NEXT();
    1627             :         }
    1628             : 
    1629             :         /* check that a strict aggregate's input isn't NULL */
    1630             :         EEO_CASE(EEOP_AGG_STRICT_TRANS_CHECK)
    1631             :         {
    1632             :             AggState   *aggstate;
    1633             :             AggStatePerGroup pergroup;
    1634             : 
    1635    11582612 :             aggstate = op->d.agg_strict_trans_check.aggstate;
    1636    23165224 :             pergroup = &aggstate->all_pergroups
    1637    11582612 :                 [op->d.agg_strict_trans_check.setoff]
    1638    11582612 :                 [op->d.agg_strict_trans_check.transno];
    1639             : 
    1640    11582612 :             if (unlikely(pergroup->transValueIsNull))
    1641       40012 :                 EEO_JUMP(op->d.agg_strict_trans_check.jumpnull);
    1642             : 
    1643    11542600 :             EEO_NEXT();
    1644             :         }
    1645             : 
    1646             :         /*
    1647             :          * Evaluate aggregate transition / combine function that has a
    1648             :          * by-value transition type. That's a separate case from the
    1649             :          * by-reference implementation because it's a bit simpler.
    1650             :          */
    1651             :         EEO_CASE(EEOP_AGG_PLAIN_TRANS_BYVAL)
    1652             :         {
    1653             :             AggState   *aggstate;
    1654             :             AggStatePerTrans pertrans;
    1655             :             AggStatePerGroup pergroup;
    1656             :             FunctionCallInfo fcinfo;
    1657             :             MemoryContext oldContext;
    1658             :             Datum       newVal;
    1659             : 
    1660    14773334 :             aggstate = op->d.agg_trans.aggstate;
    1661    14773334 :             pertrans = op->d.agg_trans.pertrans;
    1662             : 
    1663    29546668 :             pergroup = &aggstate->all_pergroups
    1664    14773334 :                 [op->d.agg_trans.setoff]
    1665    14773334 :                 [op->d.agg_trans.transno];
    1666             : 
    1667             :             Assert(pertrans->transtypeByVal);
    1668             : 
    1669    14773334 :             fcinfo = pertrans->transfn_fcinfo;
    1670             : 
    1671             :             /* cf. select_current_set() */
    1672    14773334 :             aggstate->curaggcontext = op->d.agg_trans.aggcontext;
    1673    14773334 :             aggstate->current_set = op->d.agg_trans.setno;
    1674             : 
    1675             :             /* set up aggstate->curpertrans for AggGetAggref() */
    1676    14773334 :             aggstate->curpertrans = pertrans;
    1677             : 
    1678             :             /* invoke transition function in per-tuple context */
    1679    14773334 :             oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
    1680             : 
    1681    14773334 :             fcinfo->args[0].value = pergroup->transValue;
    1682    14773334 :             fcinfo->args[0].isnull = pergroup->transValueIsNull;
    1683    14773334 :             fcinfo->isnull = false; /* just in case transfn doesn't set it */
    1684             : 
    1685    14773334 :             newVal = FunctionCallInvoke(fcinfo);
    1686             : 
    1687    14773310 :             pergroup->transValue = newVal;
    1688    14773310 :             pergroup->transValueIsNull = fcinfo->isnull;
    1689             : 
    1690    14773310 :             MemoryContextSwitchTo(oldContext);
    1691             : 
    1692    14773310 :             EEO_NEXT();
    1693             :         }
    1694             : 
    1695             :         /*
    1696             :          * Evaluate aggregate transition / combine function that has a
    1697             :          * by-reference transition type.
    1698             :          *
    1699             :          * Could optimize a bit further by splitting off by-reference
    1700             :          * fixed-length types, but currently that doesn't seem worth it.
    1701             :          */
    1702             :         EEO_CASE(EEOP_AGG_PLAIN_TRANS)
    1703             :         {
    1704             :             AggState   *aggstate;
    1705             :             AggStatePerTrans pertrans;
    1706             :             AggStatePerGroup pergroup;
    1707             :             FunctionCallInfo fcinfo;
    1708             :             MemoryContext oldContext;
    1709             :             Datum       newVal;
    1710             : 
    1711     1812906 :             aggstate = op->d.agg_trans.aggstate;
    1712     1812906 :             pertrans = op->d.agg_trans.pertrans;
    1713             : 
    1714     3625812 :             pergroup = &aggstate->all_pergroups
    1715     1812906 :                 [op->d.agg_trans.setoff]
    1716     1812906 :                 [op->d.agg_trans.transno];
    1717             : 
    1718             :             Assert(!pertrans->transtypeByVal);
    1719             : 
    1720     1812906 :             fcinfo = pertrans->transfn_fcinfo;
    1721             : 
    1722             :             /* cf. select_current_set() */
    1723     1812906 :             aggstate->curaggcontext = op->d.agg_trans.aggcontext;
    1724     1812906 :             aggstate->current_set = op->d.agg_trans.setno;
    1725             : 
    1726             :             /* set up aggstate->curpertrans for AggGetAggref() */
    1727     1812906 :             aggstate->curpertrans = pertrans;
    1728             : 
    1729             :             /* invoke transition function in per-tuple context */
    1730     1812906 :             oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
    1731             : 
    1732     1812906 :             fcinfo->args[0].value = pergroup->transValue;
    1733     1812906 :             fcinfo->args[0].isnull = pergroup->transValueIsNull;
    1734     1812906 :             fcinfo->isnull = false; /* just in case transfn doesn't set it */
    1735             : 
    1736     1812906 :             newVal = FunctionCallInvoke(fcinfo);
    1737             : 
    1738             :             /*
    1739             :              * For pass-by-ref datatype, must copy the new value into
    1740             :              * aggcontext and free the prior transValue.  But if transfn
    1741             :              * returned a pointer to its first input, we don't need to do
    1742             :              * anything.  Also, if transfn returned a pointer to a R/W
    1743             :              * expanded object that is already a child of the aggcontext,
    1744             :              * assume we can adopt that value without copying it.
    1745             :              */
    1746     1812902 :             if (DatumGetPointer(newVal) != DatumGetPointer(pergroup->transValue))
    1747       52616 :                 newVal = ExecAggTransReparent(aggstate, pertrans,
    1748       26308 :                                               newVal, fcinfo->isnull,
    1749             :                                               pergroup->transValue,
    1750       26308 :                                               pergroup->transValueIsNull);
    1751             : 
    1752     1812902 :             pergroup->transValue = newVal;
    1753     1812902 :             pergroup->transValueIsNull = fcinfo->isnull;
    1754             : 
    1755     1812902 :             MemoryContextSwitchTo(oldContext);
    1756             : 
    1757     1812902 :             EEO_NEXT();
    1758             :         }
    1759             : 
    1760             :         /* process single-column ordered aggregate datum */
    1761             :         EEO_CASE(EEOP_AGG_ORDERED_TRANS_DATUM)
    1762             :         {
    1763             :             /* too complex for an inline implementation */
    1764      809608 :             ExecEvalAggOrderedTransDatum(state, op, econtext);
    1765             : 
    1766      809608 :             EEO_NEXT();
    1767             :         }
    1768             : 
    1769             :         /* process multi-column ordered aggregate tuple */
    1770             :         EEO_CASE(EEOP_AGG_ORDERED_TRANS_TUPLE)
    1771             :         {
    1772             :             /* too complex for an inline implementation */
    1773       15092 :             ExecEvalAggOrderedTransTuple(state, op, econtext);
    1774             : 
    1775       15092 :             EEO_NEXT();
    1776             :         }
    1777             : 
    1778             :         EEO_CASE(EEOP_LAST)
    1779             :         {
    1780             :             /* unreachable */
    1781             :             Assert(false);
    1782           0 :             goto out;
    1783             :         }
    1784             :     }
    1785             : 
    1786             : out:
    1787    98268966 :     *isnull = state->resnull;
    1788    98268966 :     return state->resvalue;
    1789             : }
    1790             : 
    1791             : /*
    1792             :  * Expression evaluation callback that performs extra checks before executing
    1793             :  * the expression. Declared extern so other methods of execution can use it
    1794             :  * too.
    1795             :  */
    1796             : Datum
    1797      864602 : ExecInterpExprStillValid(ExprState *state, ExprContext *econtext, bool *isNull)
    1798             : {
    1799             :     /*
    1800             :      * First time through, check whether attribute matches Var.  Might not be
    1801             :      * ok anymore, due to schema changes.
    1802             :      */
    1803      864602 :     CheckExprStillValid(state, econtext);
    1804             : 
    1805             :     /* skip the check during further executions */
    1806      864586 :     state->evalfunc = (ExprStateEvalFunc) state->evalfunc_private;
    1807             : 
    1808             :     /* and actually execute */
    1809      864586 :     return state->evalfunc(state, econtext, isNull);
    1810             : }
    1811             : 
    1812             : /*
    1813             :  * Check that an expression is still valid in the face of potential schema
    1814             :  * changes since the plan has been created.
    1815             :  */
    1816             : void
    1817      867338 : CheckExprStillValid(ExprState *state, ExprContext *econtext)
    1818             : {
    1819      867338 :     int         i = 0;
    1820             :     TupleTableSlot *innerslot;
    1821             :     TupleTableSlot *outerslot;
    1822             :     TupleTableSlot *scanslot;
    1823             : 
    1824      867338 :     innerslot = econtext->ecxt_innertuple;
    1825      867338 :     outerslot = econtext->ecxt_outertuple;
    1826      867338 :     scanslot = econtext->ecxt_scantuple;
    1827             : 
    1828     5086368 :     for (i = 0; i < state->steps_len; i++)
    1829             :     {
    1830     4219046 :         ExprEvalStep *op = &state->steps[i];
    1831             : 
    1832     4219046 :         switch (ExecEvalStepOp(state, op))
    1833             :         {
    1834             :             case EEOP_INNER_VAR:
    1835             :                 {
    1836       60018 :                     int         attnum = op->d.var.attnum;
    1837             : 
    1838       60018 :                     CheckVarSlotCompatibility(innerslot, attnum + 1, op->d.var.vartype);
    1839       60018 :                     break;
    1840             :                 }
    1841             : 
    1842             :             case EEOP_OUTER_VAR:
    1843             :                 {
    1844      146818 :                     int         attnum = op->d.var.attnum;
    1845             : 
    1846      146818 :                     CheckVarSlotCompatibility(outerslot, attnum + 1, op->d.var.vartype);
    1847      146818 :                     break;
    1848             :                 }
    1849             : 
    1850             :             case EEOP_SCAN_VAR:
    1851             :                 {
    1852      143124 :                     int         attnum = op->d.var.attnum;
    1853             : 
    1854      143124 :                     CheckVarSlotCompatibility(scanslot, attnum + 1, op->d.var.vartype);
    1855      143108 :                     break;
    1856             :                 }
    1857             :             default:
    1858     3869086 :                 break;
    1859             :         }
    1860             :     }
    1861      867322 : }
    1862             : 
    1863             : /*
    1864             :  * Check whether a user attribute in a slot can be referenced by a Var
    1865             :  * expression.  This should succeed unless there have been schema changes
    1866             :  * since the expression tree has been created.
    1867             :  */
    1868             : static void
    1869      349960 : CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype)
    1870             : {
    1871             :     /*
    1872             :      * What we have to check for here is the possibility of an attribute
    1873             :      * having been dropped or changed in type since the plan tree was created.
    1874             :      * Ideally the plan will get invalidated and not re-used, but just in
    1875             :      * case, we keep these defenses.  Fortunately it's sufficient to check
    1876             :      * once on the first time through.
    1877             :      *
    1878             :      * Note: ideally we'd check typmod as well as typid, but that seems
    1879             :      * impractical at the moment: in many cases the tupdesc will have been
    1880             :      * generated by ExecTypeFromTL(), and that can't guarantee to generate an
    1881             :      * accurate typmod in all cases, because some expression node types don't
    1882             :      * carry typmod.  Fortunately, for precisely that reason, there should be
    1883             :      * no places with a critical dependency on the typmod of a value.
    1884             :      *
    1885             :      * System attributes don't require checking since their types never
    1886             :      * change.
    1887             :      */
    1888      349960 :     if (attnum > 0)
    1889             :     {
    1890      349960 :         TupleDesc   slot_tupdesc = slot->tts_tupleDescriptor;
    1891             :         Form_pg_attribute attr;
    1892             : 
    1893      349960 :         if (attnum > slot_tupdesc->natts) /* should never happen */
    1894           0 :             elog(ERROR, "attribute number %d exceeds number of columns %d",
    1895             :                  attnum, slot_tupdesc->natts);
    1896             : 
    1897      349960 :         attr = TupleDescAttr(slot_tupdesc, attnum - 1);
    1898             : 
    1899      349960 :         if (attr->attisdropped)
    1900           8 :             ereport(ERROR,
    1901             :                     (errcode(ERRCODE_UNDEFINED_COLUMN),
    1902             :                      errmsg("attribute %d of type %s has been dropped",
    1903             :                             attnum, format_type_be(slot_tupdesc->tdtypeid))));
    1904             : 
    1905      349952 :         if (vartype != attr->atttypid)
    1906           8 :             ereport(ERROR,
    1907             :                     (errcode(ERRCODE_DATATYPE_MISMATCH),
    1908             :                      errmsg("attribute %d of type %s has wrong type",
    1909             :                             attnum, format_type_be(slot_tupdesc->tdtypeid)),
    1910             :                      errdetail("Table has type %s, but query expects %s.",
    1911             :                                format_type_be(attr->atttypid),
    1912             :                                format_type_be(vartype))));
    1913             :     }
    1914      349944 : }
    1915             : 
    1916             : /*
    1917             :  * Verify that the slot is compatible with a EEOP_*_FETCHSOME operation.
    1918             :  */
    1919             : static void
    1920   111034648 : CheckOpSlotCompatibility(ExprEvalStep *op, TupleTableSlot *slot)
    1921             : {
    1922             : #ifdef USE_ASSERT_CHECKING
    1923             :     /* there's nothing to check */
    1924             :     if (!op->d.fetch.fixed)
    1925             :         return;
    1926             : 
    1927             :     /*
    1928             :      * Should probably fixed at some point, but for now it's easier to allow
    1929             :      * buffer and heap tuples to be used interchangeably.
    1930             :      */
    1931             :     if (slot->tts_ops == &TTSOpsBufferHeapTuple &&
    1932             :         op->d.fetch.kind == &TTSOpsHeapTuple)
    1933             :         return;
    1934             :     if (slot->tts_ops == &TTSOpsHeapTuple &&
    1935             :         op->d.fetch.kind == &TTSOpsBufferHeapTuple)
    1936             :         return;
    1937             : 
    1938             :     /*
    1939             :      * At the moment we consider it OK if a virtual slot is used instead of a
    1940             :      * specific type of slot, as a virtual slot never needs to be deformed.
    1941             :      */
    1942             :     if (slot->tts_ops == &TTSOpsVirtual)
    1943             :         return;
    1944             : 
    1945             :     Assert(op->d.fetch.kind == slot->tts_ops);
    1946             : #endif
    1947   111034648 : }
    1948             : 
    1949             : /*
    1950             :  * get_cached_rowtype: utility function to lookup a rowtype tupdesc
    1951             :  *
    1952             :  * type_id, typmod: identity of the rowtype
    1953             :  * cache_field: where to cache the TupleDesc pointer in expression state node
    1954             :  *      (field must be initialized to NULL)
    1955             :  * econtext: expression context we are executing in
    1956             :  *
    1957             :  * NOTE: because the shutdown callback will be called during plan rescan,
    1958             :  * must be prepared to re-do this during any node execution; cannot call
    1959             :  * just once during expression initialization.
    1960             :  */
    1961             : static TupleDesc
    1962       73864 : get_cached_rowtype(Oid type_id, int32 typmod,
    1963             :                    TupleDesc *cache_field, ExprContext *econtext)
    1964             : {
    1965       73864 :     TupleDesc   tupDesc = *cache_field;
    1966             : 
    1967             :     /* Do lookup if no cached value or if requested type changed */
    1968      143598 :     if (tupDesc == NULL ||
    1969      139468 :         type_id != tupDesc->tdtypeid ||
    1970       69734 :         typmod != tupDesc->tdtypmod)
    1971             :     {
    1972        4130 :         tupDesc = lookup_rowtype_tupdesc(type_id, typmod);
    1973             : 
    1974        4130 :         if (*cache_field)
    1975             :         {
    1976             :             /* Release old tupdesc; but callback is already registered */
    1977           0 :             ReleaseTupleDesc(*cache_field);
    1978             :         }
    1979             :         else
    1980             :         {
    1981             :             /* Need to register shutdown callback to release tupdesc */
    1982        4130 :             RegisterExprContextCallback(econtext,
    1983             :                                         ShutdownTupleDescRef,
    1984             :                                         PointerGetDatum(cache_field));
    1985             :         }
    1986        4130 :         *cache_field = tupDesc;
    1987             :     }
    1988       73864 :     return tupDesc;
    1989             : }
    1990             : 
    1991             : /*
    1992             :  * Callback function to release a tupdesc refcount at econtext shutdown
    1993             :  */
    1994             : static void
    1995        3856 : ShutdownTupleDescRef(Datum arg)
    1996             : {
    1997        3856 :     TupleDesc  *cache_field = (TupleDesc *) DatumGetPointer(arg);
    1998             : 
    1999        3856 :     if (*cache_field)
    2000        3856 :         ReleaseTupleDesc(*cache_field);
    2001        3856 :     *cache_field = NULL;
    2002        3856 : }
    2003             : 
    2004             : /*
    2005             :  * Fast-path functions, for very simple expressions
    2006             :  */
    2007             : 
    2008             : /* implementation of ExecJust(Inner|Outer|Scan)Var */
    2009             : static pg_attribute_always_inline Datum
    2010    13215864 : ExecJustVarImpl(ExprState *state, TupleTableSlot *slot, bool *isnull)
    2011             : {
    2012    13215864 :     ExprEvalStep *op = &state->steps[1];
    2013    13215864 :     int         attnum = op->d.var.attnum + 1;
    2014             : 
    2015    13215864 :     CheckOpSlotCompatibility(&state->steps[0], slot);
    2016             : 
    2017             :     /*
    2018             :      * Since we use slot_getattr(), we don't need to implement the FETCHSOME
    2019             :      * step explicitly, and we also needn't Assert that the attnum is in range
    2020             :      * --- slot_getattr() will take care of any problems.
    2021             :      */
    2022    13215864 :     return slot_getattr(slot, attnum, isnull);
    2023             : }
    2024             : 
    2025             : /* Simple reference to inner Var */
    2026             : static Datum
    2027     3972212 : ExecJustInnerVar(ExprState *state, ExprContext *econtext, bool *isnull)
    2028             : {
    2029     3972212 :     return ExecJustVarImpl(state, econtext->ecxt_innertuple, isnull);
    2030             : }
    2031             : 
    2032             : /* Simple reference to outer Var */
    2033             : static Datum
    2034     8990356 : ExecJustOuterVar(ExprState *state, ExprContext *econtext, bool *isnull)
    2035             : {
    2036     8990356 :     return ExecJustVarImpl(state, econtext->ecxt_outertuple, isnull);
    2037             : }
    2038             : 
    2039             : /* Simple reference to scan Var */
    2040             : static Datum
    2041      253296 : ExecJustScanVar(ExprState *state, ExprContext *econtext, bool *isnull)
    2042             : {
    2043      253296 :     return ExecJustVarImpl(state, econtext->ecxt_scantuple, isnull);
    2044             : }
    2045             : 
    2046             : /* implementation of ExecJustAssign(Inner|Outer|Scan)Var */
    2047             : static pg_attribute_always_inline Datum
    2048     6637454 : ExecJustAssignVarImpl(ExprState *state, TupleTableSlot *inslot, bool *isnull)
    2049             : {
    2050     6637454 :     ExprEvalStep *op = &state->steps[1];
    2051     6637454 :     int         attnum = op->d.assign_var.attnum + 1;
    2052     6637454 :     int         resultnum = op->d.assign_var.resultnum;
    2053     6637454 :     TupleTableSlot *outslot = state->resultslot;
    2054             : 
    2055     6637454 :     CheckOpSlotCompatibility(&state->steps[0], inslot);
    2056             : 
    2057             :     /*
    2058             :      * We do not need CheckVarSlotCompatibility here; that was taken care of
    2059             :      * at compilation time.
    2060             :      *
    2061             :      * Since we use slot_getattr(), we don't need to implement the FETCHSOME
    2062             :      * step explicitly, and we also needn't Assert that the attnum is in range
    2063             :      * --- slot_getattr() will take care of any problems.
    2064             :      */
    2065    13274908 :     outslot->tts_values[resultnum] =
    2066     6637454 :         slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
    2067     6637454 :     return 0;
    2068             : }
    2069             : 
    2070             : /* Evaluate inner Var and assign to appropriate column of result tuple */
    2071             : static Datum
    2072        4510 : ExecJustAssignInnerVar(ExprState *state, ExprContext *econtext, bool *isnull)
    2073             : {
    2074        4510 :     return ExecJustAssignVarImpl(state, econtext->ecxt_innertuple, isnull);
    2075             : }
    2076             : 
    2077             : /* Evaluate outer Var and assign to appropriate column of result tuple */
    2078             : static Datum
    2079      252188 : ExecJustAssignOuterVar(ExprState *state, ExprContext *econtext, bool *isnull)
    2080             : {
    2081      252188 :     return ExecJustAssignVarImpl(state, econtext->ecxt_outertuple, isnull);
    2082             : }
    2083             : 
    2084             : /* Evaluate scan Var and assign to appropriate column of result tuple */
    2085             : static Datum
    2086     6380756 : ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool *isnull)
    2087             : {
    2088     6380756 :     return ExecJustAssignVarImpl(state, econtext->ecxt_scantuple, isnull);
    2089             : }
    2090             : 
    2091             : /* Evaluate CASE_TESTVAL and apply a strict function to it */
    2092             : static Datum
    2093        2326 : ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull)
    2094             : {
    2095        2326 :     ExprEvalStep *op = &state->steps[0];
    2096             :     FunctionCallInfo fcinfo;
    2097             :     NullableDatum *args;
    2098             :     int         argno;
    2099             :     Datum       d;
    2100             : 
    2101             :     /*
    2102             :      * XXX with some redesign of the CaseTestExpr mechanism, maybe we could
    2103             :      * get rid of this data shuffling?
    2104             :      */
    2105        2326 :     *op->resvalue = *op->d.casetest.value;
    2106        2326 :     *op->resnull = *op->d.casetest.isnull;
    2107             : 
    2108        2326 :     op++;
    2109             : 
    2110        2326 :     fcinfo = op->d.func.fcinfo_data;
    2111        2326 :     args = fcinfo->args;
    2112             : 
    2113             :     /* strict function, so check for NULL args */
    2114        4860 :     for (argno = 0; argno < op->d.func.nargs; argno++)
    2115             :     {
    2116        2542 :         if (args[argno].isnull)
    2117             :         {
    2118           8 :             *isnull = true;
    2119           8 :             return (Datum) 0;
    2120             :         }
    2121             :     }
    2122        2318 :     fcinfo->isnull = false;
    2123        2318 :     d = op->d.func.fn_addr(fcinfo);
    2124        2306 :     *isnull = fcinfo->isnull;
    2125        2306 :     return d;
    2126             : }
    2127             : 
    2128             : /* Simple Const expression */
    2129             : static Datum
    2130     1164400 : ExecJustConst(ExprState *state, ExprContext *econtext, bool *isnull)
    2131             : {
    2132     1164400 :     ExprEvalStep *op = &state->steps[0];
    2133             : 
    2134     1164400 :     *isnull = op->d.constval.isnull;
    2135     1164400 :     return op->d.constval.value;
    2136             : }
    2137             : 
    2138             : /* implementation of ExecJust(Inner|Outer|Scan)VarVirt */
    2139             : static pg_attribute_always_inline Datum
    2140    10062630 : ExecJustVarVirtImpl(ExprState *state, TupleTableSlot *slot, bool *isnull)
    2141             : {
    2142    10062630 :     ExprEvalStep *op = &state->steps[0];
    2143    10062630 :     int         attnum = op->d.var.attnum;
    2144             : 
    2145             :     /*
    2146             :      * As it is guaranteed that a virtual slot is used, there never is a need
    2147             :      * to perform tuple deforming (nor would it be possible). Therefore
    2148             :      * execExpr.c has not emitted an EEOP_*_FETCHSOME step. Verify, as much as
    2149             :      * possible, that that determination was accurate.
    2150             :      */
    2151             :     Assert(TTS_IS_VIRTUAL(slot));
    2152             :     Assert(TTS_FIXED(slot));
    2153             :     Assert(attnum >= 0 && attnum < slot->tts_nvalid);
    2154             : 
    2155    10062630 :     *isnull = slot->tts_isnull[attnum];
    2156             : 
    2157    10062630 :     return slot->tts_values[attnum];
    2158             : }
    2159             : 
    2160             : /* Like ExecJustInnerVar, optimized for virtual slots */
    2161             : static Datum
    2162      353018 : ExecJustInnerVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
    2163             : {
    2164      353018 :     return ExecJustVarVirtImpl(state, econtext->ecxt_innertuple, isnull);
    2165             : }
    2166             : 
    2167             : /* Like ExecJustOuterVar, optimized for virtual slots */
    2168             : static Datum
    2169     9709488 : ExecJustOuterVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
    2170             : {
    2171     9709488 :     return ExecJustVarVirtImpl(state, econtext->ecxt_outertuple, isnull);
    2172             : }
    2173             : 
    2174             : /* Like ExecJustScanVar, optimized for virtual slots */
    2175             : static Datum
    2176         124 : ExecJustScanVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
    2177             : {
    2178         124 :     return ExecJustVarVirtImpl(state, econtext->ecxt_scantuple, isnull);
    2179             : }
    2180             : 
    2181             : /* implementation of ExecJustAssign(Inner|Outer|Scan)VarVirt */
    2182             : static pg_attribute_always_inline Datum
    2183      482204 : ExecJustAssignVarVirtImpl(ExprState *state, TupleTableSlot *inslot, bool *isnull)
    2184             : {
    2185      482204 :     ExprEvalStep *op = &state->steps[0];
    2186      482204 :     int         attnum = op->d.assign_var.attnum;
    2187      482204 :     int         resultnum = op->d.assign_var.resultnum;
    2188      482204 :     TupleTableSlot *outslot = state->resultslot;
    2189             : 
    2190             :     /* see ExecJustVarVirtImpl for comments */
    2191             : 
    2192             :     Assert(TTS_IS_VIRTUAL(inslot));
    2193             :     Assert(TTS_FIXED(inslot));
    2194             :     Assert(attnum >= 0 && attnum < inslot->tts_nvalid);
    2195             : 
    2196      482204 :     outslot->tts_values[resultnum] = inslot->tts_values[attnum];
    2197      482204 :     outslot->tts_isnull[resultnum] = inslot->tts_isnull[attnum];
    2198             : 
    2199      482204 :     return 0;
    2200             : }
    2201             : 
    2202             : /* Like ExecJustAssignInnerVar, optimized for virtual slots */
    2203             : static Datum
    2204       80352 : ExecJustAssignInnerVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
    2205             : {
    2206       80352 :     return ExecJustAssignVarVirtImpl(state, econtext->ecxt_innertuple, isnull);
    2207             : }
    2208             : 
    2209             : /* Like ExecJustAssignOuterVar, optimized for virtual slots */
    2210             : static Datum
    2211      278460 : ExecJustAssignOuterVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
    2212             : {
    2213      278460 :     return ExecJustAssignVarVirtImpl(state, econtext->ecxt_outertuple, isnull);
    2214             : }
    2215             : 
    2216             : /* Like ExecJustAssignScanVar, optimized for virtual slots */
    2217             : static Datum
    2218      123392 : ExecJustAssignScanVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
    2219             : {
    2220      123392 :     return ExecJustAssignVarVirtImpl(state, econtext->ecxt_scantuple, isnull);
    2221             : }
    2222             : 
    2223             : #if defined(EEO_USE_COMPUTED_GOTO)
    2224             : /*
    2225             :  * Comparator used when building address->opcode lookup table for
    2226             :  * ExecEvalStepOp() in the threaded dispatch case.
    2227             :  */
    2228             : static int
    2229    25900722 : dispatch_compare_ptr(const void *a, const void *b)
    2230             : {
    2231    25900722 :     const ExprEvalOpLookup *la = (const ExprEvalOpLookup *) a;
    2232    25900722 :     const ExprEvalOpLookup *lb = (const ExprEvalOpLookup *) b;
    2233             : 
    2234    25900722 :     if (la->opcode < lb->opcode)
    2235    15925880 :         return -1;
    2236     9974842 :     else if (la->opcode > lb->opcode)
    2237     6253372 :         return 1;
    2238     3721470 :     return 0;
    2239             : }
    2240             : #endif
    2241             : 
    2242             : /*
    2243             :  * Do one-time initialization of interpretation machinery.
    2244             :  */
    2245             : static void
    2246     1184220 : ExecInitInterpreter(void)
    2247             : {
    2248             : #if defined(EEO_USE_COMPUTED_GOTO)
    2249             :     /* Set up externally-visible pointer to dispatch table */
    2250     1184220 :     if (dispatch_table == NULL)
    2251             :     {
    2252             :         int         i;
    2253             : 
    2254        6160 :         dispatch_table = (const void **)
    2255        6160 :             DatumGetPointer(ExecInterpExpr(NULL, NULL, NULL));
    2256             : 
    2257             :         /* build reverse lookup table */
    2258      542080 :         for (i = 0; i < EEOP_LAST; i++)
    2259             :         {
    2260      535920 :             reverse_dispatch_table[i].opcode = dispatch_table[i];
    2261      535920 :             reverse_dispatch_table[i].op = (ExprEvalOp) i;
    2262             :         }
    2263             : 
    2264             :         /* make it bsearch()able */
    2265        6160 :         qsort(reverse_dispatch_table,
    2266             :               EEOP_LAST /* nmembers */ ,
    2267             :               sizeof(ExprEvalOpLookup),
    2268             :               dispatch_compare_ptr);
    2269             :     }
    2270             : #endif
    2271     1184220 : }
    2272             : 
    2273             : /*
    2274             :  * Function to return the opcode of an expression step.
    2275             :  *
    2276             :  * When direct-threading is in use, ExprState->opcode isn't easily
    2277             :  * decipherable. This function returns the appropriate enum member.
    2278             :  */
    2279             : ExprEvalOp
    2280     4237622 : ExecEvalStepOp(ExprState *state, ExprEvalStep *op)
    2281             : {
    2282             : #if defined(EEO_USE_COMPUTED_GOTO)
    2283     4237622 :     if (state->flags & EEO_FLAG_DIRECT_THREADED)
    2284             :     {
    2285             :         ExprEvalOpLookup key;
    2286             :         ExprEvalOpLookup *res;
    2287             : 
    2288     3721470 :         key.opcode = (void *) op->opcode;
    2289     3721470 :         res = bsearch(&key,
    2290             :                       reverse_dispatch_table,
    2291             :                       EEOP_LAST /* nmembers */ ,
    2292             :                       sizeof(ExprEvalOpLookup),
    2293             :                       dispatch_compare_ptr);
    2294             :         Assert(res);            /* unknown ops shouldn't get looked up */
    2295     3721470 :         return res->op;
    2296             :     }
    2297             : #endif
    2298      516152 :     return (ExprEvalOp) op->opcode;
    2299             : }
    2300             : 
    2301             : 
    2302             : /*
    2303             :  * Out-of-line helper functions for complex instructions.
    2304             :  */
    2305             : 
    2306             : /*
    2307             :  * Evaluate EEOP_FUNCEXPR_FUSAGE
    2308             :  */
    2309             : void
    2310           0 : ExecEvalFuncExprFusage(ExprState *state, ExprEvalStep *op,
    2311             :                        ExprContext *econtext)
    2312             : {
    2313           0 :     FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
    2314             :     PgStat_FunctionCallUsage fcusage;
    2315             :     Datum       d;
    2316             : 
    2317           0 :     pgstat_init_function_usage(fcinfo, &fcusage);
    2318             : 
    2319           0 :     fcinfo->isnull = false;
    2320           0 :     d = op->d.func.fn_addr(fcinfo);
    2321           0 :     *op->resvalue = d;
    2322           0 :     *op->resnull = fcinfo->isnull;
    2323             : 
    2324           0 :     pgstat_end_function_usage(&fcusage, true);
    2325           0 : }
    2326             : 
    2327             : /*
    2328             :  * Evaluate EEOP_FUNCEXPR_STRICT_FUSAGE
    2329             :  */
    2330             : void
    2331           0 : ExecEvalFuncExprStrictFusage(ExprState *state, ExprEvalStep *op,
    2332             :                              ExprContext *econtext)
    2333             : {
    2334             : 
    2335           0 :     FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
    2336             :     PgStat_FunctionCallUsage fcusage;
    2337           0 :     NullableDatum *args = fcinfo->args;
    2338             :     int         argno;
    2339             :     Datum       d;
    2340             : 
    2341             :     /* strict function, so check for NULL args */
    2342           0 :     for (argno = 0; argno < op->d.func.nargs; argno++)
    2343             :     {
    2344           0 :         if (args[argno].isnull)
    2345             :         {
    2346           0 :             *op->resnull = true;
    2347           0 :             return;
    2348             :         }
    2349             :     }
    2350             : 
    2351           0 :     pgstat_init_function_usage(fcinfo, &fcusage);
    2352             : 
    2353           0 :     fcinfo->isnull = false;
    2354           0 :     d = op->d.func.fn_addr(fcinfo);
    2355           0 :     *op->resvalue = d;
    2356           0 :     *op->resnull = fcinfo->isnull;
    2357             : 
    2358           0 :     pgstat_end_function_usage(&fcusage, true);
    2359             : }
    2360             : 
    2361             : /*
    2362             :  * Evaluate a PARAM_EXEC parameter.
    2363             :  *
    2364             :  * PARAM_EXEC params (internal executor parameters) are stored in the
    2365             :  * ecxt_param_exec_vals array, and can be accessed by array index.
    2366             :  */
    2367             : void
    2368    13692760 : ExecEvalParamExec(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
    2369             : {
    2370             :     ParamExecData *prm;
    2371             : 
    2372    13692760 :     prm = &(econtext->ecxt_param_exec_vals[op->d.param.paramid]);
    2373    13692760 :     if (unlikely(prm->execPlan != NULL))
    2374             :     {
    2375             :         /* Parameter not evaluated yet, so go do it */
    2376       10060 :         ExecSetParamPlan(prm->execPlan, econtext);
    2377             :         /* ExecSetParamPlan should have processed this param... */
    2378             :         Assert(prm->execPlan == NULL);
    2379             :     }
    2380    13692750 :     *op->resvalue = prm->value;
    2381    13692750 :     *op->resnull = prm->isnull;
    2382    13692750 : }
    2383             : 
    2384             : /*
    2385             :  * Evaluate a PARAM_EXTERN parameter.
    2386             :  *
    2387             :  * PARAM_EXTERN parameters must be sought in ecxt_param_list_info.
    2388             :  */
    2389             : void
    2390      140520 : ExecEvalParamExtern(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
    2391             : {
    2392      140520 :     ParamListInfo paramInfo = econtext->ecxt_param_list_info;
    2393      140520 :     int         paramId = op->d.param.paramid;
    2394             : 
    2395      140520 :     if (likely(paramInfo &&
    2396             :                paramId > 0 && paramId <= paramInfo->numParams))
    2397             :     {
    2398             :         ParamExternData *prm;
    2399             :         ParamExternData prmdata;
    2400             : 
    2401             :         /* give hook a chance in case parameter is dynamic */
    2402      140520 :         if (paramInfo->paramFetch != NULL)
    2403         132 :             prm = paramInfo->paramFetch(paramInfo, paramId, false, &prmdata);
    2404             :         else
    2405      140388 :             prm = &paramInfo->params[paramId - 1];
    2406             : 
    2407      140520 :         if (likely(OidIsValid(prm->ptype)))
    2408             :         {
    2409             :             /* safety check in case hook did something unexpected */
    2410      140520 :             if (unlikely(prm->ptype != op->d.param.paramtype))
    2411           0 :                 ereport(ERROR,
    2412             :                         (errcode(ERRCODE_DATATYPE_MISMATCH),
    2413             :                          errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
    2414             :                                 paramId,
    2415             :                                 format_type_be(prm->ptype),
    2416             :                                 format_type_be(op->d.param.paramtype))));
    2417      140520 :             *op->resvalue = prm->value;
    2418      140520 :             *op->resnull = prm->isnull;
    2419      140520 :             return;
    2420             :         }
    2421             :     }
    2422             : 
    2423           0 :     ereport(ERROR,
    2424             :             (errcode(ERRCODE_UNDEFINED_OBJECT),
    2425             :              errmsg("no value found for parameter %d", paramId)));
    2426             : }
    2427             : 
    2428             : /*
    2429             :  * Evaluate a SQLValueFunction expression.
    2430             :  */
    2431             : void
    2432        4356 : ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op)
    2433             : {
    2434        4356 :     LOCAL_FCINFO(fcinfo, 0);
    2435        4356 :     SQLValueFunction *svf = op->d.sqlvaluefunction.svf;
    2436             : 
    2437        4356 :     *op->resnull = false;
    2438             : 
    2439             :     /*
    2440             :      * Note: current_schema() can return NULL.  current_user() etc currently
    2441             :      * cannot, but might as well code those cases the same way for safety.
    2442             :      */
    2443        4356 :     switch (svf->op)
    2444             :     {
    2445             :         case SVFOP_CURRENT_DATE:
    2446          18 :             *op->resvalue = DateADTGetDatum(GetSQLCurrentDate());
    2447          18 :             break;
    2448             :         case SVFOP_CURRENT_TIME:
    2449             :         case SVFOP_CURRENT_TIME_N:
    2450           8 :             *op->resvalue = TimeTzADTPGetDatum(GetSQLCurrentTime(svf->typmod));
    2451           8 :             break;
    2452             :         case SVFOP_CURRENT_TIMESTAMP:
    2453             :         case SVFOP_CURRENT_TIMESTAMP_N:
    2454         252 :             *op->resvalue = TimestampTzGetDatum(GetSQLCurrentTimestamp(svf->typmod));
    2455         252 :             break;
    2456             :         case SVFOP_LOCALTIME:
    2457             :         case SVFOP_LOCALTIME_N:
    2458           8 :             *op->resvalue = TimeADTGetDatum(GetSQLLocalTime(svf->typmod));
    2459           8 :             break;
    2460             :         case SVFOP_LOCALTIMESTAMP:
    2461             :         case SVFOP_LOCALTIMESTAMP_N:
    2462          36 :             *op->resvalue = TimestampGetDatum(GetSQLLocalTimestamp(svf->typmod));
    2463          36 :             break;
    2464             :         case SVFOP_CURRENT_ROLE:
    2465             :         case SVFOP_CURRENT_USER:
    2466             :         case SVFOP_USER:
    2467        3966 :             InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
    2468        3966 :             *op->resvalue = current_user(fcinfo);
    2469        3966 :             *op->resnull = fcinfo->isnull;
    2470        3966 :             break;
    2471             :         case SVFOP_SESSION_USER:
    2472          52 :             InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
    2473          52 :             *op->resvalue = session_user(fcinfo);
    2474          52 :             *op->resnull = fcinfo->isnull;
    2475          52 :             break;
    2476             :         case SVFOP_CURRENT_CATALOG:
    2477           4 :             InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
    2478           4 :             *op->resvalue = current_database(fcinfo);
    2479           4 :             *op->resnull = fcinfo->isnull;
    2480           4 :             break;
    2481             :         case SVFOP_CURRENT_SCHEMA:
    2482          12 :             InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
    2483          12 :             *op->resvalue = current_schema(fcinfo);
    2484          12 :             *op->resnull = fcinfo->isnull;
    2485          12 :             break;
    2486             :     }
    2487        4356 : }
    2488             : 
    2489             : /*
    2490             :  * Raise error if a CURRENT OF expression is evaluated.
    2491             :  *
    2492             :  * The planner should convert CURRENT OF into a TidScan qualification, or some
    2493             :  * other special handling in a ForeignScan node.  So we have to be able to do
    2494             :  * ExecInitExpr on a CurrentOfExpr, but we shouldn't ever actually execute it.
    2495             :  * If we get here, we suppose we must be dealing with CURRENT OF on a foreign
    2496             :  * table whose FDW doesn't handle it, and complain accordingly.
    2497             :  */
    2498             : void
    2499           2 : ExecEvalCurrentOfExpr(ExprState *state, ExprEvalStep *op)
    2500             : {
    2501           2 :     ereport(ERROR,
    2502             :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2503             :              errmsg("WHERE CURRENT OF is not supported for this table type")));
    2504             : }
    2505             : 
    2506             : /*
    2507             :  * Evaluate NextValueExpr.
    2508             :  */
    2509             : void
    2510         196 : ExecEvalNextValueExpr(ExprState *state, ExprEvalStep *op)
    2511             : {
    2512         196 :     int64       newval = nextval_internal(op->d.nextvalueexpr.seqid, false);
    2513             : 
    2514         196 :     switch (op->d.nextvalueexpr.seqtypid)
    2515             :     {
    2516             :         case INT2OID:
    2517          20 :             *op->resvalue = Int16GetDatum((int16) newval);
    2518          20 :             break;
    2519             :         case INT4OID:
    2520         156 :             *op->resvalue = Int32GetDatum((int32) newval);
    2521         156 :             break;
    2522             :         case INT8OID:
    2523          20 :             *op->resvalue = Int64GetDatum((int64) newval);
    2524          20 :             break;
    2525             :         default:
    2526           0 :             elog(ERROR, "unsupported sequence type %u",
    2527             :                  op->d.nextvalueexpr.seqtypid);
    2528             :     }
    2529         196 :     *op->resnull = false;
    2530         196 : }
    2531             : 
    2532             : /*
    2533             :  * Evaluate NullTest / IS NULL for rows.
    2534             :  */
    2535             : void
    2536         388 : ExecEvalRowNull(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
    2537             : {
    2538         388 :     ExecEvalRowNullInt(state, op, econtext, true);
    2539         388 : }
    2540             : 
    2541             : /*
    2542             :  * Evaluate NullTest / IS NOT NULL for rows.
    2543             :  */
    2544             : void
    2545         216 : ExecEvalRowNotNull(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
    2546             : {
    2547         216 :     ExecEvalRowNullInt(state, op, econtext, false);
    2548         216 : }
    2549             : 
    2550             : /* Common code for IS [NOT] NULL on a row value */
    2551             : static void
    2552         604 : ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op,
    2553             :                    ExprContext *econtext, bool checkisnull)
    2554             : {
    2555         604 :     Datum       value = *op->resvalue;
    2556         604 :     bool        isnull = *op->resnull;
    2557             :     HeapTupleHeader tuple;
    2558             :     Oid         tupType;
    2559             :     int32       tupTypmod;
    2560             :     TupleDesc   tupDesc;
    2561             :     HeapTupleData tmptup;
    2562             :     int         att;
    2563             : 
    2564         604 :     *op->resnull = false;
    2565             : 
    2566             :     /* NULL row variables are treated just as NULL scalar columns */
    2567         604 :     if (isnull)
    2568             :     {
    2569          78 :         *op->resvalue = BoolGetDatum(checkisnull);
    2570         482 :         return;
    2571             :     }
    2572             : 
    2573             :     /*
    2574             :      * The SQL standard defines IS [NOT] NULL for a non-null rowtype argument
    2575             :      * as:
    2576             :      *
    2577             :      * "R IS NULL" is true if every field is the null value.
    2578             :      *
    2579             :      * "R IS NOT NULL" is true if no field is the null value.
    2580             :      *
    2581             :      * This definition is (apparently intentionally) not recursive; so our
    2582             :      * tests on the fields are primitive attisnull tests, not recursive checks
    2583             :      * to see if they are all-nulls or no-nulls rowtypes.
    2584             :      *
    2585             :      * The standard does not consider the possibility of zero-field rows, but
    2586             :      * here we consider them to vacuously satisfy both predicates.
    2587             :      */
    2588             : 
    2589         526 :     tuple = DatumGetHeapTupleHeader(value);
    2590             : 
    2591         526 :     tupType = HeapTupleHeaderGetTypeId(tuple);
    2592         526 :     tupTypmod = HeapTupleHeaderGetTypMod(tuple);
    2593             : 
    2594             :     /* Lookup tupdesc if first time through or if type changes */
    2595         526 :     tupDesc = get_cached_rowtype(tupType, tupTypmod,
    2596             :                                  &op->d.nulltest_row.argdesc,
    2597             :                                  econtext);
    2598             : 
    2599             :     /*
    2600             :      * heap_attisnull needs a HeapTuple not a bare HeapTupleHeader.
    2601             :      */
    2602         526 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
    2603         526 :     tmptup.t_data = tuple;
    2604             : 
    2605         962 :     for (att = 1; att <= tupDesc->natts; att++)
    2606             :     {
    2607             :         /* ignore dropped columns */
    2608         762 :         if (TupleDescAttr(tupDesc, att - 1)->attisdropped)
    2609           0 :             continue;
    2610         762 :         if (heap_attisnull(&tmptup, att, tupDesc))
    2611             :         {
    2612             :             /* null field disproves IS NOT NULL */
    2613          40 :             if (!checkisnull)
    2614             :             {
    2615          24 :                 *op->resvalue = BoolGetDatum(false);
    2616          24 :                 return;
    2617             :             }
    2618             :         }
    2619             :         else
    2620             :         {
    2621             :             /* non-null field disproves IS NULL */
    2622         722 :             if (checkisnull)
    2623             :             {
    2624         302 :                 *op->resvalue = BoolGetDatum(false);
    2625         302 :                 return;
    2626             :             }
    2627             :         }
    2628             :     }
    2629             : 
    2630         200 :     *op->resvalue = BoolGetDatum(true);
    2631             : }
    2632             : 
    2633             : /*
    2634             :  * Evaluate an ARRAY[] expression.
    2635             :  *
    2636             :  * The individual array elements (or subarrays) have already been evaluated
    2637             :  * into op->d.arrayexpr.elemvalues[]/elemnulls[].
    2638             :  */
    2639             : void
    2640      261762 : ExecEvalArrayExpr(ExprState *state, ExprEvalStep *op)
    2641             : {
    2642             :     ArrayType  *result;
    2643      261762 :     Oid         element_type = op->d.arrayexpr.elemtype;
    2644      261762 :     int         nelems = op->d.arrayexpr.nelems;
    2645      261762 :     int         ndims = 0;
    2646             :     int         dims[MAXDIM];
    2647             :     int         lbs[MAXDIM];
    2648             : 
    2649             :     /* Set non-null as default */
    2650      261762 :     *op->resnull = false;
    2651             : 
    2652      261762 :     if (!op->d.arrayexpr.multidims)
    2653             :     {
    2654             :         /* Elements are presumably of scalar type */
    2655      261410 :         Datum      *dvalues = op->d.arrayexpr.elemvalues;
    2656      261410 :         bool       *dnulls = op->d.arrayexpr.elemnulls;
    2657             : 
    2658             :         /* setup for 1-D array of the given length */
    2659      261410 :         ndims = 1;
    2660      261410 :         dims[0] = nelems;
    2661      261410 :         lbs[0] = 1;
    2662             : 
    2663      784230 :         result = construct_md_array(dvalues, dnulls, ndims, dims, lbs,
    2664             :                                     element_type,
    2665      261410 :                                     op->d.arrayexpr.elemlength,
    2666      261410 :                                     op->d.arrayexpr.elembyval,
    2667      261410 :                                     op->d.arrayexpr.elemalign);
    2668             :     }
    2669             :     else
    2670             :     {
    2671             :         /* Must be nested array expressions */
    2672         352 :         int         nbytes = 0;
    2673         352 :         int         nitems = 0;
    2674         352 :         int         outer_nelems = 0;
    2675         352 :         int         elem_ndims = 0;
    2676         352 :         int        *elem_dims = NULL;
    2677         352 :         int        *elem_lbs = NULL;
    2678         352 :         bool        firstone = true;
    2679         352 :         bool        havenulls = false;
    2680         352 :         bool        haveempty = false;
    2681             :         char      **subdata;
    2682             :         bits8     **subbitmaps;
    2683             :         int        *subbytes;
    2684             :         int        *subnitems;
    2685             :         int32       dataoffset;
    2686             :         char       *dat;
    2687             :         int         iitem;
    2688             :         int         elemoff;
    2689             :         int         i;
    2690             : 
    2691         352 :         subdata = (char **) palloc(nelems * sizeof(char *));
    2692         352 :         subbitmaps = (bits8 **) palloc(nelems * sizeof(bits8 *));
    2693         352 :         subbytes = (int *) palloc(nelems * sizeof(int));
    2694         352 :         subnitems = (int *) palloc(nelems * sizeof(int));
    2695             : 
    2696             :         /* loop through and get data area from each element */
    2697         992 :         for (elemoff = 0; elemoff < nelems; elemoff++)
    2698             :         {
    2699             :             Datum       arraydatum;
    2700             :             bool        eisnull;
    2701             :             ArrayType  *array;
    2702             :             int         this_ndims;
    2703             : 
    2704         640 :             arraydatum = op->d.arrayexpr.elemvalues[elemoff];
    2705         640 :             eisnull = op->d.arrayexpr.elemnulls[elemoff];
    2706             : 
    2707             :             /* temporarily ignore null subarrays */
    2708         640 :             if (eisnull)
    2709             :             {
    2710           0 :                 haveempty = true;
    2711           0 :                 continue;
    2712             :             }
    2713             : 
    2714         640 :             array = DatumGetArrayTypeP(arraydatum);
    2715             : 
    2716             :             /* run-time double-check on element type */
    2717         640 :             if (element_type != ARR_ELEMTYPE(array))
    2718           0 :                 ereport(ERROR,
    2719             :                         (errcode(ERRCODE_DATATYPE_MISMATCH),
    2720             :                          errmsg("cannot merge incompatible arrays"),
    2721             :                          errdetail("Array with element type %s cannot be "
    2722             :                                    "included in ARRAY construct with element type %s.",
    2723             :                                    format_type_be(ARR_ELEMTYPE(array)),
    2724             :                                    format_type_be(element_type))));
    2725             : 
    2726         640 :             this_ndims = ARR_NDIM(array);
    2727             :             /* temporarily ignore zero-dimensional subarrays */
    2728         640 :             if (this_ndims <= 0)
    2729             :             {
    2730           0 :                 haveempty = true;
    2731           0 :                 continue;
    2732             :             }
    2733             : 
    2734         640 :             if (firstone)
    2735             :             {
    2736             :                 /* Get sub-array details from first member */
    2737         352 :                 elem_ndims = this_ndims;
    2738         352 :                 ndims = elem_ndims + 1;
    2739         352 :                 if (ndims <= 0 || ndims > MAXDIM)
    2740           0 :                     ereport(ERROR,
    2741             :                             (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    2742             :                              errmsg("number of array dimensions (%d) exceeds " \
    2743             :                                     "the maximum allowed (%d)", ndims, MAXDIM)));
    2744             : 
    2745         352 :                 elem_dims = (int *) palloc(elem_ndims * sizeof(int));
    2746         352 :                 memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int));
    2747         352 :                 elem_lbs = (int *) palloc(elem_ndims * sizeof(int));
    2748         352 :                 memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int));
    2749             : 
    2750         352 :                 firstone = false;
    2751             :             }
    2752             :             else
    2753             :             {
    2754             :                 /* Check other sub-arrays are compatible */
    2755         576 :                 if (elem_ndims != this_ndims ||
    2756         288 :                     memcmp(elem_dims, ARR_DIMS(array),
    2757         288 :                            elem_ndims * sizeof(int)) != 0 ||
    2758         288 :                     memcmp(elem_lbs, ARR_LBOUND(array),
    2759             :                            elem_ndims * sizeof(int)) != 0)
    2760           0 :                     ereport(ERROR,
    2761             :                             (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
    2762             :                              errmsg("multidimensional arrays must have array "
    2763             :                                     "expressions with matching dimensions")));
    2764             :             }
    2765             : 
    2766         640 :             subdata[outer_nelems] = ARR_DATA_PTR(array);
    2767         640 :             subbitmaps[outer_nelems] = ARR_NULLBITMAP(array);
    2768         640 :             subbytes[outer_nelems] = ARR_SIZE(array) - ARR_DATA_OFFSET(array);
    2769         640 :             nbytes += subbytes[outer_nelems];
    2770         640 :             subnitems[outer_nelems] = ArrayGetNItems(this_ndims,
    2771             :                                                      ARR_DIMS(array));
    2772         640 :             nitems += subnitems[outer_nelems];
    2773         640 :             havenulls |= ARR_HASNULL(array);
    2774         640 :             outer_nelems++;
    2775             :         }
    2776             : 
    2777             :         /*
    2778             :          * If all items were null or empty arrays, return an empty array;
    2779             :          * otherwise, if some were and some weren't, raise error.  (Note: we
    2780             :          * must special-case this somehow to avoid trying to generate a 1-D
    2781             :          * array formed from empty arrays.  It's not ideal...)
    2782             :          */
    2783         352 :         if (haveempty)
    2784             :         {
    2785           0 :             if (ndims == 0)     /* didn't find any nonempty array */
    2786             :             {
    2787           0 :                 *op->resvalue = PointerGetDatum(construct_empty_array(element_type));
    2788           0 :                 return;
    2789             :             }
    2790           0 :             ereport(ERROR,
    2791             :                     (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
    2792             :                      errmsg("multidimensional arrays must have array "
    2793             :                             "expressions with matching dimensions")));
    2794             :         }
    2795             : 
    2796             :         /* setup for multi-D array */
    2797         352 :         dims[0] = outer_nelems;
    2798         352 :         lbs[0] = 1;
    2799         880 :         for (i = 1; i < ndims; i++)
    2800             :         {
    2801         528 :             dims[i] = elem_dims[i - 1];
    2802         528 :             lbs[i] = elem_lbs[i - 1];
    2803             :         }
    2804             : 
    2805         352 :         if (havenulls)
    2806             :         {
    2807          28 :             dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
    2808          28 :             nbytes += dataoffset;
    2809             :         }
    2810             :         else
    2811             :         {
    2812         324 :             dataoffset = 0;     /* marker for no null bitmap */
    2813         324 :             nbytes += ARR_OVERHEAD_NONULLS(ndims);
    2814             :         }
    2815             : 
    2816         352 :         result = (ArrayType *) palloc(nbytes);
    2817         352 :         SET_VARSIZE(result, nbytes);
    2818         352 :         result->ndim = ndims;
    2819         352 :         result->dataoffset = dataoffset;
    2820         352 :         result->elemtype = element_type;
    2821         352 :         memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
    2822         352 :         memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
    2823             : 
    2824         352 :         dat = ARR_DATA_PTR(result);
    2825         352 :         iitem = 0;
    2826         992 :         for (i = 0; i < outer_nelems; i++)
    2827             :         {
    2828         640 :             memcpy(dat, subdata[i], subbytes[i]);
    2829         640 :             dat += subbytes[i];
    2830         640 :             if (havenulls)
    2831         112 :                 array_bitmap_copy(ARR_NULLBITMAP(result), iitem,
    2832          56 :                                   subbitmaps[i], 0,
    2833          56 :                                   subnitems[i]);
    2834         640 :             iitem += subnitems[i];
    2835             :         }
    2836             :     }
    2837             : 
    2838      261762 :     *op->resvalue = PointerGetDatum(result);
    2839             : }
    2840             : 
    2841             : /*
    2842             :  * Evaluate an ArrayCoerceExpr expression.
    2843             :  *
    2844             :  * Source array is in step's result variable.
    2845             :  */
    2846             : void
    2847       38458 : ExecEvalArrayCoerce(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
    2848             : {
    2849             :     Datum       arraydatum;
    2850             : 
    2851             :     /* NULL array -> NULL result */
    2852       38458 :     if (*op->resnull)
    2853          40 :         return;
    2854             : 
    2855       38418 :     arraydatum = *op->resvalue;
    2856             : 
    2857             :     /*
    2858             :      * If it's binary-compatible, modify the element type in the array header,
    2859             :      * but otherwise leave the array as we received it.
    2860             :      */
    2861       38418 :     if (op->d.arraycoerce.elemexprstate == NULL)
    2862             :     {
    2863             :         /* Detoast input array if necessary, and copy in any case */
    2864       38192 :         ArrayType  *array = DatumGetArrayTypePCopy(arraydatum);
    2865             : 
    2866       38192 :         ARR_ELEMTYPE(array) = op->d.arraycoerce.resultelemtype;
    2867       38192 :         *op->resvalue = PointerGetDatum(array);
    2868       38192 :         return;
    2869             :     }
    2870             : 
    2871             :     /*
    2872             :      * Use array_map to apply the sub-expression to each array element.
    2873             :      */
    2874         678 :     *op->resvalue = array_map(arraydatum,
    2875         226 :                               op->d.arraycoerce.elemexprstate,
    2876             :                               econtext,
    2877             :                               op->d.arraycoerce.resultelemtype,
    2878         226 :                               op->d.arraycoerce.amstate);
    2879             : }
    2880             : 
    2881             : /*
    2882             :  * Evaluate a ROW() expression.
    2883             :  *
    2884             :  * The individual columns have already been evaluated into
    2885             :  * op->d.row.elemvalues[]/elemnulls[].
    2886             :  */
    2887             : void
    2888       20568 : ExecEvalRow(ExprState *state, ExprEvalStep *op)
    2889             : {
    2890             :     HeapTuple   tuple;
    2891             : 
    2892             :     /* build tuple from evaluated field values */
    2893       20568 :     tuple = heap_form_tuple(op->d.row.tupdesc,
    2894             :                             op->d.row.elemvalues,
    2895             :                             op->d.row.elemnulls);
    2896             : 
    2897       20568 :     *op->resvalue = HeapTupleGetDatum(tuple);
    2898       20568 :     *op->resnull = false;
    2899       20568 : }
    2900             : 
    2901             : /*
    2902             :  * Evaluate GREATEST() or LEAST() expression (note this is *not* MIN()/MAX()).
    2903             :  *
    2904             :  * All of the to-be-compared expressions have already been evaluated into
    2905             :  * op->d.minmax.values[]/nulls[].
    2906             :  */
    2907             : void
    2908        2578 : ExecEvalMinMax(ExprState *state, ExprEvalStep *op)
    2909             : {
    2910        2578 :     Datum      *values = op->d.minmax.values;
    2911        2578 :     bool       *nulls = op->d.minmax.nulls;
    2912        2578 :     FunctionCallInfo fcinfo = op->d.minmax.fcinfo_data;
    2913        2578 :     MinMaxOp    operator = op->d.minmax.op;
    2914             :     int         off;
    2915             : 
    2916             :     /* set at initialization */
    2917             :     Assert(fcinfo->args[0].isnull == false);
    2918             :     Assert(fcinfo->args[1].isnull == false);
    2919             : 
    2920             :     /* default to null result */
    2921        2578 :     *op->resnull = true;
    2922             : 
    2923        7930 :     for (off = 0; off < op->d.minmax.nelems; off++)
    2924             :     {
    2925             :         /* ignore NULL inputs */
    2926        5352 :         if (nulls[off])
    2927          90 :             continue;
    2928             : 
    2929        5262 :         if (*op->resnull)
    2930             :         {
    2931             :             /* first nonnull input, adopt value */
    2932        2578 :             *op->resvalue = values[off];
    2933        2578 :             *op->resnull = false;
    2934             :         }
    2935             :         else
    2936             :         {
    2937             :             int         cmpresult;
    2938             : 
    2939             :             /* apply comparison function */
    2940        2684 :             fcinfo->args[0].value = *op->resvalue;
    2941        2684 :             fcinfo->args[1].value = values[off];
    2942             : 
    2943        2684 :             fcinfo->isnull = false;
    2944        2684 :             cmpresult = DatumGetInt32(FunctionCallInvoke(fcinfo));
    2945        2684 :             if (fcinfo->isnull) /* probably should not happen */
    2946           0 :                 continue;
    2947             : 
    2948        2684 :             if (cmpresult > 0 && operator == IS_LEAST)
    2949         170 :                 *op->resvalue = values[off];
    2950        2514 :             else if (cmpresult < 0 && operator == IS_GREATEST)
    2951          64 :                 *op->resvalue = values[off];
    2952             :         }
    2953             :     }
    2954        2578 : }
    2955             : 
    2956             : /*
    2957             :  * Evaluate a FieldSelect node.
    2958             :  *
    2959             :  * Source record is in step's result variable.
    2960             :  */
    2961             : void
    2962       73216 : ExecEvalFieldSelect(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
    2963             : {
    2964       73216 :     AttrNumber  fieldnum = op->d.fieldselect.fieldnum;
    2965             :     Datum       tupDatum;
    2966             :     HeapTupleHeader tuple;
    2967             :     Oid         tupType;
    2968             :     int32       tupTypmod;
    2969             :     TupleDesc   tupDesc;
    2970             :     Form_pg_attribute attr;
    2971             :     HeapTupleData tmptup;
    2972             : 
    2973             :     /* NULL record -> NULL result */
    2974       73216 :     if (*op->resnull)
    2975         260 :         return;
    2976             : 
    2977       73086 :     tupDatum = *op->resvalue;
    2978             : 
    2979             :     /* We can special-case expanded records for speed */
    2980       73086 :     if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(tupDatum)))
    2981         480 :     {
    2982         480 :         ExpandedRecordHeader *erh = (ExpandedRecordHeader *) DatumGetEOHP(tupDatum);
    2983             : 
    2984             :         Assert(erh->er_magic == ER_MAGIC);
    2985             : 
    2986             :         /* Extract record's TupleDesc */
    2987         480 :         tupDesc = expanded_record_get_tupdesc(erh);
    2988             : 
    2989             :         /*
    2990             :          * Find field's attr record.  Note we don't support system columns
    2991             :          * here: a datum tuple doesn't have valid values for most of the
    2992             :          * interesting system columns anyway.
    2993             :          */
    2994         480 :         if (fieldnum <= 0)       /* should never happen */
    2995           0 :             elog(ERROR, "unsupported reference to system column %d in FieldSelect",
    2996             :                  fieldnum);
    2997         480 :         if (fieldnum > tupDesc->natts)    /* should never happen */
    2998           0 :             elog(ERROR, "attribute number %d exceeds number of columns %d",
    2999             :                  fieldnum, tupDesc->natts);
    3000         480 :         attr = TupleDescAttr(tupDesc, fieldnum - 1);
    3001             : 
    3002             :         /* Check for dropped column, and force a NULL result if so */
    3003         480 :         if (attr->attisdropped)
    3004             :         {
    3005           0 :             *op->resnull = true;
    3006           0 :             return;
    3007             :         }
    3008             : 
    3009             :         /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
    3010             :         /* As in CheckVarSlotCompatibility, we should but can't check typmod */
    3011         480 :         if (op->d.fieldselect.resulttype != attr->atttypid)
    3012           0 :             ereport(ERROR,
    3013             :                     (errcode(ERRCODE_DATATYPE_MISMATCH),
    3014             :                      errmsg("attribute %d has wrong type", fieldnum),
    3015             :                      errdetail("Table has type %s, but query expects %s.",
    3016             :                                format_type_be(attr->atttypid),
    3017             :                                format_type_be(op->d.fieldselect.resulttype))));
    3018             : 
    3019             :         /* extract the field */
    3020         480 :         *op->resvalue = expanded_record_get_field(erh, fieldnum,
    3021             :                                                   op->resnull);
    3022             :     }
    3023             :     else
    3024             :     {
    3025             :         /* Get the composite datum and extract its type fields */
    3026       72606 :         tuple = DatumGetHeapTupleHeader(tupDatum);
    3027             : 
    3028       72606 :         tupType = HeapTupleHeaderGetTypeId(tuple);
    3029       72606 :         tupTypmod = HeapTupleHeaderGetTypMod(tuple);
    3030             : 
    3031             :         /* Lookup tupdesc if first time through or if type changes */
    3032       72606 :         tupDesc = get_cached_rowtype(tupType, tupTypmod,
    3033             :                                      &op->d.fieldselect.argdesc,
    3034             :                                      econtext);
    3035             : 
    3036             :         /*
    3037             :          * Find field's attr record.  Note we don't support system columns
    3038             :          * here: a datum tuple doesn't have valid values for most of the
    3039             :          * interesting system columns anyway.
    3040             :          */
    3041       72606 :         if (fieldnum <= 0)       /* should never happen */
    3042           0 :             elog(ERROR, "unsupported reference to system column %d in FieldSelect",
    3043             :                  fieldnum);
    3044       72606 :         if (fieldnum > tupDesc->natts)    /* should never happen */
    3045           0 :             elog(ERROR, "attribute number %d exceeds number of columns %d",
    3046             :                  fieldnum, tupDesc->natts);
    3047       72606 :         attr = TupleDescAttr(tupDesc, fieldnum - 1);
    3048             : 
    3049             :         /* Check for dropped column, and force a NULL result if so */
    3050       72606 :         if (attr->attisdropped)
    3051             :         {
    3052           0 :             *op->resnull = true;
    3053           0 :             return;
    3054             :         }
    3055             : 
    3056             :         /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
    3057             :         /* As in CheckVarSlotCompatibility, we should but can't check typmod */
    3058       72606 :         if (op->d.fieldselect.resulttype != attr->atttypid)
    3059           0 :             ereport(ERROR,
    3060             :                     (errcode(ERRCODE_DATATYPE_MISMATCH),
    3061             :                      errmsg("attribute %d has wrong type", fieldnum),
    3062             :                      errdetail("Table has type %s, but query expects %s.",
    3063             :                                format_type_be(attr->atttypid),
    3064             :                                format_type_be(op->d.fieldselect.resulttype))));
    3065             : 
    3066             :         /* heap_getattr needs a HeapTuple not a bare HeapTupleHeader */
    3067       72606 :         tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
    3068       72606 :         tmptup.t_data = tuple;
    3069             : 
    3070             :         /* extract the field */
    3071       72606 :         *op->resvalue = heap_getattr(&tmptup,
    3072             :                                      fieldnum,
    3073             :                                      tupDesc,
    3074             :                                      op->resnull);
    3075             :     }
    3076             : }
    3077             : 
    3078             : /*
    3079             :  * Deform source tuple, filling in the step's values/nulls arrays, before
    3080             :  * evaluating individual new values as part of a FieldStore expression.
    3081             :  * Subsequent steps will overwrite individual elements of the values/nulls
    3082             :  * arrays with the new field values, and then FIELDSTORE_FORM will build the
    3083             :  * new tuple value.
    3084             :  *
    3085             :  * Source record is in step's result variable.
    3086             :  */
    3087             : void
    3088         224 : ExecEvalFieldStoreDeForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
    3089             : {
    3090             :     TupleDesc   tupDesc;
    3091             : 
    3092             :     /* Lookup tupdesc if first time through or after rescan */
    3093         224 :     tupDesc = get_cached_rowtype(op->d.fieldstore.fstore->resulttype, -1,
    3094             :                                  op->d.fieldstore.argdesc, econtext);
    3095             : 
    3096             :     /* Check that current tupdesc doesn't have more fields than we allocated */
    3097         224 :     if (unlikely(tupDesc->natts > op->d.fieldstore.ncolumns))
    3098           0 :         elog(ERROR, "too many columns in composite type %u",
    3099             :              op->d.fieldstore.fstore->resulttype);
    3100             : 
    3101         224 :     if (*op->resnull)
    3102             :     {
    3103             :         /* Convert null input tuple into an all-nulls row */
    3104          96 :         memset(op->d.fieldstore.nulls, true,
    3105          96 :                op->d.fieldstore.ncolumns * sizeof(bool));
    3106             :     }
    3107             :     else
    3108             :     {
    3109             :         /*
    3110             :          * heap_deform_tuple needs a HeapTuple not a bare HeapTupleHeader. We
    3111             :          * set all the fields in the struct just in case.
    3112             :          */
    3113         128 :         Datum       tupDatum = *op->resvalue;
    3114             :         HeapTupleHeader tuphdr;
    3115             :         HeapTupleData tmptup;
    3116             : 
    3117         128 :         tuphdr = DatumGetHeapTupleHeader(tupDatum);
    3118         128 :         tmptup.t_len = HeapTupleHeaderGetDatumLength(tuphdr);
    3119         128 :         ItemPointerSetInvalid(&(tmptup.t_self));
    3120         128 :         tmptup.t_tableOid = InvalidOid;
    3121         128 :         tmptup.t_data = tuphdr;
    3122             : 
    3123         128 :         heap_deform_tuple(&tmptup, tupDesc,
    3124             :                           op->d.fieldstore.values,
    3125             :                           op->d.fieldstore.nulls);
    3126             :     }
    3127         224 : }
    3128             : 
    3129             : /*
    3130             :  * Compute the new composite datum after each individual field value of a
    3131             :  * FieldStore expression has been evaluated.
    3132             :  */
    3133             : void
    3134         224 : ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
    3135             : {
    3136             :     HeapTuple   tuple;
    3137             : 
    3138             :     /* argdesc should already be valid from the DeForm step */
    3139         224 :     tuple = heap_form_tuple(*op->d.fieldstore.argdesc,
    3140             :                             op->d.fieldstore.values,
    3141             :                             op->d.fieldstore.nulls);
    3142             : 
    3143         224 :     *op->resvalue = HeapTupleGetDatum(tuple);
    3144         224 :     *op->resnull = false;
    3145         224 : }
    3146             : 
    3147             : /*
    3148             :  * Process a subscript in a SubscriptingRef expression.
    3149             :  *
    3150             :  * If subscript is NULL, throw error in assignment case, or in fetch case
    3151             :  * set result to NULL and return false (instructing caller to skip the rest
    3152             :  * of the SubscriptingRef sequence).
    3153             :  *
    3154             :  * Subscript expression result is in subscriptvalue/subscriptnull.
    3155             :  * On success, integer subscript value has been saved in upperindex[] or
    3156             :  * lowerindex[] for use later.
    3157             :  */
    3158             : bool
    3159      448070 : ExecEvalSubscriptingRef(ExprState *state, ExprEvalStep *op)
    3160             : {
    3161      448070 :     SubscriptingRefState *sbsrefstate = op->d.sbsref_subscript.state;
    3162             :     int        *indexes;
    3163             :     int         off;
    3164             : 
    3165             :     /* If any index expr yields NULL, result is NULL or error */
    3166      448070 :     if (sbsrefstate->subscriptnull)
    3167             :     {
    3168          24 :         if (sbsrefstate->isassignment)
    3169          12 :             ereport(ERROR,
    3170             :                     (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    3171             :                      errmsg("array subscript in assignment must not be null")));
    3172          12 :         *op->resnull = true;
    3173          12 :         return false;
    3174             :     }
    3175             : 
    3176             :     /* Convert datum to int, save in appropriate place */
    3177      448046 :     if (op->d.sbsref_subscript.isupper)
    3178      447558 :         indexes = sbsrefstate->upperindex;
    3179             :     else
    3180         488 :         indexes = sbsrefstate->lowerindex;
    3181      448046 :     off = op->d.sbsref_subscript.off;
    3182             : 
    3183      448046 :     indexes[off] = DatumGetInt32(sbsrefstate->subscriptvalue);
    3184             : 
    3185      448046 :     return true;
    3186             : }
    3187             : 
    3188             : /*
    3189             :  * Evaluate SubscriptingRef fetch.
    3190             :  *
    3191             :  * Source container is in step's result variable.
    3192             :  */
    3193             : void
    3194      446716 : ExecEvalSubscriptingRefFetch(ExprState *state, ExprEvalStep *op)
    3195             : {
    3196      446716 :     SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
    3197             : 
    3198             :     /* Should not get here if source container (or any subscript) is null */
    3199             :     Assert(!(*op->resnull));
    3200             : 
    3201      446716 :     if (sbsrefstate->numlower == 0)
    3202             :     {
    3203             :         /* Scalar case */
    3204     2678880 :         *op->resvalue = array_get_element(*op->resvalue,
    3205             :                                           sbsrefstate->numupper,
    3206      446480 :                                           sbsrefstate->upperindex,
    3207      446480 :                                           sbsrefstate->refattrlength,
    3208      446480 :                                           sbsrefstate->refelemlength,
    3209      446480 :                                           sbsrefstate->refelembyval,
    3210      446480 :                                           sbsrefstate->refelemalign,
    3211             :                                           op->resnull);
    3212             :     }
    3213             :     else
    3214             :     {
    3215             :         /* Slice case */
    3216        1416 :         *op->resvalue = array_get_slice(*op->resvalue,
    3217             :                                         sbsrefstate->numupper,
    3218         236 :                                         sbsrefstate->upperindex,
    3219         236 :                                         sbsrefstate->lowerindex,
    3220         236 :                                         sbsrefstate->upperprovided,
    3221         236 :                                         sbsrefstate->lowerprovided,
    3222         236 :                                         sbsrefstate->refattrlength,
    3223         236 :                                         sbsrefstate->refelemlength,
    3224         236 :                                         sbsrefstate->refelembyval,
    3225         236 :                                         sbsrefstate->refelemalign);
    3226             :     }
    3227      446700 : }
    3228             : 
    3229             : /*
    3230             :  * Compute old container element/slice value for a SubscriptingRef assignment
    3231             :  * expression. Will only be generated if the new-value subexpression
    3232             :  * contains SubscriptingRef or FieldStore. The value is stored into the
    3233             :  * SubscriptingRefState's prevvalue/prevnull fields.
    3234             :  */
    3235             : void
    3236         132 : ExecEvalSubscriptingRefOld(ExprState *state, ExprEvalStep *op)
    3237             : {
    3238         132 :     SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
    3239             : 
    3240         132 :     if (*op->resnull)
    3241             :     {
    3242             :         /* whole array is null, so any element or slice is too */
    3243          36 :         sbsrefstate->prevvalue = (Datum) 0;
    3244          36 :         sbsrefstate->prevnull = true;
    3245             :     }
    3246          96 :     else if (sbsrefstate->numlower == 0)
    3247             :     {
    3248             :         /* Scalar case */
    3249         576 :         sbsrefstate->prevvalue = array_get_element(*op->resvalue,
    3250             :                                                    sbsrefstate->numupper,
    3251          96 :                                                    sbsrefstate->upperindex,
    3252          96 :                                                    sbsrefstate->refattrlength,
    3253          96 :                                                    sbsrefstate->refelemlength,
    3254          96 :                                                    sbsrefstate->refelembyval,
    3255          96 :                                                    sbsrefstate->refelemalign,
    3256             :                                                    &sbsrefstate->prevnull);
    3257             :     }
    3258             :     else
    3259             :     {
    3260             :         /* Slice case */
    3261             :         /* this is currently unreachable */
    3262           0 :         sbsrefstate->prevvalue = array_get_slice(*op->resvalue,
    3263             :                                                  sbsrefstate->numupper,
    3264           0 :                                                  sbsrefstate->upperindex,
    3265           0 :                                                  sbsrefstate->lowerindex,
    3266           0 :                                                  sbsrefstate->upperprovided,
    3267           0 :                                                  sbsrefstate->lowerprovided,
    3268           0 :                                                  sbsrefstate->refattrlength,
    3269           0 :                                                  sbsrefstate->refelemlength,
    3270           0 :                                                  sbsrefstate->refelembyval,
    3271           0 :                                                  sbsrefstate->refelemalign);
    3272           0 :         sbsrefstate->prevnull = false;
    3273             :     }
    3274         132 : }
    3275             : 
    3276             : /*
    3277             :  * Evaluate SubscriptingRef assignment.
    3278             :  *
    3279             :  * Input container (possibly null) is in result area, replacement value is in
    3280             :  * SubscriptingRefState's replacevalue/replacenull.
    3281             :  */
    3282             : void
    3283         618 : ExecEvalSubscriptingRefAssign(ExprState *state, ExprEvalStep *op)
    3284             : {
    3285         618 :     SubscriptingRefState *sbsrefstate = op->d.sbsref_subscript.state;
    3286             : 
    3287             :     /*
    3288             :      * For an assignment to a fixed-length container type, both the original
    3289             :      * container and the value to be assigned into it must be non-NULL, else
    3290             :      * we punt and return the original container.
    3291             :      */
    3292         618 :     if (sbsrefstate->refattrlength > 0)
    3293             :     {
    3294          24 :         if (*op->resnull || sbsrefstate->replacenull)
    3295          12 :             return;
    3296             :     }
    3297             : 
    3298             :     /*
    3299             :      * For assignment to varlena arrays, we handle a NULL original array by
    3300             :      * substituting an empty (zero-dimensional) array; insertion of the new
    3301             :      * element will result in a singleton array value.  It does not matter
    3302             :      * whether the new element is NULL.
    3303             :      */
    3304         606 :     if (*op->resnull)
    3305             :     {
    3306         136 :         *op->resvalue = PointerGetDatum(construct_empty_array(sbsrefstate->refelemtype));
    3307         136 :         *op->resnull = false;
    3308             :     }
    3309             : 
    3310         606 :     if (sbsrefstate->numlower == 0)
    3311             :     {
    3312             :         /* Scalar case */
    3313        3122 :         *op->resvalue = array_set_element(*op->resvalue,
    3314             :                                           sbsrefstate->numupper,
    3315         446 :                                           sbsrefstate->upperindex,
    3316             :                                           sbsrefstate->replacevalue,
    3317         446 :                                           sbsrefstate->replacenull,
    3318         446 :                                           sbsrefstate->refattrlength,
    3319         446 :                                           sbsrefstate->refelemlength,
    3320         446 :                                           sbsrefstate->refelembyval,
    3321         446 :                                           sbsrefstate->refelemalign);
    3322             :     }
    3323             :     else
    3324             :     {
    3325             :         /* Slice case */
    3326        1120 :         *op->resvalue = array_set_slice(*op->resvalue,
    3327             :                                         sbsrefstate->numupper,
    3328         160 :                                         sbsrefstate->upperindex,
    3329         160 :                                         sbsrefstate->lowerindex,
    3330         160 :                                         sbsrefstate->upperprovided,
    3331         160 :                                         sbsrefstate->lowerprovided,
    3332             :                                         sbsrefstate->replacevalue,
    3333         160 :                                         sbsrefstate->replacenull,
    3334         160 :                                         sbsrefstate->refattrlength,
    3335         160 :                                         sbsrefstate->refelemlength,
    3336         160 :                                         sbsrefstate->refelembyval,
    3337         160 :                                         sbsrefstate->refelemalign);
    3338             :     }
    3339             : }
    3340             : 
    3341             : /*
    3342             :  * Evaluate a rowtype coercion operation.
    3343             :  * This may require rearranging field positions.
    3344             :  *
    3345             :  * Source record is in step's result variable.
    3346             :  */
    3347             : void
    3348       10150 : ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
    3349             : {
    3350       10150 :     ConvertRowtypeExpr *convert = op->d.convert_rowtype.convert;
    3351             :     HeapTuple   result;
    3352             :     Datum       tupDatum;
    3353             :     HeapTupleHeader tuple;
    3354             :     HeapTupleData tmptup;
    3355             :     TupleDesc   indesc,
    3356             :                 outdesc;
    3357             : 
    3358             :     /* NULL in -> NULL out */
    3359       10150 :     if (*op->resnull)
    3360           4 :         return;
    3361             : 
    3362       10146 :     tupDatum = *op->resvalue;
    3363       10146 :     tuple = DatumGetHeapTupleHeader(tupDatum);
    3364             : 
    3365             :     /* Lookup tupdescs if first time through or after rescan */
    3366       10146 :     if (op->d.convert_rowtype.indesc == NULL)
    3367             :     {
    3368         254 :         get_cached_rowtype(exprType((Node *) convert->arg), -1,
    3369             :                            &op->d.convert_rowtype.indesc,
    3370             :                            econtext);
    3371         254 :         op->d.convert_rowtype.initialized = false;
    3372             :     }
    3373       10146 :     if (op->d.convert_rowtype.outdesc == NULL)
    3374             :     {
    3375         254 :         get_cached_rowtype(convert->resulttype, -1,
    3376             :                            &op->d.convert_rowtype.outdesc,
    3377             :                            econtext);
    3378         254 :         op->d.convert_rowtype.initialized = false;
    3379             :     }
    3380             : 
    3381       10146 :     indesc = op->d.convert_rowtype.indesc;
    3382       10146 :     outdesc = op->d.convert_rowtype.outdesc;
    3383             : 
    3384             :     /*
    3385             :      * We used to be able to assert that incoming tuples are marked with
    3386             :      * exactly the rowtype of indesc.  However, now that ExecEvalWholeRowVar
    3387             :      * might change the tuples' marking to plain RECORD due to inserting
    3388             :      * aliases, we can only make this weak test:
    3389             :      */
    3390             :     Assert(HeapTupleHeaderGetTypeId(tuple) == indesc->tdtypeid ||
    3391             :            HeapTupleHeaderGetTypeId(tuple) == RECORDOID);
    3392             : 
    3393             :     /* if first time through, initialize conversion map */
    3394       10146 :     if (!op->d.convert_rowtype.initialized)
    3395             :     {
    3396             :         MemoryContext old_cxt;
    3397             : 
    3398             :         /* allocate map in long-lived memory context */
    3399         254 :         old_cxt = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
    3400             : 
    3401             :         /* prepare map from old to new attribute numbers */
    3402         254 :         op->d.convert_rowtype.map = convert_tuples_by_name(indesc, outdesc);
    3403         254 :         op->d.convert_rowtype.initialized = true;
    3404             : 
    3405         254 :         MemoryContextSwitchTo(old_cxt);
    3406             :     }
    3407             : 
    3408             :     /* Following steps need a HeapTuple not a bare HeapTupleHeader */
    3409       10146 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
    3410       10146 :     tmptup.t_data = tuple;
    3411             : 
    3412       10146 :     if (op->d.convert_rowtype.map != NULL)
    3413             :     {
    3414             :         /* Full conversion with attribute rearrangement needed */
    3415         448 :         result = execute_attr_map_tuple(&tmptup, op->d.convert_rowtype.map);
    3416             :         /* Result already has appropriate composite-datum header fields */
    3417         448 :         *op->resvalue = HeapTupleGetDatum(result);
    3418             :     }
    3419             :     else
    3420             :     {
    3421             :         /*
    3422             :          * The tuple is physically compatible as-is, but we need to insert the
    3423             :          * destination rowtype OID in its composite-datum header field, so we
    3424             :          * have to copy it anyway.  heap_copy_tuple_as_datum() is convenient
    3425             :          * for this since it will both make the physical copy and insert the
    3426             :          * correct composite header fields.  Note that we aren't expecting to
    3427             :          * have to flatten any toasted fields: the input was a composite
    3428             :          * datum, so it shouldn't contain any.  So heap_copy_tuple_as_datum()
    3429             :          * is overkill here, but its check for external fields is cheap.
    3430             :          */
    3431        9698 :         *op->resvalue = heap_copy_tuple_as_datum(&tmptup, outdesc);
    3432             :     }
    3433             : }
    3434             : 
    3435             : /*
    3436             :  * Evaluate "scalar op ANY/ALL (array)".
    3437             :  *
    3438             :  * Source array is in our result area, scalar arg is already evaluated into
    3439             :  * fcinfo->args[0].
    3440             :  *
    3441             :  * The operator always yields boolean, and we combine the results across all
    3442             :  * array elements using OR and AND (for ANY and ALL respectively).  Of course
    3443             :  * we short-circuit as soon as the result is known.
    3444             :  */
    3445             : void
    3446     2288474 : ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
    3447             : {
    3448     2288474 :     FunctionCallInfo fcinfo = op->d.scalararrayop.fcinfo_data;
    3449     2288474 :     bool        useOr = op->d.scalararrayop.useOr;
    3450     2288474 :     bool        strictfunc = op->d.scalararrayop.finfo->fn_strict;
    3451             :     ArrayType  *arr;
    3452             :     int         nitems;
    3453             :     Datum       result;
    3454             :     bool        resultnull;
    3455             :     int         i;
    3456             :     int16       typlen;
    3457             :     bool        typbyval;
    3458             :     char        typalign;
    3459             :     char       *s;
    3460             :     bits8      *bitmap;
    3461             :     int         bitmask;
    3462             : 
    3463             :     /*
    3464             :      * If the array is NULL then we return NULL --- it's not very meaningful
    3465             :      * to do anything else, even if the operator isn't strict.
    3466             :      */
    3467     2288474 :     if (*op->resnull)
    3468       71084 :         return;
    3469             : 
    3470             :     /* Else okay to fetch and detoast the array */
    3471     2217390 :     arr = DatumGetArrayTypeP(*op->resvalue);
    3472             : 
    3473             :     /*
    3474             :      * If the array is empty, we return either FALSE or TRUE per the useOr
    3475             :      * flag.  This is correct even if the scalar is NULL; since we would
    3476             :      * evaluate the operator zero times, it matters not whether it would want
    3477             :      * to return NULL.
    3478             :      */
    3479     2217390 :     nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
    3480     2217390 :     if (nitems <= 0)
    3481             :     {
    3482        2500 :         *op->resvalue = BoolGetDatum(!useOr);
    3483        2500 :         *op->resnull = false;
    3484        2500 :         return;
    3485             :     }
    3486             : 
    3487             :     /*
    3488             :      * If the scalar is NULL, and the function is strict, return NULL; no
    3489             :      * point in iterating the loop.
    3490             :      */
    3491     2214890 :     if (fcinfo->args[0].isnull && strictfunc)
    3492             :     {
    3493         396 :         *op->resnull = true;
    3494         396 :         return;
    3495             :     }
    3496             : 
    3497             :     /*
    3498             :      * We arrange to look up info about the element type only once per series
    3499             :      * of calls, assuming the element type doesn't change underneath us.
    3500             :      */
    3501     2214494 :     if (op->d.scalararrayop.element_type != ARR_ELEMTYPE(arr))
    3502             :     {
    3503        9360 :         get_typlenbyvalalign(ARR_ELEMTYPE(arr),
    3504             :                              &op->d.scalararrayop.typlen,
    3505             :                              &op->d.scalararrayop.typbyval,
    3506             :                              &op->d.scalararrayop.typalign);
    3507        9360 :         op->d.scalararrayop.element_type = ARR_ELEMTYPE(arr);
    3508             :     }
    3509             : 
    3510     2214494 :     typlen = op->d.scalararrayop.typlen;
    3511     2214494 :     typbyval = op->d.scalararrayop.typbyval;
    3512     2214494 :     typalign = op->d.scalararrayop.typalign;
    3513             : 
    3514             :     /* Initialize result appropriately depending on useOr */
    3515     2214494 :     result = BoolGetDatum(!useOr);
    3516     2214494 :     resultnull = false;
    3517             : 
    3518             :     /* Loop over the array elements */
    3519     2214494 :     s = (char *) ARR_DATA_PTR(arr);
    3520     2214494 :     bitmap = ARR_NULLBITMAP(arr);
    3521     2214494 :     bitmask = 1;
    3522             : 
    3523     6199586 :     for (i = 0; i < nitems; i++)
    3524             :     {
    3525             :         Datum       elt;
    3526             :         Datum       thisresult;
    3527             : 
    3528             :         /* Get array element, checking for NULL */
    3529     4695572 :         if (bitmap && (*bitmap & bitmask) == 0)
    3530             :         {
    3531         432 :             fcinfo->args[1].value = (Datum) 0;
    3532         432 :             fcinfo->args[1].isnull = true;
    3533             :         }
    3534             :         else
    3535             :         {
    3536     4695140 :             elt = fetch_att(s, typbyval, typlen);
    3537     4695140 :             s = att_addlength_pointer(s, typlen, s);
    3538     4695140 :             s = (char *) att_align_nominal(s, typalign);
    3539     4695140 :             fcinfo->args[1].value = elt;
    3540     4695140 :             fcinfo->args[1].isnull = false;
    3541             :         }
    3542             : 
    3543             :         /* Call comparison function */
    3544     4695572 :         if (fcinfo->args[1].isnull && strictfunc)
    3545             :         {
    3546         432 :             fcinfo->isnull = true;
    3547         432 :             thisresult = (Datum) 0;
    3548             :         }
    3549             :         else
    3550             :         {
    3551     4695140 :             fcinfo->isnull = false;
    3552     4695140 :             thisresult = op->d.scalararrayop.fn_addr(fcinfo);
    3553             :         }
    3554             : 
    3555             :         /* Combine results per OR or AND semantics */
    3556     4695572 :         if (fcinfo->isnull)
    3557         432 :             resultnull = true;
    3558     4695140 :         else if (useOr)
    3559             :         {
    3560     4273448 :             if (DatumGetBool(thisresult))
    3561             :             {
    3562      500094 :                 result = BoolGetDatum(true);
    3563      500094 :                 resultnull = false;
    3564      500094 :                 break;          /* needn't look at any more elements */
    3565             :             }
    3566             :         }
    3567             :         else
    3568             :         {
    3569      421692 :             if (!DatumGetBool(thisresult))
    3570             :             {
    3571      210386 :                 result = BoolGetDatum(false);
    3572      210386 :                 resultnull = false;
    3573      210386 :                 break;          /* needn't look at any more elements */
    3574             :             }
    3575             :         }
    3576             : 
    3577             :         /* advance bitmap pointer if any */
    3578     3985092 :         if (bitmap)
    3579             :         {
    3580        5946 :             bitmask <<= 1;
    3581        5946 :             if (bitmask == 0x100)
    3582             :             {
    3583         526 :                 bitmap++;
    3584         526 :                 bitmask = 1;
    3585             :             }
    3586             :         }
    3587             :     }
    3588             : 
    3589     2214494 :     *op->resvalue = result;
    3590     2214494 :     *op->resnull = resultnull;
    3591             : }
    3592             : 
    3593             : /*
    3594             :  * Evaluate a NOT NULL domain constraint.
    3595             :  */
    3596             : void
    3597         250 : ExecEvalConstraintNotNull(ExprState *state, ExprEvalStep *op)
    3598             : {
    3599         250 :     if (*op->resnull)
    3600          64 :         ereport(ERROR,
    3601             :                 (errcode(ERRCODE_NOT_NULL_VIOLATION),
    3602             :                  errmsg("domain %s does not allow null values",
    3603             :                         format_type_be(op->d.domaincheck.resulttype)),
    3604             :                  errdatatype(op->d.domaincheck.resulttype)));
    3605         186 : }
    3606             : 
    3607             : /*
    3608             :  * Evaluate a CHECK domain constraint.
    3609             :  */
    3610             : void
    3611       28566 : ExecEvalConstraintCheck(ExprState *state, ExprEvalStep *op)
    3612             : {
    3613       53526 :     if (!*op->d.domaincheck.checknull &&
    3614       24960 :         !DatumGetBool(*op->d.domaincheck.checkvalue))
    3615         244 :         ereport(ERROR,
    3616             :                 (errcode(ERRCODE_CHECK_VIOLATION),
    3617             :                  errmsg("value for domain %s violates check constraint \"%s\"",
    3618             :                         format_type_be(op->d.domaincheck.resulttype),
    3619             :                         op->d.domaincheck.constraintname),
    3620             :                  errdomainconstraint(op->d.domaincheck.resulttype,
    3621             :                                      op->d.domaincheck.constraintname)));
    3622       28322 : }
    3623             : 
    3624             : /*
    3625             :  * Evaluate the various forms of XmlExpr.
    3626             :  *
    3627             :  * Arguments have been evaluated into named_argvalue/named_argnull
    3628             :  * and/or argvalue/argnull arrays.
    3629             :  */
    3630             : void
    3631       26140 : ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op)
    3632             : {
    3633       26140 :     XmlExpr    *xexpr = op->d.xmlexpr.xexpr;
    3634             :     Datum       value;
    3635             :     int         i;
    3636             : 
    3637       26140 :     *op->resnull = true;     /* until we get a result */
    3638       26140 :     *op->resvalue = (Datum) 0;
    3639             : 
    3640       26140 :     switch (xexpr->op)
    3641             :     {
    3642             :         case IS_XMLCONCAT:
    3643             :             {
    3644          36 :                 Datum      *argvalue = op->d.xmlexpr.argvalue;
    3645          36 :                 bool       *argnull = op->d.xmlexpr.argnull;
    3646          36 :                 List       *values = NIL;
    3647             : 
    3648         116 :                 for (i = 0; i < list_length(xexpr->args); i++)
    3649             :                 {
    3650          80 :                     if (!argnull[i])
    3651          60 :                         values = lappend(values, DatumGetPointer(argvalue[i]));
    3652             :                 }
    3653             : 
    3654          36 :                 if (values != NIL)
    3655             :                 {
    3656          28 :                     *op->resvalue = PointerGetDatum(xmlconcat(values));
    3657          28 :                     *op->resnull = false;
    3658             :                 }
    3659             :             }
    3660          36 :             break;
    3661             : 
    3662             :         case IS_XMLFOREST:
    3663             :             {
    3664       12896 :                 Datum      *argvalue = op->d.xmlexpr.named_argvalue;
    3665       12896 :                 bool       *argnull = op->d.xmlexpr.named_argnull;
    3666             :                 StringInfoData buf;
    3667             :                 ListCell   *lc;
    3668             :                 ListCell   *lc2;
    3669             : 
    3670       12896 :                 initStringInfo(&buf);
    3671             : 
    3672       12896 :                 i = 0;
    3673       90192 :                 forboth(lc, xexpr->named_args, lc2, xexpr->arg_names)
    3674             :                 {
    3675       77296 :                     Expr       *e = (Expr *) lfirst(lc);
    3676       77296 :                     char       *argname = strVal(lfirst(lc2));
    3677             : 
    3678       77296 :                     if (!argnull[i])
    3679             :                     {
    3680       64284 :                         value = argvalue[i];
    3681       64284 :                         appendStringInfo(&buf, "<%s>%s</%s>",
    3682             :                                          argname,
    3683             :                                          map_sql_value_to_xml_value(value,
    3684             :                                                                     exprType((Node *) e), true),
    3685             :                                          argname);
    3686       64284 :                         *op->resnull = false;
    3687             :                     }
    3688       77296 :                     i++;
    3689             :                 }
    3690             : 
    3691       12896 :                 if (!*op->resnull)
    3692             :                 {
    3693             :                     text       *result;
    3694             : 
    3695       12896 :                     result = cstring_to_text_with_len(buf.data, buf.len);
    3696       12896 :                     *op->resvalue = PointerGetDatum(result);
    3697             :                 }
    3698             : 
    3699       12896 :                 pfree(buf.data);
    3700             :             }
    3701       12896 :             break;
    3702             : 
    3703             :         case IS_XMLELEMENT:
    3704       13000 :             *op->resvalue = PointerGetDatum(xmlelement(xexpr,
    3705             :                                                        op->d.xmlexpr.named_argvalue,
    3706             :                                                        op->d.xmlexpr.named_argnull,
    3707             :                                                        op->d.xmlexpr.argvalue,
    3708             :                                                        op->d.xmlexpr.argnull));
    3709       12996 :             *op->resnull = false;
    3710       12996 :             break;
    3711             : 
    3712             :         case IS_XMLPARSE:
    3713             :             {
    3714          88 :                 Datum      *argvalue = op->d.xmlexpr.argvalue;
    3715          88 :                 bool       *argnull = op->d.xmlexpr.argnull;
    3716             :                 text       *data;
    3717             :                 bool        preserve_whitespace;
    3718             : 
    3719             :                 /* arguments are known to be text, bool */
    3720             :                 Assert(list_length(xexpr->args) == 2);
    3721             : 
    3722          88 :                 if (argnull[0])
    3723           0 :                     return;
    3724          88 :                 value = argvalue[0];
    3725          88 :                 data = DatumGetTextPP(value);
    3726             : 
    3727          88 :                 if (argnull[1]) /* probably can't happen */
    3728           0 :                     return;
    3729          88 :                 value = argvalue[1];
    3730          88 :                 preserve_whitespace = DatumGetBool(value);
    3731             : 
    3732          88 :                 *op->resvalue = PointerGetDatum(xmlparse(data,
    3733             :                                                          xexpr->xmloption,
    3734             :                                                          preserve_whitespace));
    3735          56 :                 *op->resnull = false;
    3736             :             }
    3737          56 :             break;
    3738             : 
    3739             :         case IS_XMLPI:
    3740             :             {
    3741             :                 text       *arg;
    3742             :                 bool        isnull;
    3743             : 
    3744             :                 /* optional argument is known to be text */
    3745             :                 Assert(list_length(xexpr->args) <= 1);
    3746             : 
    3747          48 :                 if (xexpr->args)
    3748             :                 {
    3749          28 :                     isnull = op->d.xmlexpr.argnull[0];
    3750          28 :                     if (isnull)
    3751          12 :                         arg = NULL;
    3752             :                     else
    3753          16 :                         arg = DatumGetTextPP(op->d.xmlexpr.argvalue[0]);
    3754             :                 }
    3755             :                 else
    3756             :                 {
    3757          20 :                     arg = NULL;
    3758          20 :                     isnull = false;
    3759             :                 }
    3760             : 
    3761          48 :                 *op->resvalue = PointerGetDatum(xmlpi(xexpr->name,
    3762             :                                                       arg,
    3763             :                                                       isnull,
    3764             :                                                       op->resnull));
    3765             :             }
    3766          36 :             break;
    3767             : 
    3768             :         case IS_XMLROOT:
    3769             :             {
    3770          40 :                 Datum      *argvalue = op->d.xmlexpr.argvalue;
    3771          40 :                 bool       *argnull = op->d.xmlexpr.argnull;
    3772             :                 xmltype    *data;
    3773             :                 text       *version;
    3774             :                 int         standalone;
    3775             : 
    3776             :                 /* arguments are known to be xml, text, int */
    3777             :                 Assert(list_length(xexpr->args) == 3);
    3778             : 
    3779          40 :                 if (argnull[0])
    3780           0 :                     return;
    3781          40 :                 data = DatumGetXmlP(argvalue[0]);
    3782             : 
    3783          40 :                 if (argnull[1])
    3784          24 :                     version = NULL;
    3785             :                 else
    3786          16 :                     version = DatumGetTextPP(argvalue[1]);
    3787             : 
    3788             :                 Assert(!argnull[2]);    /* always present */
    3789          40 :                 standalone = DatumGetInt32(argvalue[2]);
    3790             : 
    3791          40 :                 *op->resvalue = PointerGetDatum(xmlroot(data,
    3792             :                                                         version,
    3793             :                                                         standalone));
    3794          40 :                 *op->resnull = false;
    3795             :             }
    3796          40 :             break;
    3797             : 
    3798             :         case IS_XMLSERIALIZE:
    3799             :             {
    3800          16 :                 Datum      *argvalue = op->d.xmlexpr.argvalue;
    3801          16 :                 bool       *argnull = op->d.xmlexpr.argnull;
    3802             : 
    3803             :                 /* argument type is known to be xml */
    3804             :                 Assert(list_length(xexpr->args) == 1);
    3805             : 
    3806          16 :                 if (argnull[0])
    3807           0 :                     return;
    3808          16 :                 value = argvalue[0];
    3809             : 
    3810          16 :                 *op->resvalue = PointerGetDatum(
    3811             :                                                 xmltotext_with_xmloption(DatumGetXmlP(value),
    3812             :                                                                          xexpr->xmloption));
    3813          12 :                 *op->resnull = false;
    3814             :             }
    3815          12 :             break;
    3816             : 
    3817             :         case IS_DOCUMENT:
    3818             :             {
    3819          16 :                 Datum      *argvalue = op->d.xmlexpr.argvalue;
    3820          16 :                 bool       *argnull = op->d.xmlexpr.argnull;
    3821             : 
    3822             :                 /* optional argument is known to be xml */
    3823             :                 Assert(list_length(xexpr->args) == 1);
    3824             : 
    3825          16 :                 if (argnull[0])
    3826           0 :                     return;
    3827          16 :                 value = argvalue[0];
    3828             : 
    3829          32 :                 *op->resvalue =
    3830          16 :                     BoolGetDatum(xml_is_document(DatumGetXmlP(value)));
    3831          16 :                 *op->resnull = false;
    3832             :             }
    3833          16 :             break;
    3834             : 
    3835             :         default:
    3836           0 :             elog(ERROR, "unrecognized XML operation");
    3837             :             break;
    3838             :     }
    3839             : }
    3840             : 
    3841             : /*
    3842             :  * ExecEvalGroupingFunc
    3843             :  *
    3844             :  * Computes a bitmask with a bit for each (unevaluated) argument expression
    3845             :  * (rightmost arg is least significant bit).
    3846             :  *
    3847             :  * A bit is set if the corresponding expression is NOT part of the set of
    3848             :  * grouping expressions in the current grouping set.
    3849             :  */
    3850             : void
    3851        1094 : ExecEvalGroupingFunc(ExprState *state, ExprEvalStep *op)
    3852             : {
    3853        1094 :     int         result = 0;
    3854        1094 :     Bitmapset  *grouped_cols = op->d.grouping_func.parent->grouped_cols;
    3855             :     ListCell   *lc;
    3856             : 
    3857        2738 :     foreach(lc, op->d.grouping_func.clauses)
    3858             :     {
    3859        1644 :         int         attnum = lfirst_int(lc);
    3860             : 
    3861        1644 :         result <<= 1;
    3862             : 
    3863        1644 :         if (!bms_is_member(attnum, grouped_cols))
    3864         640 :             result |= 1;
    3865             :     }
    3866             : 
    3867        1094 :     *op->resvalue = Int32GetDatum(result);
    3868        1094 :     *op->resnull = false;
    3869        1094 : }
    3870             : 
    3871             : /*
    3872             :  * Hand off evaluation of a subplan to nodeSubplan.c
    3873             :  */
    3874             : void
    3875     2290508 : ExecEvalSubPlan(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
    3876             : {
    3877     2290508 :     SubPlanState *sstate = op->d.subplan.sstate;
    3878             : 
    3879             :     /* could potentially be nested, so make sure there's enough stack */
    3880     2290508 :     check_stack_depth();
    3881             : 
    3882     2290508 :     *op->resvalue = ExecSubPlan(sstate, econtext, op->resnull);
    3883     2290504 : }
    3884             : 
    3885             : /*
    3886             :  * Hand off evaluation of an alternative subplan to nodeSubplan.c
    3887             :  */
    3888             : void
    3889      489886 : ExecEvalAlternativeSubPlan(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
    3890             : {
    3891      489886 :     AlternativeSubPlanState *asstate = op->d.alternative_subplan.asstate;
    3892             : 
    3893             :     /* could potentially be nested, so make sure there's enough stack */
    3894      489886 :     check_stack_depth();
    3895             : 
    3896      489886 :     *op->resvalue = ExecAlternativeSubPlan(asstate, econtext, op->resnull);
    3897      489886 : }
    3898             : 
    3899             : /*
    3900             :  * Evaluate a wholerow Var expression.
    3901             :  *
    3902             :  * Returns a Datum whose value is the value of a whole-row range variable
    3903             :  * with respect to given expression context.
    3904             :  */
    3905             : void
    3906       32488 : ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
    3907             : {
    3908       32488 :     Var        *variable = op->d.wholerow.var;
    3909             :     TupleTableSlot *slot;
    3910             :     TupleDesc   output_tupdesc;
    3911             :     MemoryContext oldcontext;
    3912             :     HeapTupleHeader dtuple;
    3913             :     HeapTuple   tuple;
    3914             : 
    3915             :     /* This was checked by ExecInitExpr */
    3916             :     Assert(variable->varattno == InvalidAttrNumber);
    3917             : 
    3918             :     /* Get the input slot we want */
    3919       32488 :     switch (variable->varno)
    3920             :     {
    3921             :         case INNER_VAR:
    3922             :             /* get the tuple from the inner node */
    3923          60 :             slot = econtext->ecxt_innertuple;
    3924          60 :             break;
    3925             : 
    3926             :         case OUTER_VAR:
    3927             :             /* get the tuple from the outer node */
    3928          12 :             slot = econtext->ecxt_outertuple;
    3929          12 :             break;
    3930             : 
    3931             :             /* INDEX_VAR is handled by default case */
    3932             : 
    3933             :         default:
    3934             :             /* get the tuple from the relation being scanned */
    3935       32416 :             slot = econtext->ecxt_scantuple;
    3936       32416 :             break;
    3937             :     }
    3938             : 
    3939             :     /* Apply the junkfilter if any */
    3940       32488 :     if (op->d.wholerow.junkFilter != NULL)
    3941          40 :         slot = ExecFilterJunk(op->d.wholerow.junkFilter, slot);
    3942             : 
    3943             :     /*
    3944             :      * If first time through, obtain tuple descriptor and check compatibility.
    3945             :      *
    3946             :      * XXX: It'd be great if this could be moved to the expression
    3947             :      * initialization phase, but due to using slots that's currently not
    3948             :      * feasible.
    3949             :      */
    3950       32488 :     if (op->d.wholerow.first)
    3951             :     {
    3952             :         /* optimistically assume we don't need slow path */
    3953        1424 :         op->d.wholerow.slow = false;
    3954             : 
    3955             :         /*
    3956             :          * If the Var identifies a named composite type, we must check that
    3957             :          * the actual tuple type is compatible with it.
    3958             :          */
    3959        1424 :         if (variable->vartype != RECORDOID)
    3960             :         {
    3961             :             TupleDesc   var_tupdesc;
    3962             :             TupleDesc   slot_tupdesc;
    3963             :             int         i;
    3964             : 
    3965             :             /*
    3966             :              * We really only care about numbers of attributes and data types.
    3967             :              * Also, we can ignore type mismatch on columns that are dropped
    3968             :              * in the destination type, so long as (1) the physical storage
    3969             :              * matches or (2) the actual column value is NULL.  Case (1) is
    3970             :              * helpful in some cases involving out-of-date cached plans, while
    3971             :              * case (2) is expected behavior in situations such as an INSERT
    3972             :              * into a table with dropped columns (the planner typically
    3973             :              * generates an INT4 NULL regardless of the dropped column type).
    3974             :              * If we find a dropped column and cannot verify that case (1)
    3975             :              * holds, we have to use the slow path to check (2) for each row.
    3976             :              *
    3977             :              * If vartype is a domain over composite, just look through that
    3978             :              * to the base composite type.
    3979             :              */
    3980         918 :             var_tupdesc = lookup_rowtype_tupdesc_domain(variable->vartype,
    3981             :                                                         -1, false);
    3982             : 
    3983         918 :             slot_tupdesc = slot->tts_tupleDescriptor;
    3984             : 
    3985         918 :             if (var_tupdesc->natts != slot_tupdesc->natts)
    3986           0 :                 ereport(ERROR,
    3987             :                         (errcode(ERRCODE_DATATYPE_MISMATCH),
    3988             :                          errmsg("table row type and query-specified row type do not match"),
    3989             :                          errdetail_plural("Table row contains %d attribute, but query expects %d.",
    3990             :                                           "Table row contains %d attributes, but query expects %d.",
    3991             :                                           slot_tupdesc->natts,
    3992             :                                           slot_tupdesc->natts,
    3993             :                                           var_tupdesc->natts)));
    3994             : 
    3995        3774 :             for (i = 0; i < var_tupdesc->natts; i++)
    3996             :             {
    3997        2856 :                 Form_pg_attribute vattr = TupleDescAttr(var_tupdesc, i);
    3998        2856 :                 Form_pg_attribute sattr = TupleDescAttr(slot_tupdesc, i);
    3999             : 
    4000        2856 :                 if (vattr->atttypid == sattr->atttypid)
    4001        2844 :                     continue;   /* no worries */
    4002          12 :                 if (!vattr->attisdropped)
    4003           0 :                     ereport(ERROR,
    4004             :                             (errcode(ERRCODE_DATATYPE_MISMATCH),
    4005             :                              errmsg("table row type and query-specified row type do not match"),
    4006             :                              errdetail("Table has type %s at ordinal position %d, but query expects %s.",
    4007             :                                        format_type_be(sattr->atttypid),
    4008             :                                        i + 1,
    4009             :                                        format_type_be(vattr->atttypid))));
    4010             : 
    4011          12 :                 if (vattr->attlen != sattr->attlen ||
    4012           0 :                     vattr->attalign != sattr->attalign)
    4013          12 :                     op->d.wholerow.slow = true; /* need to check for nulls */
    4014             :             }
    4015             : 
    4016             :             /*
    4017             :              * Use the variable's declared rowtype as the descriptor for the
    4018             :              * output values, modulo possibly assigning new column names
    4019             :              * below. In particular, we *must* absorb any attisdropped
    4020             :              * markings.
    4021             :              */
    4022         918 :             oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
    4023         918 :             output_tupdesc = CreateTupleDescCopy(var_tupdesc);
    4024         918 :             MemoryContextSwitchTo(oldcontext);
    4025             : 
    4026         918 :             ReleaseTupleDesc(var_tupdesc);
    4027             :         }
    4028             :         else
    4029             :         {
    4030             :             /*
    4031             :              * In the RECORD case, we use the input slot's rowtype as the
    4032             :              * descriptor for the output values, modulo possibly assigning new
    4033             :              * column names below.
    4034             :              */
    4035         506 :             oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
    4036         506 :             output_tupdesc = CreateTupleDescCopy(slot->tts_tupleDescriptor);
    4037         506 :             MemoryContextSwitchTo(oldcontext);
    4038             :         }
    4039             : 
    4040             :         /*
    4041             :          * Construct a tuple descriptor for the composite values we'll
    4042             :          * produce, and make sure its record type is "blessed".  The main
    4043             :          * reason to do this is to be sure that operations such as
    4044             :          * row_to_json() will see the desired column names when they look up
    4045             :          * the descriptor from the type information embedded in the composite
    4046             :          * values.
    4047             :          *
    4048             :          * We already got the correct physical datatype info above, but now we
    4049             :          * should try to find the source RTE and adopt its column aliases, in
    4050             :          * case they are different from the original rowtype's names.  For
    4051             :          * example, in "SELECT foo(t) FROM tab t(x,y)", the first two columns
    4052             :          * in the composite output should be named "x" and "y" regardless of
    4053             :          * tab's column names.
    4054             :          *
    4055             :          * If we can't locate the RTE, assume the column names we've got are
    4056             :          * OK.  (As of this writing, the only cases where we can't locate the
    4057             :          * RTE are in execution of trigger WHEN clauses, and then the Var will
    4058             :          * have the trigger's relation's rowtype, so its names are fine.)
    4059             :          * Also, if the creator of the RTE didn't bother to fill in an eref
    4060             :          * field, assume our column names are OK.  (This happens in COPY, and
    4061             :          * perhaps other places.)
    4062             :          */
    4063        2848 :         if (econtext->ecxt_estate &&
    4064        1424 :             variable->varno <= econtext->ecxt_estate->es_range_table_size)
    4065             :         {
    4066        1368 :             RangeTblEntry *rte = exec_rt_fetch(variable->varno,
    4067        1368 :                                                econtext->ecxt_estate);
    4068             : 
    4069        1368 :             if (rte->eref)
    4070        1368 :                 ExecTypeSetColNames(output_tupdesc, rte->eref->colnames);
    4071             :         }
    4072             : 
    4073             :         /* Bless the tupdesc if needed, and save it in the execution state */
    4074        1424 :         op->d.wholerow.tupdesc = BlessTupleDesc(output_tupdesc);
    4075             : 
    4076        1424 :         op->d.wholerow.first = false;
    4077             :     }
    4078             : 
    4079             :     /*
    4080             :      * Make sure all columns of the slot are accessible in the slot's
    4081             :      * Datum/isnull arrays.
    4082             :      */
    4083       32488 :     slot_getallattrs(slot);
    4084             : 
    4085       32488 :     if (op->d.wholerow.slow)
    4086             :     {
    4087             :         /* Check to see if any dropped attributes are non-null */
    4088          20 :         TupleDesc   tupleDesc = slot->tts_tupleDescriptor;
    4089          20 :         TupleDesc   var_tupdesc = op->d.wholerow.tupdesc;
    4090             :         int         i;
    4091             : 
    4092             :         Assert(var_tupdesc->natts == tupleDesc->natts);
    4093             : 
    4094         100 :         for (i = 0; i < var_tupdesc->natts; i++)
    4095             :         {
    4096          80 :             Form_pg_attribute vattr = TupleDescAttr(var_tupdesc, i);
    4097          80 :             Form_pg_attribute sattr = TupleDescAttr(tupleDesc, i);
    4098             : 
    4099          80 :             if (!vattr->attisdropped)
    4100          60 :                 continue;       /* already checked non-dropped cols */
    4101          20 :             if (slot->tts_isnull[i])
    4102          20 :                 continue;       /* null is always okay */
    4103           0 :             if (vattr->attlen != sattr->attlen ||
    4104           0 :                 vattr->attalign != sattr->attalign)
    4105           0 :                 ereport(ERROR,
    4106             :                         (errcode(ERRCODE_DATATYPE_MISMATCH),
    4107             :                          errmsg("table row type and query-specified row type do not match"),
    4108             :                          errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
    4109             :                                    i + 1)));
    4110             :         }
    4111             :     }
    4112             : 
    4113             :     /*
    4114             :      * Build a composite datum, making sure any toasted fields get detoasted.
    4115             :      *
    4116             :      * (Note: it is critical that we not change the slot's state here.)
    4117             :      */
    4118       32488 :     tuple = toast_build_flattened_tuple(slot->tts_tupleDescriptor,
    4119             :                                         slot->tts_values,
    4120             :                                         slot->tts_isnull);
    4121       32488 :     dtuple = tuple->t_data;
    4122             : 
    4123             :     /*
    4124             :      * Label the datum with the composite type info we identified before.
    4125             :      *
    4126             :      * (Note: we could skip doing this by passing op->d.wholerow.tupdesc to
    4127             :      * the tuple build step; but that seems a tad risky so let's not.)
    4128             :      */
    4129       32488 :     HeapTupleHeaderSetTypeId(dtuple, op->d.wholerow.tupdesc->tdtypeid);
    4130       32488 :     HeapTupleHeaderSetTypMod(dtuple, op->d.wholerow.tupdesc->tdtypmod);
    4131             : 
    4132       32488 :     *op->resvalue = PointerGetDatum(dtuple);
    4133       32488 :     *op->resnull = false;
    4134       32488 : }
    4135             : 
    4136             : void
    4137     4999950 : ExecEvalSysVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
    4138             :                TupleTableSlot *slot)
    4139             : {
    4140             :     Datum       d;
    4141             : 
    4142             :     /* slot_getsysattr has sufficient defenses against bad attnums */
    4143     4999950 :     d = slot_getsysattr(slot,
    4144             :                         op->d.var.attnum,
    4145             :                         op->resnull);
    4146     4999950 :     *op->resvalue = d;
    4147             :     /* this ought to be unreachable, but it's cheap enough to check */
    4148     4999950 :     if (unlikely(*op->resnull))
    4149           0 :         elog(ERROR, "failed to fetch attribute from slot");
    4150     4999950 : }
    4151             : 
    4152             : /*
    4153             :  * Transition value has not been initialized. This is the first non-NULL input
    4154             :  * value for a group. We use it as the initial value for transValue.
    4155             :  */
    4156             : void
    4157        5912 : ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup)
    4158             : {
    4159        5912 :     FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
    4160             :     MemoryContext oldContext;
    4161             : 
    4162             :     /*
    4163             :      * We must copy the datum into aggcontext if it is pass-by-ref. We do not
    4164             :      * need to pfree the old transValue, since it's NULL.  (We already checked
    4165             :      * that the agg's input type is binary-compatible with its transtype, so
    4166             :      * straight copy here is OK.)
    4167             :      */
    4168        5912 :     oldContext = MemoryContextSwitchTo(
    4169        5912 :                                        aggstate->curaggcontext->ecxt_per_tuple_memory);
    4170       11824 :     pergroup->transValue = datumCopy(fcinfo->args[1].value,
    4171        5912 :                                      pertrans->transtypeByVal,
    4172        5912 :                                      pertrans->transtypeLen);
    4173        5912 :     pergroup->transValueIsNull = false;
    4174        5912 :     pergroup->noTransValue = false;
    4175        5912 :     MemoryContextSwitchTo(oldContext);
    4176        5912 : }
    4177             : 
    4178             : /*
    4179             :  * Ensure that the current transition value is a child of the aggcontext,
    4180             :  * rather than the per-tuple context.
    4181             :  *
    4182             :  * NB: This can change the current memory context.
    4183             :  */
    4184             : Datum
    4185       26308 : ExecAggTransReparent(AggState *aggstate, AggStatePerTrans pertrans,
    4186             :                      Datum newValue, bool newValueIsNull,
    4187             :                      Datum oldValue, bool oldValueIsNull)
    4188             : {
    4189       26308 :     if (!newValueIsNull)
    4190             :     {
    4191       26308 :         MemoryContextSwitchTo(aggstate->curaggcontext->ecxt_per_tuple_memory);
    4192       26408 :         if (DatumIsReadWriteExpandedObject(newValue,
    4193             :                                            false,
    4194       26408 :                                            pertrans->transtypeLen) &&
    4195         100 :             MemoryContextGetParent(DatumGetEOHP(newValue)->eoh_context) == CurrentMemoryContext)
    4196             :              /* do nothing */ ;
    4197             :         else
    4198       52600 :             newValue = datumCopy(newValue,
    4199       26300 :                                  pertrans->transtypeByVal,
    4200       26300 :                                  pertrans->transtypeLen);
    4201             :     }
    4202       26308 :     if (!oldValueIsNull)
    4203             :     {
    4204       26256 :         if (DatumIsReadWriteExpandedObject(oldValue,
    4205             :                                            false,
    4206             :                                            pertrans->transtypeLen))
    4207           0 :             DeleteExpandedObject(oldValue);
    4208             :         else
    4209       26256 :             pfree(DatumGetPointer(oldValue));
    4210             :     }
    4211             : 
    4212       26308 :     return newValue;
    4213             : }
    4214             : 
    4215             : /*
    4216             :  * Invoke ordered transition function, with a datum argument.
    4217             :  */
    4218             : void
    4219      809608 : ExecEvalAggOrderedTransDatum(ExprState *state, ExprEvalStep *op,
    4220             :                              ExprContext *econtext)
    4221             : {
    4222      809608 :     AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
    4223      809608 :     int         setno = op->d.agg_trans.setno;
    4224             : 
    4225     1619216 :     tuplesort_putdatum(pertrans->sortstates[setno],
    4226     1619216 :                        *op->resvalue, *op->resnull);
    4227      809608 : }
    4228             : 
    4229             : /*
    4230             :  * Invoke ordered transition function, with a tuple argument.
    4231             :  */
    4232             : void
    4233       15092 : ExecEvalAggOrderedTransTuple(ExprState *state, ExprEvalStep *op,
    4234             :                              ExprContext *econtext)
    4235             : {
    4236       15092 :     AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
    4237       15092 :     int         setno = op->d.agg_trans.setno;
    4238             : 
    4239       15092 :     ExecClearTuple(pertrans->sortslot);
    4240       15092 :     pertrans->sortslot->tts_nvalid = pertrans->numInputs;
    4241       15092 :     ExecStoreVirtualTuple(pertrans->sortslot);
    4242       15092 :     tuplesort_puttupleslot(pertrans->sortstates[setno], pertrans->sortslot);
    4243       15092 : }

Generated by: LCOV version 1.13