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