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-2025, 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 : 40 : 41 : /* ---------------------------------------------------------------- 42 : * ExecUnique 43 : * ---------------------------------------------------------------- 44 : */ 45 : static TupleTableSlot * /* return: a tuple or NULL */ 46 93214 : ExecUnique(PlanState *pstate) 47 : { 48 93214 : UniqueState *node = castNode(UniqueState, pstate); 49 93214 : ExprContext *econtext = node->ps.ps_ExprContext; 50 : TupleTableSlot *resultTupleSlot; 51 : TupleTableSlot *slot; 52 : PlanState *outerPlan; 53 : 54 93214 : CHECK_FOR_INTERRUPTS(); 55 : 56 : /* 57 : * get information from the node 58 : */ 59 93214 : outerPlan = outerPlanState(node); 60 93214 : resultTupleSlot = node->ps.ps_ResultTupleSlot; 61 : 62 : /* 63 : * now loop, returning only non-duplicate tuples. We assume that the 64 : * tuples arrive in sorted order so we can detect duplicates easily. The 65 : * first tuple of each group is returned. 66 : */ 67 : for (;;) 68 : { 69 : /* 70 : * fetch a tuple from the outer subplan 71 : */ 72 463544 : slot = ExecProcNode(outerPlan); 73 463544 : if (TupIsNull(slot)) 74 : { 75 : /* end of subplan, so we're done */ 76 4714 : ExecClearTuple(resultTupleSlot); 77 4714 : return NULL; 78 : } 79 : 80 : /* 81 : * Always return the first tuple from the subplan. 82 : */ 83 458830 : if (TupIsNull(resultTupleSlot)) 84 : break; 85 : 86 : /* 87 : * Else test if the new tuple and the previously returned tuple match. 88 : * If so then we loop back and fetch another new tuple from the 89 : * subplan. 90 : */ 91 456936 : econtext->ecxt_innertuple = slot; 92 456936 : econtext->ecxt_outertuple = resultTupleSlot; 93 456936 : if (!ExecQualAndReset(node->eqfunction, econtext)) 94 86606 : break; 95 : } 96 : 97 : /* 98 : * We have a new tuple different from the previous saved tuple (if any). 99 : * Save it and return it. We must copy it because the source subplan 100 : * won't guarantee that this source tuple is still accessible after 101 : * fetching the next source tuple. 102 : */ 103 88500 : return ExecCopySlot(resultTupleSlot, slot); 104 : } 105 : 106 : /* ---------------------------------------------------------------- 107 : * ExecInitUnique 108 : * 109 : * This initializes the unique node state structures and 110 : * the node's subplan. 111 : * ---------------------------------------------------------------- 112 : */ 113 : UniqueState * 114 5056 : ExecInitUnique(Unique *node, EState *estate, int eflags) 115 : { 116 : UniqueState *uniquestate; 117 : 118 : /* check for unsupported flags */ 119 : Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); 120 : 121 : /* 122 : * create state structure 123 : */ 124 5056 : uniquestate = makeNode(UniqueState); 125 5056 : uniquestate->ps.plan = (Plan *) node; 126 5056 : uniquestate->ps.state = estate; 127 5056 : uniquestate->ps.ExecProcNode = ExecUnique; 128 : 129 : /* 130 : * create expression context 131 : */ 132 5056 : ExecAssignExprContext(estate, &uniquestate->ps); 133 : 134 : /* 135 : * then initialize outer plan 136 : */ 137 5056 : outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate, eflags); 138 : 139 : /* 140 : * Initialize result slot and type. Unique nodes do no projections, so 141 : * initialize projection info for this node appropriately. 142 : */ 143 5056 : ExecInitResultTupleSlotTL(&uniquestate->ps, &TTSOpsMinimalTuple); 144 5056 : uniquestate->ps.ps_ProjInfo = NULL; 145 : 146 : /* 147 : * Precompute fmgr lookup data for inner loop 148 : */ 149 5056 : uniquestate->eqfunction = 150 5056 : execTuplesMatchPrepare(ExecGetResultType(outerPlanState(uniquestate)), 151 : node->numCols, 152 5056 : node->uniqColIdx, 153 5056 : node->uniqOperators, 154 5056 : node->uniqCollations, 155 : &uniquestate->ps); 156 : 157 5056 : return uniquestate; 158 : } 159 : 160 : /* ---------------------------------------------------------------- 161 : * ExecEndUnique 162 : * 163 : * This shuts down the subplan and frees resources allocated 164 : * to this node. 165 : * ---------------------------------------------------------------- 166 : */ 167 : void 168 5056 : ExecEndUnique(UniqueState *node) 169 : { 170 5056 : ExecEndNode(outerPlanState(node)); 171 5056 : } 172 : 173 : 174 : void 175 0 : ExecReScanUnique(UniqueState *node) 176 : { 177 0 : PlanState *outerPlan = outerPlanState(node); 178 : 179 : /* must clear result tuple so first input tuple is returned */ 180 0 : ExecClearTuple(node->ps.ps_ResultTupleSlot); 181 : 182 : /* 183 : * if chgParam of subnode is not null then plan will be re-scanned by 184 : * first ExecProcNode. 185 : */ 186 0 : if (outerPlan->chgParam == NULL) 187 0 : ExecReScan(outerPlan); 188 0 : }