00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "postgres.h"
00026
00027 #include "access/relscan.h"
00028 #include "access/visibilitymap.h"
00029 #include "executor/execdebug.h"
00030 #include "executor/nodeIndexonlyscan.h"
00031 #include "executor/nodeIndexscan.h"
00032 #include "storage/bufmgr.h"
00033 #include "storage/predicate.h"
00034 #include "utils/memutils.h"
00035 #include "utils/rel.h"
00036
00037
00038 static TupleTableSlot *IndexOnlyNext(IndexOnlyScanState *node);
00039 static void StoreIndexTuple(TupleTableSlot *slot, IndexTuple itup,
00040 TupleDesc itupdesc);
00041
00042
00043
00044
00045
00046
00047
00048
00049 static TupleTableSlot *
00050 IndexOnlyNext(IndexOnlyScanState *node)
00051 {
00052 EState *estate;
00053 ExprContext *econtext;
00054 ScanDirection direction;
00055 IndexScanDesc scandesc;
00056 TupleTableSlot *slot;
00057 ItemPointer tid;
00058
00059
00060
00061
00062 estate = node->ss.ps.state;
00063 direction = estate->es_direction;
00064
00065 if (ScanDirectionIsBackward(((IndexOnlyScan *) node->ss.ps.plan)->indexorderdir))
00066 {
00067 if (ScanDirectionIsForward(direction))
00068 direction = BackwardScanDirection;
00069 else if (ScanDirectionIsBackward(direction))
00070 direction = ForwardScanDirection;
00071 }
00072 scandesc = node->ioss_ScanDesc;
00073 econtext = node->ss.ps.ps_ExprContext;
00074 slot = node->ss.ss_ScanTupleSlot;
00075
00076
00077
00078
00079 while ((tid = index_getnext_tid(scandesc, direction)) != NULL)
00080 {
00081 HeapTuple tuple = NULL;
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 if (!visibilitymap_test(scandesc->heapRelation,
00102 ItemPointerGetBlockNumber(tid),
00103 &node->ioss_VMBuffer))
00104 {
00105
00106
00107
00108 node->ioss_HeapFetches++;
00109 tuple = index_fetch_heap(scandesc);
00110 if (tuple == NULL)
00111 continue;
00112
00113
00114
00115
00116
00117
00118
00119 if (scandesc->xs_continue_hot)
00120 elog(ERROR, "non-MVCC snapshots are not supported in index-only scans");
00121
00122
00123
00124
00125
00126
00127
00128 }
00129
00130
00131
00132
00133 StoreIndexTuple(slot, scandesc->xs_itup, scandesc->xs_itupdesc);
00134
00135
00136
00137
00138
00139
00140 if (scandesc->xs_recheck)
00141 {
00142 econtext->ecxt_scantuple = slot;
00143 ResetExprContext(econtext);
00144 if (!ExecQual(node->indexqual, econtext, false))
00145 {
00146
00147 InstrCountFiltered2(node, 1);
00148 continue;
00149 }
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159 if (tuple == NULL)
00160 PredicateLockPage(scandesc->heapRelation,
00161 ItemPointerGetBlockNumber(tid),
00162 estate->es_snapshot);
00163
00164 return slot;
00165 }
00166
00167
00168
00169
00170
00171 return ExecClearTuple(slot);
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181 static void
00182 StoreIndexTuple(TupleTableSlot *slot, IndexTuple itup, TupleDesc itupdesc)
00183 {
00184 int nindexatts = itupdesc->natts;
00185 Datum *values = slot->tts_values;
00186 bool *isnull = slot->tts_isnull;
00187 int i;
00188
00189
00190
00191
00192
00193
00194
00195
00196 Assert(slot->tts_tupleDescriptor->natts == nindexatts);
00197
00198 ExecClearTuple(slot);
00199 for (i = 0; i < nindexatts; i++)
00200 values[i] = index_getattr(itup, i + 1, itupdesc, &isnull[i]);
00201 ExecStoreVirtualTuple(slot);
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 static bool
00213 IndexOnlyRecheck(IndexOnlyScanState *node, TupleTableSlot *slot)
00214 {
00215 elog(ERROR, "EvalPlanQual recheck is not supported in index-only scans");
00216 return false;
00217 }
00218
00219
00220
00221
00222
00223 TupleTableSlot *
00224 ExecIndexOnlyScan(IndexOnlyScanState *node)
00225 {
00226
00227
00228
00229 if (node->ioss_NumRuntimeKeys != 0 && !node->ioss_RuntimeKeysReady)
00230 ExecReScan((PlanState *) node);
00231
00232 return ExecScan(&node->ss,
00233 (ExecScanAccessMtd) IndexOnlyNext,
00234 (ExecScanRecheckMtd) IndexOnlyRecheck);
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 void
00249 ExecReScanIndexOnlyScan(IndexOnlyScanState *node)
00250 {
00251
00252
00253
00254
00255
00256
00257
00258 if (node->ioss_NumRuntimeKeys != 0)
00259 {
00260 ExprContext *econtext = node->ioss_RuntimeContext;
00261
00262 ResetExprContext(econtext);
00263 ExecIndexEvalRuntimeKeys(econtext,
00264 node->ioss_RuntimeKeys,
00265 node->ioss_NumRuntimeKeys);
00266 }
00267 node->ioss_RuntimeKeysReady = true;
00268
00269
00270 index_rescan(node->ioss_ScanDesc,
00271 node->ioss_ScanKeys, node->ioss_NumScanKeys,
00272 node->ioss_OrderByKeys, node->ioss_NumOrderByKeys);
00273
00274 ExecScanReScan(&node->ss);
00275 }
00276
00277
00278
00279
00280
00281
00282 void
00283 ExecEndIndexOnlyScan(IndexOnlyScanState *node)
00284 {
00285 Relation indexRelationDesc;
00286 IndexScanDesc indexScanDesc;
00287 Relation relation;
00288
00289
00290
00291
00292 indexRelationDesc = node->ioss_RelationDesc;
00293 indexScanDesc = node->ioss_ScanDesc;
00294 relation = node->ss.ss_currentRelation;
00295
00296
00297 if (node->ioss_VMBuffer != InvalidBuffer)
00298 {
00299 ReleaseBuffer(node->ioss_VMBuffer);
00300 node->ioss_VMBuffer = InvalidBuffer;
00301 }
00302
00303
00304
00305
00306 #ifdef NOT_USED
00307 ExecFreeExprContext(&node->ss.ps);
00308 if (node->ioss_RuntimeContext)
00309 FreeExprContext(node->ioss_RuntimeContext, true);
00310 #endif
00311
00312
00313
00314
00315 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
00316 ExecClearTuple(node->ss.ss_ScanTupleSlot);
00317
00318
00319
00320
00321 if (indexScanDesc)
00322 index_endscan(indexScanDesc);
00323 if (indexRelationDesc)
00324 index_close(indexRelationDesc, NoLock);
00325
00326
00327
00328
00329 ExecCloseScanRelation(relation);
00330 }
00331
00332
00333
00334
00335
00336 void
00337 ExecIndexOnlyMarkPos(IndexOnlyScanState *node)
00338 {
00339 index_markpos(node->ioss_ScanDesc);
00340 }
00341
00342
00343
00344
00345
00346 void
00347 ExecIndexOnlyRestrPos(IndexOnlyScanState *node)
00348 {
00349 index_restrpos(node->ioss_ScanDesc);
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 IndexOnlyScanState *
00364 ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
00365 {
00366 IndexOnlyScanState *indexstate;
00367 Relation currentRelation;
00368 bool relistarget;
00369 TupleDesc tupDesc;
00370
00371
00372
00373
00374 indexstate = makeNode(IndexOnlyScanState);
00375 indexstate->ss.ps.plan = (Plan *) node;
00376 indexstate->ss.ps.state = estate;
00377 indexstate->ioss_HeapFetches = 0;
00378
00379
00380
00381
00382
00383
00384 ExecAssignExprContext(estate, &indexstate->ss.ps);
00385
00386 indexstate->ss.ps.ps_TupFromTlist = false;
00387
00388
00389
00390
00391
00392
00393
00394 indexstate->ss.ps.targetlist = (List *)
00395 ExecInitExpr((Expr *) node->scan.plan.targetlist,
00396 (PlanState *) indexstate);
00397 indexstate->ss.ps.qual = (List *)
00398 ExecInitExpr((Expr *) node->scan.plan.qual,
00399 (PlanState *) indexstate);
00400 indexstate->indexqual = (List *)
00401 ExecInitExpr((Expr *) node->indexqual,
00402 (PlanState *) indexstate);
00403
00404
00405
00406
00407 ExecInitResultTupleSlot(estate, &indexstate->ss.ps);
00408 ExecInitScanTupleSlot(estate, &indexstate->ss);
00409
00410
00411
00412
00413 currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
00414
00415 indexstate->ss.ss_currentRelation = currentRelation;
00416 indexstate->ss.ss_currentScanDesc = NULL;
00417
00418
00419
00420
00421
00422
00423
00424
00425 tupDesc = ExecTypeFromTL(node->indextlist, false);
00426 ExecAssignScanType(&indexstate->ss, tupDesc);
00427
00428
00429
00430
00431 ExecAssignResultTypeFromTL(&indexstate->ss.ps);
00432 ExecAssignScanProjectionInfo(&indexstate->ss);
00433
00434
00435
00436
00437
00438
00439 if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
00440 return indexstate;
00441
00442
00443
00444
00445
00446
00447
00448
00449 relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid);
00450 indexstate->ioss_RelationDesc = index_open(node->indexid,
00451 relistarget ? NoLock : AccessShareLock);
00452
00453
00454
00455
00456 indexstate->ioss_RuntimeKeysReady = false;
00457 indexstate->ioss_RuntimeKeys = NULL;
00458 indexstate->ioss_NumRuntimeKeys = 0;
00459
00460
00461
00462
00463 ExecIndexBuildScanKeys((PlanState *) indexstate,
00464 indexstate->ioss_RelationDesc,
00465 node->indexqual,
00466 false,
00467 &indexstate->ioss_ScanKeys,
00468 &indexstate->ioss_NumScanKeys,
00469 &indexstate->ioss_RuntimeKeys,
00470 &indexstate->ioss_NumRuntimeKeys,
00471 NULL,
00472 NULL);
00473
00474
00475
00476
00477 ExecIndexBuildScanKeys((PlanState *) indexstate,
00478 indexstate->ioss_RelationDesc,
00479 node->indexorderby,
00480 true,
00481 &indexstate->ioss_OrderByKeys,
00482 &indexstate->ioss_NumOrderByKeys,
00483 &indexstate->ioss_RuntimeKeys,
00484 &indexstate->ioss_NumRuntimeKeys,
00485 NULL,
00486 NULL);
00487
00488
00489
00490
00491
00492
00493
00494 if (indexstate->ioss_NumRuntimeKeys != 0)
00495 {
00496 ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
00497
00498 ExecAssignExprContext(estate, &indexstate->ss.ps);
00499 indexstate->ioss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
00500 indexstate->ss.ps.ps_ExprContext = stdecontext;
00501 }
00502 else
00503 {
00504 indexstate->ioss_RuntimeContext = NULL;
00505 }
00506
00507
00508
00509
00510 indexstate->ioss_ScanDesc = index_beginscan(currentRelation,
00511 indexstate->ioss_RelationDesc,
00512 estate->es_snapshot,
00513 indexstate->ioss_NumScanKeys,
00514 indexstate->ioss_NumOrderByKeys);
00515
00516
00517 indexstate->ioss_ScanDesc->xs_want_itup = true;
00518 indexstate->ioss_VMBuffer = InvalidBuffer;
00519
00520
00521
00522
00523
00524 if (indexstate->ioss_NumRuntimeKeys == 0)
00525 index_rescan(indexstate->ioss_ScanDesc,
00526 indexstate->ioss_ScanKeys,
00527 indexstate->ioss_NumScanKeys,
00528 indexstate->ioss_OrderByKeys,
00529 indexstate->ioss_NumOrderByKeys);
00530
00531
00532
00533
00534 return indexstate;
00535 }