LCOV - differential code coverage report
Current view: top level - src/backend/executor - nodeMaterial.c (source / functions) Coverage Total Hit UBC GNC CBC DCB
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 94.4 % 89 84 5 84 1
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 6 6 1 5
Baseline: 16@8cea358b128 Branches: 82.3 % 62 51 11 51
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 94.4 % 89 84 5 84
Function coverage date bins:
(240..) days: 100.0 % 6 6 1 5
Branch coverage date bins:
(240..) days: 82.3 % 62 51 11 51

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * nodeMaterial.c
                                  4                 :                :  *    Routines to handle materialization nodes.
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *
                                 10                 :                :  * IDENTIFICATION
                                 11                 :                :  *    src/backend/executor/nodeMaterial.c
                                 12                 :                :  *
                                 13                 :                :  *-------------------------------------------------------------------------
                                 14                 :                :  */
                                 15                 :                : /*
                                 16                 :                :  * INTERFACE ROUTINES
                                 17                 :                :  *      ExecMaterial            - materialize the result of a subplan
                                 18                 :                :  *      ExecInitMaterial        - initialize node and subnodes
                                 19                 :                :  *      ExecEndMaterial         - shutdown node and subnodes
                                 20                 :                :  *
                                 21                 :                :  */
                                 22                 :                : #include "postgres.h"
                                 23                 :                : 
                                 24                 :                : #include "executor/executor.h"
                                 25                 :                : #include "executor/nodeMaterial.h"
                                 26                 :                : #include "miscadmin.h"
                                 27                 :                : 
                                 28                 :                : /* ----------------------------------------------------------------
                                 29                 :                :  *      ExecMaterial
                                 30                 :                :  *
                                 31                 :                :  *      As long as we are at the end of the data collected in the tuplestore,
                                 32                 :                :  *      we collect one new row from the subplan on each call, and stash it
                                 33                 :                :  *      aside in the tuplestore before returning it.  The tuplestore is
                                 34                 :                :  *      only read if we are asked to scan backwards, rescan, or mark/restore.
                                 35                 :                :  *
                                 36                 :                :  * ----------------------------------------------------------------
                                 37                 :                :  */
                                 38                 :                : static TupleTableSlot *         /* result tuple from subplan */
 2463 andres@anarazel.de         39                 :CBC     1048703 : ExecMaterial(PlanState *pstate)
                                 40                 :                : {
                                 41                 :        1048703 :     MaterialState *node = castNode(MaterialState, pstate);
                                 42                 :                :     EState     *estate;
                                 43                 :                :     ScanDirection dir;
                                 44                 :                :     bool        forward;
                                 45                 :                :     Tuplestorestate *tuplestorestate;
                                 46                 :                :     bool        eof_tuplestore;
                                 47                 :                :     TupleTableSlot *slot;
                                 48                 :                : 
 2455                            49         [ -  + ]:        1048703 :     CHECK_FOR_INTERRUPTS();
                                 50                 :                : 
                                 51                 :                :     /*
                                 52                 :                :      * get state info from node
                                 53                 :                :      */
 7801 tgl@sss.pgh.pa.us          54                 :        1048703 :     estate = node->ss.ps.state;
 9716 bruce@momjian.us           55                 :        1048703 :     dir = estate->es_direction;
 7707 tgl@sss.pgh.pa.us          56                 :        1048703 :     forward = ScanDirectionIsForward(dir);
 5674                            57                 :        1048703 :     tuplestorestate = node->tuplestorestate;
                                 58                 :                : 
                                 59                 :                :     /*
                                 60                 :                :      * If first time through, and we need a tuplestore, initialize it.
                                 61                 :                :      */
 6173                            62   [ +  +  +  + ]:        1048703 :     if (tuplestorestate == NULL && node->eflags != 0)
                                 63                 :                :     {
 7376                            64                 :           1324 :         tuplestorestate = tuplestore_begin_heap(true, false, work_mem);
 6173                            65                 :           1324 :         tuplestore_set_eflags(tuplestorestate, node->eflags);
 5674                            66         [ +  + ]:           1324 :         if (node->eflags & EXEC_FLAG_MARK)
                                 67                 :                :         {
                                 68                 :                :             /*
                                 69                 :                :              * Allocate a second read pointer to serve as the mark. We know it
                                 70                 :                :              * must have index 1, so needn't store that.
                                 71                 :                :              */
                                 72                 :                :             int         ptrno PG_USED_FOR_ASSERTS_ONLY;
                                 73                 :                : 
 5587                            74                 :             60 :             ptrno = tuplestore_alloc_read_pointer(tuplestorestate,
                                 75                 :                :                                                   node->eflags);
                                 76         [ -  + ]:             60 :             Assert(ptrno == 1);
                                 77                 :                :         }
 5674                            78                 :           1324 :         node->tuplestorestate = tuplestorestate;
                                 79                 :                :     }
                                 80                 :                : 
                                 81                 :                :     /*
                                 82                 :                :      * If we are not at the end of the tuplestore, or are going backwards, try
                                 83                 :                :      * to fetch a tuple from tuplestore.
                                 84                 :                :      */
 6620                            85   [ +  +  +  + ]:        2097341 :     eof_tuplestore = (tuplestorestate == NULL) ||
                                 86                 :        1048638 :         tuplestore_ateof(tuplestorestate);
                                 87                 :                : 
 7707                            88   [ +  +  +  + ]:        1048703 :     if (!forward && eof_tuplestore)
                                 89                 :                :     {
                                 90         [ -  + ]:              6 :         if (!node->eof_underlying)
                                 91                 :                :         {
                                 92                 :                :             /*
                                 93                 :                :              * When reversing direction at tuplestore EOF, the first
                                 94                 :                :              * gettupleslot call will fetch the last-added tuple; but we want
                                 95                 :                :              * to return the one before that, if possible. So do an extra
                                 96                 :                :              * fetch.
                                 97                 :                :              */
 6501 tgl@sss.pgh.pa.us          98         [ #  # ]:UBC           0 :             if (!tuplestore_advance(tuplestorestate, forward))
 7559 bruce@momjian.us           99                 :              0 :                 return NULL;    /* the tuplestore must be empty */
                                100                 :                :         }
 7707 tgl@sss.pgh.pa.us         101                 :CBC           6 :         eof_tuplestore = false;
                                102                 :                :     }
                                103                 :                : 
                                104                 :                :     /*
                                105                 :                :      * If we can fetch another tuple from the tuplestore, return it.
                                106                 :                :      */
 6501                           107                 :        1048703 :     slot = node->ss.ps.ps_ResultTupleSlot;
 7707                           108         [ +  + ]:        1048703 :     if (!eof_tuplestore)
                                109                 :                :     {
 5497                           110         [ +  + ]:        1037545 :         if (tuplestore_gettupleslot(tuplestorestate, forward, false, slot))
 6501                           111                 :         976833 :             return slot;
                                112         [ +  + ]:          60712 :         if (forward)
 7707                           113                 :          60706 :             eof_tuplestore = true;
                                114                 :                :     }
                                115                 :                : 
                                116                 :                :     /*
                                117                 :                :      * If necessary, try to fetch another row from the subplan.
                                118                 :                :      *
                                119                 :                :      * Note: the eof_underlying state variable exists to short-circuit further
                                120                 :                :      * subplan calls.  It's not optional, unfortunately, because some plan
                                121                 :                :      * node types are not robust about being called again when they've already
                                122                 :                :      * returned NULL.
                                123                 :                :      */
                                124   [ +  +  +  + ]:          71870 :     if (eof_tuplestore && !node->eof_underlying)
                                125                 :                :     {
                                126                 :                :         PlanState  *outerNode;
                                127                 :                :         TupleTableSlot *outerslot;
                                128                 :                : 
                                129                 :                :         /*
                                130                 :                :          * We can only get here with forward==true, so no need to worry about
                                131                 :                :          * which direction the subplan will go.
                                132                 :                :          */
                                133                 :          15623 :         outerNode = outerPlanState(node);
                                134                 :          15623 :         outerslot = ExecProcNode(outerNode);
                                135   [ +  +  +  + ]:          15623 :         if (TupIsNull(outerslot))
                                136                 :                :         {
                                137                 :           1232 :             node->eof_underlying = true;
                                138                 :           1232 :             return NULL;
                                139                 :                :         }
                                140                 :                : 
                                141                 :                :         /*
                                142                 :                :          * Append a copy of the returned tuple to tuplestore.  NOTE: because
                                143                 :                :          * the tuplestore is certainly in EOF state, its read position will
                                144                 :                :          * move forward over the added tuple.  This is what we want.
                                145                 :                :          */
 6620                           146         [ +  + ]:          14391 :         if (tuplestorestate)
 6501                           147                 :          14329 :             tuplestore_puttupleslot(tuplestorestate, outerslot);
                                148                 :                : 
 1977 andres@anarazel.de        149                 :          14391 :         ExecCopySlot(slot, outerslot);
                                150                 :          14391 :         return slot;
                                151                 :                :     }
                                152                 :                : 
                                153                 :                :     /*
                                154                 :                :      * Nothing left ...
                                155                 :                :      */
 6501 tgl@sss.pgh.pa.us         156                 :          56247 :     return ExecClearTuple(slot);
                                157                 :                : }
                                158                 :                : 
                                159                 :                : /* ----------------------------------------------------------------
                                160                 :                :  *      ExecInitMaterial
                                161                 :                :  * ----------------------------------------------------------------
                                162                 :                :  */
                                163                 :                : MaterialState *
 6620                           164                 :           1869 : ExecInitMaterial(Material *node, EState *estate, int eflags)
                                165                 :                : {
                                166                 :                :     MaterialState *matstate;
                                167                 :                :     Plan       *outerPlan;
                                168                 :                : 
                                169                 :                :     /*
                                170                 :                :      * create state structure
                                171                 :                :      */
 9716 bruce@momjian.us          172                 :           1869 :     matstate = makeNode(MaterialState);
 7801 tgl@sss.pgh.pa.us         173                 :           1869 :     matstate->ss.ps.plan = (Plan *) node;
                                174                 :           1869 :     matstate->ss.ps.state = estate;
 2463 andres@anarazel.de        175                 :           1869 :     matstate->ss.ps.ExecProcNode = ExecMaterial;
                                176                 :                : 
                                177                 :                :     /*
                                178                 :                :      * We must have a tuplestore buffering the subplan output to do backward
                                179                 :                :      * scan or mark/restore.  We also prefer to materialize the subplan output
                                180                 :                :      * if we might be called on to rewind and replay it many times. However,
                                181                 :                :      * if none of these cases apply, we can skip storing the data.
                                182                 :                :      */
 6173 tgl@sss.pgh.pa.us         183                 :           1869 :     matstate->eflags = (eflags & (EXEC_FLAG_REWIND |
                                184                 :                :                                   EXEC_FLAG_BACKWARD |
                                185                 :                :                                   EXEC_FLAG_MARK));
                                186                 :                : 
                                187                 :                :     /*
                                188                 :                :      * Tuplestore's interpretation of the flag bits is subtly different from
                                189                 :                :      * the general executor meaning: it doesn't think BACKWARD necessarily
                                190                 :                :      * means "backwards all the way to start".  If told to support BACKWARD we
                                191                 :                :      * must include REWIND in the tuplestore eflags, else tuplestore_trim
                                192                 :                :      * might throw away too much.
                                193                 :                :      */
 5587                           194         [ +  + ]:           1869 :     if (eflags & EXEC_FLAG_BACKWARD)
                                195                 :              9 :         matstate->eflags |= EXEC_FLAG_REWIND;
                                196                 :                : 
 7707                           197                 :           1869 :     matstate->eof_underlying = false;
 6620                           198                 :           1869 :     matstate->tuplestorestate = NULL;
                                199                 :                : 
                                200                 :                :     /*
                                201                 :                :      * Miscellaneous initialization
                                202                 :                :      *
                                203                 :                :      * Materialization nodes don't need ExprContexts because they never call
                                204                 :                :      * ExecQual or ExecProject.
                                205                 :                :      */
                                206                 :                : 
                                207                 :                :     /*
                                208                 :                :      * initialize child nodes
                                209                 :                :      *
                                210                 :                :      * We shield the child node from the need to support REWIND, BACKWARD, or
                                211                 :                :      * MARK/RESTORE.
                                212                 :                :      */
                                213                 :           1869 :     eflags &= ~(EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK);
                                214                 :                : 
 7801                           215                 :           1869 :     outerPlan = outerPlan(node);
 6620                           216                 :           1869 :     outerPlanState(matstate) = ExecInitNode(outerPlan, estate, eflags);
                                217                 :                : 
                                218                 :                :     /*
                                219                 :                :      * Initialize result type and slot. No need to initialize projection info
                                220                 :                :      * because this node doesn't do projections.
                                221                 :                :      *
                                222                 :                :      * material nodes only return tuples from their materialized relation.
                                223                 :                :      */
 1977 andres@anarazel.de        224                 :           1869 :     ExecInitResultTupleSlotTL(&matstate->ss.ps, &TTSOpsMinimalTuple);
 7801 tgl@sss.pgh.pa.us         225                 :           1869 :     matstate->ss.ps.ps_ProjInfo = NULL;
                                226                 :                : 
                                227                 :                :     /*
                                228                 :                :      * initialize tuple type.
                                229                 :                :      */
 1977 andres@anarazel.de        230                 :           1869 :     ExecCreateScanSlotFromOuterPlan(estate, &matstate->ss, &TTSOpsMinimalTuple);
                                231                 :                : 
 7801 tgl@sss.pgh.pa.us         232                 :           1869 :     return matstate;
                                233                 :                : }
                                234                 :                : 
                                235                 :                : /* ----------------------------------------------------------------
                                236                 :                :  *      ExecEndMaterial
                                237                 :                :  * ----------------------------------------------------------------
                                238                 :                :  */
                                239                 :                : void
                                240                 :           1838 : ExecEndMaterial(MaterialState *node)
                                241                 :                : {
                                242                 :                :     /*
                                243                 :                :      * Release tuplestore resources
                                244                 :                :      */
                                245         [ +  + ]:           1838 :     if (node->tuplestorestate != NULL)
 5674                           246                 :           1287 :         tuplestore_end(node->tuplestorestate);
 7801                           247                 :           1838 :     node->tuplestorestate = NULL;
                                248                 :                : 
                                249                 :                :     /*
                                250                 :                :      * shut down the subplan
                                251                 :                :      */
 7791                           252                 :           1838 :     ExecEndNode(outerPlanState(node));
 9716 bruce@momjian.us          253                 :           1838 : }
                                254                 :                : 
                                255                 :                : /* ----------------------------------------------------------------
                                256                 :                :  *      ExecMaterialMarkPos
                                257                 :                :  *
                                258                 :                :  *      Calls tuplestore to save the current position in the stored file.
                                259                 :                :  * ----------------------------------------------------------------
                                260                 :                :  */
                                261                 :                : void
 7801 tgl@sss.pgh.pa.us         262                 :           3318 : ExecMaterialMarkPos(MaterialState *node)
                                263                 :                : {
 6173                           264         [ -  + ]:           3318 :     Assert(node->eflags & EXEC_FLAG_MARK);
                                265                 :                : 
                                266                 :                :     /*
                                267                 :                :      * if we haven't materialized yet, just return.
                                268                 :                :      */
 7801                           269         [ +  + ]:           3318 :     if (!node->tuplestorestate)
 9557 vadim4o@yahoo.com         270                 :              6 :         return;
                                271                 :                : 
                                272                 :                :     /*
                                273                 :                :      * copy the active read pointer to the mark.
                                274                 :                :      */
 5674 tgl@sss.pgh.pa.us         275                 :           3312 :     tuplestore_copy_read_pointer(node->tuplestorestate, 0, 1);
                                276                 :                : 
                                277                 :                :     /*
                                278                 :                :      * since we may have advanced the mark, try to truncate the tuplestore.
                                279                 :                :      */
 5587                           280                 :           3312 :     tuplestore_trim(node->tuplestorestate);
                                281                 :                : }
                                282                 :                : 
                                283                 :                : /* ----------------------------------------------------------------
                                284                 :                :  *      ExecMaterialRestrPos
                                285                 :                :  *
                                286                 :                :  *      Calls tuplestore to restore the last saved file position.
                                287                 :                :  * ----------------------------------------------------------------
                                288                 :                :  */
                                289                 :                : void
 7801                           290                 :          27151 : ExecMaterialRestrPos(MaterialState *node)
                                291                 :                : {
 6173                           292         [ -  + ]:          27151 :     Assert(node->eflags & EXEC_FLAG_MARK);
                                293                 :                : 
                                294                 :                :     /*
                                295                 :                :      * if we haven't materialized yet, just return.
                                296                 :                :      */
 7801                           297         [ -  + ]:          27151 :     if (!node->tuplestorestate)
 8701 tgl@sss.pgh.pa.us         298                 :UBC           0 :         return;
                                299                 :                : 
                                300                 :                :     /*
                                301                 :                :      * copy the mark to the active read pointer.
                                302                 :                :      */
 5674 tgl@sss.pgh.pa.us         303                 :CBC       27151 :     tuplestore_copy_read_pointer(node->tuplestorestate, 1, 0);
                                304                 :                : }
                                305                 :                : 
                                306                 :                : /* ----------------------------------------------------------------
                                307                 :                :  *      ExecReScanMaterial
                                308                 :                :  *
                                309                 :                :  *      Rescans the materialized relation.
                                310                 :                :  * ----------------------------------------------------------------
                                311                 :                :  */
                                312                 :                : void
 5025                           313                 :          60884 : ExecReScanMaterial(MaterialState *node)
                                314                 :                : {
 3249 bruce@momjian.us          315                 :          60884 :     PlanState  *outerPlan = outerPlanState(node);
                                316                 :                : 
 7801 tgl@sss.pgh.pa.us         317                 :          60884 :     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
                                318                 :                : 
 6173                           319         [ +  + ]:          60884 :     if (node->eflags != 0)
                                320                 :                :     {
                                321                 :                :         /*
                                322                 :                :          * If we haven't materialized yet, just return. If outerplan's
                                323                 :                :          * chgParam is not NULL then it will be re-scanned by ExecProcNode,
                                324                 :                :          * else no reason to re-scan it at all.
                                325                 :                :          */
 6620                           326         [ +  + ]:          60882 :         if (!node->tuplestorestate)
                                327                 :           1255 :             return;
                                328                 :                : 
                                329                 :                :         /*
                                330                 :                :          * If subnode is to be rescanned then we forget previous stored
                                331                 :                :          * results; we have to re-read the subplan and re-store.  Also, if we
                                332                 :                :          * told tuplestore it needn't support rescan, we lose and must
                                333                 :                :          * re-read.  (This last should not happen in common cases; else our
                                334                 :                :          * caller lied by not passing EXEC_FLAG_REWIND to us.)
                                335                 :                :          *
                                336                 :                :          * Otherwise we can just rewind and rescan the stored output. The
                                337                 :                :          * state of the subnode does not change.
                                338                 :                :          */
 3268 rhaas@postgresql.org      339         [ +  + ]:          59627 :         if (outerPlan->chgParam != NULL ||
 6173 tgl@sss.pgh.pa.us         340         [ -  + ]:          59621 :             (node->eflags & EXEC_FLAG_REWIND) == 0)
                                341                 :                :         {
 5674                           342                 :              6 :             tuplestore_end(node->tuplestorestate);
 6620                           343                 :              6 :             node->tuplestorestate = NULL;
 3268 rhaas@postgresql.org      344         [ -  + ]:              6 :             if (outerPlan->chgParam == NULL)
 3268 rhaas@postgresql.org      345                 :UBC           0 :                 ExecReScan(outerPlan);
 6620 tgl@sss.pgh.pa.us         346                 :CBC           6 :             node->eof_underlying = false;
                                347                 :                :         }
                                348                 :                :         else
 5674                           349                 :          59621 :             tuplestore_rescan(node->tuplestorestate);
                                350                 :                :     }
                                351                 :                :     else
                                352                 :                :     {
                                353                 :                :         /* In this case we are just passing on the subquery's output */
                                354                 :                : 
                                355                 :                :         /*
                                356                 :                :          * if chgParam of subnode is not null then plan will be re-scanned by
                                357                 :                :          * first ExecProcNode.
                                358                 :                :          */
 3268 rhaas@postgresql.org      359         [ -  + ]:              2 :         if (outerPlan->chgParam == NULL)
 3268 rhaas@postgresql.org      360                 :UBC           0 :             ExecReScan(outerPlan);
 6620 tgl@sss.pgh.pa.us         361                 :CBC           2 :         node->eof_underlying = false;
                                362                 :                :     }
                                363                 :                : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622