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 84134 : ExecUnique(PlanState *pstate) 48 : { 49 84134 : UniqueState *node = castNode(UniqueState, pstate); 50 84134 : ExprContext *econtext = node->ps.ps_ExprContext; 51 : TupleTableSlot *resultTupleSlot; 52 : TupleTableSlot *slot; 53 : PlanState *outerPlan; 54 : 55 84134 : CHECK_FOR_INTERRUPTS(); 56 : 57 : /* 58 : * get information from the node 59 : */ 60 84134 : outerPlan = outerPlanState(node); 61 84134 : 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 401498 : slot = ExecProcNode(outerPlan); 74 401498 : if (TupIsNull(slot)) 75 : { 76 : /* end of subplan, so we're done */ 77 1518 : ExecClearTuple(resultTupleSlot); 78 1518 : return NULL; 79 : } 80 : 81 : /* 82 : * Always return the first tuple from the subplan. 83 : */ 84 399980 : 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 398552 : econtext->ecxt_innertuple = slot; 93 398552 : econtext->ecxt_outertuple = resultTupleSlot; 94 398552 : if (!ExecQualAndReset(node->eqfunction, econtext)) 95 81188 : 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 82616 : 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 1748 : ExecInitUnique(Unique *node, EState *estate, int eflags) 116 : { 117 : UniqueState *uniquestate; 118 : 119 : /* check for unsupported flags */ 120 : Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); 121 : 122 : /* 123 : * create state structure 124 : */ 125 1748 : uniquestate = makeNode(UniqueState); 126 1748 : uniquestate->ps.plan = (Plan *) node; 127 1748 : uniquestate->ps.state = estate; 128 1748 : uniquestate->ps.ExecProcNode = ExecUnique; 129 : 130 : /* 131 : * create expression context 132 : */ 133 1748 : ExecAssignExprContext(estate, &uniquestate->ps); 134 : 135 : /* 136 : * then initialize outer plan 137 : */ 138 1748 : 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 1748 : ExecInitResultTupleSlotTL(&uniquestate->ps, &TTSOpsMinimalTuple); 145 1748 : uniquestate->ps.ps_ProjInfo = NULL; 146 : 147 : /* 148 : * Precompute fmgr lookup data for inner loop 149 : */ 150 1748 : uniquestate->eqfunction = 151 1748 : execTuplesMatchPrepare(ExecGetResultType(outerPlanState(uniquestate)), 152 : node->numCols, 153 1748 : node->uniqColIdx, 154 1748 : node->uniqOperators, 155 1748 : node->uniqCollations, 156 : &uniquestate->ps); 157 : 158 1748 : 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 1748 : ExecEndUnique(UniqueState *node) 170 : { 171 1748 : ExecEndNode(outerPlanState(node)); 172 1748 : } 173 : 174 : 175 : void 176 0 : ExecReScanUnique(UniqueState *node) 177 : { 178 0 : PlanState *outerPlan = outerPlanState(node); 179 : 180 : /* must clear result tuple so first input tuple is returned */ 181 0 : ExecClearTuple(node->ps.ps_ResultTupleSlot); 182 : 183 : /* 184 : * if chgParam of subnode is not null then plan will be re-scanned by 185 : * first ExecProcNode. 186 : */ 187 0 : if (outerPlan->chgParam == NULL) 188 0 : ExecReScan(outerPlan); 189 0 : }