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

Generated by: LCOV version 1.13