Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * nodeNamedtuplestorescan.c 4 : * routines to handle NamedTuplestoreScan nodes. 5 : * 6 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group 7 : * Portions Copyright (c) 1994, Regents of the University of California 8 : * 9 : * 10 : * IDENTIFICATION 11 : * src/backend/executor/nodeNamedtuplestorescan.c 12 : * 13 : *------------------------------------------------------------------------- 14 : */ 15 : 16 : #include "postgres.h" 17 : 18 : #include "executor/execdebug.h" 19 : #include "executor/nodeNamedtuplestorescan.h" 20 : #include "miscadmin.h" 21 : #include "utils/queryenvironment.h" 22 : 23 : static TupleTableSlot *NamedTuplestoreScanNext(NamedTuplestoreScanState *node); 24 : 25 : /* ---------------------------------------------------------------- 26 : * NamedTuplestoreScanNext 27 : * 28 : * This is a workhorse for ExecNamedTuplestoreScan 29 : * ---------------------------------------------------------------- 30 : */ 31 : static TupleTableSlot * 32 66612 : NamedTuplestoreScanNext(NamedTuplestoreScanState *node) 33 : { 34 : TupleTableSlot *slot; 35 : 36 : /* We intentionally do not support backward scan. */ 37 : Assert(ScanDirectionIsForward(node->ss.ps.state->es_direction)); 38 : 39 : /* 40 : * Get the next tuple from tuplestore. Return NULL if no more tuples. 41 : */ 42 66612 : slot = node->ss.ss_ScanTupleSlot; 43 66612 : tuplestore_select_read_pointer(node->relation, node->readptr); 44 66612 : (void) tuplestore_gettupleslot(node->relation, true, false, slot); 45 66612 : return slot; 46 : } 47 : 48 : /* 49 : * NamedTuplestoreScanRecheck -- access method routine to recheck a tuple in 50 : * EvalPlanQual 51 : */ 52 : static bool 53 0 : NamedTuplestoreScanRecheck(NamedTuplestoreScanState *node, TupleTableSlot *slot) 54 : { 55 : /* nothing to check */ 56 0 : return true; 57 : } 58 : 59 : /* ---------------------------------------------------------------- 60 : * ExecNamedTuplestoreScan(node) 61 : * 62 : * Scans the CTE sequentially and returns the next qualifying tuple. 63 : * We call the ExecScan() routine and pass it the appropriate 64 : * access method functions. 65 : * ---------------------------------------------------------------- 66 : */ 67 : static TupleTableSlot * 68 66612 : ExecNamedTuplestoreScan(PlanState *pstate) 69 : { 70 66612 : NamedTuplestoreScanState *node = castNode(NamedTuplestoreScanState, pstate); 71 : 72 66612 : return ExecScan(&node->ss, 73 : (ExecScanAccessMtd) NamedTuplestoreScanNext, 74 : (ExecScanRecheckMtd) NamedTuplestoreScanRecheck); 75 : } 76 : 77 : 78 : /* ---------------------------------------------------------------- 79 : * ExecInitNamedTuplestoreScan 80 : * ---------------------------------------------------------------- 81 : */ 82 : NamedTuplestoreScanState * 83 660 : ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflags) 84 : { 85 : NamedTuplestoreScanState *scanstate; 86 : EphemeralNamedRelation enr; 87 : 88 : /* check for unsupported flags */ 89 : Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); 90 : 91 : /* 92 : * NamedTuplestoreScan should not have any children. 93 : */ 94 : Assert(outerPlan(node) == NULL); 95 : Assert(innerPlan(node) == NULL); 96 : 97 : /* 98 : * create new NamedTuplestoreScanState for node 99 : */ 100 660 : scanstate = makeNode(NamedTuplestoreScanState); 101 660 : scanstate->ss.ps.plan = (Plan *) node; 102 660 : scanstate->ss.ps.state = estate; 103 660 : scanstate->ss.ps.ExecProcNode = ExecNamedTuplestoreScan; 104 : 105 660 : enr = get_ENR(estate->es_queryEnv, node->enrname); 106 660 : if (!enr) 107 0 : elog(ERROR, "executor could not find named tuplestore \"%s\"", 108 : node->enrname); 109 : 110 : Assert(enr->reldata); 111 660 : scanstate->relation = (Tuplestorestate *) enr->reldata; 112 660 : scanstate->tupdesc = ENRMetadataGetTupDesc(&(enr->md)); 113 660 : scanstate->readptr = 114 660 : tuplestore_alloc_read_pointer(scanstate->relation, EXEC_FLAG_REWIND); 115 : 116 : /* 117 : * The new read pointer copies its position from read pointer 0, which 118 : * could be anywhere, so explicitly rewind it. 119 : */ 120 660 : tuplestore_select_read_pointer(scanstate->relation, scanstate->readptr); 121 660 : tuplestore_rescan(scanstate->relation); 122 : 123 : /* 124 : * XXX: Should we add a function to free that read pointer when done? 125 : * 126 : * This was attempted, but it did not improve performance or memory usage 127 : * in any tested cases. 128 : */ 129 : 130 : /* 131 : * Miscellaneous initialization 132 : * 133 : * create expression context for node 134 : */ 135 660 : ExecAssignExprContext(estate, &scanstate->ss.ps); 136 : 137 : /* 138 : * The scan tuple type is specified for the tuplestore. 139 : */ 140 660 : ExecInitScanTupleSlot(estate, &scanstate->ss, scanstate->tupdesc, 141 : &TTSOpsMinimalTuple); 142 : 143 : /* 144 : * Initialize result type and projection. 145 : */ 146 660 : ExecInitResultTypeTL(&scanstate->ss.ps); 147 660 : ExecAssignScanProjectionInfo(&scanstate->ss); 148 : 149 : /* 150 : * initialize child expressions 151 : */ 152 660 : scanstate->ss.ps.qual = 153 660 : ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate); 154 : 155 660 : return scanstate; 156 : } 157 : 158 : /* ---------------------------------------------------------------- 159 : * ExecEndNamedTuplestoreScan 160 : * 161 : * frees any storage allocated through C routines. 162 : * ---------------------------------------------------------------- 163 : */ 164 : void 165 660 : ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node) 166 : { 167 : /* 168 : * Free exprcontext 169 : */ 170 660 : ExecFreeExprContext(&node->ss.ps); 171 : 172 : /* 173 : * clean out the tuple table 174 : */ 175 660 : if (node->ss.ps.ps_ResultTupleSlot) 176 588 : ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); 177 660 : ExecClearTuple(node->ss.ss_ScanTupleSlot); 178 660 : } 179 : 180 : /* ---------------------------------------------------------------- 181 : * ExecReScanNamedTuplestoreScan 182 : * 183 : * Rescans the relation. 184 : * ---------------------------------------------------------------- 185 : */ 186 : void 187 0 : ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node) 188 : { 189 0 : Tuplestorestate *tuplestorestate = node->relation; 190 : 191 0 : if (node->ss.ps.ps_ResultTupleSlot) 192 0 : ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); 193 : 194 0 : ExecScanReScan(&node->ss); 195 : 196 : /* 197 : * Rewind my own pointer. 198 : */ 199 0 : tuplestore_select_read_pointer(tuplestorestate, node->readptr); 200 0 : tuplestore_rescan(tuplestorestate); 201 0 : }