LCOV - differential code coverage report
Current view: top level - src/backend/executor - execUtils.c (source / functions) Coverage Total Hit UNC UBC GBC GNC CBC DUB DCB
Current: bed3ffbf9d952be6c7d739d068cdce44c046dfb7 vs 574581b50ac9c63dd9e4abebb731a3b67e5b50f6 Lines: 91.8 % 450 413 1 36 7 9 397 1 2
Current Date: 2026-05-05 10:23:31 +0900 Functions: 95.7 % 46 44 1 1 1 4 39
Baseline: lcov-20260505-025707-baseline Branches: 72.5 % 200 145 55 6 4 135
Baseline Date: 2026-05-05 10:27:06 +0900 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 90.0 % 10 9 1 9
(360..) days: 91.8 % 440 404 36 7 397
Function coverage date bins:
(30,360] days: 100.0 % 1 1 1
(360..) days: 95.6 % 45 43 1 1 1 3 39
Branch coverage date bins:
(30,360] days: 100.0 % 4 4 4
(360..) days: 71.9 % 196 141 55 6 135

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * execUtils.c
                                  4                 :                :  *    miscellaneous executor utility routines
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *
                                 10                 :                :  * IDENTIFICATION
                                 11                 :                :  *    src/backend/executor/execUtils.c
                                 12                 :                :  *
                                 13                 :                :  *-------------------------------------------------------------------------
                                 14                 :                :  */
                                 15                 :                : /*
                                 16                 :                :  * INTERFACE ROUTINES
                                 17                 :                :  *      CreateExecutorState     Create/delete executor working state
                                 18                 :                :  *      FreeExecutorState
                                 19                 :                :  *      CreateExprContext
                                 20                 :                :  *      CreateStandaloneExprContext
                                 21                 :                :  *      FreeExprContext
                                 22                 :                :  *      ReScanExprContext
                                 23                 :                :  *
                                 24                 :                :  *      ExecAssignExprContext   Common code for plan node init routines.
                                 25                 :                :  *      etc
                                 26                 :                :  *
                                 27                 :                :  *      ExecOpenScanRelation    Common code for scan node init routines.
                                 28                 :                :  *
                                 29                 :                :  *      ExecInitRangeTable      Set up executor's range-table-related data.
                                 30                 :                :  *
                                 31                 :                :  *      ExecGetRangeTableRelation       Fetch Relation for a rangetable entry.
                                 32                 :                :  *
                                 33                 :                :  *      executor_errposition    Report syntactic position of an error.
                                 34                 :                :  *
                                 35                 :                :  *      RegisterExprContextCallback    Register function shutdown callback
                                 36                 :                :  *      UnregisterExprContextCallback  Deregister function shutdown callback
                                 37                 :                :  *
                                 38                 :                :  *      GetAttributeByName      Runtime extraction of columns from tuples.
                                 39                 :                :  *      GetAttributeByNum
                                 40                 :                :  *
                                 41                 :                :  *   NOTES
                                 42                 :                :  *      This file has traditionally been the place to stick misc.
                                 43                 :                :  *      executor support stuff that doesn't really go anyplace else.
                                 44                 :                :  */
                                 45                 :                : 
                                 46                 :                : #include "postgres.h"
                                 47                 :                : 
                                 48                 :                : #include "access/parallel.h"
                                 49                 :                : #include "access/table.h"
                                 50                 :                : #include "access/tableam.h"
                                 51                 :                : #include "access/tupconvert.h"
                                 52                 :                : #include "executor/executor.h"
                                 53                 :                : #include "executor/nodeModifyTable.h"
                                 54                 :                : #include "jit/jit.h"
                                 55                 :                : #include "mb/pg_wchar.h"
                                 56                 :                : #include "miscadmin.h"
                                 57                 :                : #include "parser/parse_relation.h"
                                 58                 :                : #include "partitioning/partdesc.h"
                                 59                 :                : #include "port/pg_bitutils.h"
                                 60                 :                : #include "storage/lmgr.h"
                                 61                 :                : #include "utils/builtins.h"
                                 62                 :                : #include "utils/memutils.h"
                                 63                 :                : #include "utils/rel.h"
                                 64                 :                : #include "utils/typcache.h"
                                 65                 :                : 
                                 66                 :                : 
                                 67                 :                : static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc);
                                 68                 :                : static void ShutdownExprContext(ExprContext *econtext, bool isCommit);
                                 69                 :                : static RTEPermissionInfo *GetResultRTEPermissionInfo(ResultRelInfo *relinfo, EState *estate);
                                 70                 :                : 
                                 71                 :                : 
                                 72                 :                : /* ----------------------------------------------------------------
                                 73                 :                :  *               Executor state and memory management functions
                                 74                 :                :  * ----------------------------------------------------------------
                                 75                 :                :  */
                                 76                 :                : 
                                 77                 :                : /* ----------------
                                 78                 :                :  *      CreateExecutorState
                                 79                 :                :  *
                                 80                 :                :  *      Create and initialize an EState node, which is the root of
                                 81                 :                :  *      working storage for an entire Executor invocation.
                                 82                 :                :  *
                                 83                 :                :  * Principally, this creates the per-query memory context that will be
                                 84                 :                :  * used to hold all working data that lives till the end of the query.
                                 85                 :                :  * Note that the per-query context will become a child of the caller's
                                 86                 :                :  * CurrentMemoryContext.
                                 87                 :                :  * ----------------
                                 88                 :                :  */
                                 89                 :                : EState *
 8542 tgl@sss.pgh.pa.us          90                 :CBC      772138 : CreateExecutorState(void)
                                 91                 :                : {
                                 92                 :                :     EState     *estate;
                                 93                 :                :     MemoryContext qcontext;
                                 94                 :                :     MemoryContext oldcontext;
                                 95                 :                : 
                                 96                 :                :     /*
                                 97                 :                :      * Create the per-query context for this Executor run.
                                 98                 :                :      */
                                 99                 :         772138 :     qcontext = AllocSetContextCreate(CurrentMemoryContext,
                                100                 :                :                                      "ExecutorState",
                                101                 :                :                                      ALLOCSET_DEFAULT_SIZES);
                                102                 :                : 
                                103                 :                :     /*
                                104                 :                :      * Make the EState node within the per-query context.  This way, we don't
                                105                 :                :      * need a separate pfree() operation for it at shutdown.
                                106                 :                :      */
                                107                 :         772138 :     oldcontext = MemoryContextSwitchTo(qcontext);
                                108                 :                : 
                                109                 :         772138 :     estate = makeNode(EState);
                                110                 :                : 
                                111                 :                :     /*
                                112                 :                :      * Initialize all fields of the Executor State structure
                                113                 :                :      */
                                114                 :         772138 :     estate->es_direction = ForwardScanDirection;
 3240                           115                 :         772138 :     estate->es_snapshot = InvalidSnapshot;   /* caller must initialize this */
 7906                           116                 :         772138 :     estate->es_crosscheck_snapshot = InvalidSnapshot;    /* no crosscheck */
 8542                           117                 :         772138 :     estate->es_range_table = NIL;
 2770                           118                 :         772138 :     estate->es_range_table_size = 0;
                                119                 :         772138 :     estate->es_relations = NULL;
 2766                           120                 :         772138 :     estate->es_rowmarks = NULL;
 1156                           121                 :         772138 :     estate->es_rteperminfos = NIL;
 6035                           122                 :         772138 :     estate->es_plannedstmt = NULL;
  460 amitlan@postgresql.o      123                 :         772138 :     estate->es_part_prune_infos = NIL;
   51 melanieplageman@gmai      124                 :GNC      772138 :     estate->es_part_prune_states = NIL;
                                125                 :         772138 :     estate->es_part_prune_results = NIL;
                                126                 :         772138 :     estate->es_unpruned_relids = NULL;
                                127                 :                : 
 6049 tgl@sss.pgh.pa.us         128                 :CBC      772138 :     estate->es_junkFilter = NULL;
                                129                 :                : 
 6731                           130                 :         772138 :     estate->es_output_cid = (CommandId) 0;
                                131                 :                : 
 8542                           132                 :         772138 :     estate->es_result_relations = NULL;
 2030 heikki.linnakangas@i      133                 :         772138 :     estate->es_opened_result_relations = NIL;
 3008 rhaas@postgresql.org      134                 :         772138 :     estate->es_tuple_routing_result_relations = NIL;
 6838 tgl@sss.pgh.pa.us         135                 :         772138 :     estate->es_trig_target_relations = NIL;
                                136                 :                : 
 1244 efujita@postgresql.o      137                 :         772138 :     estate->es_insert_pending_result_relations = NIL;
                                138                 :         772138 :     estate->es_insert_pending_modifytables = NIL;
                                139                 :                : 
 8542 tgl@sss.pgh.pa.us         140                 :         772138 :     estate->es_param_list_info = NULL;
                                141                 :         772138 :     estate->es_param_exec_vals = NULL;
                                142                 :                : 
 3322 kgrittn@postgresql.o      143                 :         772138 :     estate->es_queryEnv = NULL;
                                144                 :                : 
 8542 tgl@sss.pgh.pa.us         145                 :         772138 :     estate->es_query_cxt = qcontext;
                                146                 :                : 
 6064                           147                 :         772138 :     estate->es_tupleTable = NIL;
                                148                 :                : 
 8542                           149                 :         772138 :     estate->es_processed = 0;
 1125 michael@paquier.xyz       150                 :         772138 :     estate->es_total_processed = 0;
                                151                 :                : 
 5546 tgl@sss.pgh.pa.us         152                 :         772138 :     estate->es_top_eflags = 0;
                                153                 :         772138 :     estate->es_instrument = 0;
                                154                 :         772138 :     estate->es_finished = false;
                                155                 :                : 
 8542                           156                 :         772138 :     estate->es_exprcontexts = NIL;
                                157                 :                : 
 7007                           158                 :         772138 :     estate->es_subplanstates = NIL;
                                159                 :                : 
 5548                           160                 :         772138 :     estate->es_auxmodifytables = NIL;
                                161                 :                : 
 8542                           162                 :         772138 :     estate->es_per_tuple_exprcontext = NULL;
                                163                 :                : 
 3359 rhaas@postgresql.org      164                 :         772138 :     estate->es_sourceText = NULL;
                                165                 :                : 
 3112                           166                 :         772138 :     estate->es_use_parallel_mode = false;
  573 michael@paquier.xyz       167                 :         772138 :     estate->es_parallel_workers_to_launch = 0;
                                168                 :         772138 :     estate->es_parallel_workers_launched = 0;
                                169                 :                : 
 2966 andres@anarazel.de        170                 :         772138 :     estate->es_jit_flags = 0;
                                171                 :         772138 :     estate->es_jit = NULL;
                                172                 :                : 
                                173                 :                :     /*
                                174                 :                :      * Return the executor state structure
                                175                 :                :      */
 8542 tgl@sss.pgh.pa.us         176                 :         772138 :     MemoryContextSwitchTo(oldcontext);
                                177                 :                : 
                                178                 :         772138 :     return estate;
                                179                 :                : }
                                180                 :                : 
                                181                 :                : /* ----------------
                                182                 :                :  *      FreeExecutorState
                                183                 :                :  *
                                184                 :                :  *      Release an EState along with all remaining working storage.
                                185                 :                :  *
                                186                 :                :  * Note: this is not responsible for releasing non-memory resources, such as
                                187                 :                :  * open relations or buffer pins.  But it will shut down any still-active
                                188                 :                :  * ExprContexts within the EState and deallocate associated JITed expressions.
                                189                 :                :  * That is sufficient cleanup for situations where the EState has only been
                                190                 :                :  * used for expression evaluation, and not to run a complete Plan.
                                191                 :                :  *
                                192                 :                :  * This can be called in any memory context ... so long as it's not one
                                193                 :                :  * of the ones to be freed.
                                194                 :                :  * ----------------
                                195                 :                :  */
                                196                 :                : void
                                197                 :         748624 : FreeExecutorState(EState *estate)
                                198                 :                : {
                                199                 :                :     /*
                                200                 :                :      * Shut down and free any remaining ExprContexts.  We do this explicitly
                                201                 :                :      * to ensure that any remaining shutdown callbacks get called (since they
                                202                 :                :      * might need to release resources that aren't simply memory within the
                                203                 :                :      * per-query memory context).
                                204                 :                :      */
                                205         [ +  + ]:        2041295 :     while (estate->es_exprcontexts)
                                206                 :                :     {
                                207                 :                :         /*
                                208                 :                :          * XXX: seems there ought to be a faster way to implement this than
                                209                 :                :          * repeated list_delete(), no?
                                210                 :                :          */
 6135                           211                 :        1292671 :         FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts),
                                212                 :                :                         true);
                                213                 :                :         /* FreeExprContext removed the list link for us */
                                214                 :                :     }
                                215                 :                : 
                                216                 :                :     /* release JIT context, if allocated */
 2841 andres@anarazel.de        217         [ -  + ]:         748624 :     if (estate->es_jit)
                                218                 :                :     {
 2841 andres@anarazel.de        219                 :UBC           0 :         jit_release_context(estate->es_jit);
                                220                 :              0 :         estate->es_jit = NULL;
                                221                 :                :     }
                                222                 :                : 
                                223                 :                :     /* release partition directory, if allocated */
 2616 rhaas@postgresql.org      224         [ +  + ]:CBC      748624 :     if (estate->es_partition_directory)
                                225                 :                :     {
                                226                 :           3596 :         DestroyPartitionDirectory(estate->es_partition_directory);
                                227                 :           3596 :         estate->es_partition_directory = NULL;
                                228                 :                :     }
                                229                 :                : 
                                230                 :                :     /*
                                231                 :                :      * Free the per-query memory context, thereby releasing all working
                                232                 :                :      * memory, including the EState node itself.
                                233                 :                :      */
 7007 tgl@sss.pgh.pa.us         234                 :         748624 :     MemoryContextDelete(estate->es_query_cxt);
10892 scrappy@hub.org           235                 :         748624 : }
                                236                 :                : 
                                237                 :                : /*
                                238                 :                :  * Internal implementation for CreateExprContext() and CreateWorkExprContext()
                                239                 :                :  * that allows control over the AllocSet parameters.
                                240                 :                :  */
                                241                 :                : static ExprContext *
 2219 jdavis@postgresql.or      242                 :        1386861 : CreateExprContextInternal(EState *estate, Size minContextSize,
                                243                 :                :                           Size initBlockSize, Size maxBlockSize)
                                244                 :                : {
                                245                 :                :     ExprContext *econtext;
                                246                 :                :     MemoryContext oldcontext;
                                247                 :                : 
                                248                 :                :     /* Create the ExprContext node within the per-query memory context */
 8542 tgl@sss.pgh.pa.us         249                 :        1386861 :     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
                                250                 :                : 
                                251                 :        1386861 :     econtext = makeNode(ExprContext);
                                252                 :                : 
                                253                 :                :     /* Initialize fields of ExprContext */
                                254                 :        1386861 :     econtext->ecxt_scantuple = NULL;
 9428                           255                 :        1386861 :     econtext->ecxt_innertuple = NULL;
                                256                 :        1386861 :     econtext->ecxt_outertuple = NULL;
                                257                 :                : 
 8542                           258                 :        1386861 :     econtext->ecxt_per_query_memory = estate->es_query_cxt;
                                259                 :                : 
                                260                 :                :     /*
                                261                 :                :      * Create working memory for expression evaluation in this context.
                                262                 :                :      */
 9428                           263                 :        1386861 :     econtext->ecxt_per_tuple_memory =
 8542                           264                 :        1386861 :         AllocSetContextCreate(estate->es_query_cxt,
                                265                 :                :                               "ExprContext",
                                266                 :                :                               minContextSize,
                                267                 :                :                               initBlockSize,
                                268                 :                :                               maxBlockSize);
                                269                 :                : 
                                270                 :        1386861 :     econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
                                271                 :        1386861 :     econtext->ecxt_param_list_info = estate->es_param_list_info;
                                272                 :                : 
 9428                           273                 :        1386861 :     econtext->ecxt_aggvalues = NULL;
                                274                 :        1386861 :     econtext->ecxt_aggnulls = NULL;
                                275                 :                : 
 8084                           276                 :        1386861 :     econtext->caseValue_datum = (Datum) 0;
                                277                 :        1386861 :     econtext->caseValue_isNull = true;
                                278                 :                : 
 8542                           279                 :        1386861 :     econtext->domainValue_datum = (Datum) 0;
                                280                 :        1386861 :     econtext->domainValue_isNull = true;
                                281                 :                : 
                                282                 :        1386861 :     econtext->ecxt_estate = estate;
                                283                 :                : 
 8759                           284                 :        1386861 :     econtext->ecxt_callbacks = NULL;
                                285                 :                : 
                                286                 :                :     /*
                                287                 :                :      * Link the ExprContext into the EState to ensure it is shut down when the
                                288                 :                :      * EState is freed.  Because we use lcons(), shutdowns will occur in
                                289                 :                :      * reverse order of creation, which may not be essential but can't hurt.
                                290                 :                :      */
 8542                           291                 :        1386861 :     estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);
                                292                 :                : 
                                293                 :        1386861 :     MemoryContextSwitchTo(oldcontext);
                                294                 :                : 
 9428                           295                 :        1386861 :     return econtext;
                                296                 :                : }
                                297                 :                : 
                                298                 :                : /* ----------------
                                299                 :                :  *      CreateExprContext
                                300                 :                :  *
                                301                 :                :  *      Create a context for expression evaluation within an EState.
                                302                 :                :  *
                                303                 :                :  * An executor run may require multiple ExprContexts (we usually make one
                                304                 :                :  * for each Plan node, and a separate one for per-output-tuple processing
                                305                 :                :  * such as constraint checking).  Each ExprContext has its own "per-tuple"
                                306                 :                :  * memory context.
                                307                 :                :  *
                                308                 :                :  * Note we make no assumption about the caller's memory context.
                                309                 :                :  * ----------------
                                310                 :                :  */
                                311                 :                : ExprContext *
 2219 jdavis@postgresql.or      312                 :        1382000 : CreateExprContext(EState *estate)
                                313                 :                : {
                                314                 :        1382000 :     return CreateExprContextInternal(estate, ALLOCSET_DEFAULT_SIZES);
                                315                 :                : }
                                316                 :                : 
                                317                 :                : 
                                318                 :                : /* ----------------
                                319                 :                :  *      CreateWorkExprContext
                                320                 :                :  *
                                321                 :                :  * Like CreateExprContext, but specifies the AllocSet sizes to be reasonable
                                322                 :                :  * in proportion to work_mem. If the maximum block allocation size is too
                                323                 :                :  * large, it's easy to skip right past work_mem with a single allocation.
                                324                 :                :  * ----------------
                                325                 :                :  */
                                326                 :                : ExprContext *
                                327                 :           4861 : CreateWorkExprContext(EState *estate)
                                328                 :                : {
                                329                 :                :     Size        maxBlockSize;
                                330                 :                : 
  407                           331                 :           4861 :     maxBlockSize = pg_prevpower2_size_t(work_mem * (Size) 1024 / 16);
                                332                 :                : 
                                333                 :                :     /* But no bigger than ALLOCSET_DEFAULT_MAXSIZE */
                                334                 :           4861 :     maxBlockSize = Min(maxBlockSize, ALLOCSET_DEFAULT_MAXSIZE);
                                335                 :                : 
                                336                 :                :     /* and no smaller than ALLOCSET_DEFAULT_INITSIZE */
                                337                 :           4861 :     maxBlockSize = Max(maxBlockSize, ALLOCSET_DEFAULT_INITSIZE);
                                338                 :                : 
                                339                 :           4861 :     return CreateExprContextInternal(estate, ALLOCSET_DEFAULT_MINSIZE,
                                340                 :                :                                      ALLOCSET_DEFAULT_INITSIZE, maxBlockSize);
                                341                 :                : }
                                342                 :                : 
                                343                 :                : /* ----------------
                                344                 :                :  *      CreateStandaloneExprContext
                                345                 :                :  *
                                346                 :                :  *      Create a context for standalone expression evaluation.
                                347                 :                :  *
                                348                 :                :  * An ExprContext made this way can be used for evaluation of expressions
                                349                 :                :  * that contain no Params, subplans, or Var references (it might work to
                                350                 :                :  * put tuple references into the scantuple field, but it seems unwise).
                                351                 :                :  *
                                352                 :                :  * The ExprContext struct is allocated in the caller's current memory
                                353                 :                :  * context, which also becomes its "per query" context.
                                354                 :                :  *
                                355                 :                :  * It is caller's responsibility to free the ExprContext when done,
                                356                 :                :  * or at least ensure that any shutdown callbacks have been called
                                357                 :                :  * (ReScanExprContext() is suitable).  Otherwise, non-memory resources
                                358                 :                :  * might be leaked.
                                359                 :                :  * ----------------
                                360                 :                :  */
                                361                 :                : ExprContext *
 7214 tgl@sss.pgh.pa.us         362                 :           6769 : CreateStandaloneExprContext(void)
                                363                 :                : {
                                364                 :                :     ExprContext *econtext;
                                365                 :                : 
                                366                 :                :     /* Create the ExprContext node within the caller's memory context */
                                367                 :           6769 :     econtext = makeNode(ExprContext);
                                368                 :                : 
                                369                 :                :     /* Initialize fields of ExprContext */
                                370                 :           6769 :     econtext->ecxt_scantuple = NULL;
                                371                 :           6769 :     econtext->ecxt_innertuple = NULL;
                                372                 :           6769 :     econtext->ecxt_outertuple = NULL;
                                373                 :                : 
                                374                 :           6769 :     econtext->ecxt_per_query_memory = CurrentMemoryContext;
                                375                 :                : 
                                376                 :                :     /*
                                377                 :                :      * Create working memory for expression evaluation in this context.
                                378                 :                :      */
                                379                 :           6769 :     econtext->ecxt_per_tuple_memory =
                                380                 :           6769 :         AllocSetContextCreate(CurrentMemoryContext,
                                381                 :                :                               "ExprContext",
                                382                 :                :                               ALLOCSET_DEFAULT_SIZES);
                                383                 :                : 
                                384                 :           6769 :     econtext->ecxt_param_exec_vals = NULL;
                                385                 :           6769 :     econtext->ecxt_param_list_info = NULL;
                                386                 :                : 
                                387                 :           6769 :     econtext->ecxt_aggvalues = NULL;
                                388                 :           6769 :     econtext->ecxt_aggnulls = NULL;
                                389                 :                : 
                                390                 :           6769 :     econtext->caseValue_datum = (Datum) 0;
                                391                 :           6769 :     econtext->caseValue_isNull = true;
                                392                 :                : 
                                393                 :           6769 :     econtext->domainValue_datum = (Datum) 0;
                                394                 :           6769 :     econtext->domainValue_isNull = true;
                                395                 :                : 
                                396                 :           6769 :     econtext->ecxt_estate = NULL;
                                397                 :                : 
                                398                 :           6769 :     econtext->ecxt_callbacks = NULL;
                                399                 :                : 
                                400                 :           6769 :     return econtext;
                                401                 :                : }
                                402                 :                : 
                                403                 :                : /* ----------------
                                404                 :                :  *      FreeExprContext
                                405                 :                :  *
                                406                 :                :  *      Free an expression context, including calling any remaining
                                407                 :                :  *      shutdown callbacks.
                                408                 :                :  *
                                409                 :                :  * Since we free the temporary context used for expression evaluation,
                                410                 :                :  * any previously computed pass-by-reference expression result will go away!
                                411                 :                :  *
                                412                 :                :  * If isCommit is false, we are being called in error cleanup, and should
                                413                 :                :  * not call callbacks but only release memory.  (It might be better to call
                                414                 :                :  * the callbacks and pass the isCommit flag to them, but that would require
                                415                 :                :  * more invasive code changes than currently seems justified.)
                                416                 :                :  *
                                417                 :                :  * Note we make no assumption about the caller's memory context.
                                418                 :                :  * ----------------
                                419                 :                :  */
                                420                 :                : void
 6135                           421                 :        1358603 : FreeExprContext(ExprContext *econtext, bool isCommit)
                                422                 :                : {
                                423                 :                :     EState     *estate;
                                424                 :                : 
                                425                 :                :     /* Call any registered callbacks */
                                426                 :        1358603 :     ShutdownExprContext(econtext, isCommit);
                                427                 :                :     /* And clean up the memory used */
 9428                           428                 :        1358603 :     MemoryContextDelete(econtext->ecxt_per_tuple_memory);
                                429                 :                :     /* Unlink self from owning EState, if any */
 8542                           430                 :        1358603 :     estate = econtext->ecxt_estate;
 7214                           431         [ +  - ]:        1358603 :     if (estate)
                                432                 :        1358603 :         estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts,
                                433                 :                :                                                   econtext);
                                434                 :                :     /* And delete the ExprContext node */
 9428                           435                 :        1358603 :     pfree(econtext);
10892 scrappy@hub.org           436                 :        1358603 : }
                                437                 :                : 
                                438                 :                : /*
                                439                 :                :  * ReScanExprContext
                                440                 :                :  *
                                441                 :                :  *      Reset an expression context in preparation for a rescan of its
                                442                 :                :  *      plan node.  This requires calling any registered shutdown callbacks,
                                443                 :                :  *      since any partially complete set-returning-functions must be canceled.
                                444                 :                :  *
                                445                 :                :  * Note we make no assumption about the caller's memory context.
                                446                 :                :  */
                                447                 :                : void
 8174 tgl@sss.pgh.pa.us         448                 :        2887313 : ReScanExprContext(ExprContext *econtext)
                                449                 :                : {
                                450                 :                :     /* Call any registered callbacks */
 6135                           451                 :        2887313 :     ShutdownExprContext(econtext, true);
                                452                 :                :     /* And clean up the memory used */
 8174                           453                 :        2887313 :     MemoryContextReset(econtext->ecxt_per_tuple_memory);
                                454                 :        2887313 : }
                                455                 :                : 
                                456                 :                : /*
                                457                 :                :  * Build a per-output-tuple ExprContext for an EState.
                                458                 :                :  *
                                459                 :                :  * This is normally invoked via GetPerTupleExprContext() macro,
                                460                 :                :  * not directly.
                                461                 :                :  */
                                462                 :                : ExprContext *
 9234                           463                 :         427627 : MakePerTupleExprContext(EState *estate)
                                464                 :                : {
                                465         [ +  - ]:         427627 :     if (estate->es_per_tuple_exprcontext == NULL)
 8542                           466                 :         427627 :         estate->es_per_tuple_exprcontext = CreateExprContext(estate);
                                467                 :                : 
 9234                           468                 :         427627 :     return estate->es_per_tuple_exprcontext;
                                469                 :                : }
                                470                 :                : 
                                471                 :                : 
                                472                 :                : /* ----------------------------------------------------------------
                                473                 :                :  *               miscellaneous node-init support functions
                                474                 :                :  *
                                475                 :                :  * Note: all of these are expected to be called with CurrentMemoryContext
                                476                 :                :  * equal to the per-query memory context.
                                477                 :                :  * ----------------------------------------------------------------
                                478                 :                :  */
                                479                 :                : 
                                480                 :                : /* ----------------
                                481                 :                :  *      ExecAssignExprContext
                                482                 :                :  *
                                483                 :                :  *      This initializes the ps_ExprContext field.  It is only necessary
                                484                 :                :  *      to do this for nodes which use ExecQual or ExecProject
                                485                 :                :  *      because those routines require an econtext. Other nodes that
                                486                 :                :  *      don't have to evaluate expressions don't need to do this.
                                487                 :                :  * ----------------
                                488                 :                :  */
                                489                 :                : void
 8306 bruce@momjian.us          490                 :         874260 : ExecAssignExprContext(EState *estate, PlanState *planstate)
                                491                 :                : {
 8542 tgl@sss.pgh.pa.us         492                 :         874260 :     planstate->ps_ExprContext = CreateExprContext(estate);
                                493                 :         874260 : }
                                494                 :                : 
                                495                 :                : /* ----------------
                                496                 :                :  *      ExecGetResultType
                                497                 :                :  * ----------------
                                498                 :                :  */
                                499                 :                : TupleDesc
 8306 bruce@momjian.us          500                 :        1084885 : ExecGetResultType(PlanState *planstate)
                                501                 :                : {
 2734 andres@anarazel.de        502                 :        1084885 :     return planstate->ps_ResultTupleDesc;
                                503                 :                : }
                                504                 :                : 
                                505                 :                : /*
                                506                 :                :  * ExecGetResultSlotOps - information about node's type of result slot
                                507                 :                :  */
                                508                 :                : const TupleTableSlotOps *
 2728                           509                 :         501870 : ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
                                510                 :                : {
                                511   [ +  -  +  + ]:         501870 :     if (planstate->resultopsset && planstate->resultops)
                                512                 :                :     {
                                513         [ +  + ]:         500732 :         if (isfixed)
                                514                 :         453452 :             *isfixed = planstate->resultopsfixed;
                                515                 :         500732 :         return planstate->resultops;
                                516                 :                :     }
                                517                 :                : 
                                518         [ +  + ]:           1138 :     if (isfixed)
                                519                 :                :     {
                                520         [ +  - ]:           1116 :         if (planstate->resultopsset)
                                521                 :           1116 :             *isfixed = planstate->resultopsfixed;
 2728 andres@anarazel.de        522         [ #  # ]:UBC           0 :         else if (planstate->ps_ResultTupleSlot)
                                523                 :              0 :             *isfixed = TTS_FIXED(planstate->ps_ResultTupleSlot);
                                524                 :                :         else
                                525                 :              0 :             *isfixed = false;
                                526                 :                :     }
                                527                 :                : 
 2728 andres@anarazel.de        528         [ +  - ]:CBC        1138 :     if (!planstate->ps_ResultTupleSlot)
                                529                 :           1138 :         return &TTSOpsVirtual;
                                530                 :                : 
 2728 andres@anarazel.de        531                 :UBC           0 :     return planstate->ps_ResultTupleSlot->tts_ops;
                                532                 :                : }
                                533                 :                : 
                                534                 :                : /*
                                535                 :                :  * ExecGetCommonSlotOps - identify common result slot type, if any
                                536                 :                :  *
                                537                 :                :  * If all the given PlanState nodes return the same fixed tuple slot type,
                                538                 :                :  * return the slot ops struct for that slot type.  Else, return NULL.
                                539                 :                :  */
                                540                 :                : const TupleTableSlotOps *
  502 tgl@sss.pgh.pa.us         541                 :CBC       13569 : ExecGetCommonSlotOps(PlanState **planstates, int nplans)
                                542                 :                : {
                                543                 :                :     const TupleTableSlotOps *result;
                                544                 :                :     bool        isfixed;
                                545                 :                : 
                                546         [ +  + ]:          13569 :     if (nplans <= 0)
                                547                 :             68 :         return NULL;
                                548                 :          13501 :     result = ExecGetResultSlotOps(planstates[0], &isfixed);
                                549         [ +  + ]:          13501 :     if (!isfixed)
                                550                 :             60 :         return NULL;
                                551         [ +  + ]:          40521 :     for (int i = 1; i < nplans; i++)
                                552                 :                :     {
                                553                 :                :         const TupleTableSlotOps *thisops;
                                554                 :                : 
                                555                 :          27733 :         thisops = ExecGetResultSlotOps(planstates[i], &isfixed);
                                556         [ +  + ]:          27733 :         if (!isfixed)
                                557                 :             27 :             return NULL;
                                558         [ +  + ]:          27706 :         if (result != thisops)
                                559                 :            626 :             return NULL;
                                560                 :                :     }
                                561                 :          12788 :     return result;
                                562                 :                : }
                                563                 :                : 
                                564                 :                : /*
                                565                 :                :  * ExecGetCommonChildSlotOps - as above, for the PlanState's standard children
                                566                 :                :  */
                                567                 :                : const TupleTableSlotOps *
                                568                 :            583 : ExecGetCommonChildSlotOps(PlanState *ps)
                                569                 :                : {
                                570                 :                :     PlanState  *planstates[2];
                                571                 :                : 
                                572                 :            583 :     planstates[0] = outerPlanState(ps);
                                573                 :            583 :     planstates[1] = innerPlanState(ps);
                                574                 :            583 :     return ExecGetCommonSlotOps(planstates, 2);
                                575                 :                : }
                                576                 :                : 
                                577                 :                : 
                                578                 :                : /* ----------------
                                579                 :                :  *      ExecAssignProjectionInfo
                                580                 :                :  *
                                581                 :                :  * forms the projection information from the node's targetlist
                                582                 :                :  *
                                583                 :                :  * Notes for inputDesc are same as for ExecBuildProjectionInfo: supply it
                                584                 :                :  * for a relation-scan node, can pass NULL for upper-level nodes
                                585                 :                :  * ----------------
                                586                 :                :  */
                                587                 :                : void
 7032                           588                 :         486381 : ExecAssignProjectionInfo(PlanState *planstate,
                                589                 :                :                          TupleDesc inputDesc)
                                590                 :                : {
 8514                           591                 :         486341 :     planstate->ps_ProjInfo =
 3339 andres@anarazel.de        592                 :         486381 :         ExecBuildProjectionInfo(planstate->plan->targetlist,
                                593                 :                :                                 planstate->ps_ExprContext,
                                594                 :                :                                 planstate->ps_ResultTupleSlot,
                                595                 :                :                                 planstate,
                                596                 :                :                                 inputDesc);
10892 scrappy@hub.org           597                 :         486341 : }
                                598                 :                : 
                                599                 :                : 
                                600                 :                : /* ----------------
                                601                 :                :  *      ExecConditionalAssignProjectionInfo
                                602                 :                :  *
                                603                 :                :  * as ExecAssignProjectionInfo, but store NULL rather than building projection
                                604                 :                :  * info if no projection is required
                                605                 :                :  * ----------------
                                606                 :                :  */
                                607                 :                : void
 3083 rhaas@postgresql.org      608                 :         376440 : ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc,
                                609                 :                :                                     int varno)
                                610                 :                : {
                                611         [ +  + ]:         376440 :     if (tlist_matches_tupdesc(planstate,
                                612                 :         376440 :                               planstate->plan->targetlist,
                                613                 :                :                               varno,
                                614                 :                :                               inputDesc))
                                615                 :                :     {
                                616                 :         196267 :         planstate->ps_ProjInfo = NULL;
 2728 andres@anarazel.de        617                 :         196267 :         planstate->resultopsset = planstate->scanopsset;
                                618                 :         196267 :         planstate->resultopsfixed = planstate->scanopsfixed;
                                619                 :         196267 :         planstate->resultops = planstate->scanops;
                                620                 :                :     }
                                621                 :                :     else
                                622                 :                :     {
 2734                           623         [ +  - ]:         180173 :         if (!planstate->ps_ResultTupleSlot)
                                624                 :                :         {
 2728                           625                 :         180173 :             ExecInitResultSlot(planstate, &TTSOpsVirtual);
                                626                 :         180173 :             planstate->resultops = &TTSOpsVirtual;
                                627                 :         180173 :             planstate->resultopsfixed = true;
                                628                 :         180173 :             planstate->resultopsset = true;
                                629                 :                :         }
 3083 rhaas@postgresql.org      630                 :         180173 :         ExecAssignProjectionInfo(planstate, inputDesc);
                                631                 :                :     }
                                632                 :         376440 : }
                                633                 :                : 
                                634                 :                : static bool
 1693 tgl@sss.pgh.pa.us         635                 :         376440 : tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc)
                                636                 :                : {
 3083 rhaas@postgresql.org      637                 :         376440 :     int         numattrs = tupdesc->natts;
                                638                 :                :     int         attrno;
                                639                 :         376440 :     ListCell   *tlist_item = list_head(tlist);
                                640                 :                : 
                                641                 :                :     /* Check the tlist attributes */
                                642         [ +  + ]:        2527958 :     for (attrno = 1; attrno <= numattrs; attrno++)
                                643                 :                :     {
                                644                 :        2323825 :         Form_pg_attribute att_tup = TupleDescAttr(tupdesc, attrno - 1);
                                645                 :                :         Var        *var;
                                646                 :                : 
                                647         [ +  + ]:        2323825 :         if (tlist_item == NULL)
                                648                 :          23704 :             return false;       /* tlist too short */
                                649                 :        2300121 :         var = (Var *) ((TargetEntry *) lfirst(tlist_item))->expr;
                                650   [ +  -  +  + ]:        2300121 :         if (!var || !IsA(var, Var))
                                651                 :          44776 :             return false;       /* tlist item not a Var */
                                652                 :                :         /* if these Asserts fail, planner messed up */
                                653         [ -  + ]:        2255345 :         Assert(var->varno == varno);
                                654         [ -  + ]:        2255345 :         Assert(var->varlevelsup == 0);
                                655         [ +  + ]:        2255345 :         if (var->varattno != attrno)
                                656                 :         103609 :             return false;       /* out of order */
                                657         [ -  + ]:        2151736 :         if (att_tup->attisdropped)
 3083 rhaas@postgresql.org      658                 :UBC           0 :             return false;       /* table contains dropped columns */
 2960 andrew@dunslane.net       659         [ +  + ]:CBC     2151736 :         if (att_tup->atthasmissing)
                                660                 :            214 :             return false;       /* table contains cols with missing values */
                                661                 :                : 
                                662                 :                :         /*
                                663                 :                :          * Note: usually the Var's type should match the tupdesc exactly, but
                                664                 :                :          * in situations involving unions of columns that have different
                                665                 :                :          * typmods, the Var may have come from above the union and hence have
                                666                 :                :          * typmod -1.  This is a legitimate situation since the Var still
                                667                 :                :          * describes the column, just not as exactly as the tupdesc does. We
                                668                 :                :          * could change the planner to prevent it, but it'd then insert
                                669                 :                :          * projection steps just to convert from specific typmod to typmod -1,
                                670                 :                :          * which is pretty silly.
                                671                 :                :          */
 3083 rhaas@postgresql.org      672         [ +  + ]:        2151522 :         if (var->vartype != att_tup->atttypid ||
                                673         [ +  + ]:        2151518 :             (var->vartypmod != att_tup->atttypmod &&
                                674         [ -  + ]:              4 :              var->vartypmod != -1))
                                675                 :              4 :             return false;       /* type mismatch */
                                676                 :                : 
 2486 tgl@sss.pgh.pa.us         677                 :        2151518 :         tlist_item = lnext(tlist, tlist_item);
                                678                 :                :     }
                                679                 :                : 
 3083 rhaas@postgresql.org      680         [ +  + ]:         204133 :     if (tlist_item)
                                681                 :           7866 :         return false;           /* tlist too long */
                                682                 :                : 
                                683                 :         196267 :     return true;
                                684                 :                : }
                                685                 :                : 
                                686                 :                : 
                                687                 :                : /* ----------------------------------------------------------------
                                688                 :                :  *                Scan node support
                                689                 :                :  * ----------------------------------------------------------------
                                690                 :                :  */
                                691                 :                : 
                                692                 :                : /* ----------------
                                693                 :                :  *      ExecAssignScanType
                                694                 :                :  * ----------------
                                695                 :                :  */
                                696                 :                : void
 7263 tgl@sss.pgh.pa.us         697                 :            581 : ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
                                698                 :                : {
 8552                           699                 :            581 :     TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
                                700                 :                : 
 7263                           701                 :            581 :     ExecSetSlotDescriptor(slot, tupDesc);
10892 scrappy@hub.org           702                 :            581 : }
                                703                 :                : 
                                704                 :                : /* ----------------
                                705                 :                :  *      ExecCreateScanSlotFromOuterPlan
                                706                 :                :  * ----------------
                                707                 :                :  */
                                708                 :                : void
 2728 andres@anarazel.de        709                 :          97415 : ExecCreateScanSlotFromOuterPlan(EState *estate,
                                710                 :                :                                 ScanState *scanstate,
                                711                 :                :                                 const TupleTableSlotOps *tts_ops)
                                712                 :                : {
                                713                 :                :     PlanState  *outerPlan;
                                714                 :                :     TupleDesc   tupDesc;
                                715                 :                : 
 8552 tgl@sss.pgh.pa.us         716                 :          97415 :     outerPlan = outerPlanState(scanstate);
 8401                           717                 :          97415 :     tupDesc = ExecGetResultType(outerPlan);
                                718                 :                : 
   50 drowley@postgresql.o      719                 :GNC       97415 :     ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops, 0);
10892 scrappy@hub.org           720                 :CBC       97415 : }
                                721                 :                : 
                                722                 :                : /* ----------------------------------------------------------------
                                723                 :                :  *      ExecRelationIsTargetRelation
                                724                 :                :  *
                                725                 :                :  *      Detect whether a relation (identified by rangetable index)
                                726                 :                :  *      is one of the target relations of the query.
                                727                 :                :  *
                                728                 :                :  * Note: This is currently no longer used in core.  We keep it around
                                729                 :                :  * because FDWs may wish to use it to determine if their foreign table
                                730                 :                :  * is a target relation.
                                731                 :                :  * ----------------------------------------------------------------
                                732                 :                :  */
                                733                 :                : bool
 7458 tgl@sss.pgh.pa.us         734                 :UBC           0 : ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
                                735                 :                : {
   36 melanieplageman@gmai      736                 :UNC           0 :     return bms_is_member(scanrelid, estate->es_plannedstmt->resultRelationRelids);
                                737                 :                : }
                                738                 :                : 
                                739                 :                : /*
                                740                 :                :  * Return true if the scan node's relation is not modified by the query.
                                741                 :                :  *
                                742                 :                :  * This is not perfectly accurate. INSERT ... SELECT from the same table does
                                743                 :                :  * not add the scan relation to resultRelationRelids, so it will be reported
                                744                 :                :  * as read-only even though the query modifies it.
                                745                 :                :  *
                                746                 :                :  * Conversely, when any relation in the query has a modifying row mark, all
                                747                 :                :  * other relations get a ROW_MARK_REFERENCE, causing them to be reported as
                                748                 :                :  * not read-only even though they may be.
                                749                 :                :  */
                                750                 :                : bool
   36 melanieplageman@gmai      751                 :GNC      237758 : ScanRelIsReadOnly(ScanState *ss)
                                752                 :                : {
                                753                 :         237758 :     Index       scanrelid = ((Scan *) ss->ps.plan)->scanrelid;
                                754                 :         237758 :     PlannedStmt *pstmt = ss->ps.state->es_plannedstmt;
                                755                 :                : 
                                756         [ +  + ]:         456795 :     return !bms_is_member(scanrelid, pstmt->resultRelationRelids) &&
                                757         [ +  + ]:         219037 :         !bms_is_member(scanrelid, pstmt->rowMarkRelids);
                                758                 :                : }
                                759                 :                : 
                                760                 :                : /* ----------------------------------------------------------------
                                761                 :                :  *      ExecOpenScanRelation
                                762                 :                :  *
                                763                 :                :  *      Open the heap relation to be scanned by a base-level scan plan node.
                                764                 :                :  *      This should be called during the node's ExecInit routine.
                                765                 :                :  * ----------------------------------------------------------------
                                766                 :                :  */
                                767                 :                : Relation
 4756 tgl@sss.pgh.pa.us         768                 :CBC      305510 : ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
                                769                 :                : {
                                770                 :                :     Relation    rel;
                                771                 :                : 
                                772                 :                :     /* Open the relation. */
  412 amitlan@postgresql.o      773                 :         305510 :     rel = ExecGetRangeTableRelation(estate, scanrelid, false);
                                774                 :                : 
                                775                 :                :     /*
                                776                 :                :      * Complain if we're attempting a scan of an unscannable relation, except
                                777                 :                :      * when the query won't actually be run.  This is a slightly klugy place
                                778                 :                :      * to do this, perhaps, but there is no better place.
                                779                 :                :      */
 4756 tgl@sss.pgh.pa.us         780         [ +  + ]:         305510 :     if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
                                781         [ +  + ]:         282570 :         !RelationIsScannable(rel))
                                782         [ +  - ]:              8 :         ereport(ERROR,
                                783                 :                :                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                                784                 :                :                  errmsg("materialized view \"%s\" has not been populated",
                                785                 :                :                         RelationGetRelationName(rel)),
                                786                 :                :                  errhint("Use the REFRESH MATERIALIZED VIEW command.")));
                                787                 :                : 
                                788                 :         305502 :     return rel;
                                789                 :                : }
                                790                 :                : 
                                791                 :                : /*
                                792                 :                :  * ExecInitRangeTable
                                793                 :                :  *      Set up executor's range-table-related data
                                794                 :                :  *
                                795                 :                :  * In addition to the range table proper, initialize arrays that are
                                796                 :                :  * indexed by rangetable index.
                                797                 :                :  */
                                798                 :                : void
  452 amitlan@postgresql.o      799                 :         530402 : ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos,
                                800                 :                :                    Bitmapset *unpruned_relids)
                                801                 :                : {
                                802                 :                :     /* Remember the range table List as-is */
 2770 tgl@sss.pgh.pa.us         803                 :         530402 :     estate->es_range_table = rangeTable;
                                804                 :                : 
                                805                 :                :     /* ... and the RTEPermissionInfo List too */
 1156                           806                 :         530402 :     estate->es_rteperminfos = permInfos;
                                807                 :                : 
                                808                 :                :     /* Set size of associated arrays */
 2770                           809                 :         530402 :     estate->es_range_table_size = list_length(rangeTable);
                                810                 :                : 
                                811                 :                :     /*
                                812                 :                :      * Initialize the bitmapset of RT indexes (es_unpruned_relids)
                                813                 :                :      * representing relations that will be scanned during execution. This set
                                814                 :                :      * is initially populated by the caller and may be extended later by
                                815                 :                :      * ExecDoInitialPruning() to include RT indexes of unpruned leaf
                                816                 :                :      * partitions.
                                817                 :                :      */
  452 amitlan@postgresql.o      818                 :         530402 :     estate->es_unpruned_relids = unpruned_relids;
                                819                 :                : 
                                820                 :                :     /*
                                821                 :                :      * Allocate an array to store an open Relation corresponding to each
                                822                 :                :      * rangetable entry, and initialize entries to NULL.  Relations are opened
                                823                 :                :      * and stored here as needed.
                                824                 :                :      */
 2770 tgl@sss.pgh.pa.us         825                 :         530402 :     estate->es_relations = (Relation *)
                                826                 :         530402 :         palloc0(estate->es_range_table_size * sizeof(Relation));
                                827                 :                : 
                                828                 :                :     /*
                                829                 :                :      * es_result_relations and es_rowmarks are also parallel to
                                830                 :                :      * es_range_table, but are allocated only if needed.
                                831                 :                :      */
 2030 heikki.linnakangas@i      832                 :         530402 :     estate->es_result_relations = NULL;
 2766 tgl@sss.pgh.pa.us         833                 :         530402 :     estate->es_rowmarks = NULL;
 2770                           834                 :         530402 : }
                                835                 :                : 
                                836                 :                : /*
                                837                 :                :  * ExecGetRangeTableRelation
                                838                 :                :  *      Open the Relation for a range table entry, if not already done
                                839                 :                :  *
                                840                 :                :  * The Relations will be closed in ExecEndPlan().
                                841                 :                :  *
                                842                 :                :  * If isResultRel is true, the relation is being used as a result relation.
                                843                 :                :  * Such a relation might have been pruned, which is OK for result relations,
                                844                 :                :  * but not for scan relations; see the details in ExecInitModifyTable(). If
                                845                 :                :  * isResultRel is false, the caller must ensure that 'rti' refers to an
                                846                 :                :  * unpruned relation (i.e., it is a member of estate->es_unpruned_relids)
                                847                 :                :  * before calling this function. Attempting to open a pruned relation for
                                848                 :                :  * scanning will result in an error.
                                849                 :                :  */
                                850                 :                : Relation
  412 amitlan@postgresql.o      851                 :         391727 : ExecGetRangeTableRelation(EState *estate, Index rti, bool isResultRel)
                                852                 :                : {
                                853                 :                :     Relation    rel;
                                854                 :                : 
 2770 tgl@sss.pgh.pa.us         855   [ +  -  -  + ]:         391727 :     Assert(rti > 0 && rti <= estate->es_range_table_size);
                                856                 :                : 
  412 amitlan@postgresql.o      857   [ +  +  -  + ]:         391727 :     if (!isResultRel && !bms_is_member(rti, estate->es_unpruned_relids))
  439 amitlan@postgresql.o      858         [ #  # ]:UBC           0 :         elog(ERROR, "trying to open a pruned relation");
                                859                 :                : 
 2770 tgl@sss.pgh.pa.us         860                 :CBC      391727 :     rel = estate->es_relations[rti - 1];
                                861         [ +  + ]:         391727 :     if (rel == NULL)
                                862                 :                :     {
                                863                 :                :         /* First time through, so open the relation */
                                864                 :         363679 :         RangeTblEntry *rte = exec_rt_fetch(rti, estate);
                                865                 :                : 
                                866         [ -  + ]:         363679 :         Assert(rte->rtekind == RTE_RELATION);
                                867                 :                : 
 2768                           868         [ +  + ]:         363679 :         if (!IsParallelWorker())
                                869                 :                :         {
                                870                 :                :             /*
                                871                 :                :              * In a normal query, we should already have the appropriate lock,
                                872                 :                :              * but verify that through an Assert.  Since there's already an
                                873                 :                :              * Assert inside table_open that insists on holding some lock, it
                                874                 :                :              * seems sufficient to check this only when rellockmode is higher
                                875                 :                :              * than the minimum.
                                876                 :                :              */
 2661 andres@anarazel.de        877                 :         358829 :             rel = table_open(rte->relid, NoLock);
 2768 tgl@sss.pgh.pa.us         878   [ +  +  -  + ]:         358829 :             Assert(rte->rellockmode == AccessShareLock ||
                                879                 :                :                    CheckRelationLockedByMe(rel, rte->rellockmode, false));
                                880                 :                :         }
                                881                 :                :         else
                                882                 :                :         {
                                883                 :                :             /*
                                884                 :                :              * If we are a parallel worker, we need to obtain our own local
                                885                 :                :              * lock on the relation.  This ensures sane behavior in case the
                                886                 :                :              * parent process exits before we do.
                                887                 :                :              */
 2661 andres@anarazel.de        888                 :           4850 :             rel = table_open(rte->relid, rte->rellockmode);
                                889                 :                :         }
                                890                 :                : 
 2768 tgl@sss.pgh.pa.us         891                 :         363679 :         estate->es_relations[rti - 1] = rel;
                                892                 :                :     }
                                893                 :                : 
 2770                           894                 :         391727 :     return rel;
                                895                 :                : }
                                896                 :                : 
                                897                 :                : /*
                                898                 :                :  * ExecInitResultRelation
                                899                 :                :  *      Open relation given by the passed-in RT index and fill its
                                900                 :                :  *      ResultRelInfo node
                                901                 :                :  *
                                902                 :                :  * Here, we also save the ResultRelInfo in estate->es_result_relations array
                                903                 :                :  * such that it can be accessed later using the RT index.
                                904                 :                :  */
                                905                 :                : void
 2030 heikki.linnakangas@i      906                 :          77337 : ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo,
                                907                 :                :                        Index rti)
                                908                 :                : {
                                909                 :                :     Relation    resultRelationDesc;
                                910                 :                : 
  412 amitlan@postgresql.o      911                 :          77337 :     resultRelationDesc = ExecGetRangeTableRelation(estate, rti, true);
 2030 heikki.linnakangas@i      912                 :          77337 :     InitResultRelInfo(resultRelInfo,
                                913                 :                :                       resultRelationDesc,
                                914                 :                :                       rti,
                                915                 :                :                       NULL,
                                916                 :                :                       estate->es_instrument);
                                917                 :                : 
                                918         [ +  + ]:          77337 :     if (estate->es_result_relations == NULL)
                                919                 :          73702 :         estate->es_result_relations = (ResultRelInfo **)
                                920                 :          73702 :             palloc0(estate->es_range_table_size * sizeof(ResultRelInfo *));
                                921                 :          77337 :     estate->es_result_relations[rti - 1] = resultRelInfo;
                                922                 :                : 
                                923                 :                :     /*
                                924                 :                :      * Saving in the list allows to avoid needlessly traversing the whole
                                925                 :                :      * array when only a few of its entries are possibly non-NULL.
                                926                 :                :      */
                                927                 :          77337 :     estate->es_opened_result_relations =
                                928                 :          77337 :         lappend(estate->es_opened_result_relations, resultRelInfo);
                                929                 :          77337 : }
                                930                 :                : 
                                931                 :                : /*
                                932                 :                :  * UpdateChangedParamSet
                                933                 :                :  *      Add changed parameters to a plan node's chgParam set
                                934                 :                :  */
                                935                 :                : void
 8306 bruce@momjian.us          936                 :         762983 : UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
                                937                 :                : {
                                938                 :                :     Bitmapset  *parmset;
                                939                 :                : 
                                940                 :                :     /*
                                941                 :                :      * The plan node only depends on params listed in its allParam set. Don't
                                942                 :                :      * include anything else into its chgParam set.
                                943                 :                :      */
 8486 tgl@sss.pgh.pa.us         944                 :         762983 :     parmset = bms_intersect(node->plan->allParam, newchg);
 1160                           945                 :         762983 :     node->chgParam = bms_join(node->chgParam, parmset);
10308 vadim4o@yahoo.com         946                 :         762983 : }
                                947                 :                : 
                                948                 :                : /*
                                949                 :                :  * executor_errposition
                                950                 :                :  *      Report an execution-time cursor position, if possible.
                                951                 :                :  *
                                952                 :                :  * This is expected to be used within an ereport() call.  The return value
                                953                 :                :  * is a dummy (always 0, in fact).
                                954                 :                :  *
                                955                 :                :  * The locations stored in parsetrees are byte offsets into the source string.
                                956                 :                :  * We have to convert them to 1-based character indexes for reporting to
                                957                 :                :  * clients.  (We do things this way to avoid unnecessary overhead in the
                                958                 :                :  * normal non-error case: computing character indexes would be much more
                                959                 :                :  * expensive than storing token offsets.)
                                960                 :                :  */
                                961                 :                : int
 3304 tgl@sss.pgh.pa.us         962                 :GBC          16 : executor_errposition(EState *estate, int location)
                                963                 :                : {
                                964                 :                :     int         pos;
                                965                 :                : 
                                966                 :                :     /* No-op if location was not provided */
                                967         [ -  + ]:             16 :     if (location < 0)
 2232 tgl@sss.pgh.pa.us         968                 :UBC           0 :         return 0;
                                969                 :                :     /* Can't do anything if source text is not available */
 3304 tgl@sss.pgh.pa.us         970   [ +  -  -  + ]:GBC          16 :     if (estate == NULL || estate->es_sourceText == NULL)
 2232 tgl@sss.pgh.pa.us         971                 :UBC           0 :         return 0;
                                972                 :                :     /* Convert offset to character number */
 3304 tgl@sss.pgh.pa.us         973                 :GBC          16 :     pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1;
                                974                 :                :     /* And pass it to the ereport mechanism */
 2232                           975                 :             16 :     return errposition(pos);
                                976                 :                : }
                                977                 :                : 
                                978                 :                : /*
                                979                 :                :  * Register a shutdown callback in an ExprContext.
                                980                 :                :  *
                                981                 :                :  * Shutdown callbacks will be called (in reverse order of registration)
                                982                 :                :  * when the ExprContext is deleted or rescanned.  This provides a hook
                                983                 :                :  * for functions called in the context to do any cleanup needed --- it's
                                984                 :                :  * particularly useful for functions returning sets.  Note that the
                                985                 :                :  * callback will *not* be called in the event that execution is aborted
                                986                 :                :  * by an error.
                                987                 :                :  */
                                988                 :                : void
 8759 tgl@sss.pgh.pa.us         989                 :CBC      190738 : RegisterExprContextCallback(ExprContext *econtext,
                                990                 :                :                             ExprContextCallbackFunction function,
                                991                 :                :                             Datum arg)
                                992                 :                : {
                                993                 :                :     ExprContext_CB *ecxt_callback;
                                994                 :                : 
                                995                 :                :     /* Save the info in appropriate memory context */
                                996                 :                :     ecxt_callback = (ExprContext_CB *)
                                997                 :         190738 :         MemoryContextAlloc(econtext->ecxt_per_query_memory,
                                998                 :                :                            sizeof(ExprContext_CB));
                                999                 :                : 
                               1000                 :         190738 :     ecxt_callback->function = function;
                               1001                 :         190738 :     ecxt_callback->arg = arg;
                               1002                 :                : 
                               1003                 :                :     /* link to front of list for appropriate execution order */
                               1004                 :         190738 :     ecxt_callback->next = econtext->ecxt_callbacks;
                               1005                 :         190738 :     econtext->ecxt_callbacks = ecxt_callback;
                               1006                 :         190738 : }
                               1007                 :                : 
                               1008                 :                : /*
                               1009                 :                :  * Deregister a shutdown callback in an ExprContext.
                               1010                 :                :  *
                               1011                 :                :  * Any list entries matching the function and arg will be removed.
                               1012                 :                :  * This can be used if it's no longer necessary to call the callback.
                               1013                 :                :  */
                               1014                 :                : void
                               1015                 :         175532 : UnregisterExprContextCallback(ExprContext *econtext,
                               1016                 :                :                               ExprContextCallbackFunction function,
                               1017                 :                :                               Datum arg)
                               1018                 :                : {
                               1019                 :                :     ExprContext_CB **prev_callback;
                               1020                 :                :     ExprContext_CB *ecxt_callback;
                               1021                 :                : 
                               1022                 :         175532 :     prev_callback = &econtext->ecxt_callbacks;
                               1023                 :                : 
                               1024         [ +  + ]:         504029 :     while ((ecxt_callback = *prev_callback) != NULL)
                               1025                 :                :     {
                               1026   [ +  +  +  + ]:         328497 :         if (ecxt_callback->function == function && ecxt_callback->arg == arg)
                               1027                 :                :         {
                               1028                 :         175532 :             *prev_callback = ecxt_callback->next;
                               1029                 :         175532 :             pfree(ecxt_callback);
                               1030                 :                :         }
                               1031                 :                :         else
                               1032                 :         152965 :             prev_callback = &ecxt_callback->next;
                               1033                 :                :     }
                               1034                 :         175532 : }
                               1035                 :                : 
                               1036                 :                : /*
                               1037                 :                :  * Call all the shutdown callbacks registered in an ExprContext.
                               1038                 :                :  *
                               1039                 :                :  * The callback list is emptied (important in case this is only a rescan
                               1040                 :                :  * reset, and not deletion of the ExprContext).
                               1041                 :                :  *
                               1042                 :                :  * If isCommit is false, just clean the callback list but don't call 'em.
                               1043                 :                :  * (See comment for FreeExprContext.)
                               1044                 :                :  */
                               1045                 :                : static void
 6135                          1046                 :        4245916 : ShutdownExprContext(ExprContext *econtext, bool isCommit)
                               1047                 :                : {
                               1048                 :                :     ExprContext_CB *ecxt_callback;
                               1049                 :                :     MemoryContext oldcontext;
                               1050                 :                : 
                               1051                 :                :     /* Fast path in normal case where there's nothing to do. */
 8542                          1052         [ +  + ]:        4245916 :     if (econtext->ecxt_callbacks == NULL)
                               1053                 :        4232365 :         return;
                               1054                 :                : 
                               1055                 :                :     /*
                               1056                 :                :      * Call the callbacks in econtext's per-tuple context.  This ensures that
                               1057                 :                :      * any memory they might leak will get cleaned up.
                               1058                 :                :      */
                               1059                 :          13551 :     oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
                               1060                 :                : 
                               1061                 :                :     /*
                               1062                 :                :      * Call each callback function in reverse registration order.
                               1063                 :                :      */
 8759                          1064         [ +  + ]:          27481 :     while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
                               1065                 :                :     {
                               1066                 :          13930 :         econtext->ecxt_callbacks = ecxt_callback->next;
 6135                          1067         [ +  - ]:          13930 :         if (isCommit)
 3162 peter_e@gmx.net          1068                 :          13930 :             ecxt_callback->function(ecxt_callback->arg);
 8759 tgl@sss.pgh.pa.us        1069                 :          13930 :         pfree(ecxt_callback);
                               1070                 :                :     }
                               1071                 :                : 
 8542                          1072                 :          13551 :     MemoryContextSwitchTo(oldcontext);
                               1073                 :                : }
                               1074                 :                : 
                               1075                 :                : /*
                               1076                 :                :  *      GetAttributeByName
                               1077                 :                :  *      GetAttributeByNum
                               1078                 :                :  *
                               1079                 :                :  *      These functions return the value of the requested attribute
                               1080                 :                :  *      out of the given tuple Datum.
                               1081                 :                :  *      C functions which take a tuple as an argument are expected
                               1082                 :                :  *      to use these.  Ex: overpaid(EMP) might call GetAttributeByNum().
                               1083                 :                :  *      Note: these are actually rather slow because they do a typcache
                               1084                 :                :  *      lookup on each call.
                               1085                 :                :  */
                               1086                 :                : Datum
 3339 andres@anarazel.de       1087                 :             24 : GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
                               1088                 :                : {
                               1089                 :                :     AttrNumber  attrno;
                               1090                 :                :     Datum       result;
                               1091                 :                :     Oid         tupType;
                               1092                 :                :     int32       tupTypmod;
                               1093                 :                :     TupleDesc   tupDesc;
                               1094                 :                :     HeapTupleData tmptup;
                               1095                 :                :     int         i;
                               1096                 :                : 
                               1097         [ -  + ]:             24 :     if (attname == NULL)
 3339 andres@anarazel.de       1098         [ #  # ]:UBC           0 :         elog(ERROR, "invalid attribute name");
                               1099                 :                : 
 3339 andres@anarazel.de       1100         [ -  + ]:CBC          24 :     if (isNull == NULL)
 3339 andres@anarazel.de       1101         [ #  # ]:UBC           0 :         elog(ERROR, "a NULL isNull pointer was passed");
                               1102                 :                : 
 3339 andres@anarazel.de       1103         [ -  + ]:CBC          24 :     if (tuple == NULL)
                               1104                 :                :     {
                               1105                 :                :         /* Kinda bogus but compatible with old behavior... */
 3339 andres@anarazel.de       1106                 :UBC           0 :         *isNull = true;
                               1107                 :              0 :         return (Datum) 0;
                               1108                 :                :     }
                               1109                 :                : 
 3339 andres@anarazel.de       1110                 :CBC          24 :     tupType = HeapTupleHeaderGetTypeId(tuple);
                               1111                 :             24 :     tupTypmod = HeapTupleHeaderGetTypMod(tuple);
                               1112                 :             24 :     tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
                               1113                 :                : 
                               1114                 :             24 :     attrno = InvalidAttrNumber;
                               1115         [ +  - ]:             96 :     for (i = 0; i < tupDesc->natts; i++)
                               1116                 :                :     {
 3180                          1117                 :             96 :         Form_pg_attribute att = TupleDescAttr(tupDesc, i);
                               1118                 :                : 
                               1119         [ +  + ]:             96 :         if (namestrcmp(&(att->attname), attname) == 0)
                               1120                 :                :         {
                               1121                 :             24 :             attrno = att->attnum;
 3339                          1122                 :             24 :             break;
                               1123                 :                :         }
                               1124                 :                :     }
                               1125                 :                : 
                               1126         [ -  + ]:             24 :     if (attrno == InvalidAttrNumber)
 3339 andres@anarazel.de       1127         [ #  # ]:UBC           0 :         elog(ERROR, "attribute \"%s\" does not exist", attname);
                               1128                 :                : 
                               1129                 :                :     /*
                               1130                 :                :      * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
                               1131                 :                :      * the fields in the struct just in case user tries to inspect system
                               1132                 :                :      * columns.
                               1133                 :                :      */
 3339 andres@anarazel.de       1134                 :CBC          24 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
                               1135                 :             24 :     ItemPointerSetInvalid(&(tmptup.t_self));
                               1136                 :             24 :     tmptup.t_tableOid = InvalidOid;
                               1137                 :             24 :     tmptup.t_data = tuple;
                               1138                 :                : 
                               1139                 :             24 :     result = heap_getattr(&tmptup,
                               1140                 :                :                           attrno,
                               1141                 :                :                           tupDesc,
                               1142                 :                :                           isNull);
                               1143                 :                : 
                               1144         [ +  - ]:             24 :     ReleaseTupleDesc(tupDesc);
                               1145                 :                : 
                               1146                 :             24 :     return result;
                               1147                 :                : }
                               1148                 :                : 
                               1149                 :                : Datum
 3339 andres@anarazel.de       1150                 :UBC           0 : GetAttributeByNum(HeapTupleHeader tuple,
                               1151                 :                :                   AttrNumber attrno,
                               1152                 :                :                   bool *isNull)
                               1153                 :                : {
                               1154                 :                :     Datum       result;
                               1155                 :                :     Oid         tupType;
                               1156                 :                :     int32       tupTypmod;
                               1157                 :                :     TupleDesc   tupDesc;
                               1158                 :                :     HeapTupleData tmptup;
                               1159                 :                : 
                               1160         [ #  # ]:              0 :     if (!AttributeNumberIsValid(attrno))
                               1161         [ #  # ]:              0 :         elog(ERROR, "invalid attribute number %d", attrno);
                               1162                 :                : 
                               1163         [ #  # ]:              0 :     if (isNull == NULL)
                               1164         [ #  # ]:              0 :         elog(ERROR, "a NULL isNull pointer was passed");
                               1165                 :                : 
                               1166         [ #  # ]:              0 :     if (tuple == NULL)
                               1167                 :                :     {
                               1168                 :                :         /* Kinda bogus but compatible with old behavior... */
                               1169                 :              0 :         *isNull = true;
                               1170                 :              0 :         return (Datum) 0;
                               1171                 :                :     }
                               1172                 :                : 
                               1173                 :              0 :     tupType = HeapTupleHeaderGetTypeId(tuple);
                               1174                 :              0 :     tupTypmod = HeapTupleHeaderGetTypMod(tuple);
                               1175                 :              0 :     tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
                               1176                 :                : 
                               1177                 :                :     /*
                               1178                 :                :      * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
                               1179                 :                :      * the fields in the struct just in case user tries to inspect system
                               1180                 :                :      * columns.
                               1181                 :                :      */
                               1182                 :              0 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
                               1183                 :              0 :     ItemPointerSetInvalid(&(tmptup.t_self));
                               1184                 :              0 :     tmptup.t_tableOid = InvalidOid;
                               1185                 :              0 :     tmptup.t_data = tuple;
                               1186                 :                : 
                               1187                 :              0 :     result = heap_getattr(&tmptup,
                               1188                 :                :                           attrno,
                               1189                 :                :                           tupDesc,
                               1190                 :                :                           isNull);
                               1191                 :                : 
                               1192         [ #  # ]:              0 :     ReleaseTupleDesc(tupDesc);
                               1193                 :                : 
                               1194                 :              0 :     return result;
                               1195                 :                : }
                               1196                 :                : 
                               1197                 :                : /*
                               1198                 :                :  * Number of items in a tlist (including any resjunk items!)
                               1199                 :                :  */
                               1200                 :                : int
 3339 andres@anarazel.de       1201                 :CBC      900023 : ExecTargetListLength(List *targetlist)
                               1202                 :                : {
                               1203                 :                :     /* This used to be more complex, but fjoins are dead */
                               1204                 :         900023 :     return list_length(targetlist);
                               1205                 :                : }
                               1206                 :                : 
                               1207                 :                : /*
                               1208                 :                :  * Number of items in a tlist, not including any resjunk items
                               1209                 :                :  */
                               1210                 :                : int
                               1211                 :          92856 : ExecCleanTargetListLength(List *targetlist)
                               1212                 :                : {
                               1213                 :          92856 :     int         len = 0;
                               1214                 :                :     ListCell   *tl;
                               1215                 :                : 
                               1216   [ +  +  +  +  :         391844 :     foreach(tl, targetlist)
                                              +  + ]
                               1217                 :                :     {
 3312 tgl@sss.pgh.pa.us        1218                 :         298988 :         TargetEntry *curTle = lfirst_node(TargetEntry, tl);
                               1219                 :                : 
 3339 andres@anarazel.de       1220         [ +  + ]:         298988 :         if (!curTle->resjunk)
                               1221                 :         278608 :             len++;
                               1222                 :                :     }
                               1223                 :          92856 :     return len;
                               1224                 :                : }
                               1225                 :                : 
                               1226                 :                : /*
                               1227                 :                :  * Return a relInfo's tuple slot for a trigger's OLD tuples.
                               1228                 :                :  */
                               1229                 :                : TupleTableSlot *
 2625                          1230                 :         617682 : ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo)
                               1231                 :                : {
                               1232         [ +  + ]:         617682 :     if (relInfo->ri_TrigOldSlot == NULL)
                               1233                 :                :     {
                               1234                 :           6894 :         Relation    rel = relInfo->ri_RelationDesc;
                               1235                 :           6894 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
                               1236                 :                : 
                               1237                 :           6894 :         relInfo->ri_TrigOldSlot =
                               1238                 :           6894 :             ExecInitExtraTupleSlot(estate,
                               1239                 :                :                                    RelationGetDescr(rel),
                               1240                 :                :                                    table_slot_callbacks(rel));
                               1241                 :                : 
                               1242                 :           6894 :         MemoryContextSwitchTo(oldcontext);
                               1243                 :                :     }
                               1244                 :                : 
                               1245                 :         617682 :     return relInfo->ri_TrigOldSlot;
                               1246                 :                : }
                               1247                 :                : 
                               1248                 :                : /*
                               1249                 :                :  * Return a relInfo's tuple slot for a trigger's NEW tuples.
                               1250                 :                :  */
                               1251                 :                : TupleTableSlot *
                               1252                 :           2386 : ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo)
                               1253                 :                : {
                               1254         [ +  + ]:           2386 :     if (relInfo->ri_TrigNewSlot == NULL)
                               1255                 :                :     {
                               1256                 :           1502 :         Relation    rel = relInfo->ri_RelationDesc;
                               1257                 :           1502 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
                               1258                 :                : 
                               1259                 :           1502 :         relInfo->ri_TrigNewSlot =
                               1260                 :           1502 :             ExecInitExtraTupleSlot(estate,
                               1261                 :                :                                    RelationGetDescr(rel),
                               1262                 :                :                                    table_slot_callbacks(rel));
                               1263                 :                : 
                               1264                 :           1502 :         MemoryContextSwitchTo(oldcontext);
                               1265                 :                :     }
                               1266                 :                : 
                               1267                 :           2386 :     return relInfo->ri_TrigNewSlot;
                               1268                 :                : }
                               1269                 :                : 
                               1270                 :                : /*
                               1271                 :                :  * Return a relInfo's tuple slot for processing returning tuples.
                               1272                 :                :  */
                               1273                 :                : TupleTableSlot *
                               1274                 :            817 : ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo)
                               1275                 :                : {
                               1276         [ +  + ]:            817 :     if (relInfo->ri_ReturningSlot == NULL)
                               1277                 :                :     {
                               1278                 :            443 :         Relation    rel = relInfo->ri_RelationDesc;
                               1279                 :            443 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
                               1280                 :                : 
                               1281                 :            443 :         relInfo->ri_ReturningSlot =
                               1282                 :            443 :             ExecInitExtraTupleSlot(estate,
                               1283                 :                :                                    RelationGetDescr(rel),
                               1284                 :                :                                    table_slot_callbacks(rel));
                               1285                 :                : 
                               1286                 :            443 :         MemoryContextSwitchTo(oldcontext);
                               1287                 :                :     }
                               1288                 :                : 
                               1289                 :            817 :     return relInfo->ri_ReturningSlot;
                               1290                 :                : }
                               1291                 :                : 
                               1292                 :                : /*
                               1293                 :                :  * Return a relInfo's all-NULL tuple slot for processing returning tuples.
                               1294                 :                :  *
                               1295                 :                :  * Note: this slot is intentionally filled with NULLs in every column, and
                               1296                 :                :  * should be considered read-only --- the caller must not update it.
                               1297                 :                :  */
                               1298                 :                : TupleTableSlot *
  474 dean.a.rasheed@gmail     1299                 :            236 : ExecGetAllNullSlot(EState *estate, ResultRelInfo *relInfo)
                               1300                 :                : {
                               1301         [ +  + ]:            236 :     if (relInfo->ri_AllNullSlot == NULL)
                               1302                 :                :     {
                               1303                 :            162 :         Relation    rel = relInfo->ri_RelationDesc;
                               1304                 :            162 :         MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
                               1305                 :                :         TupleTableSlot *slot;
                               1306                 :                : 
                               1307                 :            162 :         slot = ExecInitExtraTupleSlot(estate,
                               1308                 :                :                                       RelationGetDescr(rel),
                               1309                 :                :                                       table_slot_callbacks(rel));
                               1310                 :            162 :         ExecStoreAllNullTuple(slot);
                               1311                 :                : 
                               1312                 :            162 :         relInfo->ri_AllNullSlot = slot;
                               1313                 :                : 
                               1314                 :            162 :         MemoryContextSwitchTo(oldcontext);
                               1315                 :                :     }
                               1316                 :                : 
                               1317                 :            236 :     return relInfo->ri_AllNullSlot;
                               1318                 :                : }
                               1319                 :                : 
                               1320                 :                : /*
                               1321                 :                :  * Return the map needed to convert given child result relation's tuples to
                               1322                 :                :  * the rowtype of the query's main target ("root") relation.  Note that a
                               1323                 :                :  * NULL result is valid and means that no conversion is needed.
                               1324                 :                :  */
                               1325                 :                : TupleConversionMap *
 1855 tgl@sss.pgh.pa.us        1326                 :          45404 : ExecGetChildToRootMap(ResultRelInfo *resultRelInfo)
                               1327                 :                : {
                               1328                 :                :     /* If we didn't already do so, compute the map for this child. */
                               1329         [ +  + ]:          45404 :     if (!resultRelInfo->ri_ChildToRootMapValid)
                               1330                 :                :     {
                               1331                 :           1196 :         ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
                               1332                 :                : 
                               1333         [ +  + ]:           1196 :         if (rootRelInfo)
                               1334                 :            937 :             resultRelInfo->ri_ChildToRootMap =
                               1335                 :            937 :                 convert_tuples_by_name(RelationGetDescr(resultRelInfo->ri_RelationDesc),
                               1336                 :            937 :                                        RelationGetDescr(rootRelInfo->ri_RelationDesc));
                               1337                 :                :         else                    /* this isn't a child result rel */
                               1338                 :            259 :             resultRelInfo->ri_ChildToRootMap = NULL;
                               1339                 :                : 
                               1340                 :           1196 :         resultRelInfo->ri_ChildToRootMapValid = true;
                               1341                 :                :     }
                               1342                 :                : 
                               1343                 :          45404 :     return resultRelInfo->ri_ChildToRootMap;
                               1344                 :                : }
                               1345                 :                : 
                               1346                 :                : /*
                               1347                 :                :  * Returns the map needed to convert given root result relation's tuples to
                               1348                 :                :  * the rowtype of the given child relation.  Note that a NULL result is valid
                               1349                 :                :  * and means that no conversion is needed.
                               1350                 :                :  */
                               1351                 :                : TupleConversionMap *
 1250 alvherre@alvh.no-ip.     1352                 :         636302 : ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
                               1353                 :                : {
                               1354                 :                :     /* Mustn't get called for a non-child result relation. */
                               1355         [ -  + ]:         636302 :     Assert(resultRelInfo->ri_RootResultRelInfo);
                               1356                 :                : 
                               1357                 :                :     /* If we didn't already do so, compute the map for this child. */
                               1358         [ +  + ]:         636302 :     if (!resultRelInfo->ri_RootToChildMapValid)
                               1359                 :                :     {
                               1360                 :           5649 :         ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
                               1361                 :           5649 :         TupleDesc   indesc = RelationGetDescr(rootRelInfo->ri_RelationDesc);
                               1362                 :           5649 :         TupleDesc   outdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
                               1363                 :           5649 :         Relation    childrel = resultRelInfo->ri_RelationDesc;
                               1364                 :                :         AttrMap    *attrMap;
                               1365                 :                :         MemoryContext oldcontext;
                               1366                 :                : 
                               1367                 :                :         /*
                               1368                 :                :          * When this child table is not a partition (!relispartition), it may
                               1369                 :                :          * have columns that are not present in the root table, which we ask
                               1370                 :                :          * to ignore by passing true for missing_ok.
                               1371                 :                :          */
                               1372                 :           5649 :         oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
                               1373                 :           5649 :         attrMap = build_attrmap_by_name_if_req(indesc, outdesc,
                               1374                 :           5649 :                                                !childrel->rd_rel->relispartition);
                               1375         [ +  + ]:           5649 :         if (attrMap)
                               1376                 :           1062 :             resultRelInfo->ri_RootToChildMap =
                               1377                 :           1062 :                 convert_tuples_by_name_attrmap(indesc, outdesc, attrMap);
                               1378                 :           5649 :         MemoryContextSwitchTo(oldcontext);
                               1379                 :           5649 :         resultRelInfo->ri_RootToChildMapValid = true;
                               1380                 :                :     }
                               1381                 :                : 
                               1382                 :         636302 :     return resultRelInfo->ri_RootToChildMap;
                               1383                 :                : }
                               1384                 :                : 
                               1385                 :                : /* Return a bitmap representing columns being inserted */
                               1386                 :                : Bitmapset *
 1912 heikki.linnakangas@i     1387                 :            980 : ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
                               1388                 :                : {
 1246 alvherre@alvh.no-ip.     1389                 :            980 :     RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relinfo, estate);
                               1390                 :                : 
                               1391         [ -  + ]:            980 :     if (perminfo == NULL)
 1246 alvherre@alvh.no-ip.     1392                 :UBC           0 :         return NULL;
                               1393                 :                : 
                               1394                 :                :     /* Map the columns to child's attribute numbers if needed. */
 1246 alvherre@alvh.no-ip.     1395         [ +  + ]:CBC         980 :     if (relinfo->ri_RootResultRelInfo)
                               1396                 :                :     {
 1250                          1397                 :             53 :         TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
                               1398                 :                : 
 1246                          1399         [ +  + ]:             53 :         if (map)
                               1400                 :              2 :             return execute_attr_map_cols(map->attrMap, perminfo->insertedCols);
                               1401                 :                :     }
                               1402                 :                : 
                               1403                 :            978 :     return perminfo->insertedCols;
                               1404                 :                : }
                               1405                 :                : 
                               1406                 :                : /* Return a bitmap representing columns being updated */
                               1407                 :                : Bitmapset *
 1912 heikki.linnakangas@i     1408                 :          32491 : ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
                               1409                 :                : {
 1246 alvherre@alvh.no-ip.     1410                 :          32491 :     RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relinfo, estate);
                               1411                 :                : 
                               1412         [ +  + ]:          32491 :     if (perminfo == NULL)
 1246 alvherre@alvh.no-ip.     1413                 :GBC           2 :         return NULL;
                               1414                 :                : 
                               1415                 :                :     /* Map the columns to child's attribute numbers if needed. */
 1246 alvherre@alvh.no-ip.     1416         [ +  + ]:CBC       32489 :     if (relinfo->ri_RootResultRelInfo)
                               1417                 :                :     {
 1250                          1418                 :           1163 :         TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
                               1419                 :                : 
 1246                          1420         [ +  + ]:           1163 :         if (map)
                               1421                 :            329 :             return execute_attr_map_cols(map->attrMap, perminfo->updatedCols);
                               1422                 :                :     }
                               1423                 :                : 
                               1424                 :          32160 :     return perminfo->updatedCols;
                               1425                 :                : }
                               1426                 :                : 
                               1427                 :                : /* Return a bitmap representing generated columns being updated */
                               1428                 :                : Bitmapset *
 1912 heikki.linnakangas@i     1429                 :          31360 : ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
                               1430                 :                : {
                               1431                 :                :     /* Compute the info if we didn't already */
  452 peter@eisentraut.org     1432         [ +  + ]:          31360 :     if (!relinfo->ri_extraUpdatedCols_valid)
                               1433                 :          31230 :         ExecInitGenerated(relinfo, estate, CMD_UPDATE);
 1216 tgl@sss.pgh.pa.us        1434                 :          31360 :     return relinfo->ri_extraUpdatedCols;
                               1435                 :                : }
                               1436                 :                : 
                               1437                 :                : /*
                               1438                 :                :  * Return columns being updated, including generated columns
                               1439                 :                :  *
                               1440                 :                :  * The bitmap is allocated in per-tuple memory context. It's up to the caller to
                               1441                 :                :  * copy it into a different context with the appropriate lifespan, if needed.
                               1442                 :                :  */
                               1443                 :                : Bitmapset *
 1912 heikki.linnakangas@i     1444                 :           8779 : ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
                               1445                 :                : {
                               1446                 :                :     Bitmapset  *ret;
                               1447                 :                :     MemoryContext oldcxt;
                               1448                 :                : 
 1063 tomas.vondra@postgre     1449         [ +  + ]:           8779 :     oldcxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
                               1450                 :                : 
                               1451                 :           8779 :     ret = bms_union(ExecGetUpdatedCols(relinfo, estate),
                               1452                 :           8779 :                     ExecGetExtraUpdatedCols(relinfo, estate));
                               1453                 :                : 
                               1454                 :           8779 :     MemoryContextSwitchTo(oldcxt);
                               1455                 :                : 
                               1456                 :           8779 :     return ret;
                               1457                 :                : }
                               1458                 :                : 
                               1459                 :                : /*
                               1460                 :                :  * GetResultRTEPermissionInfo
                               1461                 :                :  *      Looks up RTEPermissionInfo for ExecGet*Cols() routines
                               1462                 :                :  */
                               1463                 :                : static RTEPermissionInfo *
 1246 alvherre@alvh.no-ip.     1464                 :          33653 : GetResultRTEPermissionInfo(ResultRelInfo *relinfo, EState *estate)
                               1465                 :                : {
                               1466                 :                :     Index       rti;
                               1467                 :                :     RangeTblEntry *rte;
                               1468                 :          33653 :     RTEPermissionInfo *perminfo = NULL;
                               1469                 :                : 
                               1470         [ +  + ]:          33653 :     if (relinfo->ri_RootResultRelInfo)
                               1471                 :                :     {
                               1472                 :                :         /*
                               1473                 :                :          * For inheritance child result relations (a partition routing target
                               1474                 :                :          * of an INSERT or a child UPDATE target), this returns the root
                               1475                 :                :          * parent's RTE to fetch the RTEPermissionInfo because that's the only
                               1476                 :                :          * one that has one assigned.
                               1477                 :                :          */
                               1478                 :           1272 :         rti = relinfo->ri_RootResultRelInfo->ri_RangeTableIndex;
                               1479                 :                :     }
                               1480         [ +  + ]:          32381 :     else if (relinfo->ri_RangeTableIndex != 0)
                               1481                 :                :     {
                               1482                 :                :         /*
                               1483                 :                :          * Non-child result relation should have their own RTEPermissionInfo.
                               1484                 :                :          */
                               1485                 :          32379 :         rti = relinfo->ri_RangeTableIndex;
                               1486                 :                :     }
                               1487                 :                :     else
                               1488                 :                :     {
                               1489                 :                :         /*
                               1490                 :                :          * The relation isn't in the range table and it isn't a partition
                               1491                 :                :          * routing target.  This ResultRelInfo must've been created only for
                               1492                 :                :          * firing triggers and the relation is not being inserted into.  (See
                               1493                 :                :          * ExecGetTriggerResultRel.)
                               1494                 :                :          */
 1246 alvherre@alvh.no-ip.     1495                 :GBC           2 :         rti = 0;
                               1496                 :                :     }
                               1497                 :                : 
 1246 alvherre@alvh.no-ip.     1498         [ +  + ]:CBC       33653 :     if (rti > 0)
                               1499                 :                :     {
                               1500                 :          33651 :         rte = exec_rt_fetch(rti, estate);
                               1501                 :          33651 :         perminfo = getRTEPermissionInfo(estate->es_rteperminfos, rte);
                               1502                 :                :     }
                               1503                 :                : 
                               1504                 :          33653 :     return perminfo;
                               1505                 :                : }
                               1506                 :                : 
                               1507                 :                : /*
                               1508                 :                :  * ExecGetResultRelCheckAsUser
                               1509                 :                :  *      Returns the user to modify passed-in result relation as
                               1510                 :                :  *
                               1511                 :                :  * The user is chosen by looking up the relation's or, if a child table, its
                               1512                 :                :  * root parent's RTEPermissionInfo.
                               1513                 :                :  */
                               1514                 :                : Oid
                               1515                 :            182 : ExecGetResultRelCheckAsUser(ResultRelInfo *relInfo, EState *estate)
                               1516                 :                : {
                               1517                 :            182 :     RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relInfo, estate);
                               1518                 :                : 
                               1519                 :                :     /* XXX - maybe ok to return GetUserId() in this case? */
                               1520         [ -  + ]:            182 :     if (perminfo == NULL)
 1246 alvherre@alvh.no-ip.     1521         [ #  # ]:UBC           0 :         elog(ERROR, "no RTEPermissionInfo found for result relation with OID %u",
                               1522                 :                :              RelationGetRelid(relInfo->ri_RelationDesc));
                               1523                 :                : 
 1246 alvherre@alvh.no-ip.     1524         [ +  + ]:CBC         182 :     return perminfo->checkAsUser ? perminfo->checkAsUser : GetUserId();
                               1525                 :                : }
        

Generated by: LCOV version 2.5.0-beta