1 /*-------------------------------------------------------------------------
4 * Routines to support indexes and indexed scans of relations
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.13 1998/01/07 21:02:54 momjian Exp $
12 *-------------------------------------------------------------------------
16 * ExecInsertIndexTuples inserts tuples into indices on result relation
18 * ExecIndexScan scans a relation using indices
19 * ExecIndexNext using index to retrieve next tuple
20 * ExecInitIndexScan creates and initializes state info.
21 * ExecIndexReScan rescans the indexed relation.
22 * ExecEndIndexScan releases all storage.
23 * ExecIndexMarkPos marks scan position.
24 * ExecIndexRestrPos restores scan position.
27 * the code supporting ExecInsertIndexTuples should be
28 * collected and merged with the genam stuff.
33 #include "executor/executor.h"
34 #include "executor/execdebug.h"
35 #include "executor/nodeIndexscan.h"
37 #include "optimizer/clauses.h" /* for get_op, get_leftop, get_rightop */
38 #include "parser/parsetree.h" /* for rt_fetch() */
40 #include "access/skey.h"
41 #include "access/heapam.h"
42 #include "access/genam.h"
43 #include "utils/palloc.h"
44 #include "utils/mcxt.h"
45 #include "catalog/index.h"
46 #include "storage/bufmgr.h"
47 #include "storage/lmgr.h"
48 #include "nodes/nodeFuncs.h"
51 * Misc stuff to move to executor.h soon -cim 6/5/90
58 static TupleTableSlot *IndexNext(IndexScan *node);
60 /* ----------------------------------------------------------------
63 * Retrieve a tuple from the IndexScan node's currentRelation
64 * using the indices in the IndexScanState information.
66 * note: the old code mentions 'Primary indices'. to my knowledge
67 * we only support a single secondary index. -cim 9/11/89
70 * retrieve a tuple from relation using the indices given.
71 * The indices are used in the order they appear in 'indices'.
72 * The indices may be primary or secondary indices:
73 * * primary index -- scan the relation 'relID' using keys supplied.
74 * * secondary index -- scan the index relation to get the 'tid' for
75 * a tuple in the relation 'relID'.
76 * If the current index(pointed by 'indexPtr') fails to return a
77 * tuple, the next index in the indices is used.
79 * bug fix so that it should retrieve on a null scan key.
80 * ----------------------------------------------------------------
82 static TupleTableSlot *
83 IndexNext(IndexScan *node)
86 CommonScanState *scanstate;
87 IndexScanState *indexstate;
88 ScanDirection direction;
90 IndexScanDescPtr scanDescs;
91 IndexScanDesc scandesc;
92 Relation heapRelation;
93 RetrieveIndexResult result;
97 Buffer buffer = InvalidBuffer;
100 * extract necessary information from index scan node
103 estate = node->scan.plan.state;
104 direction = estate->es_direction;
105 scanstate = node->scan.scanstate;
106 indexstate = node->indxstate;
107 indexPtr = indexstate->iss_IndexPtr;
108 scanDescs = indexstate->iss_ScanDescs;
109 scandesc = scanDescs[indexPtr];
110 heapRelation = scanstate->css_currentRelation;
112 slot = scanstate->css_ScanTupleSlot;
115 * ok, now that we have what we need, fetch an index tuple.
121 result = index_getnext(scandesc, direction);
123 * if scanning this index succeeded then return the
124 * appropriate heap tuple.. else return NULL.
129 iptr = &result->heap_iptr;
130 tuple = heap_fetch(heapRelation,
140 * we found a deleted tuple, so keep on scanning..
143 if (BufferIsValid(buffer))
144 ReleaseBuffer(buffer);
149 * store the scanned tuple in the scan tuple slot of
150 * the scan state. Eventually we will only do this and not
151 * return a tuple. Note: we pass 'false' because tuples
152 * returned by amgetnext are pointers onto disk pages and
153 * were not created with palloc() and so should not be pfree()'d.
156 ExecStoreTuple(tuple, /* tuple to store */
157 slot,/* slot to store in */
158 buffer, /* buffer associated with tuple */
159 false); /* don't pfree */
165 * if we get here it means the index scan failed so we
166 * are at the end of the scan..
169 return ExecClearTuple(slot);
173 /* ----------------------------------------------------------------
174 * ExecIndexScan(node)
177 * Scans the relation using primary or secondary indices and returns
178 * the next qualifying tuple in the direction specified.
179 * It calls ExecScan() and passes it the access methods which returns
180 * the next tuple using the indices.
183 * -- the "cursor" maintained by the AMI is positioned at the tuple
184 * returned previously.
187 * -- the relation indicated is opened for scanning so that the
188 * "cursor" is positioned before the first qualifying tuple.
189 * -- all index realtions are opened for scanning.
190 * -- indexPtr points to the first index.
191 * -- state variable ruleFlag = nil.
192 * ----------------------------------------------------------------
195 ExecIndexScan(IndexScan *node)
197 TupleTableSlot *returnTuple;
200 * use IndexNext as access method
203 returnTuple = ExecScan(&node->scan, IndexNext);
207 /* ----------------------------------------------------------------
208 * ExecIndexReScan(node)
210 * Recalculates the value of the scan keys whose value depends on
211 * information known at runtime and rescans the indexed relation.
212 * Updating the scan key was formerly done separately in
213 * ExecUpdateIndexScanKeys. Integrating it into ReScan
214 * makes rescans of indices and
215 * relations/general streams more uniform.
217 * ----------------------------------------------------------------
220 ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
223 IndexScanState *indexstate;
224 ScanDirection direction;
225 IndexScanDescPtr scanDescs;
232 Pointer *runtimeKeyInfo;
247 indexstate = node->indxstate;
248 estate = node->scan.plan.state;
249 direction = estate->es_direction;
250 indexstate = node->indxstate;
251 numIndices = indexstate->iss_NumIndices;
252 scanDescs = indexstate->iss_ScanDescs;
253 scanKeys = indexstate->iss_ScanKeys;
255 runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
257 if (runtimeKeyInfo != NULL)
261 * get the index qualifications and recalculate the appropriate
264 indexPtr = indexstate->iss_IndexPtr;
265 indxqual = node->indxqual;
266 qual = nth(indexPtr, indxqual);
267 numScanKeys = indexstate->iss_NumScanKeys;
268 n_keys = numScanKeys[indexPtr];
269 run_keys = (int *) runtimeKeyInfo[indexPtr];
270 scan_keys = (ScanKey) scanKeys[indexPtr];
272 for (j = 0; j < n_keys; j++)
276 * If we have a run-time key, then extract the run-time
277 * expression and evaluate it with respect to the current
278 * outer tuple. We then stick the result into the scan key.
280 if (run_keys[j] != NO_OP)
282 clause = nth(j, qual);
283 scanexpr = (run_keys[j] == RIGHT_OP) ?
284 (Node *) get_rightop(clause) : (Node *) get_leftop(clause);
287 * pass in isDone but ignore it. We don't iterate in
291 ExecEvalExpr(scanexpr, exprCtxt, &isNull, &isDone);
292 scan_keys[j].sk_argument = scanvalue;
295 scan_keys[j].sk_flags |= SK_ISNULL;
299 scan_keys[j].sk_flags &= ~SK_ISNULL;
306 * rescans all indices
308 * note: AMrescan assumes only one scan key. This may have to change if
309 * we ever decide to support multiple keys.
311 for (i = 0; i < numIndices; i++)
313 sdesc = scanDescs[i];
315 index_rescan(sdesc, direction, skey);
319 * perhaps return something meaningful
325 /* ----------------------------------------------------------------
329 * Releases any storage allocated through C routines.
331 * ----------------------------------------------------------------
334 ExecEndIndexScan(IndexScan *node)
336 CommonScanState *scanstate;
337 IndexScanState *indexstate;
342 scanstate = node->scan.scanstate;
343 indexstate = node->indxstate;
346 * extract information from the node
349 numIndices = indexstate->iss_NumIndices;
350 scanKeys = indexstate->iss_ScanKeys;
353 * Free the projection info and the scan attribute info
355 * Note: we don't ExecFreeResultType(scanstate)
356 * because the rule manager depends on the tupType
357 * returned by ExecMain(). So for now, this
358 * is freed at end-transaction time. -cim 6/2/91
361 ExecFreeProjectionInfo(&scanstate->cstate);
364 * close the heap and index relations
367 ExecCloseR((Plan *) node);
370 * free the scan keys used in scanning the indices
373 for (i = 0; i < numIndices; i++)
375 if (scanKeys[i] != NULL)
381 * clear out tuple table slots
384 ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
385 ExecClearTuple(scanstate->css_ScanTupleSlot);
386 /* ExecClearTuple(scanstate->css_RawTupleSlot); */
389 /* ----------------------------------------------------------------
393 * Marks scan position by marking the current index.
395 * ----------------------------------------------------------------
398 ExecIndexMarkPos(IndexScan *node)
400 IndexScanState *indexstate;
401 IndexScanDescPtr indexScanDescs;
402 IndexScanDesc scanDesc;
405 indexstate = node->indxstate;
406 indexPtr = indexstate->iss_IndexPtr;
407 indexScanDescs = indexstate->iss_ScanDescs;
408 scanDesc = indexScanDescs[indexPtr];
411 * XXX access methods don't return marked positions so
414 IndexScanMarkPosition(scanDesc);
418 /* ----------------------------------------------------------------
422 * Restores scan position by restoring the current index.
425 * XXX Assumes previously marked scan position belongs to current index
426 * ----------------------------------------------------------------
429 ExecIndexRestrPos(IndexScan *node)
431 IndexScanState *indexstate;
432 IndexScanDescPtr indexScanDescs;
433 IndexScanDesc scanDesc;
436 indexstate = node->indxstate;
437 indexPtr = indexstate->iss_IndexPtr;
438 indexScanDescs = indexstate->iss_ScanDescs;
439 scanDesc = indexScanDescs[indexPtr];
441 IndexScanRestorePosition(scanDesc);
444 /* ----------------------------------------------------------------
447 * Initializes the index scan's state information, creates
448 * scan keys, and opens the base and index relations.
450 * Note: index scans have 2 sets of state information because
451 * we have to keep track of the base relation and the
455 * Creates the run-time state information for the node and
456 * sets the relation id to contain relevant decriptors.
459 * node: IndexNode node produced by the planner.
460 * estate: the execution state initialized in InitPlan.
461 * ----------------------------------------------------------------
464 ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
466 IndexScanState *indexstate;
467 CommonScanState *scanstate;
475 RelationPtr relationDescs;
476 IndexScanDescPtr scanDescs;
477 Pointer *runtimeKeyInfo;
478 bool have_runtime_keys;
480 RangeTblEntry *rtentry;
484 Relation currentRelation;
485 HeapScanDesc currentScanDesc;
486 ScanDirection direction;
490 * assign execution state to node
493 node->scan.plan.state = estate;
495 /* --------------------------------
496 * Part 1) initialize scan state
498 * create new CommonScanState for node
499 * --------------------------------
501 scanstate = makeNode(CommonScanState);
503 scanstate->ss_ProcOuterFlag = false;
504 scanstate->ss_OldRelId = 0;
507 node->scan.scanstate = scanstate;
510 * assign node's base_id .. we don't use AssignNodeBaseid() because
511 * the increment is done later on after we assign the index scan's
512 * scanstate. see below.
515 baseid = estate->es_BaseId;
516 /* scanstate->csstate.cstate.bnode.base_id = baseid; */
517 scanstate->cstate.cs_base_id = baseid;
520 * create expression context for node
523 ExecAssignExprContext(estate, &scanstate->cstate);
525 #define INDEXSCAN_NSLOTS 3
527 * tuple table initialization
530 ExecInitResultTupleSlot(estate, &scanstate->cstate);
531 ExecInitScanTupleSlot(estate, scanstate);
532 /* ExecInitRawTupleSlot(estate, scanstate); */
535 * initialize projection info. result type comes from scan desc
539 ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
541 /* --------------------------------
542 * Part 2) initialize index scan state
544 * create new IndexScanState for node
545 * --------------------------------
547 indexstate = makeNode(IndexScanState);
548 indexstate->iss_NumIndices = 0;
549 indexstate->iss_IndexPtr = 0;
550 indexstate->iss_ScanKeys = NULL;
551 indexstate->iss_NumScanKeys = NULL;
552 indexstate->iss_RuntimeKeyInfo = NULL;
553 indexstate->iss_RelationDescs = NULL;
554 indexstate->iss_ScanDescs = NULL;
556 node->indxstate = indexstate;
559 * assign base id to index scan state also
562 indexstate->cstate.cs_base_id = baseid;
564 estate->es_BaseId = baseid;
567 * get the index node information
570 indxid = node->indxid;
571 indxqual = node->indxqual;
572 numIndices = length(indxid);
575 CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);
578 * scanKeys is used to keep track of the ScanKey's. This is needed
579 * because a single scan may use several indices and each index has
583 numScanKeys = (int *) palloc(numIndices * sizeof(int));
584 scanKeys = (ScanKey *) palloc(numIndices * sizeof(ScanKey));
585 relationDescs = (RelationPtr) palloc(numIndices * sizeof(Relation));
586 scanDescs = (IndexScanDescPtr) palloc(numIndices * sizeof(IndexScanDesc));
589 * initialize runtime key info.
592 have_runtime_keys = false;
593 runtimeKeyInfo = (Pointer *)
594 palloc(numIndices * sizeof(Pointer));
597 * build the index scan keys from the index qualification
600 for (i = 0; i < numIndices; i++)
608 qual = nth(i, indxqual);
609 n_keys = length(qual);
610 scan_keys = (n_keys <= 0) ? NULL :
611 (ScanKey) palloc(n_keys * sizeof(ScanKeyData));
612 run_keys = (n_keys <= 0) ? NULL :
613 (int *) palloc(n_keys * sizeof(int));
615 CXT1_printf("ExecInitIndexScan: context is %d\n",
616 CurrentMemoryContext);
619 * for each opclause in the given qual,
620 * convert each qual's opclause into a single scan key
623 for (j = 0; j < n_keys; j++)
625 Expr *clause; /* one part of index qual */
626 Oper *op; /* operator used in scan.. */
627 Node *leftop; /* expr on lhs of operator */
628 Node *rightop;/* expr on rhs ... */
631 int scanvar;/* which var identifies varattno */
632 AttrNumber varattno = 0; /* att number used in scan */
633 Oid opid; /* operator id used in scan */
634 Datum scanvalue = 0; /* value used in scan (if const) */
637 * extract clause information from the qualification
640 clause = nth(j, qual);
642 op = (Oper *) clause->oper;
644 elog(ERROR, "ExecInitIndexScan: op not an Oper!");
649 * Here we figure out the contents of the index qual.
650 * The usual case is (op var const) or (op const var)
651 * which means we form a scan key for the attribute
652 * listed in the var node and use the value of the const.
654 * If we don't have a const node, then it means that
655 * one of the var nodes refers to the "scan" tuple and
656 * is used to determine which attribute to scan, and the
657 * other expression is used to calculate the value used in
658 * scanning the index.
660 * This means our index scan's scan key is a function of
661 * information obtained during the execution of the plan
662 * in which case we need to recalculate the index scan key
665 * Hence, we set have_runtime_keys to true and then set
666 * the appropriate flag in run_keys to LEFT_OP or RIGHT_OP.
667 * The corresponding scan keys are recomputed at run time.
674 * determine information in leftop
677 leftop = (Node *) get_leftop(clause);
679 if (IsA(leftop, Var) &&var_is_rel((Var *) leftop))
682 * if the leftop is a "rel-var", then it means
683 * that it is a var node which tells us which
684 * attribute to use for our scan key.
687 varattno = ((Var *) leftop)->varattno;
690 else if (IsA(leftop, Const))
693 * if the leftop is a const node then it means
694 * it identifies the value to place in our scan key.
698 scanvalue = ((Const *) leftop)->constvalue;
699 #ifdef INDEXSCAN_PATCH
701 else if (IsA(leftop, Param))
706 * if the leftop is a Param node then it means
707 * it identifies the value to place in our scan key.
711 scanvalue = ExecEvalParam((Param *) leftop,
712 scanstate->cstate.cs_ExprContext,
718 else if (leftop != NULL &&
719 is_funcclause(leftop) &&
720 var_is_rel(lfirst(((Expr *) leftop)->args)))
723 * if the leftop is a func node then it means
724 * it identifies the value to place in our scan key.
725 * Since functional indices have only one attribute
726 * the attno must always be set to 1.
736 * otherwise, the leftop contains information usable
737 * at runtime to figure out the value to place in our
741 have_runtime_keys = true;
742 run_keys[j] = LEFT_OP;
743 scanvalue = Int32GetDatum((int32) true);
747 * now determine information in rightop
750 rightop = (Node *) get_rightop(clause);
752 if (IsA(rightop, Var) &&var_is_rel((Var *) rightop))
755 * here we make sure only one op identifies the
759 if (scanvar == LEFT_OP)
760 elog(ERROR, "ExecInitIndexScan: %s",
761 "both left and right op's are rel-vars");
764 * if the rightop is a "rel-var", then it means
765 * that it is a var node which tells us which
766 * attribute to use for our scan key.
769 varattno = ((Var *) rightop)->varattno;
773 else if (IsA(rightop, Const))
776 * if the leftop is a const node then it means
777 * it identifies the value to place in our scan key.
781 scanvalue = ((Const *) rightop)->constvalue;
782 #ifdef INDEXSCAN_PATCH
784 else if (IsA(rightop, Param))
789 * if the rightop is a Param node then it means
790 * it identifies the value to place in our scan key.
794 scanvalue = ExecEvalParam((Param *) rightop,
795 scanstate->cstate.cs_ExprContext,
801 else if (rightop != NULL &&
802 is_funcclause(rightop) &&
803 var_is_rel(lfirst(((Expr *) rightop)->args)))
806 * if the rightop is a func node then it means
807 * it identifies the value to place in our scan key.
808 * Since functional indices have only one attribute
809 * the attno must always be set to 1.
812 if (scanvar == LEFT_OP)
813 elog(ERROR, "ExecInitIndexScan: %s",
814 "both left and right ops are rel-vars");
823 * otherwise, the leftop contains information usable
824 * at runtime to figure out the value to place in our
828 have_runtime_keys = true;
829 run_keys[j] = RIGHT_OP;
830 scanvalue = Int32GetDatum((int32) true);
834 * now check that at least one op tells us the scan
838 if (scanvar == NO_OP)
839 elog(ERROR, "ExecInitIndexScan: %s",
840 "neither leftop nor rightop refer to scan relation");
843 * initialize the scan key's fields appropriately
846 ScanKeyEntryInitialize(&scan_keys[j],
848 varattno, /* attribute number to
850 (RegProcedure) opid, /* reg proc to use */
851 (Datum) scanvalue); /* constant */
855 * store the key information into our array.
858 numScanKeys[i] = n_keys;
859 scanKeys[i] = scan_keys;
860 runtimeKeyInfo[i] = (Pointer) run_keys;
863 indexstate->iss_NumIndices = numIndices;
864 indexstate->iss_IndexPtr = indexPtr;
865 indexstate->iss_ScanKeys = scanKeys;
866 indexstate->iss_NumScanKeys = numScanKeys;
869 * If all of our keys have the form (op var const) , then we have no
870 * runtime keys so we store NULL in the runtime key info.
871 * Otherwise runtime key info contains an array of pointers
872 * (one for each index) to arrays of flags (one for each key)
873 * which indicate that the qual needs to be evaluated at runtime.
877 if (have_runtime_keys)
879 indexstate->iss_RuntimeKeyInfo = (Pointer) runtimeKeyInfo;
883 indexstate->iss_RuntimeKeyInfo = NULL;
884 for (i = 0; i < numIndices; i++)
889 qual = nth(i, indxqual);
890 n_keys = length(qual);
892 pfree(runtimeKeyInfo[i]);
894 pfree(runtimeKeyInfo);
898 * get the range table and direction information
899 * from the execution state (these are needed to
900 * open the relations).
903 rangeTable = estate->es_range_table;
904 direction = estate->es_direction;
907 * open the base relation
910 relid = node->scan.scanrelid;
911 rtentry = rt_fetch(relid, rangeTable);
912 reloid = rtentry->relid;
914 ExecOpenScanR(reloid, /* relation */
916 (ScanKey) NULL, /* scan key */
918 direction, /* scan direction */
919 ¤tRelation, /* return: rel desc */
920 (Pointer *) ¤tScanDesc); /* return: scan desc */
922 scanstate->css_currentRelation = currentRelation;
923 scanstate->css_currentScanDesc = currentScanDesc;
927 * get the scan type from the relation descriptor.
930 ExecAssignScanType(scanstate, RelationGetTupleDescriptor(currentRelation));
931 ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
934 * index scans don't have subtrees..
937 /* scanstate->ss_ProcOuterFlag = false; */
940 * open the index relations and initialize
941 * relation and scan descriptors.
944 for (i = 0; i < numIndices; i++)
948 indexOid = (Oid) nthi(i, indxid);
952 ExecOpenScanR(indexOid, /* relation */
953 numScanKeys[i], /* nkeys */
954 scanKeys[i], /* scan key */
956 direction, /* scan direction */
957 &(relationDescs[i]), /* return: rel desc */
958 (Pointer *) &(scanDescs[i]));
959 /* return: scan desc */
963 indexstate->iss_RelationDescs = relationDescs;
964 indexstate->iss_ScanDescs = scanDescs;
966 indexstate->cstate.cs_TupFromTlist = false;
976 ExecCountSlotsIndexScan(IndexScan *node)
978 return ExecCountSlotsNode(outerPlan((Plan *) node)) +
979 ExecCountSlotsNode(innerPlan((Plan *) node)) +