Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * execScan.c 4 : * This code provides support for generalized relation scans. ExecScan 5 : * is passed a node and a pointer to a function to "do the right thing" 6 : * and return a tuple from the relation. ExecScan then does the tedious 7 : * stuff - checking the qualification and projecting the tuple 8 : * appropriately. 9 : * 10 : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group 11 : * Portions Copyright (c) 1994, Regents of the University of California 12 : * 13 : * 14 : * IDENTIFICATION 15 : * src/backend/executor/execScan.c 16 : * 17 : *------------------------------------------------------------------------- 18 : */ 19 : #include "postgres.h" 20 : 21 : #include "executor/executor.h" 22 : #include "executor/execScan.h" 23 : #include "miscadmin.h" 24 : 25 : /* ---------------------------------------------------------------- 26 : * ExecScan 27 : * 28 : * Scans the relation using the 'access method' indicated and 29 : * returns the next qualifying tuple. 30 : * The access method returns the next tuple and ExecScan() is 31 : * responsible for checking the tuple returned against the qual-clause. 32 : * 33 : * A 'recheck method' must also be provided that can check an 34 : * arbitrary tuple of the relation against any qual conditions 35 : * that are implemented internal to the access method. 36 : * 37 : * Conditions: 38 : * -- the "cursor" maintained by the AMI is positioned at the tuple 39 : * returned previously. 40 : * 41 : * Initial States: 42 : * -- the relation indicated is opened for scanning so that the 43 : * "cursor" is positioned before the first qualifying tuple. 44 : * ---------------------------------------------------------------- 45 : */ 46 : TupleTableSlot * 47 29140508 : ExecScan(ScanState *node, 48 : ExecScanAccessMtd accessMtd, /* function returning a tuple */ 49 : ExecScanRecheckMtd recheckMtd) 50 : { 51 : EPQState *epqstate; 52 : ExprState *qual; 53 : ProjectionInfo *projInfo; 54 : 55 29140508 : epqstate = node->ps.state->es_epq_active; 56 29140508 : qual = node->ps.qual; 57 29140508 : projInfo = node->ps.ps_ProjInfo; 58 : 59 29140508 : return ExecScanExtended(node, 60 : accessMtd, 61 : recheckMtd, 62 : epqstate, 63 : qual, 64 : projInfo); 65 : } 66 : 67 : /* 68 : * ExecAssignScanProjectionInfo 69 : * Set up projection info for a scan node, if necessary. 70 : * 71 : * We can avoid a projection step if the requested tlist exactly matches 72 : * the underlying tuple type. If so, we just set ps_ProjInfo to NULL. 73 : * Note that this case occurs not only for simple "SELECT * FROM ...", but 74 : * also in most cases where there are joins or other processing nodes above 75 : * the scan node, because the planner will preferentially generate a matching 76 : * tlist. 77 : * 78 : * The scan slot's descriptor must have been set already. 79 : */ 80 : void 81 578162 : ExecAssignScanProjectionInfo(ScanState *node) 82 : { 83 578162 : Scan *scan = (Scan *) node->ps.plan; 84 578162 : TupleDesc tupdesc = node->ss_ScanTupleSlot->tts_tupleDescriptor; 85 : 86 578162 : ExecConditionalAssignProjectionInfo(&node->ps, tupdesc, scan->scanrelid); 87 578156 : } 88 : 89 : /* 90 : * ExecAssignScanProjectionInfoWithVarno 91 : * As above, but caller can specify varno expected in Vars in the tlist. 92 : */ 93 : void 94 18422 : ExecAssignScanProjectionInfoWithVarno(ScanState *node, int varno) 95 : { 96 18422 : TupleDesc tupdesc = node->ss_ScanTupleSlot->tts_tupleDescriptor; 97 : 98 18422 : ExecConditionalAssignProjectionInfo(&node->ps, tupdesc, varno); 99 18422 : } 100 : 101 : /* 102 : * ExecScanReScan 103 : * 104 : * This must be called within the ReScan function of any plan node type 105 : * that uses ExecScan(). 106 : */ 107 : void 108 2014408 : ExecScanReScan(ScanState *node) 109 : { 110 2014408 : EState *estate = node->ps.state; 111 : 112 : /* 113 : * We must clear the scan tuple so that observers (e.g., execCurrent.c) 114 : * can tell that this plan node is not positioned on a tuple. 115 : */ 116 2014408 : ExecClearTuple(node->ss_ScanTupleSlot); 117 : 118 : /* 119 : * Rescan EvalPlanQual tuple(s) if we're inside an EvalPlanQual recheck. 120 : * But don't lose the "blocked" status of blocked target relations. 121 : */ 122 2014408 : if (estate->es_epq_active != NULL) 123 : { 124 356 : EPQState *epqstate = estate->es_epq_active; 125 356 : Index scanrelid = ((Scan *) node->ps.plan)->scanrelid; 126 : 127 356 : if (scanrelid > 0) 128 356 : epqstate->relsubs_done[scanrelid - 1] = 129 356 : epqstate->relsubs_blocked[scanrelid - 1]; 130 : else 131 : { 132 : Bitmapset *relids; 133 0 : int rtindex = -1; 134 : 135 : /* 136 : * If an FDW or custom scan provider has replaced the join with a 137 : * scan, there are multiple RTIs; reset the epqScanDone flag for 138 : * all of them. 139 : */ 140 0 : if (IsA(node->ps.plan, ForeignScan)) 141 0 : relids = ((ForeignScan *) node->ps.plan)->fs_base_relids; 142 0 : else if (IsA(node->ps.plan, CustomScan)) 143 0 : relids = ((CustomScan *) node->ps.plan)->custom_relids; 144 : else 145 0 : elog(ERROR, "unexpected scan node: %d", 146 : (int) nodeTag(node->ps.plan)); 147 : 148 0 : while ((rtindex = bms_next_member(relids, rtindex)) >= 0) 149 : { 150 : Assert(rtindex > 0); 151 0 : epqstate->relsubs_done[rtindex - 1] = 152 0 : epqstate->relsubs_blocked[rtindex - 1]; 153 : } 154 : } 155 : } 156 2014408 : }