LCOV - differential code coverage report
Current view: top level - src/backend/executor - nodeGroup.c (source / functions) Coverage Total Hit UBC CBC
Current: bed3ffbf9d952be6c7d739d068cdce44c046dfb7 vs 574581b50ac9c63dd9e4abebb731a3b67e5b50f6 Lines: 93.7 % 63 59 4 59
Current Date: 2026-05-05 10:23:31 +0900 Functions: 100.0 % 4 4 4
Baseline: lcov-20260505-025707-baseline Branches: 63.3 % 30 19 11 19
Baseline Date: 2026-05-05 10:27:06 +0900 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(360..) days: 93.7 % 63 59 4 59
Function coverage date bins:
(360..) days: 100.0 % 4 4 4
Branch coverage date bins:
(360..) days: 63.3 % 30 19 11 19

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * nodeGroup.c
                                  4                 :                :  *    Routines to handle group nodes (used for queries with GROUP BY clause).
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *
                                 10                 :                :  * DESCRIPTION
                                 11                 :                :  *    The Group node is designed for handling queries with a GROUP BY clause.
                                 12                 :                :  *    Its outer plan must deliver tuples that are sorted in the order
                                 13                 :                :  *    specified by the grouping columns (ie. tuples from the same group are
                                 14                 :                :  *    consecutive).  That way, we just have to compare adjacent tuples to
                                 15                 :                :  *    locate group boundaries.
                                 16                 :                :  *
                                 17                 :                :  * IDENTIFICATION
                                 18                 :                :  *    src/backend/executor/nodeGroup.c
                                 19                 :                :  *
                                 20                 :                :  *-------------------------------------------------------------------------
                                 21                 :                :  */
                                 22                 :                : 
                                 23                 :                : #include "postgres.h"
                                 24                 :                : 
                                 25                 :                : #include "executor/executor.h"
                                 26                 :                : #include "executor/instrument.h"
                                 27                 :                : #include "executor/nodeGroup.h"
                                 28                 :                : #include "miscadmin.h"
                                 29                 :                : 
                                 30                 :                : 
                                 31                 :                : /*
                                 32                 :                :  *   ExecGroup -
                                 33                 :                :  *
                                 34                 :                :  *      Return one tuple for each group of matching input tuples.
                                 35                 :                :  */
                                 36                 :                : static TupleTableSlot *
 3214 andres@anarazel.de         37                 :CBC        4977 : ExecGroup(PlanState *pstate)
                                 38                 :                : {
                                 39                 :           4977 :     GroupState *node = castNode(GroupState, pstate);
                                 40                 :                :     ExprContext *econtext;
                                 41                 :                :     TupleTableSlot *firsttupleslot;
                                 42                 :                :     TupleTableSlot *outerslot;
                                 43                 :                : 
 3206                            44         [ -  + ]:           4977 :     CHECK_FOR_INTERRUPTS();
                                 45                 :                : 
                                 46                 :                :     /*
                                 47                 :                :      * get state info from node
                                 48                 :                :      */
 8552 tgl@sss.pgh.pa.us          49         [ -  + ]:           4977 :     if (node->grp_done)
10467 bruce@momjian.us           50                 :UBC           0 :         return NULL;
 8552 tgl@sss.pgh.pa.us          51                 :CBC        4977 :     econtext = node->ss.ps.ps_ExprContext;
                                 52                 :                : 
                                 53                 :                :     /*
                                 54                 :                :      * The ScanTupleSlot holds the (copied) first tuple of each group.
                                 55                 :                :      */
 7720                            56                 :           4977 :     firsttupleslot = node->ss.ss_ScanTupleSlot;
                                 57                 :                : 
                                 58                 :                :     /*
                                 59                 :                :      * We need not call ResetExprContext here because ExecQualAndReset() will
                                 60                 :                :      * reset the per-tuple memory context once per input tuple.
                                 61                 :                :      */
                                 62                 :                : 
                                 63                 :                :     /*
                                 64                 :                :      * If first time through, acquire first input tuple and determine whether
                                 65                 :                :      * to return it or not.
                                 66                 :                :      */
                                 67   [ +  -  +  + ]:           4977 :     if (TupIsNull(firsttupleslot))
                                 68                 :                :     {
 8552                            69                 :            112 :         outerslot = ExecProcNode(outerPlanState(node));
10021 vadim4o@yahoo.com          70   [ +  +  +  + ]:            112 :         if (TupIsNull(outerslot))
                                 71                 :                :         {
                                 72                 :                :             /* empty input, so return nothing */
 3184 peter_e@gmx.net            73                 :             25 :             node->grp_done = true;
10467 bruce@momjian.us           74                 :             25 :             return NULL;
                                 75                 :                :         }
                                 76                 :                :         /* Copy tuple into firsttupleslot */
 7720 tgl@sss.pgh.pa.us          77                 :             87 :         ExecCopySlot(firsttupleslot, outerslot);
                                 78                 :                : 
                                 79                 :                :         /*
                                 80                 :                :          * Set it up as input for qual test and projection.  The expressions
                                 81                 :                :          * will access the input tuple as varno OUTER.
                                 82                 :                :          */
 7012                            83                 :             87 :         econtext->ecxt_outertuple = firsttupleslot;
                                 84                 :                : 
                                 85                 :                :         /*
                                 86                 :                :          * Check the qual (HAVING clause); if the group does not match, ignore
                                 87                 :                :          * it and fall into scan loop.
                                 88                 :                :          */
 3339 andres@anarazel.de         89         [ +  - ]:             87 :         if (ExecQual(node->ss.ps.qual, econtext))
                                 90                 :                :         {
                                 91                 :                :             /*
                                 92                 :                :              * Form and return a projection tuple using the first input tuple.
                                 93                 :                :              */
 3393                            94                 :             87 :             return ExecProject(node->ss.ps.ps_ProjInfo);
                                 95                 :                :         }
                                 96                 :                :         else
 5339 tgl@sss.pgh.pa.us          97         [ #  # ]:UBC           0 :             InstrCountFiltered1(node, 1);
                                 98                 :                :     }
                                 99                 :                : 
                                100                 :                :     /*
                                101                 :                :      * This loop iterates once per input tuple group.  At the head of the
                                102                 :                :      * loop, we have finished processing the first tuple of the group and now
                                103                 :                :      * need to scan over all the other group members.
                                104                 :                :      */
10467 bruce@momjian.us          105                 :              0 :     for (;;)
                                106                 :                :     {
                                107                 :                :         /*
                                108                 :                :          * Scan over all remaining tuples that belong to this group
                                109                 :                :          */
                                110                 :                :         for (;;)
                                111                 :                :         {
 7726 tgl@sss.pgh.pa.us         112                 :CBC       43975 :             outerslot = ExecProcNode(outerPlanState(node));
                                113   [ +  +  +  + ]:          24420 :             if (TupIsNull(outerslot))
                                114                 :                :             {
                                115                 :                :                 /* no more groups, so we're done */
 3184 peter_e@gmx.net           116                 :             87 :                 node->grp_done = true;
 7726 tgl@sss.pgh.pa.us         117                 :             87 :                 return NULL;
                                118                 :                :             }
                                119                 :                : 
                                120                 :                :             /*
                                121                 :                :              * Compare with first tuple and see if this tuple is of the same
                                122                 :                :              * group.  If so, ignore it and keep scanning.
                                123                 :                :              */
 3001 andres@anarazel.de        124                 :          24333 :             econtext->ecxt_innertuple = firsttupleslot;
                                125                 :          24333 :             econtext->ecxt_outertuple = outerslot;
                                126         [ +  + ]:          24333 :             if (!ExecQualAndReset(node->eqfunction, econtext))
 7726 tgl@sss.pgh.pa.us         127                 :           4778 :                 break;
                                128                 :                :         }
                                129                 :                : 
                                130                 :                :         /*
                                131                 :                :          * We have the first tuple of the next input group.  See if we want to
                                132                 :                :          * return it.
                                133                 :                :          */
                                134                 :                :         /* Copy tuple, set up as input for qual test and projection */
 7720                           135                 :           4778 :         ExecCopySlot(firsttupleslot, outerslot);
 7012                           136                 :           4778 :         econtext->ecxt_outertuple = firsttupleslot;
                                137                 :                : 
                                138                 :                :         /*
                                139                 :                :          * Check the qual (HAVING clause); if the group does not match, ignore
                                140                 :                :          * it and loop back to scan the rest of the group.
                                141                 :                :          */
 3339 andres@anarazel.de        142         [ +  - ]:           4778 :         if (ExecQual(node->ss.ps.qual, econtext))
                                143                 :                :         {
                                144                 :                :             /*
                                145                 :                :              * Form and return a projection tuple using the first input tuple.
                                146                 :                :              */
 3393                           147                 :           4778 :             return ExecProject(node->ss.ps.ps_ProjInfo);
                                148                 :                :         }
                                149                 :                :         else
 5339 tgl@sss.pgh.pa.us         150         [ #  # ]:UBC           0 :             InstrCountFiltered1(node, 1);
                                151                 :                :     }
                                152                 :                : }
                                153                 :                : 
                                154                 :                : /* -----------------
                                155                 :                :  * ExecInitGroup
                                156                 :                :  *
                                157                 :                :  *  Creates the run-time information for the group node produced by the
                                158                 :                :  *  planner and initializes its outer subtree
                                159                 :                :  * -----------------
                                160                 :                :  */
                                161                 :                : GroupState *
 7371 tgl@sss.pgh.pa.us         162                 :CBC         166 : ExecInitGroup(Group *node, EState *estate, int eflags)
                                163                 :                : {
                                164                 :                :     GroupState *grpstate;
                                165                 :                :     const TupleTableSlotOps *tts_ops;
                                166                 :                : 
                                167                 :                :     /* check for unsupported flags */
                                168         [ -  + ]:            166 :     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
                                169                 :                : 
                                170                 :                :     /*
                                171                 :                :      * create state structure
                                172                 :                :      */
10467 bruce@momjian.us          173                 :            166 :     grpstate = makeNode(GroupState);
 8552 tgl@sss.pgh.pa.us         174                 :            166 :     grpstate->ss.ps.plan = (Plan *) node;
                                175                 :            166 :     grpstate->ss.ps.state = estate;
 3214 andres@anarazel.de        176                 :            166 :     grpstate->ss.ps.ExecProcNode = ExecGroup;
 3184 peter_e@gmx.net           177                 :            166 :     grpstate->grp_done = false;
                                178                 :                : 
                                179                 :                :     /*
                                180                 :                :      * create expression context
                                181                 :                :      */
 8552 tgl@sss.pgh.pa.us         182                 :            166 :     ExecAssignExprContext(estate, &grpstate->ss.ps);
                                183                 :                : 
                                184                 :                :     /*
                                185                 :                :      * initialize child nodes
                                186                 :                :      */
 7371                           187                 :            166 :     outerPlanState(grpstate) = ExecInitNode(outerPlan(node), estate, eflags);
                                188                 :                : 
                                189                 :                :     /*
                                190                 :                :      * Initialize scan slot and type.
                                191                 :                :      */
 2728 andres@anarazel.de        192                 :            166 :     tts_ops = ExecGetResultSlotOps(outerPlanState(&grpstate->ss), NULL);
                                193                 :            166 :     ExecCreateScanSlotFromOuterPlan(estate, &grpstate->ss, tts_ops);
                                194                 :                : 
                                195                 :                :     /*
                                196                 :                :      * Initialize result slot, type and projection.
                                197                 :                :      */
                                198                 :            166 :     ExecInitResultTupleSlotTL(&grpstate->ss.ps, &TTSOpsVirtual);
 7032 tgl@sss.pgh.pa.us         199                 :            166 :     ExecAssignProjectionInfo(&grpstate->ss.ps, NULL);
                                200                 :                : 
                                201                 :                :     /*
                                202                 :                :      * initialize child expressions
                                203                 :                :      */
 3000 andres@anarazel.de        204                 :            166 :     grpstate->ss.ps.qual =
                                205                 :            166 :         ExecInitQual(node->plan.qual, (PlanState *) grpstate);
                                206                 :                : 
                                207                 :                :     /*
                                208                 :                :      * Precompute fmgr lookup data for inner loop
                                209                 :                :      */
 3001                           210                 :            166 :     grpstate->eqfunction =
                                211                 :            166 :         execTuplesMatchPrepare(ExecGetResultType(outerPlanState(grpstate)),
                                212                 :                :                                node->numCols,
 2998 tgl@sss.pgh.pa.us         213                 :            166 :                                node->grpColIdx,
 3001 andres@anarazel.de        214                 :            166 :                                node->grpOperators,
 2601 peter@eisentraut.org      215                 :            166 :                                node->grpCollations,
                                216                 :                :                                &grpstate->ss.ps);
                                217                 :                : 
 8552 tgl@sss.pgh.pa.us         218                 :            166 :     return grpstate;
                                219                 :                : }
                                220                 :                : 
                                221                 :                : /* ------------------------
                                222                 :                :  *      ExecEndGroup(node)
                                223                 :                :  *
                                224                 :                :  * -----------------------
                                225                 :                :  */
                                226                 :                : void
                                227                 :            166 : ExecEndGroup(GroupState *node)
                                228                 :                : {
                                229                 :                :     PlanState  *outerPlan;
                                230                 :                : 
 8542                           231                 :            166 :     outerPlan = outerPlanState(node);
                                232                 :            166 :     ExecEndNode(outerPlan);
10892 scrappy@hub.org           233                 :            166 : }
                                234                 :                : 
                                235                 :                : void
 5776 tgl@sss.pgh.pa.us         236                 :             15 : ExecReScanGroup(GroupState *node)
                                237                 :                : {
 4000 bruce@momjian.us          238                 :             15 :     PlanState  *outerPlan = outerPlanState(node);
                                239                 :                : 
 3184 peter_e@gmx.net           240                 :             15 :     node->grp_done = false;
                                241                 :                :     /* must clear first tuple */
 7720 tgl@sss.pgh.pa.us         242                 :             15 :     ExecClearTuple(node->ss.ss_ScanTupleSlot);
                                243                 :                : 
                                244                 :                :     /*
                                245                 :                :      * if chgParam of subnode is not null then plan will be re-scanned by
                                246                 :                :      * first ExecProcNode.
                                247                 :                :      */
 4019 rhaas@postgresql.org      248         [ +  - ]:             15 :     if (outerPlan->chgParam == NULL)
                                249                 :             15 :         ExecReScan(outerPlan);
 9595 tgl@sss.pgh.pa.us         250                 :             15 : }
        

Generated by: LCOV version 2.5.0-beta