LCOV - differential code coverage report
Current view: top level - src/backend/executor - nodeUnique.c (source / functions) Coverage Total Hit UNC UIC UBC CBC EUB
Current: Differential Code Coverage HEAD vs 15 Lines: 86.0 % 43 37 3 1 2 37 4
Current Date: 2023-04-08 15:15:32 Functions: 75.0 % 4 3 1 3
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * nodeUnique.c
       4                 :  *    Routines to handle unique'ing of queries where appropriate
       5                 :  *
       6                 :  * Unique is a very simple node type that just filters out duplicate
       7                 :  * tuples from a stream of sorted tuples from its subplan.  It's essentially
       8                 :  * a dumbed-down form of Group: the duplicate-removal functionality is
       9                 :  * identical.  However, Unique doesn't do projection nor qual checking,
      10                 :  * so it's marginally more efficient for cases where neither is needed.
      11                 :  * (It's debatable whether the savings justifies carrying two plan node
      12                 :  * types, though.)
      13                 :  *
      14                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
      15                 :  * Portions Copyright (c) 1994, Regents of the University of California
      16                 :  *
      17                 :  *
      18                 :  * IDENTIFICATION
      19                 :  *    src/backend/executor/nodeUnique.c
      20                 :  *
      21                 :  *-------------------------------------------------------------------------
      22                 :  */
      23                 : /*
      24                 :  * INTERFACE ROUTINES
      25                 :  *      ExecUnique      - generate a unique'd temporary relation
      26                 :  *      ExecInitUnique  - initialize node and subnodes
      27                 :  *      ExecEndUnique   - shutdown node and subnodes
      28                 :  *
      29                 :  * NOTES
      30                 :  *      Assumes tuples returned from subplan arrive in
      31                 :  *      sorted order.
      32                 :  */
      33                 : 
      34                 : #include "postgres.h"
      35                 : 
      36                 : #include "executor/executor.h"
      37                 : #include "executor/nodeUnique.h"
      38                 : #include "miscadmin.h"
      39                 : #include "utils/memutils.h"
      40                 : 
      41                 : 
      42                 : /* ----------------------------------------------------------------
      43                 :  *      ExecUnique
      44                 :  * ----------------------------------------------------------------
      45                 :  */
      46                 : static TupleTableSlot *         /* return: a tuple or NULL */
      47 CBC       41396 : ExecUnique(PlanState *pstate)
      48                 : {
      49           41396 :     UniqueState *node = castNode(UniqueState, pstate);
      50           41396 :     ExprContext *econtext = node->ps.ps_ExprContext;
      51                 :     TupleTableSlot *resultTupleSlot;
      52                 :     TupleTableSlot *slot;
      53                 :     PlanState  *outerPlan;
      54                 : 
      55           41396 :     CHECK_FOR_INTERRUPTS();
      56                 : 
      57                 :     /*
      58                 :      * get information from the node
      59                 :      */
      60           41396 :     outerPlan = outerPlanState(node);
      61           41396 :     resultTupleSlot = node->ps.ps_ResultTupleSlot;
      62                 : 
      63                 :     /*
      64                 :      * now loop, returning only non-duplicate tuples. We assume that the
      65                 :      * tuples arrive in sorted order so we can detect duplicates easily. The
      66                 :      * first tuple of each group is returned.
      67                 :      */
      68                 :     for (;;)
      69                 :     {
      70                 :         /*
      71                 :          * fetch a tuple from the outer subplan
      72                 :          */
      73          198736 :         slot = ExecProcNode(outerPlan);
      74          198736 :         if (TupIsNull(slot))
      75                 :         {
      76                 :             /* end of subplan, so we're done */
      77             678 :             ExecClearTuple(resultTupleSlot);
      78             678 :             return NULL;
      79                 :         }
      80                 : 
      81                 :         /*
      82                 :          * Always return the first tuple from the subplan.
      83                 :          */
      84          198058 :         if (TupIsNull(resultTupleSlot))
      85                 :             break;
      86                 : 
      87                 :         /*
      88                 :          * Else test if the new tuple and the previously returned tuple match.
      89                 :          * If so then we loop back and fetch another new tuple from the
      90                 :          * subplan.
      91                 :          */
      92          197419 :         econtext->ecxt_innertuple = slot;
      93          197419 :         econtext->ecxt_outertuple = resultTupleSlot;
      94          197419 :         if (!ExecQualAndReset(node->eqfunction, econtext))
      95           40079 :             break;
      96                 :     }
      97                 : 
      98                 :     /*
      99                 :      * We have a new tuple different from the previous saved tuple (if any).
     100                 :      * Save it and return it.  We must copy it because the source subplan
     101                 :      * won't guarantee that this source tuple is still accessible after
     102                 :      * fetching the next source tuple.
     103                 :      */
     104           40718 :     return ExecCopySlot(resultTupleSlot, slot);
     105                 : }
     106                 : 
     107                 : /* ----------------------------------------------------------------
     108                 :  *      ExecInitUnique
     109                 :  *
     110                 :  *      This initializes the unique node state structures and
     111                 :  *      the node's subplan.
     112                 :  * ----------------------------------------------------------------
     113                 :  */
     114                 : UniqueState *
     115             793 : ExecInitUnique(Unique *node, EState *estate, int eflags)
     116                 : {
     117                 :     UniqueState *uniquestate;
     118                 : 
     119                 :     /* check for unsupported flags */
     120             793 :     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
     121                 : 
     122                 :     /*
     123                 :      * create state structure
     124                 :      */
     125             793 :     uniquestate = makeNode(UniqueState);
     126             793 :     uniquestate->ps.plan = (Plan *) node;
     127             793 :     uniquestate->ps.state = estate;
     128             793 :     uniquestate->ps.ExecProcNode = ExecUnique;
     129                 : 
     130                 :     /*
     131                 :      * create expression context
     132                 :      */
     133             793 :     ExecAssignExprContext(estate, &uniquestate->ps);
     134                 : 
     135                 :     /*
     136                 :      * then initialize outer plan
     137                 :      */
     138             793 :     outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate, eflags);
     139                 : 
     140                 :     /*
     141                 :      * Initialize result slot and type. Unique nodes do no projections, so
     142                 :      * initialize projection info for this node appropriately.
     143                 :      */
     144             793 :     ExecInitResultTupleSlotTL(&uniquestate->ps, &TTSOpsMinimalTuple);
     145             793 :     uniquestate->ps.ps_ProjInfo = NULL;
     146                 : 
     147                 :     /*
     148                 :      * Precompute fmgr lookup data for inner loop
     149                 :      */
     150             793 :     uniquestate->eqfunction =
     151             793 :         execTuplesMatchPrepare(ExecGetResultType(outerPlanState(uniquestate)),
     152                 :                                node->numCols,
     153             793 :                                node->uniqColIdx,
     154             793 :                                node->uniqOperators,
     155             793 :                                node->uniqCollations,
     156                 :                                &uniquestate->ps);
     157                 : 
     158             793 :     return uniquestate;
     159                 : }
     160                 : 
     161                 : /* ----------------------------------------------------------------
     162                 :  *      ExecEndUnique
     163                 :  *
     164                 :  *      This shuts down the subplan and frees resources allocated
     165                 :  *      to this node.
     166                 :  * ----------------------------------------------------------------
     167                 :  */
     168                 : void
     169             793 : ExecEndUnique(UniqueState *node)
     170                 : {
     171                 :     /* clean up tuple table */
     172             793 :     ExecClearTuple(node->ps.ps_ResultTupleSlot);
     173                 : 
     174             793 :     ExecFreeExprContext(&node->ps);
     175                 : 
     176             793 :     ExecEndNode(outerPlanState(node));
     177             793 : }
     178                 : 
     179                 : 
     180                 : void
     181 UBC           0 : ExecReScanUnique(UniqueState *node)
     182                 : {
     183 UNC           0 :     PlanState  *outerPlan = outerPlanState(node);
     184                 : 
     185 EUB             :     /* must clear result tuple so first input tuple is returned */
     186 UIC           0 :     ExecClearTuple(node->ps.ps_ResultTupleSlot);
     187                 : 
     188 EUB             :     /*
     189                 :      * if chgParam of subnode is not null then plan will be re-scanned by
     190                 :      * first ExecProcNode.
     191                 :      */
     192 UNC           0 :     if (outerPlan->chgParam == NULL)
     193               0 :         ExecReScan(outerPlan);
     194 UBC           0 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a