Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "postgres.h"
00020
00021 #include "executor/executor.h"
00022 #include "miscadmin.h"
00023 #include "utils/memutils.h"
00024
00025
00026 static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc);
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 static inline TupleTableSlot *
00037 ExecScanFetch(ScanState *node,
00038 ExecScanAccessMtd accessMtd,
00039 ExecScanRecheckMtd recheckMtd)
00040 {
00041 EState *estate = node->ps.state;
00042
00043 if (estate->es_epqTuple != NULL)
00044 {
00045
00046
00047
00048
00049
00050 Index scanrelid = ((Scan *) node->ps.plan)->scanrelid;
00051
00052 Assert(scanrelid > 0);
00053 if (estate->es_epqTupleSet[scanrelid - 1])
00054 {
00055 TupleTableSlot *slot = node->ss_ScanTupleSlot;
00056
00057
00058 if (estate->es_epqScanDone[scanrelid - 1])
00059 return ExecClearTuple(slot);
00060
00061 estate->es_epqScanDone[scanrelid - 1] = true;
00062
00063
00064 if (estate->es_epqTuple[scanrelid - 1] == NULL)
00065 return ExecClearTuple(slot);
00066
00067
00068 ExecStoreTuple(estate->es_epqTuple[scanrelid - 1],
00069 slot, InvalidBuffer, false);
00070
00071
00072 if (!(*recheckMtd) (node, slot))
00073 ExecClearTuple(slot);
00074
00075 return slot;
00076 }
00077 }
00078
00079
00080
00081
00082 return (*accessMtd) (node);
00083 }
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 TupleTableSlot *
00108 ExecScan(ScanState *node,
00109 ExecScanAccessMtd accessMtd,
00110 ExecScanRecheckMtd recheckMtd)
00111 {
00112 ExprContext *econtext;
00113 List *qual;
00114 ProjectionInfo *projInfo;
00115 ExprDoneCond isDone;
00116 TupleTableSlot *resultSlot;
00117
00118
00119
00120
00121 qual = node->ps.qual;
00122 projInfo = node->ps.ps_ProjInfo;
00123 econtext = node->ps.ps_ExprContext;
00124
00125
00126
00127
00128
00129 if (!qual && !projInfo)
00130 {
00131 ResetExprContext(econtext);
00132 return ExecScanFetch(node, accessMtd, recheckMtd);
00133 }
00134
00135
00136
00137
00138
00139
00140 if (node->ps.ps_TupFromTlist)
00141 {
00142 Assert(projInfo);
00143 resultSlot = ExecProject(projInfo, &isDone);
00144 if (isDone == ExprMultipleResult)
00145 return resultSlot;
00146
00147 node->ps.ps_TupFromTlist = false;
00148 }
00149
00150
00151
00152
00153
00154
00155 ResetExprContext(econtext);
00156
00157
00158
00159
00160
00161 for (;;)
00162 {
00163 TupleTableSlot *slot;
00164
00165 CHECK_FOR_INTERRUPTS();
00166
00167 slot = ExecScanFetch(node, accessMtd, recheckMtd);
00168
00169
00170
00171
00172
00173
00174
00175 if (TupIsNull(slot))
00176 {
00177 if (projInfo)
00178 return ExecClearTuple(projInfo->pi_slot);
00179 else
00180 return slot;
00181 }
00182
00183
00184
00185
00186 econtext->ecxt_scantuple = slot;
00187
00188
00189
00190
00191
00192
00193
00194
00195 if (!qual || ExecQual(qual, econtext, false))
00196 {
00197
00198
00199
00200 if (projInfo)
00201 {
00202
00203
00204
00205
00206
00207 resultSlot = ExecProject(projInfo, &isDone);
00208 if (isDone != ExprEndResult)
00209 {
00210 node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
00211 return resultSlot;
00212 }
00213 }
00214 else
00215 {
00216
00217
00218
00219 return slot;
00220 }
00221 }
00222 else
00223 InstrCountFiltered1(node, 1);
00224
00225
00226
00227
00228 ResetExprContext(econtext);
00229 }
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 void
00246 ExecAssignScanProjectionInfo(ScanState *node)
00247 {
00248 Scan *scan = (Scan *) node->ps.plan;
00249 Index varno;
00250
00251
00252 if (IsA(scan, IndexOnlyScan))
00253 varno = INDEX_VAR;
00254 else
00255 varno = scan->scanrelid;
00256
00257 if (tlist_matches_tupdesc(&node->ps,
00258 scan->plan.targetlist,
00259 varno,
00260 node->ss_ScanTupleSlot->tts_tupleDescriptor))
00261 node->ps.ps_ProjInfo = NULL;
00262 else
00263 ExecAssignProjectionInfo(&node->ps,
00264 node->ss_ScanTupleSlot->tts_tupleDescriptor);
00265 }
00266
00267 static bool
00268 tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc)
00269 {
00270 int numattrs = tupdesc->natts;
00271 int attrno;
00272 bool hasoid;
00273 ListCell *tlist_item = list_head(tlist);
00274
00275
00276 for (attrno = 1; attrno <= numattrs; attrno++)
00277 {
00278 Form_pg_attribute att_tup = tupdesc->attrs[attrno - 1];
00279 Var *var;
00280
00281 if (tlist_item == NULL)
00282 return false;
00283 var = (Var *) ((TargetEntry *) lfirst(tlist_item))->expr;
00284 if (!var || !IsA(var, Var))
00285 return false;
00286
00287 Assert(var->varno == varno);
00288 Assert(var->varlevelsup == 0);
00289 if (var->varattno != attrno)
00290 return false;
00291 if (att_tup->attisdropped)
00292 return false;
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 if (var->vartype != att_tup->atttypid ||
00305 (var->vartypmod != att_tup->atttypmod &&
00306 var->vartypmod != -1))
00307 return false;
00308
00309 tlist_item = lnext(tlist_item);
00310 }
00311
00312 if (tlist_item)
00313 return false;
00314
00315
00316
00317
00318
00319 if (ExecContextForcesOids(ps, &hasoid) &&
00320 hasoid != tupdesc->tdhasoid)
00321 return false;
00322
00323 return true;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332 void
00333 ExecScanReScan(ScanState *node)
00334 {
00335 EState *estate = node->ps.state;
00336
00337
00338 node->ps.ps_TupFromTlist = false;
00339
00340
00341 if (estate->es_epqScanDone != NULL)
00342 {
00343 Index scanrelid = ((Scan *) node->ps.plan)->scanrelid;
00344
00345 Assert(scanrelid > 0);
00346
00347 estate->es_epqScanDone[scanrelid - 1] = false;
00348 }
00349 }