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-2026, 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 15519456 : 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 15519456 : epqstate = node->ps.state->es_epq_active;
56 15519456 : qual = node->ps.qual;
57 15519456 : projInfo = node->ps.ps_ProjInfo;
58 :
59 15519456 : 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 286865 : ExecAssignScanProjectionInfo(ScanState *node)
82 : {
83 286865 : Scan *scan = (Scan *) node->ps.plan;
84 286865 : TupleDesc tupdesc = node->ss_ScanTupleSlot->tts_tupleDescriptor;
85 :
86 286865 : ExecConditionalAssignProjectionInfo(&node->ps, tupdesc, scan->scanrelid);
87 286865 : }
88 :
89 : /*
90 : * ExecAssignScanProjectionInfoWithVarno
91 : * As above, but caller can specify varno expected in Vars in the tlist.
92 : */
93 : void
94 11050 : ExecAssignScanProjectionInfoWithVarno(ScanState *node, int varno)
95 : {
96 11050 : TupleDesc tupdesc = node->ss_ScanTupleSlot->tts_tupleDescriptor;
97 :
98 11050 : ExecConditionalAssignProjectionInfo(&node->ps, tupdesc, varno);
99 11050 : }
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 1328987 : ExecScanReScan(ScanState *node)
109 : {
110 1328987 : 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 1328987 : 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 1328987 : if (estate->es_epq_active != NULL)
123 : {
124 191 : EPQState *epqstate = estate->es_epq_active;
125 191 : Index scanrelid = ((Scan *) node->ps.plan)->scanrelid;
126 :
127 191 : if (scanrelid > 0)
128 190 : epqstate->relsubs_done[scanrelid - 1] =
129 190 : epqstate->relsubs_blocked[scanrelid - 1];
130 : else
131 : {
132 : Bitmapset *relids;
133 1 : 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 relsubs_done flag for
138 : * all of them.
139 : */
140 1 : if (IsA(node->ps.plan, ForeignScan))
141 1 : 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 3 : while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
149 : {
150 : Assert(rtindex > 0);
151 2 : epqstate->relsubs_done[rtindex - 1] =
152 2 : epqstate->relsubs_blocked[rtindex - 1];
153 : }
154 : }
155 : }
156 1328987 : }
|