LCOV - differential code coverage report
Current view: top level - src/backend/executor - nodeGather.c (source / functions) Coverage Total Hit UBC CBC
Current: 0e5ff9b9b45a657aea12440478dc002e9b01f138 vs 0123ce131fca454009439dfa3b2266d1d40737d7 Lines: 99.3 % 140 139 1 139
Current Date: 2026-03-14 14:10:32 -0400 Functions: 100.0 % 8 8 8
Baseline: lcov-20260315-024220-baseline Branches: 90.2 % 82 74 8 74
Baseline Date: 2026-03-14 15:27:56 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(360..) days: 99.3 % 140 139 1 139
Function coverage date bins:
(360..) days: 100.0 % 8 8 8
Branch coverage date bins:
(360..) days: 90.2 % 82 74 8 74

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * nodeGather.c
                                  4                 :                :  *    Support routines for scanning a plan via multiple workers.
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  * A Gather executor launches parallel workers to run multiple copies of a
                                 10                 :                :  * plan.  It can also run the plan itself, if the workers are not available
                                 11                 :                :  * or have not started up yet.  It then merges all of the results it produces
                                 12                 :                :  * and the results from the workers into a single output stream.  Therefore,
                                 13                 :                :  * it will normally be used with a plan where running multiple copies of the
                                 14                 :                :  * same plan does not produce duplicate output, such as parallel-aware
                                 15                 :                :  * SeqScan.
                                 16                 :                :  *
                                 17                 :                :  * Alternatively, a Gather node can be configured to use just one worker
                                 18                 :                :  * and the single-copy flag can be set.  In this case, the Gather node will
                                 19                 :                :  * run the plan in one worker and will not execute the plan itself.  In
                                 20                 :                :  * this case, it simply returns whatever tuples were returned by the worker.
                                 21                 :                :  * If a worker cannot be obtained, then it will run the plan itself and
                                 22                 :                :  * return the results.  Therefore, a plan used with a single-copy Gather
                                 23                 :                :  * node need not be parallel-aware.
                                 24                 :                :  *
                                 25                 :                :  * IDENTIFICATION
                                 26                 :                :  *    src/backend/executor/nodeGather.c
                                 27                 :                :  *
                                 28                 :                :  *-------------------------------------------------------------------------
                                 29                 :                :  */
                                 30                 :                : 
                                 31                 :                : #include "postgres.h"
                                 32                 :                : 
                                 33                 :                : #include "executor/execParallel.h"
                                 34                 :                : #include "executor/executor.h"
                                 35                 :                : #include "executor/nodeGather.h"
                                 36                 :                : #include "executor/tqueue.h"
                                 37                 :                : #include "miscadmin.h"
                                 38                 :                : #include "optimizer/optimizer.h"
                                 39                 :                : #include "storage/latch.h"
                                 40                 :                : #include "utils/wait_event.h"
                                 41                 :                : 
                                 42                 :                : 
                                 43                 :                : static TupleTableSlot *ExecGather(PlanState *pstate);
                                 44                 :                : static TupleTableSlot *gather_getnext(GatherState *gatherstate);
                                 45                 :                : static MinimalTuple gather_readnext(GatherState *gatherstate);
                                 46                 :                : static void ExecShutdownGatherWorkers(GatherState *node);
                                 47                 :                : 
                                 48                 :                : 
                                 49                 :                : /* ----------------------------------------------------------------
                                 50                 :                :  *      ExecInitGather
                                 51                 :                :  * ----------------------------------------------------------------
                                 52                 :                :  */
                                 53                 :                : GatherState *
 3819 rhaas@postgresql.org       54                 :CBC         587 : ExecInitGather(Gather *node, EState *estate, int eflags)
                                 55                 :                : {
                                 56                 :                :     GatherState *gatherstate;
                                 57                 :                :     Plan       *outerNode;
                                 58                 :                :     TupleDesc   tupDesc;
                                 59                 :                : 
                                 60                 :                :     /* Gather node doesn't have innerPlan node. */
                                 61         [ -  + ]:            587 :     Assert(innerPlan(node) == NULL);
                                 62                 :                : 
                                 63                 :                :     /*
                                 64                 :                :      * create state structure
                                 65                 :                :      */
                                 66                 :            587 :     gatherstate = makeNode(GatherState);
                                 67                 :            587 :     gatherstate->ps.plan = (Plan *) node;
                                 68                 :            587 :     gatherstate->ps.state = estate;
 3163 andres@anarazel.de         69                 :            587 :     gatherstate->ps.ExecProcNode = ExecGather;
                                 70                 :                : 
 3119 tgl@sss.pgh.pa.us          71                 :            587 :     gatherstate->initialized = false;
 3042 rhaas@postgresql.org       72                 :            587 :     gatherstate->need_to_scan_locally =
                                 73   [ +  +  +  + ]:            587 :         !node->single_copy && parallel_leader_participation;
 3120                            74                 :            587 :     gatherstate->tuples_needed = -1;
                                 75                 :                : 
                                 76                 :                :     /*
                                 77                 :                :      * Miscellaneous initialization
                                 78                 :                :      *
                                 79                 :                :      * create expression context for node
                                 80                 :                :      */
 3819                            81                 :            587 :     ExecAssignExprContext(estate, &gatherstate->ps);
                                 82                 :                : 
                                 83                 :                :     /*
                                 84                 :                :      * now initialize outer plan
                                 85                 :                :      */
 3791                            86                 :            587 :     outerNode = outerPlan(node);
                                 87                 :            587 :     outerPlanState(gatherstate) = ExecInitNode(outerNode, estate, eflags);
 2949 andres@anarazel.de         88                 :            587 :     tupDesc = ExecGetResultType(outerPlanState(gatherstate));
                                 89                 :                : 
                                 90                 :                :     /*
                                 91                 :                :      * Leader may access ExecProcNode result directly (if
                                 92                 :                :      * need_to_scan_locally), or from workers via tuple queue.  So we can't
                                 93                 :                :      * trivially rely on the slot type being fixed for expressions evaluated
                                 94                 :                :      * within this node.
                                 95                 :                :      */
 2677                            96                 :            587 :     gatherstate->ps.outeropsset = true;
                                 97                 :            587 :     gatherstate->ps.outeropsfixed = false;
                                 98                 :                : 
                                 99                 :                :     /*
                                100                 :                :      * Initialize result type and projection.
                                101                 :                :      */
 2683                           102                 :            587 :     ExecInitResultTypeTL(&gatherstate->ps);
 2949                           103                 :            587 :     ExecConditionalAssignProjectionInfo(&gatherstate->ps, tupDesc, OUTER_VAR);
                                104                 :                : 
                                105                 :                :     /*
                                106                 :                :      * Without projections result slot type is not trivially known, see
                                107                 :                :      * comment above.
                                108                 :                :      */
 2677                           109         [ +  + ]:            587 :     if (gatherstate->ps.ps_ProjInfo == NULL)
                                110                 :                :     {
                                111                 :            548 :         gatherstate->ps.resultopsset = true;
                                112                 :            548 :         gatherstate->ps.resultopsfixed = false;
                                113                 :                :     }
                                114                 :                : 
                                115                 :                :     /*
                                116                 :                :      * Initialize funnel slot to same tuple descriptor as outer plan.
                                117                 :                :      */
                                118                 :            587 :     gatherstate->funnel_slot = ExecInitExtraTupleSlot(estate, tupDesc,
                                119                 :                :                                                       &TTSOpsMinimalTuple);
                                120                 :                : 
                                121                 :                :     /*
                                122                 :                :      * Gather doesn't support checking a qual (it's always more efficient to
                                123                 :                :      * do it in the child node).
                                124                 :                :      */
 2949                           125         [ -  + ]:            587 :     Assert(!node->plan.qual);
                                126                 :                : 
 3819 rhaas@postgresql.org      127                 :            587 :     return gatherstate;
                                128                 :                : }
                                129                 :                : 
                                130                 :                : /* ----------------------------------------------------------------
                                131                 :                :  *      ExecGather(node)
                                132                 :                :  *
                                133                 :                :  *      Scans the relation via multiple workers and returns
                                134                 :                :  *      the next qualifying tuple.
                                135                 :                :  * ----------------------------------------------------------------
                                136                 :                :  */
                                137                 :                : static TupleTableSlot *
 3163 andres@anarazel.de        138                 :        1623180 : ExecGather(PlanState *pstate)
                                139                 :                : {
                                140                 :        1623180 :     GatherState *node = castNode(GatherState, pstate);
                                141                 :                :     TupleTableSlot *slot;
                                142                 :                :     ExprContext *econtext;
                                143                 :                : 
 3155                           144         [ +  + ]:        1623180 :     CHECK_FOR_INTERRUPTS();
                                145                 :                : 
                                146                 :                :     /*
                                147                 :                :      * Initialize the parallel context and workers on first execution. We do
                                148                 :                :      * this on first execution rather than during node initialization, as it
                                149                 :                :      * needs to allocate a large dynamic segment, so it is better to do it
                                150                 :                :      * only if it is really needed.
                                151                 :                :      */
 3803 rhaas@postgresql.org      152         [ +  + ]:        1623180 :     if (!node->initialized)
                                153                 :                :     {
 3819                           154                 :            450 :         EState     *estate = node->ps.state;
 3803                           155                 :            450 :         Gather     *gather = (Gather *) node->ps.plan;
                                156                 :                : 
                                157                 :                :         /*
                                158                 :                :          * Sometimes we might have to run without parallelism; but if parallel
                                159                 :                :          * mode is active then we can try to fire up some workers.
                                160                 :                :          */
 3061                           161   [ +  -  +  + ]:            450 :         if (gather->num_workers > 0 && estate->es_use_parallel_mode)
                                162                 :                :         {
                                163                 :                :             ParallelContext *pcxt;
                                164                 :                : 
                                165                 :                :             /* Initialize, or re-initialize, shared state needed by workers. */
 3789                           166         [ +  + ]:            429 :             if (!node->pei)
 1347 tgl@sss.pgh.pa.us         167                 :            315 :                 node->pei = ExecInitParallelPlan(outerPlanState(node),
                                168                 :                :                                                  estate,
                                169                 :                :                                                  gather->initParam,
                                170                 :                :                                                  gather->num_workers,
                                171                 :                :                                                  node->tuples_needed);
                                172                 :                :             else
                                173                 :            114 :                 ExecParallelReinitialize(outerPlanState(node),
 3041 rhaas@postgresql.org      174                 :            114 :                                          node->pei,
                                175                 :                :                                          gather->initParam);
                                176                 :                : 
                                177                 :                :             /*
                                178                 :                :              * Register backend workers. We might not get as many as we
                                179                 :                :              * requested, or indeed any at all.
                                180                 :                :              */
 3782                           181                 :            429 :             pcxt = node->pei->pcxt;
                                182                 :            429 :             LaunchParallelWorkers(pcxt);
                                183                 :                :             /* We save # workers launched for the benefit of EXPLAIN */
 3621                           184                 :            429 :             node->nworkers_launched = pcxt->nworkers_launched;
                                185                 :                : 
                                186                 :                :             /*
                                187                 :                :              * Count number of workers originally wanted and actually
                                188                 :                :              * launched.
                                189                 :                :              */
  522 michael@paquier.xyz       190                 :            429 :             estate->es_parallel_workers_to_launch += pcxt->nworkers_to_launch;
                                191                 :            429 :             estate->es_parallel_workers_launched += pcxt->nworkers_launched;
                                192                 :                : 
                                193                 :                :             /* Set up tuple queue readers to read the results. */
 3663 rhaas@postgresql.org      194         [ +  + ]:            429 :             if (pcxt->nworkers_launched > 0)
                                195                 :                :             {
 3104 andres@anarazel.de        196                 :            426 :                 ExecParallelCreateReaders(node->pei);
                                197                 :                :                 /* Make a working array showing the active readers */
 3117 tgl@sss.pgh.pa.us         198                 :            426 :                 node->nreaders = pcxt->nworkers_launched;
                                199                 :            426 :                 node->reader = (TupleQueueReader **)
                                200                 :            426 :                     palloc(node->nreaders * sizeof(TupleQueueReader *));
                                201                 :            426 :                 memcpy(node->reader, node->pei->reader,
                                202                 :            426 :                        node->nreaders * sizeof(TupleQueueReader *));
                                203                 :                :             }
                                204                 :                :             else
                                205                 :                :             {
                                206                 :                :                 /* No workers?  Then never mind. */
                                207                 :              3 :                 node->nreaders = 0;
                                208                 :              3 :                 node->reader = NULL;
                                209                 :                :             }
                                210                 :            429 :             node->nextreader = 0;
                                211                 :                :         }
                                212                 :                : 
                                213                 :                :         /* Run plan locally if no workers or enabled and not single-copy. */
                                214                 :            900 :         node->need_to_scan_locally = (node->nreaders == 0)
 3042 rhaas@postgresql.org      215   [ +  +  +  +  :            450 :             || (!gather->single_copy && parallel_leader_participation);
                                              +  + ]
 3803                           216                 :            450 :         node->initialized = true;
                                217                 :                :     }
                                218                 :                : 
                                219                 :                :     /*
                                220                 :                :      * Reset per-tuple memory context to free any expression evaluation
                                221                 :                :      * storage allocated in the previous tuple cycle.
                                222                 :                :      */
 3791                           223                 :        1623180 :     econtext = node->ps.ps_ExprContext;
                                224                 :        1623180 :     ResetExprContext(econtext);
                                225                 :                : 
                                226                 :                :     /*
                                227                 :                :      * Get next tuple, either from one of our workers, or by running the plan
                                228                 :                :      * ourselves.
                                229                 :                :      */
 3339 tgl@sss.pgh.pa.us         230                 :        1623180 :     slot = gather_getnext(node);
                                231   [ +  -  +  + ]:        1623174 :     if (TupIsNull(slot))
                                232                 :            426 :         return NULL;
                                233                 :                : 
                                234                 :                :     /* If no projection is required, we're done. */
 3032 rhaas@postgresql.org      235         [ +  + ]:        1622748 :     if (node->ps.ps_ProjInfo == NULL)
                                236                 :        1622730 :         return slot;
                                237                 :                : 
                                238                 :                :     /*
                                239                 :                :      * Form the result tuple using ExecProject(), and return it.
                                240                 :                :      */
 3339 tgl@sss.pgh.pa.us         241                 :             18 :     econtext->ecxt_outertuple = slot;
                                242                 :             18 :     return ExecProject(node->ps.ps_ProjInfo);
                                243                 :                : }
                                244                 :                : 
                                245                 :                : /* ----------------------------------------------------------------
                                246                 :                :  *      ExecEndGather
                                247                 :                :  *
                                248                 :                :  *      frees any storage allocated through C routines.
                                249                 :                :  * ----------------------------------------------------------------
                                250                 :                :  */
                                251                 :                : void
 3819 rhaas@postgresql.org      252                 :            581 : ExecEndGather(GatherState *node)
                                253                 :                : {
 3224 bruce@momjian.us          254                 :            581 :     ExecEndNode(outerPlanState(node));  /* let children clean up first */
 3819 rhaas@postgresql.org      255                 :            581 :     ExecShutdownGather(node);
                                256                 :            581 : }
                                257                 :                : 
                                258                 :                : /*
                                259                 :                :  * Read the next tuple.  We might fetch a tuple from one of the tuple queues
                                260                 :                :  * using gather_readnext, or if no tuple queue contains a tuple and the
                                261                 :                :  * single_copy flag is not set, we might generate one locally instead.
                                262                 :                :  */
                                263                 :                : static TupleTableSlot *
                                264                 :        1623180 : gather_getnext(GatherState *gatherstate)
                                265                 :                : {
 3791                           266                 :        1623180 :     PlanState  *outerPlan = outerPlanState(gatherstate);
                                267                 :                :     TupleTableSlot *outerTupleSlot;
                                268                 :        1623180 :     TupleTableSlot *fslot = gatherstate->funnel_slot;
                                269                 :                :     MinimalTuple tup;
                                270                 :                : 
 3117 tgl@sss.pgh.pa.us         271   [ +  +  +  + ]:        3247019 :     while (gatherstate->nreaders > 0 || gatherstate->need_to_scan_locally)
                                272                 :                :     {
 3155 andres@anarazel.de        273         [ +  + ]:        1623413 :         CHECK_FOR_INTERRUPTS();
                                274                 :                : 
 3117 tgl@sss.pgh.pa.us         275         [ +  + ]:        1623413 :         if (gatherstate->nreaders > 0)
                                276                 :                :         {
 3782 rhaas@postgresql.org      277                 :        1488197 :             tup = gather_readnext(gatherstate);
                                278                 :                : 
 3819                           279         [ +  + ]:        1488191 :             if (HeapTupleIsValid(tup))
                                280                 :                :             {
 1768 tgl@sss.pgh.pa.us         281                 :        1080925 :                 ExecStoreMinimalTuple(tup,  /* tuple to store */
                                282                 :                :                                       fslot,    /* slot to store the tuple */
                                283                 :                :                                       false);   /* don't pfree tuple  */
 3791 rhaas@postgresql.org      284                 :        1080925 :                 return fslot;
                                285                 :                :             }
                                286                 :                :         }
                                287                 :                : 
 3819                           288         [ +  + ]:         542482 :         if (gatherstate->need_to_scan_locally)
                                289                 :                :         {
 2880 tgl@sss.pgh.pa.us         290                 :         542128 :             EState     *estate = gatherstate->ps.state;
                                291                 :                : 
                                292                 :                :             /* Install our DSA area while executing the plan. */
 3009 rhaas@postgresql.org      293                 :         542128 :             estate->es_query_dsa =
                                294         [ +  + ]:         542128 :                 gatherstate->pei ? gatherstate->pei->area : NULL;
 3819                           295                 :         542128 :             outerTupleSlot = ExecProcNode(outerPlan);
 3009                           296                 :         542128 :             estate->es_query_dsa = NULL;
                                297                 :                : 
 3819                           298   [ +  +  +  + ]:         542128 :             if (!TupIsNull(outerTupleSlot))
                                299                 :         541823 :                 return outerTupleSlot;
                                300                 :                : 
                                301                 :            305 :             gatherstate->need_to_scan_locally = false;
                                302                 :                :         }
                                303                 :                :     }
                                304                 :                : 
 3791                           305                 :            426 :     return ExecClearTuple(fslot);
                                306                 :                : }
                                307                 :                : 
                                308                 :                : /*
                                309                 :                :  * Attempt to read a tuple from one of our parallel workers.
                                310                 :                :  */
                                311                 :                : static MinimalTuple
 3782                           312                 :        1488197 : gather_readnext(GatherState *gatherstate)
                                313                 :                : {
 3516 tgl@sss.pgh.pa.us         314                 :        1488197 :     int         nvisited = 0;
                                315                 :                : 
                                316                 :                :     for (;;)
 3782 rhaas@postgresql.org      317                 :        1065133 :     {
                                318                 :                :         TupleQueueReader *reader;
                                319                 :                :         MinimalTuple tup;
                                320                 :                :         bool        readerdone;
                                321                 :                : 
                                322                 :                :         /* Check for async events, particularly messages from workers. */
 3513 tgl@sss.pgh.pa.us         323         [ +  + ]:        2553330 :         CHECK_FOR_INTERRUPTS();
                                324                 :                : 
                                325                 :                :         /*
                                326                 :                :          * Attempt to read a tuple, but don't block if none is available.
                                327                 :                :          *
                                328                 :                :          * Note that TupleQueueReaderNext will just return NULL for a worker
                                329                 :                :          * which fails to initialize.  We'll treat that worker as having
                                330                 :                :          * produced no tuples; WaitForParallelWorkersToFinish will error out
                                331                 :                :          * when we get there.
                                332                 :                :          */
 3387 rhaas@postgresql.org      333         [ -  + ]:        2553324 :         Assert(gatherstate->nextreader < gatherstate->nreaders);
 3782                           334                 :        2553324 :         reader = gatherstate->reader[gatherstate->nextreader];
                                335                 :        2553324 :         tup = TupleQueueReaderNext(reader, true, &readerdone);
                                336                 :                : 
                                337                 :                :         /*
                                338                 :                :          * If this reader is done, remove it from our working array of active
                                339                 :                :          * readers.  If all readers are done, we're outta here.
                                340                 :                :          */
                                341         [ +  + ]:        2553324 :         if (readerdone)
                                342                 :                :         {
 3516 tgl@sss.pgh.pa.us         343         [ -  + ]:           1126 :             Assert(!tup);
 3782 rhaas@postgresql.org      344                 :           1126 :             --gatherstate->nreaders;
                                345         [ +  + ]:           1126 :             if (gatherstate->nreaders == 0)
                                346                 :                :             {
 2781 akapila@postgresql.o      347                 :            420 :                 ExecShutdownGatherWorkers(gatherstate);
 3782 rhaas@postgresql.org      348                 :        1488191 :                 return NULL;
                                349                 :                :             }
 3516 tgl@sss.pgh.pa.us         350                 :            706 :             memmove(&gatherstate->reader[gatherstate->nextreader],
                                351                 :            706 :                     &gatherstate->reader[gatherstate->nextreader + 1],
                                352                 :                :                     sizeof(TupleQueueReader *)
                                353                 :            706 :                     * (gatherstate->nreaders - gatherstate->nextreader));
                                354         [ +  + ]:            706 :             if (gatherstate->nextreader >= gatherstate->nreaders)
                                355                 :            235 :                 gatherstate->nextreader = 0;
 3782 rhaas@postgresql.org      356                 :            706 :             continue;
                                357                 :                :         }
                                358                 :                : 
                                359                 :                :         /* If we got a tuple, return it. */
                                360         [ +  + ]:        2552198 :         if (tup)
                                361                 :        1080925 :             return tup;
                                362                 :                : 
                                363                 :                :         /*
                                364                 :                :          * Advance nextreader pointer in round-robin fashion.  Note that we
                                365                 :                :          * only reach this code if we weren't able to get a tuple from the
                                366                 :                :          * current worker.  We used to advance the nextreader pointer after
                                367                 :                :          * every tuple, but it turns out to be much more efficient to keep
                                368                 :                :          * reading from the same queue until that would require blocking.
                                369                 :                :          */
 3516 tgl@sss.pgh.pa.us         370                 :        1471273 :         gatherstate->nextreader++;
                                371         [ +  + ]:        1471273 :         if (gatherstate->nextreader >= gatherstate->nreaders)
                                372                 :         410498 :             gatherstate->nextreader = 0;
                                373                 :                : 
                                374                 :                :         /* Have we visited every (surviving) TupleQueueReader? */
                                375                 :        1471273 :         nvisited++;
                                376         [ +  + ]:        1471273 :         if (nvisited >= gatherstate->nreaders)
                                377                 :                :         {
                                378                 :                :             /*
                                379                 :                :              * If (still) running plan locally, return NULL so caller can
                                380                 :                :              * generate another tuple from the local copy of the plan.
                                381                 :                :              */
 3782 rhaas@postgresql.org      382         [ +  + ]:         410197 :             if (gatherstate->need_to_scan_locally)
                                383                 :         406846 :                 return NULL;
                                384                 :                : 
                                385                 :                :             /* Nothing to do except wait for developments. */
 2669 tmunro@postgresql.or      386                 :           3351 :             (void) WaitLatch(MyLatch, WL_LATCH_SET | WL_EXIT_ON_PM_DEATH, 0,
                                387                 :                :                              WAIT_EVENT_EXECUTE_GATHER);
 3782 rhaas@postgresql.org      388                 :           3351 :             ResetLatch(MyLatch);
 3516 tgl@sss.pgh.pa.us         389                 :           3351 :             nvisited = 0;
                                390                 :                :         }
                                391                 :                :     }
                                392                 :                : }
                                393                 :                : 
                                394                 :                : /* ----------------------------------------------------------------
                                395                 :                :  *      ExecShutdownGatherWorkers
                                396                 :                :  *
                                397                 :                :  *      Stop all the parallel workers.
                                398                 :                :  * ----------------------------------------------------------------
                                399                 :                :  */
                                400                 :                : static void
 3789 rhaas@postgresql.org      401                 :           1487 : ExecShutdownGatherWorkers(GatherState *node)
                                402                 :                : {
 3803                           403         [ +  + ]:           1487 :     if (node->pei != NULL)
                                404                 :            843 :         ExecParallelFinish(node->pei);
                                405                 :                : 
                                406                 :                :     /* Flush local copy of reader array */
 3117 tgl@sss.pgh.pa.us         407         [ +  + ]:           1487 :     if (node->reader)
                                408                 :            420 :         pfree(node->reader);
                                409                 :           1487 :     node->reader = NULL;
 3789 rhaas@postgresql.org      410                 :           1487 : }
                                411                 :                : 
                                412                 :                : /* ----------------------------------------------------------------
                                413                 :                :  *      ExecShutdownGather
                                414                 :                :  *
                                415                 :                :  *      Destroy the setup for parallel workers including parallel context.
                                416                 :                :  * ----------------------------------------------------------------
                                417                 :                :  */
                                418                 :                : void
                                419                 :            917 : ExecShutdownGather(GatherState *node)
                                420                 :                : {
                                421                 :            917 :     ExecShutdownGatherWorkers(node);
                                422                 :                : 
                                423                 :                :     /* Now destroy the parallel context. */
                                424         [ +  + ]:            917 :     if (node->pei != NULL)
                                425                 :                :     {
 3803                           426                 :            309 :         ExecParallelCleanup(node->pei);
                                427                 :            309 :         node->pei = NULL;
                                428                 :                :     }
 3819                           429                 :            917 : }
                                430                 :                : 
                                431                 :                : /* ----------------------------------------------------------------
                                432                 :                :  *                      Join Support
                                433                 :                :  * ----------------------------------------------------------------
                                434                 :                :  */
                                435                 :                : 
                                436                 :                : /* ----------------------------------------------------------------
                                437                 :                :  *      ExecReScanGather
                                438                 :                :  *
                                439                 :                :  *      Prepare to re-scan the result of a Gather.
                                440                 :                :  * ----------------------------------------------------------------
                                441                 :                :  */
                                442                 :                : void
                                443                 :            150 : ExecReScanGather(GatherState *node)
                                444                 :                : {
 3119 tgl@sss.pgh.pa.us         445                 :            150 :     Gather     *gather = (Gather *) node->ps.plan;
                                446                 :            150 :     PlanState  *outerPlan = outerPlanState(node);
                                447                 :                : 
                                448                 :                :     /* Make sure any existing workers are gracefully shut down */
 3789 rhaas@postgresql.org      449                 :            150 :     ExecShutdownGatherWorkers(node);
                                450                 :                : 
                                451                 :                :     /* Mark node so that shared state will be rebuilt at next call */
 3803                           452                 :            150 :     node->initialized = false;
                                453                 :                : 
                                454                 :                :     /*
                                455                 :                :      * Set child node's chgParam to tell it that the next scan might deliver a
                                456                 :                :      * different set of rows within the leader process.  (The overall rowset
                                457                 :                :      * shouldn't change, but the leader process's subset might; hence nodes
                                458                 :                :      * between here and the parallel table scan node mustn't optimize on the
                                459                 :                :      * assumption of an unchanging rowset.)
                                460                 :                :      */
 3119 tgl@sss.pgh.pa.us         461         [ +  - ]:            150 :     if (gather->rescan_param >= 0)
                                462                 :            150 :         outerPlan->chgParam = bms_add_member(outerPlan->chgParam,
                                463                 :                :                                              gather->rescan_param);
                                464                 :                : 
                                465                 :                :     /*
                                466                 :                :      * If chgParam of subnode is not null then plan will be re-scanned by
                                467                 :                :      * first ExecProcNode.  Note: because this does nothing if we have a
                                468                 :                :      * rescan_param, it's currently guaranteed that parallel-aware child nodes
                                469                 :                :      * will not see a ReScan call until after they get a ReInitializeDSM call.
                                470                 :                :      * That ordering might not be something to rely on, though.  A good rule
                                471                 :                :      * of thumb is that ReInitializeDSM should reset only shared state, ReScan
                                472                 :                :      * should reset only local state, and anything that depends on both of
                                473                 :                :      * those steps being finished must wait until the first ExecProcNode call.
                                474                 :                :      */
                                475         [ -  + ]:            150 :     if (outerPlan->chgParam == NULL)
 3119 tgl@sss.pgh.pa.us         476                 :UBC           0 :         ExecReScan(outerPlan);
 3819 rhaas@postgresql.org      477                 :CBC         150 : }
        

Generated by: LCOV version 2.4-beta