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

Generated by: LCOV version 1.13