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.21 1998/08/01 22:44:52 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;
96 Buffer buffer = InvalidBuffer;
100 * extract necessary information from index scan node
103 estate = node->scan.plan.state;
104 direction = estate->es_direction;
105 snapshot = estate->es_snapshot;
106 scanstate = node->scan.scanstate;
107 indexstate = node->indxstate;
108 scanDescs = indexstate->iss_ScanDescs;
109 heapRelation = scanstate->css_currentRelation;
110 numIndices = indexstate->iss_NumIndices;
111 slot = scanstate->css_ScanTupleSlot;
114 * ok, now that we have what we need, fetch an index tuple.
115 * if scanning this index succeeded then return the
116 * appropriate heap tuple.. else return NULL.
119 while (indexstate->iss_IndexPtr < numIndices)
121 scandesc = scanDescs[indexstate->iss_IndexPtr];
122 while ((result = index_getnext(scandesc, direction)) != NULL)
124 tuple = heap_fetch(heapRelation, snapshot,
125 &result->heap_iptr, &buffer);
131 bool prev_matches = false;
135 * store the scanned tuple in the scan tuple slot of
136 * the scan state. Eventually we will only do this and not
137 * return a tuple. Note: we pass 'false' because tuples
138 * returned by amgetnext are pointers onto disk pages and
139 * were not created with palloc() and so should not be pfree()'d.
142 ExecStoreTuple(tuple, /* tuple to store */
143 slot, /* slot to store in */
144 buffer, /* buffer associated with tuple */
145 false); /* don't pfree */
147 for (prev_index = 0; prev_index < indexstate->iss_IndexPtr;
150 if (ExecQual(nth(prev_index, node->indxqual),
151 scanstate->cstate.cs_ExprContext))
160 ExecClearTuple(slot);
162 if (BufferIsValid(buffer))
163 ReleaseBuffer(buffer);
165 if (indexstate->iss_IndexPtr < numIndices)
166 indexstate->iss_IndexPtr++;
169 * if we get here it means the index scan failed so we
170 * are at the end of the scan..
173 return ExecClearTuple(slot);
176 /* ----------------------------------------------------------------
177 * ExecIndexScan(node)
180 * Scans the relation using primary or secondary indices and returns
181 * the next qualifying tuple in the direction specified.
182 * It calls ExecScan() and passes it the access methods which returns
183 * the next tuple using the indices.
186 * -- the "cursor" maintained by the AMI is positioned at the tuple
187 * returned previously.
190 * -- the relation indicated is opened for scanning so that the
191 * "cursor" is positioned before the first qualifying tuple.
192 * -- all index realtions are opened for scanning.
193 * -- indexPtr points to the first index.
194 * -- state variable ruleFlag = nil.
195 * ----------------------------------------------------------------
198 ExecIndexScan(IndexScan *node)
201 * use IndexNext as access method
204 return 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;
246 indexstate = node->indxstate;
247 estate = node->scan.plan.state;
248 direction = estate->es_direction;
249 numIndices = indexstate->iss_NumIndices;
250 scanDescs = indexstate->iss_ScanDescs;
251 scanKeys = indexstate->iss_ScanKeys;
252 runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
253 indxqual = node->indxqual;
254 numScanKeys = indexstate->iss_NumScanKeys;
255 indexstate->iss_IndexPtr = 0;
257 /* it's possible in subselects */
258 if (exprCtxt == NULL)
259 exprCtxt = node->scan.scanstate->cstate.cs_ExprContext;
261 if (exprCtxt != NULL)
262 node->scan.scanstate->cstate.cs_ExprContext->ecxt_outertuple =
263 exprCtxt->ecxt_outertuple;
266 * get the index qualifications and recalculate the appropriate
269 for (i = 0; i < numIndices; i++)
271 if (runtimeKeyInfo && runtimeKeyInfo[i] != NULL)
273 qual = nth(i, indxqual);
274 n_keys = numScanKeys[i];
275 run_keys = (int *) runtimeKeyInfo[i];
276 scan_keys = (ScanKey) scanKeys[i];
278 for (j = 0; j < n_keys; j++)
281 * If we have a run-time key, then extract the run-time
282 * expression and evaluate it with respect to the current
283 * outer tuple. We then stick the result into the scan key.
285 if (run_keys[j] != NO_OP)
287 clause = nth(j, qual);
288 scanexpr = (run_keys[j] == RIGHT_OP) ?
289 (Node *) get_rightop(clause) : (Node *) get_leftop(clause);
292 * pass in isDone but ignore it. We don't iterate in
296 ExecEvalExpr(scanexpr, exprCtxt, &isNull, &isDone);
297 scan_keys[j].sk_argument = scanvalue;
299 scan_keys[j].sk_flags |= SK_ISNULL;
301 scan_keys[j].sk_flags &= ~SK_ISNULL;
304 sdesc = scanDescs[i];
306 index_rescan(sdesc, direction, skey);
310 * perhaps return something meaningful
316 /* ----------------------------------------------------------------
320 * Releases any storage allocated through C routines.
322 * ----------------------------------------------------------------
325 ExecEndIndexScan(IndexScan *node)
327 CommonScanState *scanstate;
328 IndexScanState *indexstate;
329 Pointer *runtimeKeyInfo;
336 scanstate = node->scan.scanstate;
337 indexstate = node->indxstate;
338 indxqual = node->indxqual;
339 runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
342 * extract information from the node
345 numIndices = indexstate->iss_NumIndices;
346 scanKeys = indexstate->iss_ScanKeys;
347 numScanKeys = indexstate->iss_NumScanKeys;
350 * Free the projection info and the scan attribute info
352 * Note: we don't ExecFreeResultType(scanstate)
353 * because the rule manager depends on the tupType
354 * returned by ExecMain(). So for now, this
355 * is freed at end-transaction time. -cim 6/2/91
358 ExecFreeProjectionInfo(&scanstate->cstate);
361 * close the heap and index relations
364 ExecCloseR((Plan *) node);
367 * free the scan keys used in scanning the indices
370 for (i = 0; i < numIndices; i++)
372 if (scanKeys[i] != NULL)
380 for (i = 0; i < numIndices; i++)
385 qual = nth(i, indxqual);
386 n_keys = length(qual);
388 pfree(runtimeKeyInfo[i]);
390 pfree(runtimeKeyInfo);
394 * clear out tuple table slots
397 ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
398 ExecClearTuple(scanstate->css_ScanTupleSlot);
399 /* ExecClearTuple(scanstate->css_RawTupleSlot); */
402 /* ----------------------------------------------------------------
406 * Marks scan position by marking the current index.
408 * ----------------------------------------------------------------
411 ExecIndexMarkPos(IndexScan *node)
413 IndexScanState *indexstate;
414 IndexScanDescPtr indexScanDescs;
415 IndexScanDesc scanDesc;
418 indexstate = node->indxstate;
419 indexPtr = indexstate->iss_IndexPtr;
420 indexScanDescs = indexstate->iss_ScanDescs;
421 scanDesc = indexScanDescs[indexPtr];
424 IndexScanMarkPosition(scanDesc);
426 index_markpos (scanDesc);
429 /* ----------------------------------------------------------------
433 * Restores scan position by restoring the current index.
436 * XXX Assumes previously marked scan position belongs to current index
437 * ----------------------------------------------------------------
440 ExecIndexRestrPos(IndexScan *node)
442 IndexScanState *indexstate;
443 IndexScanDescPtr indexScanDescs;
444 IndexScanDesc scanDesc;
447 indexstate = node->indxstate;
448 indexPtr = indexstate->iss_IndexPtr;
449 indexScanDescs = indexstate->iss_ScanDescs;
450 scanDesc = indexScanDescs[indexPtr];
453 IndexScanRestorePosition(scanDesc);
455 index_restrpos (scanDesc);
458 /* ----------------------------------------------------------------
461 * Initializes the index scan's state information, creates
462 * scan keys, and opens the base and index relations.
464 * Note: index scans have 2 sets of state information because
465 * we have to keep track of the base relation and the
469 * Creates the run-time state information for the node and
470 * sets the relation id to contain relevant decriptors.
473 * node: IndexNode node produced by the planner.
474 * estate: the execution state initialized in InitPlan.
475 * ----------------------------------------------------------------
478 ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
480 IndexScanState *indexstate;
481 CommonScanState *scanstate;
489 RelationPtr relationDescs;
490 IndexScanDescPtr scanDescs;
491 Pointer *runtimeKeyInfo;
492 bool have_runtime_keys;
494 RangeTblEntry *rtentry;
498 Relation currentRelation;
499 HeapScanDesc currentScanDesc;
500 ScanDirection direction;
503 List *execParam = NULL;
506 * assign execution state to node
509 node->scan.plan.state = estate;
511 /* --------------------------------
512 * Part 1) initialize scan state
514 * create new CommonScanState for node
515 * --------------------------------
517 scanstate = makeNode(CommonScanState);
519 scanstate->ss_ProcOuterFlag = false;
520 scanstate->ss_OldRelId = 0;
523 node->scan.scanstate = scanstate;
526 * assign node's base_id .. we don't use AssignNodeBaseid() because
527 * the increment is done later on after we assign the index scan's
528 * scanstate. see below.
531 baseid = estate->es_BaseId;
532 /* scanstate->csstate.cstate.bnode.base_id = baseid; */
533 scanstate->cstate.cs_base_id = baseid;
536 * create expression context for node
539 ExecAssignExprContext(estate, &scanstate->cstate);
541 #define INDEXSCAN_NSLOTS 3
543 * tuple table initialization
546 ExecInitResultTupleSlot(estate, &scanstate->cstate);
547 ExecInitScanTupleSlot(estate, scanstate);
548 /* ExecInitRawTupleSlot(estate, scanstate); */
551 * initialize projection info. result type comes from scan desc
555 ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
557 /* --------------------------------
558 * Part 2) initialize index scan state
560 * create new IndexScanState for node
561 * --------------------------------
563 indexstate = makeNode(IndexScanState);
564 indexstate->iss_NumIndices = 0;
565 indexstate->iss_IndexPtr = 0;
566 indexstate->iss_ScanKeys = NULL;
567 indexstate->iss_NumScanKeys = NULL;
568 indexstate->iss_RuntimeKeyInfo = NULL;
569 indexstate->iss_RelationDescs = NULL;
570 indexstate->iss_ScanDescs = NULL;
572 node->indxstate = indexstate;
575 * assign base id to index scan state also
578 indexstate->cstate.cs_base_id = baseid;
580 estate->es_BaseId = baseid;
583 * get the index node information
586 indxid = node->indxid;
587 indxqual = node->indxqual;
588 numIndices = length(indxid);
591 CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);
594 * scanKeys is used to keep track of the ScanKey's. This is needed
595 * because a single scan may use several indices and each index has
599 numScanKeys = (int *) palloc(numIndices * sizeof(int));
600 scanKeys = (ScanKey *) palloc(numIndices * sizeof(ScanKey));
601 relationDescs = (RelationPtr) palloc(numIndices * sizeof(Relation));
602 scanDescs = (IndexScanDescPtr) palloc(numIndices * sizeof(IndexScanDesc));
605 * initialize runtime key info.
608 have_runtime_keys = false;
609 runtimeKeyInfo = (Pointer *)
610 palloc(numIndices * sizeof(Pointer));
613 * build the index scan keys from the index qualification
616 for (i = 0; i < numIndices; i++)
624 qual = nth(i, indxqual);
625 n_keys = length(qual);
626 scan_keys = (n_keys <= 0) ? NULL :
627 (ScanKey) palloc(n_keys * sizeof(ScanKeyData));
628 run_keys = (n_keys <= 0) ? NULL :
629 (int *) palloc(n_keys * sizeof(int));
631 CXT1_printf("ExecInitIndexScan: context is %d\n",
632 CurrentMemoryContext);
635 * for each opclause in the given qual,
636 * convert each qual's opclause into a single scan key
639 for (j = 0; j < n_keys; j++)
641 Expr *clause; /* one part of index qual */
642 Oper *op; /* operator used in scan.. */
643 Node *leftop; /* expr on lhs of operator */
644 Node *rightop;/* expr on rhs ... */
647 int scanvar;/* which var identifies varattno */
648 AttrNumber varattno = 0; /* att number used in scan */
649 Oid opid; /* operator id used in scan */
650 Datum scanvalue = 0; /* value used in scan (if const) */
653 * extract clause information from the qualification
656 clause = nth(j, qual);
658 op = (Oper *) clause->oper;
660 elog(ERROR, "ExecInitIndexScan: op not an Oper!");
665 * Here we figure out the contents of the index qual.
666 * The usual case is (op var const) or (op const var)
667 * which means we form a scan key for the attribute
668 * listed in the var node and use the value of the const.
670 * If we don't have a const node, then it means that
671 * one of the var nodes refers to the "scan" tuple and
672 * is used to determine which attribute to scan, and the
673 * other expression is used to calculate the value used in
674 * scanning the index.
676 * This means our index scan's scan key is a function of
677 * information obtained during the execution of the plan
678 * in which case we need to recalculate the index scan key
681 * Hence, we set have_runtime_keys to true and then set
682 * the appropriate flag in run_keys to LEFT_OP or RIGHT_OP.
683 * The corresponding scan keys are recomputed at run time.
690 * determine information in leftop
693 leftop = (Node *) get_leftop(clause);
695 if (IsA(leftop, Var) &&var_is_rel((Var *) leftop))
698 * if the leftop is a "rel-var", then it means
699 * that it is a var node which tells us which
700 * attribute to use for our scan key.
703 varattno = ((Var *) leftop)->varattno;
706 else if (IsA(leftop, Const))
709 * if the leftop is a const node then it means
710 * it identifies the value to place in our scan key.
714 scanvalue = ((Const *) leftop)->constvalue;
716 else if (IsA(leftop, Param))
721 * if the leftop is a Param node then it means
722 * it identifies the value to place in our scan key.
726 /* Life was so easy before ... subselects */
727 if ( ((Param *) leftop)->paramkind == PARAM_EXEC )
729 have_runtime_keys = true;
730 run_keys[j] = LEFT_OP;
731 execParam = lappendi (execParam, ((Param*) leftop)->paramid);
735 scanvalue = ExecEvalParam((Param *) leftop,
736 scanstate->cstate.cs_ExprContext,
744 else if (leftop != NULL &&
745 is_funcclause(leftop) &&
746 var_is_rel(lfirst(((Expr *) leftop)->args)))
749 * if the leftop is a func node then it means
750 * it identifies the value to place in our scan key.
751 * Since functional indices have only one attribute
752 * the attno must always be set to 1.
762 * otherwise, the leftop contains information usable
763 * at runtime to figure out the value to place in our
767 have_runtime_keys = true;
768 run_keys[j] = LEFT_OP;
769 scanvalue = Int32GetDatum((int32) true);
773 * now determine information in rightop
776 rightop = (Node *) get_rightop(clause);
778 if (IsA(rightop, Var) &&var_is_rel((Var *) rightop))
781 * here we make sure only one op identifies the
785 if (scanvar == LEFT_OP)
786 elog(ERROR, "ExecInitIndexScan: %s",
787 "both left and right op's are rel-vars");
790 * if the rightop is a "rel-var", then it means
791 * that it is a var node which tells us which
792 * attribute to use for our scan key.
795 varattno = ((Var *) rightop)->varattno;
799 else if (IsA(rightop, Const))
802 * if the leftop is a const node then it means
803 * it identifies the value to place in our scan key.
807 scanvalue = ((Const *) rightop)->constvalue;
809 else if (IsA(rightop, Param))
814 * if the rightop is a Param node then it means
815 * it identifies the value to place in our scan key.
819 /* Life was so easy before ... subselects */
820 if ( ((Param *) rightop)->paramkind == PARAM_EXEC )
822 have_runtime_keys = true;
823 run_keys[j] = RIGHT_OP;
824 execParam = lappendi (execParam, ((Param*) rightop)->paramid);
828 scanvalue = ExecEvalParam((Param *) rightop,
829 scanstate->cstate.cs_ExprContext,
837 else if (rightop != NULL &&
838 is_funcclause(rightop) &&
839 var_is_rel(lfirst(((Expr *) rightop)->args)))
842 * if the rightop is a func node then it means
843 * it identifies the value to place in our scan key.
844 * Since functional indices have only one attribute
845 * the attno must always be set to 1.
848 if (scanvar == LEFT_OP)
849 elog(ERROR, "ExecInitIndexScan: %s",
850 "both left and right ops are rel-vars");
859 * otherwise, the leftop contains information usable
860 * at runtime to figure out the value to place in our
864 have_runtime_keys = true;
865 run_keys[j] = RIGHT_OP;
866 scanvalue = Int32GetDatum((int32) true);
870 * now check that at least one op tells us the scan
874 if (scanvar == NO_OP)
875 elog(ERROR, "ExecInitIndexScan: %s",
876 "neither leftop nor rightop refer to scan relation");
879 * initialize the scan key's fields appropriately
882 ScanKeyEntryInitialize(&scan_keys[j],
884 varattno, /* attribute number to
886 (RegProcedure) opid, /* reg proc to use */
887 (Datum) scanvalue); /* constant */
891 * store the key information into our array.
894 numScanKeys[i] = n_keys;
895 scanKeys[i] = scan_keys;
896 runtimeKeyInfo[i] = (Pointer) run_keys;
899 indexstate->iss_NumIndices = numIndices;
900 indexstate->iss_IndexPtr = indexPtr;
901 indexstate->iss_ScanKeys = scanKeys;
902 indexstate->iss_NumScanKeys = numScanKeys;
905 * If all of our keys have the form (op var const) , then we have no
906 * runtime keys so we store NULL in the runtime key info.
907 * Otherwise runtime key info contains an array of pointers
908 * (one for each index) to arrays of flags (one for each key)
909 * which indicate that the qual needs to be evaluated at runtime.
913 if (have_runtime_keys)
914 indexstate->iss_RuntimeKeyInfo = (Pointer) runtimeKeyInfo;
916 indexstate->iss_RuntimeKeyInfo = NULL;
919 * get the range table and direction information
920 * from the execution state (these are needed to
921 * open the relations).
924 rangeTable = estate->es_range_table;
925 direction = estate->es_direction;
928 * open the base relation
931 relid = node->scan.scanrelid;
932 rtentry = rt_fetch(relid, rangeTable);
933 reloid = rtentry->relid;
935 ExecOpenScanR(reloid, /* relation */
937 (ScanKey) NULL, /* scan key */
939 direction, /* scan direction */
940 estate->es_snapshot, /* */
941 ¤tRelation, /* return: rel desc */
942 (Pointer *) ¤tScanDesc); /* return: scan desc */
944 scanstate->css_currentRelation = currentRelation;
945 scanstate->css_currentScanDesc = currentScanDesc;
949 * get the scan type from the relation descriptor.
952 ExecAssignScanType(scanstate, RelationGetTupleDescriptor(currentRelation));
953 ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
956 * index scans don't have subtrees..
959 /* scanstate->ss_ProcOuterFlag = false; */
962 * open the index relations and initialize
963 * relation and scan descriptors.
966 for (i = 0; i < numIndices; i++)
970 indexOid = (Oid) nthi(i, indxid);
974 ExecOpenScanR(indexOid, /* relation */
975 numScanKeys[i], /* nkeys */
976 scanKeys[i], /* scan key */
978 direction, /* scan direction */
980 &(relationDescs[i]), /* return: rel desc */
981 (Pointer *) &(scanDescs[i]));
982 /* return: scan desc */
986 indexstate->iss_RelationDescs = relationDescs;
987 indexstate->iss_ScanDescs = scanDescs;
989 indexstate->cstate.cs_TupFromTlist = false;
992 * if there are some PARAM_EXEC in skankeys then
993 * force index rescan on first scan.
995 ((Plan*) node)->chgParam = execParam;
1005 ExecCountSlotsIndexScan(IndexScan *node)
1007 return ExecCountSlotsNode(outerPlan((Plan *) node)) +
1008 ExecCountSlotsNode(innerPlan((Plan *) node)) + INDEXSCAN_NSLOTS;