---------------------------------------------------------------- * ExecScan * * Scans the relation using the 'access method' indicated and * returns the next qualifying tuple. * The access method returns the next tuple and ExecScan() is * responsible for checking the tuple returned against the qual-clause. * * A 'recheck method' must also be provided that can check an * arbitrary t
| 159 | * ---------------------------------------------------------------- |
| 160 | */ |
| 161 | TupleTableSlot * |
| 162 | ExecScan(ScanState *node, |
| 163 | ExecScanAccessMtd accessMtd, /* function returning a tuple */ |
| 164 | ExecScanRecheckMtd recheckMtd) |
| 165 | { |
| 166 | ExprContext *econtext; |
| 167 | ExprState *qual; |
| 168 | ProjectionInfo *projInfo; |
| 169 | |
| 170 | SIMPLE_FAULT_INJECTOR("before_exec_scan"); |
| 171 | |
| 172 | /* |
| 173 | * Fetch data from node |
| 174 | */ |
| 175 | qual = node->ps.qual; |
| 176 | projInfo = node->ps.ps_ProjInfo; |
| 177 | econtext = node->ps.ps_ExprContext; |
| 178 | |
| 179 | /* interrupt checks are in ExecScanFetch */ |
| 180 | |
| 181 | /* |
| 182 | * If we have neither a qual to check nor a projection to do, just skip |
| 183 | * all the overhead and return the raw scan tuple. |
| 184 | */ |
| 185 | if (!qual && !projInfo) |
| 186 | { |
| 187 | ResetExprContext(econtext); |
| 188 | return ExecScanFetch(node, accessMtd, recheckMtd); |
| 189 | } |
| 190 | |
| 191 | /* |
| 192 | * Reset per-tuple memory context to free any expression evaluation |
| 193 | * storage allocated in the previous tuple cycle. |
| 194 | */ |
| 195 | ResetExprContext(econtext); |
| 196 | |
| 197 | /* |
| 198 | * get a tuple from the access method. Loop until we obtain a tuple that |
| 199 | * passes the qualification. |
| 200 | */ |
| 201 | for (;;) |
| 202 | { |
| 203 | TupleTableSlot *slot; |
| 204 | |
| 205 | slot = ExecScanFetch(node, accessMtd, recheckMtd); |
| 206 | |
| 207 | /* |
| 208 | * if the slot returned by the accessMtd contains NULL, then it means |
| 209 | * there is nothing more to scan so we just return an empty slot, |
| 210 | * being careful to use the projection result slot so it has correct |
| 211 | * tupleDesc. |
| 212 | */ |
| 213 | if (TupIsNull(slot)) |
| 214 | { |
| 215 | if (projInfo) |
| 216 | return ExecClearTuple(projInfo->pi_state.resultslot); |
| 217 | else |
| 218 | return slot; |
no test coverage detected