LCOV - differential code coverage report
Current view: top level - src/backend/executor - nodeValuesscan.c (source / functions) Coverage Total Hit UBC CBC
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 94.9 % 78 74 4 74
Current Date: 2025-09-06 07:49:51 +0900 Functions: 80.0 % 5 4 1 4
Baseline: lcov-20250906-005545-baseline Branches: 75.0 % 40 30 10 30
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 100.0 % 1 1 1
(360..) days: 94.8 % 77 73 4 73
Function coverage date bins:
(360..) days: 80.0 % 5 4 1 4
Branch coverage date bins:
(360..) days: 75.0 % 40 30 10 30

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * nodeValuesscan.c
                                  4                 :                :  *    Support routines for scanning Values lists
                                  5                 :                :  *    ("VALUES (...), (...), ..." in rangetable).
                                  6                 :                :  *
                                  7                 :                :  * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
                                  8                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  9                 :                :  *
                                 10                 :                :  *
                                 11                 :                :  * IDENTIFICATION
                                 12                 :                :  *    src/backend/executor/nodeValuesscan.c
                                 13                 :                :  *
                                 14                 :                :  *-------------------------------------------------------------------------
                                 15                 :                :  */
                                 16                 :                : /*
                                 17                 :                :  * INTERFACE ROUTINES
                                 18                 :                :  *      ExecValuesScan          scans a values list.
                                 19                 :                :  *      ExecValuesNext          retrieve next tuple in sequential order.
                                 20                 :                :  *      ExecInitValuesScan      creates and initializes a valuesscan node.
                                 21                 :                :  *      ExecReScanValuesScan    rescans the values list
                                 22                 :                :  */
                                 23                 :                : #include "postgres.h"
                                 24                 :                : 
                                 25                 :                : #include "executor/executor.h"
                                 26                 :                : #include "executor/nodeValuesscan.h"
                                 27                 :                : #include "jit/jit.h"
                                 28                 :                : #include "optimizer/clauses.h"
                                 29                 :                : #include "utils/expandeddatum.h"
                                 30                 :                : 
                                 31                 :                : 
                                 32                 :                : static TupleTableSlot *ValuesNext(ValuesScanState *node);
                                 33                 :                : 
                                 34                 :                : 
                                 35                 :                : /* ----------------------------------------------------------------
                                 36                 :                :  *                      Scan Support
                                 37                 :                :  * ----------------------------------------------------------------
                                 38                 :                :  */
                                 39                 :                : 
                                 40                 :                : /* ----------------------------------------------------------------
                                 41                 :                :  *      ValuesNext
                                 42                 :                :  *
                                 43                 :                :  *      This is a workhorse for ExecValuesScan
                                 44                 :                :  * ----------------------------------------------------------------
                                 45                 :                :  */
                                 46                 :                : static TupleTableSlot *
 6975 mail@joeconway.com         47                 :CBC      111716 : ValuesNext(ValuesScanState *node)
                                 48                 :                : {
                                 49                 :                :     TupleTableSlot *slot;
                                 50                 :                :     EState     *estate;
                                 51                 :                :     ExprContext *econtext;
                                 52                 :                :     ScanDirection direction;
                                 53                 :                :     int         curr_idx;
                                 54                 :                : 
                                 55                 :                :     /*
                                 56                 :                :      * get information from the estate and scan state
                                 57                 :                :      */
                                 58                 :         111716 :     estate = node->ss.ps.state;
                                 59                 :         111716 :     direction = estate->es_direction;
                                 60                 :         111716 :     slot = node->ss.ss_ScanTupleSlot;
      tgl@sss.pgh.pa.us          61                 :         111716 :     econtext = node->rowcontext;
                                 62                 :                : 
                                 63                 :                :     /*
                                 64                 :                :      * Get the next tuple. Return NULL if no more tuples.
                                 65                 :                :      */
      mail@joeconway.com         66         [ +  - ]:         111716 :     if (ScanDirectionIsForward(direction))
                                 67                 :                :     {
                                 68         [ +  - ]:         111716 :         if (node->curr_idx < node->array_len)
                                 69                 :         111716 :             node->curr_idx++;
                                 70                 :                :     }
                                 71                 :                :     else
                                 72                 :                :     {
 6975 mail@joeconway.com         73         [ #  # ]:UBC           0 :         if (node->curr_idx >= 0)
                                 74                 :              0 :             node->curr_idx--;
                                 75                 :                :     }
                                 76                 :                : 
                                 77                 :                :     /*
                                 78                 :                :      * Always clear the result slot; this is appropriate if we are at the end
                                 79                 :                :      * of the data, and if we're not, we still need it as the first step of
                                 80                 :                :      * the store-virtual-tuple protocol.  It seems wise to clear the slot
                                 81                 :                :      * before we reset the context it might have pointers into.
                                 82                 :                :      */
 6975 mail@joeconway.com         83                 :CBC      111716 :     ExecClearTuple(slot);
                                 84                 :                : 
 2059 tgl@sss.pgh.pa.us          85                 :         111716 :     curr_idx = node->curr_idx;
                                 86   [ +  -  +  + ]:         111716 :     if (curr_idx >= 0 && curr_idx < node->array_len)
                                 87                 :                :     {
                                 88                 :          77400 :         List       *exprlist = node->exprlists[curr_idx];
                                 89                 :          77400 :         List       *exprstatelist = node->exprstatelists[curr_idx];
                                 90                 :                :         MemoryContext oldContext;
                                 91                 :                :         Datum      *values;
                                 92                 :                :         bool       *isnull;
                                 93                 :                :         ListCell   *lc;
                                 94                 :                :         int         resind;
                                 95                 :                : 
                                 96                 :                :         /*
                                 97                 :                :          * Get rid of any prior cycle's leftovers.  We use ReScanExprContext
                                 98                 :                :          * not just ResetExprContext because we want any registered shutdown
                                 99                 :                :          * callbacks to be called.
                                100                 :                :          */
 6975                           101                 :          77400 :         ReScanExprContext(econtext);
                                102                 :                : 
                                103                 :                :         /*
                                104                 :                :          * Do per-VALUES-row work in the per-tuple context.
                                105                 :                :          */
                                106                 :          77400 :         oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
                                107                 :                : 
                                108                 :                :         /*
                                109                 :                :          * Unless we already made the expression eval state for this row,
                                110                 :                :          * build it in the econtext's per-tuple memory.  This is a tad
                                111                 :                :          * unusual, but we want to delete the eval state again when we move to
                                112                 :                :          * the next row, to avoid growth of memory requirements over a long
                                113                 :                :          * values list.  For rows in which that won't work, we already built
                                114                 :                :          * the eval state at plan startup.
                                115                 :                :          */
 2059                           116         [ +  + ]:          77400 :         if (exprstatelist == NIL)
                                117                 :                :         {
                                118                 :                :             /*
                                119                 :                :              * Pass parent as NULL, not my plan node, because we don't want
                                120                 :                :              * anything in this transient state linking into permanent state.
                                121                 :                :              * The only expression type that might wish to do so is a SubPlan,
                                122                 :                :              * and we already checked that there aren't any.
                                123                 :                :              *
                                124                 :                :              * Note that passing parent = NULL also disables JIT compilation
                                125                 :                :              * of the expressions, which is a win, because they're only going
                                126                 :                :              * to be used once under normal circumstances.
                                127                 :                :              */
                                128                 :          77370 :             exprstatelist = ExecInitExprList(exprlist, NULL);
                                129                 :                :         }
                                130                 :                : 
                                131                 :                :         /* parser should have checked all sublists are the same length */
 6975                           132         [ -  + ]:          77400 :         Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts);
                                133                 :                : 
                                134                 :                :         /*
                                135                 :                :          * Compute the expressions and build a virtual result tuple. We
                                136                 :                :          * already did ExecClearTuple(slot).
                                137                 :                :          */
                                138                 :          77400 :         values = slot->tts_values;
                                139                 :          77400 :         isnull = slot->tts_isnull;
                                140                 :                : 
                                141                 :          77400 :         resind = 0;
                                142   [ +  -  +  +  :         166947 :         foreach(lc, exprstatelist)
                                              +  + ]
                                143                 :                :         {
 6912 bruce@momjian.us          144                 :          89547 :             ExprState  *estate = (ExprState *) lfirst(lc);
  260 drowley@postgresql.o      145                 :          89547 :             CompactAttribute *attr = TupleDescCompactAttr(slot->tts_tupleDescriptor,
                                146                 :                :                                                           resind);
                                147                 :                : 
 6975 tgl@sss.pgh.pa.us         148                 :          89547 :             values[resind] = ExecEvalExpr(estate,
                                149                 :                :                                           econtext,
                                150                 :                :                                           &isnull[resind]);
                                151                 :                : 
                                152                 :                :             /*
                                153                 :                :              * We must force any R/W expanded datums to read-only state, in
                                154                 :                :              * case they are multiply referenced in the plan node's output
                                155                 :                :              * expressions, or in case we skip the output projection and the
                                156                 :                :              * output column is multiply referenced in higher plan nodes.
                                157                 :                :              */
 3382                           158   [ +  +  +  + ]:          89547 :             values[resind] = MakeExpandedObjectReadOnly(values[resind],
                                159                 :                :                                                         isnull[resind],
                                160                 :                :                                                         attr->attlen);
                                161                 :                : 
 6975                           162                 :          89547 :             resind++;
                                163                 :                :         }
                                164                 :                : 
                                165                 :          77400 :         MemoryContextSwitchTo(oldContext);
                                166                 :                : 
                                167                 :                :         /*
                                168                 :                :          * And return the virtual tuple.
                                169                 :                :          */
                                170                 :          77400 :         ExecStoreVirtualTuple(slot);
                                171                 :                :     }
                                172                 :                : 
                                173                 :         111716 :     return slot;
                                174                 :                : }
                                175                 :                : 
                                176                 :                : /*
                                177                 :                :  * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual
                                178                 :                :  */
                                179                 :                : static bool
 5794 tgl@sss.pgh.pa.us         180                 :UBC           0 : ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot)
                                181                 :                : {
                                182                 :                :     /* nothing to check */
                                183                 :              0 :     return true;
                                184                 :                : }
                                185                 :                : 
                                186                 :                : /* ----------------------------------------------------------------
                                187                 :                :  *      ExecValuesScan(node)
                                188                 :                :  *
                                189                 :                :  *      Scans the values lists sequentially and returns the next qualifying
                                190                 :                :  *      tuple.
                                191                 :                :  *      We call the ExecScan() routine and pass it the appropriate
                                192                 :                :  *      access method functions.
                                193                 :                :  * ----------------------------------------------------------------
                                194                 :                :  */
                                195                 :                : static TupleTableSlot *
 2973 andres@anarazel.de        196                 :CBC      111233 : ExecValuesScan(PlanState *pstate)
                                197                 :                : {
                                198                 :         111233 :     ValuesScanState *node = castNode(ValuesScanState, pstate);
                                199                 :                : 
 5794 tgl@sss.pgh.pa.us         200                 :         111233 :     return ExecScan(&node->ss,
                                201                 :                :                     (ExecScanAccessMtd) ValuesNext,
                                202                 :                :                     (ExecScanRecheckMtd) ValuesRecheck);
                                203                 :                : }
                                204                 :                : 
                                205                 :                : /* ----------------------------------------------------------------
                                206                 :                :  *      ExecInitValuesScan
                                207                 :                :  * ----------------------------------------------------------------
                                208                 :                :  */
                                209                 :                : ValuesScanState *
 6975 mail@joeconway.com        210                 :           4538 : ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
                                211                 :                : {
                                212                 :                :     ValuesScanState *scanstate;
                                213                 :                :     TupleDesc   tupdesc;
                                214                 :                :     ListCell   *vtl;
                                215                 :                :     int         i;
                                216                 :                :     PlanState  *planstate;
                                217                 :                : 
                                218                 :                :     /*
                                219                 :                :      * ValuesScan should not have any children.
                                220                 :                :      */
                                221         [ -  + ]:           4538 :     Assert(outerPlan(node) == NULL);
                                222         [ -  + ]:           4538 :     Assert(innerPlan(node) == NULL);
                                223                 :                : 
                                224                 :                :     /*
                                225                 :                :      * create new ScanState for node
                                226                 :                :      */
                                227                 :           4538 :     scanstate = makeNode(ValuesScanState);
                                228                 :           4538 :     scanstate->ss.ps.plan = (Plan *) node;
                                229                 :           4538 :     scanstate->ss.ps.state = estate;
 2973 andres@anarazel.de        230                 :           4538 :     scanstate->ss.ps.ExecProcNode = ExecValuesScan;
                                231                 :                : 
                                232                 :                :     /*
                                233                 :                :      * Miscellaneous initialization
                                234                 :                :      */
 6975 mail@joeconway.com        235                 :           4538 :     planstate = &scanstate->ss.ps;
                                236                 :                : 
                                237                 :                :     /*
                                238                 :                :      * Create expression contexts.  We need two, one for per-sublist
                                239                 :                :      * processing and one for execScan.c to use for quals and projections. We
                                240                 :                :      * cheat a little by using ExecAssignExprContext() to build both.
                                241                 :                :      */
      tgl@sss.pgh.pa.us         242                 :           4538 :     ExecAssignExprContext(estate, planstate);
                                243                 :           4538 :     scanstate->rowcontext = planstate->ps_ExprContext;
      mail@joeconway.com        244                 :           4538 :     ExecAssignExprContext(estate, planstate);
                                245                 :                : 
                                246                 :                :     /*
                                247                 :                :      * Get info about values list, initialize scan slot with it.
                                248                 :                :      */
 2759 andres@anarazel.de        249                 :           4538 :     tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
 2487                           250                 :           4538 :     ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc, &TTSOpsVirtual);
                                251                 :                : 
                                252                 :                :     /*
                                253                 :                :      * Initialize result type and projection.
                                254                 :                :      */
 2493                           255                 :           4538 :     ExecInitResultTypeTL(&scanstate->ss.ps);
 2759                           256                 :           4538 :     ExecAssignScanProjectionInfo(&scanstate->ss);
                                257                 :                : 
                                258                 :                :     /*
                                259                 :                :      * initialize child expressions
                                260                 :                :      */
                                261                 :           4538 :     scanstate->ss.ps.qual =
                                262                 :           4538 :         ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
                                263                 :                : 
                                264                 :                :     /*
                                265                 :                :      * Other node-specific setup
                                266                 :                :      */
 6975 mail@joeconway.com        267                 :           4538 :     scanstate->curr_idx = -1;
 6774 tgl@sss.pgh.pa.us         268                 :           4538 :     scanstate->array_len = list_length(node->values_lists);
                                269                 :                : 
                                270                 :                :     /*
                                271                 :                :      * Convert the list of expression sublists into an array for easier
                                272                 :                :      * addressing at runtime.  Also, detect whether any sublists contain
                                273                 :                :      * SubPlans; for just those sublists, go ahead and do expression
                                274                 :                :      * initialization.  (This avoids problems with SubPlans wanting to connect
                                275                 :                :      * themselves up to the outer plan tree.  Notably, EXPLAIN won't see the
                                276                 :                :      * subplans otherwise; also we will have troubles with dangling pointers
                                277                 :                :      * and/or leaked resources if we try to handle SubPlans the same as
                                278                 :                :      * simpler expressions.)
                                279                 :                :      */
 6975 mail@joeconway.com        280                 :           4538 :     scanstate->exprlists = (List **)
                                281                 :           4538 :         palloc(scanstate->array_len * sizeof(List *));
 2059 tgl@sss.pgh.pa.us         282                 :           4538 :     scanstate->exprstatelists = (List **)
                                283                 :           4538 :         palloc0(scanstate->array_len * sizeof(List *));
 6975 mail@joeconway.com        284                 :           4538 :     i = 0;
 6774 tgl@sss.pgh.pa.us         285   [ +  -  +  +  :          22357 :     foreach(vtl, node->values_lists)
                                              +  + ]
                                286                 :                :     {
 1510 peter@eisentraut.org      287                 :          17819 :         List       *exprs = lfirst_node(List, vtl);
                                288                 :                : 
 2059 tgl@sss.pgh.pa.us         289                 :          17819 :         scanstate->exprlists[i] = exprs;
                                290                 :                : 
                                291                 :                :         /*
                                292                 :                :          * We can avoid the cost of a contain_subplans() scan in the simple
                                293                 :                :          * case where there are no SubPlans anywhere.
                                294                 :                :          */
                                295   [ +  +  +  + ]:          18083 :         if (estate->es_subplanstates &&
                                296                 :            264 :             contain_subplans((Node *) exprs))
                                297                 :                :         {
                                298                 :                :             int         saved_jit_flags;
                                299                 :                : 
                                300                 :                :             /*
                                301                 :                :              * As these expressions are only used once, disable JIT for them.
                                302                 :                :              * This is worthwhile because it's common to insert significant
                                303                 :                :              * amounts of data via VALUES().  Note that this doesn't prevent
                                304                 :                :              * use of JIT *within* a subplan, since that's initialized
                                305                 :                :              * separately; this just affects the upper-level subexpressions.
                                306                 :                :              */
                                307                 :             18 :             saved_jit_flags = estate->es_jit_flags;
                                308                 :             18 :             estate->es_jit_flags = PGJIT_NONE;
                                309                 :                : 
                                310                 :             18 :             scanstate->exprstatelists[i] = ExecInitExprList(exprs,
                                311                 :                :                                                             &scanstate->ss.ps);
                                312                 :                : 
                                313                 :             18 :             estate->es_jit_flags = saved_jit_flags;
                                314                 :                :         }
                                315                 :          17819 :         i++;
                                316                 :                :     }
                                317                 :                : 
 6975 mail@joeconway.com        318                 :           4538 :     return scanstate;
                                319                 :                : }
                                320                 :                : 
                                321                 :                : /* ----------------------------------------------------------------
                                322                 :                :  *      ExecReScanValuesScan
                                323                 :                :  *
                                324                 :                :  *      Rescans the relation.
                                325                 :                :  * ----------------------------------------------------------------
                                326                 :                :  */
                                327                 :                : void
 5535 tgl@sss.pgh.pa.us         328                 :          30189 : ExecReScanValuesScan(ValuesScanState *node)
                                329                 :                : {
 2493 andres@anarazel.de        330         [ +  + ]:          30189 :     if (node->ss.ps.ps_ResultTupleSlot)
                                331                 :              6 :         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
                                332                 :                : 
 5794 tgl@sss.pgh.pa.us         333                 :          30189 :     ExecScanReScan(&node->ss);
                                334                 :                : 
 6975 mail@joeconway.com        335                 :          30189 :     node->curr_idx = -1;
                                336                 :          30189 : }
        

Generated by: LCOV version 2.4-beta