]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeIndexscan.c
Goodbye register keyword. Compiler knows better.
[postgresql] / src / backend / executor / nodeIndexscan.c
1 /*-------------------------------------------------------------------------
2  *
3  * nodeIndexscan.c--
4  *        Routines to support indexes and indexed scans of relations
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.13 1998/01/07 21:02:54 momjian Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 /*
15  * INTERFACE ROUTINES
16  *              ExecInsertIndexTuples   inserts tuples into indices on result relation
17  *
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.
25  *
26  *       NOTES
27  *              the code supporting ExecInsertIndexTuples should be
28  *              collected and merged with the genam stuff.
29  *
30  */
31 #include "postgres.h"
32
33 #include "executor/executor.h"
34 #include "executor/execdebug.h"
35 #include "executor/nodeIndexscan.h"
36
37 #include "optimizer/clauses.h"  /* for get_op, get_leftop, get_rightop */
38 #include "parser/parsetree.h"   /* for rt_fetch() */
39
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"
49
50 /* ----------------
51  *              Misc stuff to move to executor.h soon -cim 6/5/90
52  * ----------------
53  */
54 #define NO_OP                   0
55 #define LEFT_OP                 1
56 #define RIGHT_OP                2
57
58 static TupleTableSlot *IndexNext(IndexScan *node);
59
60 /* ----------------------------------------------------------------
61  *              IndexNext
62  *
63  *              Retrieve a tuple from the IndexScan node's currentRelation
64  *              using the indices in the IndexScanState information.
65  *
66  *              note: the old code mentions 'Primary indices'.  to my knowledge
67  *              we only support a single secondary index. -cim 9/11/89
68  *
69  * old comments:
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.
78  *
79  *                bug fix so that it should retrieve on a null scan key.
80  * ----------------------------------------------------------------
81  */
82 static TupleTableSlot *
83 IndexNext(IndexScan *node)
84 {
85         EState     *estate;
86         CommonScanState *scanstate;
87         IndexScanState *indexstate;
88         ScanDirection direction;
89         int                     indexPtr;
90         IndexScanDescPtr scanDescs;
91         IndexScanDesc scandesc;
92         Relation        heapRelation;
93         RetrieveIndexResult result;
94         ItemPointer iptr;
95         HeapTuple       tuple;
96         TupleTableSlot *slot;
97         Buffer          buffer = InvalidBuffer;
98
99         /* ----------------
100          *      extract necessary information from index scan node
101          * ----------------
102          */
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;
111
112         slot = scanstate->css_ScanTupleSlot;
113
114         /* ----------------
115          *      ok, now that we have what we need, fetch an index tuple.
116          * ----------------
117          */
118
119         for (;;)
120         {
121                 result = index_getnext(scandesc, direction);
122                 /* ----------------
123                  *      if scanning this index succeeded then return the
124                  *      appropriate heap tuple.. else return NULL.
125                  * ----------------
126                  */
127                 if (result)
128                 {
129                         iptr = &result->heap_iptr;
130                         tuple = heap_fetch(heapRelation,
131                                                            false,
132                                                            iptr,
133                                                            &buffer);
134                         /* be tidy */
135                         pfree(result);
136
137                         if (tuple == NULL)
138                         {
139                                 /* ----------------
140                                  *       we found a deleted tuple, so keep on scanning..
141                                  * ----------------
142                                  */
143                                 if (BufferIsValid(buffer))
144                                         ReleaseBuffer(buffer);
145                                 continue;
146                         }
147
148                         /* ----------------
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.
154                          * ----------------
155                          */
156                         ExecStoreTuple(tuple,           /* tuple to store */
157                                                    slot,/* slot to store in */
158                                                    buffer,              /* buffer associated with tuple  */
159                                                    false);              /* don't pfree */
160
161                         return slot;
162                 }
163
164                 /* ----------------
165                  *      if we get here it means the index scan failed so we
166                  *      are at the end of the scan..
167                  * ----------------
168                  */
169                 return ExecClearTuple(slot);
170         }
171 }
172
173 /* ----------------------------------------------------------------
174  *              ExecIndexScan(node)
175  *
176  * old comments:
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.
181  *
182  *              Conditions:
183  *                -- the "cursor" maintained by the AMI is positioned at the tuple
184  *                       returned previously.
185  *
186  *              Initial States:
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  * ----------------------------------------------------------------
193  */
194 TupleTableSlot *
195 ExecIndexScan(IndexScan *node)
196 {
197         TupleTableSlot *returnTuple;
198
199         /* ----------------
200          *      use IndexNext as access method
201          * ----------------
202          */
203         returnTuple = ExecScan(&node->scan, IndexNext);
204         return returnTuple;
205 }
206
207 /* ----------------------------------------------------------------
208  *              ExecIndexReScan(node)
209  *
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.
216  *
217  * ----------------------------------------------------------------
218  */
219 void
220 ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
221 {
222         EState     *estate;
223         IndexScanState *indexstate;
224         ScanDirection direction;
225         IndexScanDescPtr scanDescs;
226         ScanKey    *scanKeys;
227         IndexScanDesc sdesc;
228         ScanKey         skey;
229         int                     numIndices;
230         int                     i;
231
232         Pointer    *runtimeKeyInfo;
233         int                     indexPtr;
234         int                *numScanKeys;
235         List       *indxqual;
236         List       *qual;
237         int                     n_keys;
238         ScanKey         scan_keys;
239         int                *run_keys;
240         int                     j;
241         Expr       *clause;
242         Node       *scanexpr;
243         Datum           scanvalue;
244         bool            isNull;
245         bool            isDone;
246
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;
254
255         runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
256
257         if (runtimeKeyInfo != NULL)
258         {
259
260                 /*
261                  * get the index qualifications and recalculate the appropriate
262                  * values
263                  */
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];
271
272                 for (j = 0; j < n_keys; j++)
273                 {
274
275                         /*
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.
279                          */
280                         if (run_keys[j] != NO_OP)
281                         {
282                                 clause = nth(j, qual);
283                                 scanexpr = (run_keys[j] == RIGHT_OP) ?
284                                         (Node *) get_rightop(clause) : (Node *) get_leftop(clause);
285
286                                 /*
287                                  * pass in isDone but ignore it.  We don't iterate in
288                                  * quals
289                                  */
290                                 scanvalue = (Datum)
291                                         ExecEvalExpr(scanexpr, exprCtxt, &isNull, &isDone);
292                                 scan_keys[j].sk_argument = scanvalue;
293                                 if (isNull)
294                                 {
295                                         scan_keys[j].sk_flags |= SK_ISNULL;
296                                 }
297                                 else
298                                 {
299                                         scan_keys[j].sk_flags &= ~SK_ISNULL;
300                                 }
301                         }
302                 }
303         }
304
305         /*
306          * rescans all indices
307          *
308          * note: AMrescan assumes only one scan key.  This may have to change if
309          * we ever decide to support multiple keys.
310          */
311         for (i = 0; i < numIndices; i++)
312         {
313                 sdesc = scanDescs[i];
314                 skey = scanKeys[i];
315                 index_rescan(sdesc, direction, skey);
316         }
317
318         /* ----------------
319          *      perhaps return something meaningful
320          * ----------------
321          */
322         return;
323 }
324
325 /* ----------------------------------------------------------------
326  *              ExecEndIndexScan
327  *
328  * old comments
329  *              Releases any storage allocated through C routines.
330  *              Returns nothing.
331  * ----------------------------------------------------------------
332  */
333 void
334 ExecEndIndexScan(IndexScan *node)
335 {
336         CommonScanState *scanstate;
337         IndexScanState *indexstate;
338         ScanKey    *scanKeys;
339         int                     numIndices;
340         int                     i;
341
342         scanstate = node->scan.scanstate;
343         indexstate = node->indxstate;
344
345         /* ----------------
346          *      extract information from the node
347          * ----------------
348          */
349         numIndices = indexstate->iss_NumIndices;
350         scanKeys = indexstate->iss_ScanKeys;
351
352         /* ----------------
353          *      Free the projection info and the scan attribute info
354          *
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
359          * ----------------
360          */
361         ExecFreeProjectionInfo(&scanstate->cstate);
362
363         /* ----------------
364          *      close the heap and index relations
365          * ----------------
366          */
367         ExecCloseR((Plan *) node);
368
369         /* ----------------
370          *      free the scan keys used in scanning the indices
371          * ----------------
372          */
373         for (i = 0; i < numIndices; i++)
374         {
375                 if (scanKeys[i] != NULL)
376                         pfree(scanKeys[i]);
377
378         }
379
380         /* ----------------
381          *      clear out tuple table slots
382          * ----------------
383          */
384         ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
385         ExecClearTuple(scanstate->css_ScanTupleSlot);
386 /*        ExecClearTuple(scanstate->css_RawTupleSlot); */
387 }
388
389 /* ----------------------------------------------------------------
390  *              ExecIndexMarkPos
391  *
392  * old comments
393  *              Marks scan position by marking the current index.
394  *              Returns nothing.
395  * ----------------------------------------------------------------
396  */
397 void
398 ExecIndexMarkPos(IndexScan *node)
399 {
400         IndexScanState *indexstate;
401         IndexScanDescPtr indexScanDescs;
402         IndexScanDesc scanDesc;
403         int                     indexPtr;
404
405         indexstate = node->indxstate;
406         indexPtr = indexstate->iss_IndexPtr;
407         indexScanDescs = indexstate->iss_ScanDescs;
408         scanDesc = indexScanDescs[indexPtr];
409
410         /* ----------------
411          *      XXX access methods don't return marked positions so
412          * ----------------
413          */
414         IndexScanMarkPosition(scanDesc);
415         return;
416 }
417
418 /* ----------------------------------------------------------------
419  *              ExecIndexRestrPos
420  *
421  * old comments
422  *              Restores scan position by restoring the current index.
423  *              Returns nothing.
424  *
425  *              XXX Assumes previously marked scan position belongs to current index
426  * ----------------------------------------------------------------
427  */
428 void
429 ExecIndexRestrPos(IndexScan *node)
430 {
431         IndexScanState *indexstate;
432         IndexScanDescPtr indexScanDescs;
433         IndexScanDesc scanDesc;
434         int                     indexPtr;
435
436         indexstate = node->indxstate;
437         indexPtr = indexstate->iss_IndexPtr;
438         indexScanDescs = indexstate->iss_ScanDescs;
439         scanDesc = indexScanDescs[indexPtr];
440
441         IndexScanRestorePosition(scanDesc);
442 }
443
444 /* ----------------------------------------------------------------
445  *              ExecInitIndexScan
446  *
447  *              Initializes the index scan's state information, creates
448  *              scan keys, and opens the base and index relations.
449  *
450  *              Note: index scans have 2 sets of state information because
451  *                        we have to keep track of the base relation and the
452  *                        index relations.
453  *
454  * old comments
455  *              Creates the run-time state information for the node and
456  *              sets the relation id to contain relevant decriptors.
457  *
458  *              Parameters:
459  *                node: IndexNode node produced by the planner.
460  *                estate: the execution state initialized in InitPlan.
461  * ----------------------------------------------------------------
462  */
463 bool
464 ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
465 {
466         IndexScanState *indexstate;
467         CommonScanState *scanstate;
468         List       *indxqual;
469         List       *indxid;
470         int                     i;
471         int                     numIndices;
472         int                     indexPtr;
473         ScanKey    *scanKeys;
474         int                *numScanKeys;
475         RelationPtr relationDescs;
476         IndexScanDescPtr scanDescs;
477         Pointer    *runtimeKeyInfo;
478         bool            have_runtime_keys;
479         List       *rangeTable;
480         RangeTblEntry *rtentry;
481         Index           relid;
482         Oid                     reloid;
483
484         Relation        currentRelation;
485         HeapScanDesc currentScanDesc;
486         ScanDirection direction;
487         int                     baseid;
488
489         /* ----------------
490          *      assign execution state to node
491          * ----------------
492          */
493         node->scan.plan.state = estate;
494
495         /* --------------------------------
496          *      Part 1)  initialize scan state
497          *
498          *      create new CommonScanState for node
499          * --------------------------------
500          */
501         scanstate = makeNode(CommonScanState);
502 /*
503         scanstate->ss_ProcOuterFlag = false;
504         scanstate->ss_OldRelId = 0;
505 */
506
507         node->scan.scanstate = scanstate;
508
509         /* ----------------
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.
513          * ----------------
514          */
515         baseid = estate->es_BaseId;
516 /*        scanstate->csstate.cstate.bnode.base_id = baseid; */
517         scanstate->cstate.cs_base_id = baseid;
518
519         /* ----------------
520          *      create expression context for node
521          * ----------------
522          */
523         ExecAssignExprContext(estate, &scanstate->cstate);
524
525 #define INDEXSCAN_NSLOTS 3
526         /* ----------------
527          *      tuple table initialization
528          * ----------------
529          */
530         ExecInitResultTupleSlot(estate, &scanstate->cstate);
531         ExecInitScanTupleSlot(estate, scanstate);
532 /*        ExecInitRawTupleSlot(estate, scanstate); */
533
534         /* ----------------
535          *      initialize projection info.  result type comes from scan desc
536          *      below..
537          * ----------------
538          */
539         ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
540
541         /* --------------------------------
542           *  Part 2)  initialize index scan state
543           *
544           *  create new IndexScanState for node
545           * --------------------------------
546           */
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;
555
556         node->indxstate = indexstate;
557
558         /* ----------------
559          *      assign base id to index scan state also
560          * ----------------
561          */
562         indexstate->cstate.cs_base_id = baseid;
563         baseid++;
564         estate->es_BaseId = baseid;
565
566         /* ----------------
567          *      get the index node information
568          * ----------------
569          */
570         indxid = node->indxid;
571         indxqual = node->indxqual;
572         numIndices = length(indxid);
573         indexPtr = 0;
574
575         CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);
576
577         /* ----------------
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
580          *      its own ScanKey.
581          * ----------------
582          */
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));
587
588         /* ----------------
589          *      initialize runtime key info.
590          * ----------------
591          */
592         have_runtime_keys = false;
593         runtimeKeyInfo = (Pointer *)
594                 palloc(numIndices * sizeof(Pointer));
595
596         /* ----------------
597          *      build the index scan keys from the index qualification
598          * ----------------
599          */
600         for (i = 0; i < numIndices; i++)
601         {
602                 int                     j;
603                 List       *qual;
604                 int                     n_keys;
605                 ScanKey         scan_keys;
606                 int                *run_keys;
607
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));
614
615                 CXT1_printf("ExecInitIndexScan: context is %d\n",
616                                         CurrentMemoryContext);
617
618                 /* ----------------
619                  *      for each opclause in the given qual,
620                  *      convert each qual's opclause into a single scan key
621                  * ----------------
622                  */
623                 for (j = 0; j < n_keys; j++)
624                 {
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 ... */
629                         bits16          flags = 0;
630
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) */
635
636                         /* ----------------
637                          *      extract clause information from the qualification
638                          * ----------------
639                          */
640                         clause = nth(j, qual);
641
642                         op = (Oper *) clause->oper;
643                         if (!IsA(op, Oper))
644                                 elog(ERROR, "ExecInitIndexScan: op not an Oper!");
645
646                         opid = op->opid;
647
648                         /* ----------------
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.
653                          *
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.
659                          *
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
663                          *      at run time.
664                          *
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.
668                          * ----------------
669                          */
670
671                         scanvar = NO_OP;
672
673                         /* ----------------
674                          *      determine information in leftop
675                          * ----------------
676                          */
677                         leftop = (Node *) get_leftop(clause);
678
679                         if (IsA(leftop, Var) &&var_is_rel((Var *) leftop))
680                         {
681                                 /* ----------------
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.
685                                  * ----------------
686                                  */
687                                 varattno = ((Var *) leftop)->varattno;
688                                 scanvar = LEFT_OP;
689                         }
690                         else if (IsA(leftop, Const))
691                         {
692                                 /* ----------------
693                                  *      if the leftop is a const node then it means
694                                  *      it identifies the value to place in our scan key.
695                                  * ----------------
696                                  */
697                                 run_keys[j] = NO_OP;
698                                 scanvalue = ((Const *) leftop)->constvalue;
699 #ifdef INDEXSCAN_PATCH
700                         }
701                         else if (IsA(leftop, Param))
702                         {
703                                 bool            isnull;
704
705                                 /* ----------------
706                                  *      if the leftop is a Param node then it means
707                                  *      it identifies the value to place in our scan key.
708                                  * ----------------
709                                  */
710                                 run_keys[j] = NO_OP;
711                                 scanvalue = ExecEvalParam((Param *) leftop,
712                                                                                 scanstate->cstate.cs_ExprContext,
713                                                                                   &isnull);
714                                 if (isnull)
715                                         flags |= SK_ISNULL;
716 #endif
717                         }
718                         else if (leftop != NULL &&
719                                          is_funcclause(leftop) &&
720                                          var_is_rel(lfirst(((Expr *) leftop)->args)))
721                         {
722                                 /* ----------------
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.
727                                  * ----------------
728                                  */
729                                 varattno = 1;
730                                 scanvar = LEFT_OP;
731
732                         }
733                         else
734                         {
735                                 /* ----------------
736                                  *      otherwise, the leftop contains information usable
737                                  *      at runtime to figure out the value to place in our
738                                  *      scan key.
739                                  * ----------------
740                                  */
741                                 have_runtime_keys = true;
742                                 run_keys[j] = LEFT_OP;
743                                 scanvalue = Int32GetDatum((int32) true);
744                         }
745
746                         /* ----------------
747                          *      now determine information in rightop
748                          * ----------------
749                          */
750                         rightop = (Node *) get_rightop(clause);
751
752                         if (IsA(rightop, Var) &&var_is_rel((Var *) rightop))
753                         {
754                                 /* ----------------
755                                  *      here we make sure only one op identifies the
756                                  *      scan-attribute...
757                                  * ----------------
758                                  */
759                                 if (scanvar == LEFT_OP)
760                                         elog(ERROR, "ExecInitIndexScan: %s",
761                                                  "both left and right op's are rel-vars");
762
763                                 /* ----------------
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.
767                                  * ----------------
768                                  */
769                                 varattno = ((Var *) rightop)->varattno;
770                                 scanvar = RIGHT_OP;
771
772                         }
773                         else if (IsA(rightop, Const))
774                         {
775                                 /* ----------------
776                                  *      if the leftop is a const node then it means
777                                  *      it identifies the value to place in our scan key.
778                                  * ----------------
779                                  */
780                                 run_keys[j] = NO_OP;
781                                 scanvalue = ((Const *) rightop)->constvalue;
782 #ifdef INDEXSCAN_PATCH
783                         }
784                         else if (IsA(rightop, Param))
785                         {
786                                 bool            isnull;
787
788                                 /* ----------------
789                                  *      if the rightop is a Param node then it means
790                                  *      it identifies the value to place in our scan key.
791                                  * ----------------
792                                  */
793                                 run_keys[j] = NO_OP;
794                                 scanvalue = ExecEvalParam((Param *) rightop,
795                                                                                 scanstate->cstate.cs_ExprContext,
796                                                                                   &isnull);
797                                 if (isnull)
798                                         flags |= SK_ISNULL;
799 #endif
800                         }
801                         else if (rightop != NULL &&
802                                          is_funcclause(rightop) &&
803                                          var_is_rel(lfirst(((Expr *) rightop)->args)))
804                         {
805                                 /* ----------------
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.
810                                  * ----------------
811                                  */
812                                 if (scanvar == LEFT_OP)
813                                         elog(ERROR, "ExecInitIndexScan: %s",
814                                                  "both left and right ops are rel-vars");
815
816                                 varattno = 1;
817                                 scanvar = RIGHT_OP;
818
819                         }
820                         else
821                         {
822                                 /* ----------------
823                                  *      otherwise, the leftop contains information usable
824                                  *      at runtime to figure out the value to place in our
825                                  *      scan key.
826                                  * ----------------
827                                  */
828                                 have_runtime_keys = true;
829                                 run_keys[j] = RIGHT_OP;
830                                 scanvalue = Int32GetDatum((int32) true);
831                         }
832
833                         /* ----------------
834                          *      now check that at least one op tells us the scan
835                          *      attribute...
836                          * ----------------
837                          */
838                         if (scanvar == NO_OP)
839                                 elog(ERROR, "ExecInitIndexScan: %s",
840                                          "neither leftop nor rightop refer to scan relation");
841
842                         /* ----------------
843                          *      initialize the scan key's fields appropriately
844                          * ----------------
845                          */
846                         ScanKeyEntryInitialize(&scan_keys[j],
847                                                                    flags,
848                                                                    varattno,    /* attribute number to
849                                                                                                  * scan */
850                                                                    (RegProcedure) opid, /* reg proc to use */
851                                                                    (Datum) scanvalue);  /* constant */
852                 }
853
854                 /* ----------------
855                  *      store the key information into our array.
856                  * ----------------
857                  */
858                 numScanKeys[i] = n_keys;
859                 scanKeys[i] = scan_keys;
860                 runtimeKeyInfo[i] = (Pointer) run_keys;
861         }
862
863         indexstate->iss_NumIndices = numIndices;
864         indexstate->iss_IndexPtr = indexPtr;
865         indexstate->iss_ScanKeys = scanKeys;
866         indexstate->iss_NumScanKeys = numScanKeys;
867
868         /* ----------------
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.
874          *      -cim 10/24/89
875          * ----------------
876          */
877         if (have_runtime_keys)
878         {
879                 indexstate->iss_RuntimeKeyInfo = (Pointer) runtimeKeyInfo;
880         }
881         else
882         {
883                 indexstate->iss_RuntimeKeyInfo = NULL;
884                 for (i = 0; i < numIndices; i++)
885                 {
886                         List       *qual;
887                         int                     n_keys;
888
889                         qual = nth(i, indxqual);
890                         n_keys = length(qual);
891                         if (n_keys > 0)
892                                 pfree(runtimeKeyInfo[i]);
893                 }
894                 pfree(runtimeKeyInfo);
895         }
896
897         /* ----------------
898          *      get the range table and direction information
899          *      from the execution state (these are needed to
900          *      open the relations).
901          * ----------------
902          */
903         rangeTable = estate->es_range_table;
904         direction = estate->es_direction;
905
906         /* ----------------
907          *      open the base relation
908          * ----------------
909          */
910         relid = node->scan.scanrelid;
911         rtentry = rt_fetch(relid, rangeTable);
912         reloid = rtentry->relid;
913
914         ExecOpenScanR(reloid,           /* relation */
915                                   0,                    /* nkeys */
916                                   (ScanKey) NULL,               /* scan key */
917                                   0,                    /* is index */
918                                   direction,    /* scan direction */
919                                   &currentRelation,             /* return: rel desc */
920                                   (Pointer *) &currentScanDesc);                /* return: scan desc */
921
922         scanstate->css_currentRelation = currentRelation;
923         scanstate->css_currentScanDesc = currentScanDesc;
924
925
926         /* ----------------
927          *      get the scan type from the relation descriptor.
928          * ----------------
929          */
930         ExecAssignScanType(scanstate, RelationGetTupleDescriptor(currentRelation));
931         ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
932
933         /* ----------------
934          *      index scans don't have subtrees..
935          * ----------------
936          */
937 /*        scanstate->ss_ProcOuterFlag = false; */
938
939         /* ----------------
940          *      open the index relations and initialize
941          *      relation and scan descriptors.
942          * ----------------
943          */
944         for (i = 0; i < numIndices; i++)
945         {
946                 Oid                     indexOid;
947
948                 indexOid = (Oid) nthi(i, indxid);
949
950                 if (indexOid != 0)
951                 {
952                         ExecOpenScanR(indexOid,         /* relation */
953                                                   numScanKeys[i],               /* nkeys */
954                                                   scanKeys[i],  /* scan key */
955                                                   true, /* is index */
956                                                   direction,    /* scan direction */
957                                                   &(relationDescs[i]),  /* return: rel desc */
958                                                   (Pointer *) &(scanDescs[i]));
959                         /* return: scan desc */
960                 }
961         }
962
963         indexstate->iss_RelationDescs = relationDescs;
964         indexstate->iss_ScanDescs = scanDescs;
965
966         indexstate->cstate.cs_TupFromTlist = false;
967
968         /* ----------------
969          *      all done.
970          * ----------------
971          */
972         return TRUE;
973 }
974
975 int
976 ExecCountSlotsIndexScan(IndexScan *node)
977 {
978         return ExecCountSlotsNode(outerPlan((Plan *) node)) +
979         ExecCountSlotsNode(innerPlan((Plan *) node)) +
980         INDEXSCAN_NSLOTS;
981 }