]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeIndexscan.c
Remove un-needed braces around single statements.
[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.18 1998/06/15 19:28:22 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         HeapTuple       tuple;
95         TupleTableSlot *slot;
96         Buffer          buffer = InvalidBuffer;
97
98         /* ----------------
99          *      extract necessary information from index scan node
100          * ----------------
101          */
102         estate = node->scan.plan.state;
103         direction = estate->es_direction;
104         scanstate = node->scan.scanstate;
105         indexstate = node->indxstate;
106         indexPtr = indexstate->iss_IndexPtr;
107         scanDescs = indexstate->iss_ScanDescs;
108         scandesc = scanDescs[indexPtr];
109         heapRelation = scanstate->css_currentRelation;
110
111         slot = scanstate->css_ScanTupleSlot;
112
113         /* ----------------
114          *      ok, now that we have what we need, fetch an index tuple.
115          * ----------------
116          */
117
118         /* ----------------
119          *      if scanning this index succeeded then return the
120          *      appropriate heap tuple.. else return NULL.
121          * ----------------
122          */
123         while ((result = index_getnext(scandesc, direction)) != NULL)
124         {
125                 tuple = heap_fetch(heapRelation, false, &result->heap_iptr, &buffer);
126                 /* be tidy */
127                 pfree(result);
128
129                 if (tuple != NULL)
130                 {
131                         /* ----------------
132                          *      store the scanned tuple in the scan tuple slot of
133                          *      the scan state.  Eventually we will only do this and not
134                          *      return a tuple.  Note: we pass 'false' because tuples
135                          *      returned by amgetnext are pointers onto disk pages and
136                          *      were not created with palloc() and so should not be pfree()'d.
137                          * ----------------
138                          */
139                         ExecStoreTuple(tuple,           /* tuple to store */
140                                                         slot,           /* slot to store in */
141                                                         buffer,         /* buffer associated with tuple  */
142                                                         false);         /* don't pfree */
143         
144                         return slot;
145                 }
146                 else
147                 {
148                         if (BufferIsValid(buffer))
149                                 ReleaseBuffer(buffer);
150                 }
151         }
152
153         /* ----------------
154          *      if we get here it means the index scan failed so we
155          *      are at the end of the scan..
156          * ----------------
157          */
158         return ExecClearTuple(slot);
159 }
160
161 /* ----------------------------------------------------------------
162  *              ExecIndexScan(node)
163  *
164  * old comments:
165  *              Scans the relation using primary or secondary indices and returns
166  *                 the next qualifying tuple in the direction specified.
167  *              It calls ExecScan() and passes it the access methods which returns
168  *              the next tuple using the indices.
169  *
170  *              Conditions:
171  *                -- the "cursor" maintained by the AMI is positioned at the tuple
172  *                       returned previously.
173  *
174  *              Initial States:
175  *                -- the relation indicated is opened for scanning so that the
176  *                       "cursor" is positioned before the first qualifying tuple.
177  *                -- all index realtions are opened for scanning.
178  *                -- indexPtr points to the first index.
179  *                -- state variable ruleFlag = nil.
180  * ----------------------------------------------------------------
181  */
182 TupleTableSlot *
183 ExecIndexScan(IndexScan *node)
184 {
185         /* ----------------
186          *      use IndexNext as access method
187          * ----------------
188          */
189         return ExecScan(&node->scan, IndexNext);
190 }
191
192 /* ----------------------------------------------------------------
193  *              ExecIndexReScan(node)
194  *
195  *              Recalculates the value of the scan keys whose value depends on
196  *              information known at runtime and rescans the indexed relation.
197  *              Updating the scan key was formerly done separately in
198  *              ExecUpdateIndexScanKeys. Integrating it into ReScan
199  *              makes rescans of indices and
200  *              relations/general streams more uniform.
201  *
202  * ----------------------------------------------------------------
203  */
204 void
205 ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
206 {
207         EState     *estate;
208         IndexScanState *indexstate;
209         ScanDirection direction;
210         IndexScanDescPtr scanDescs;
211         ScanKey    *scanKeys;
212         IndexScanDesc sdesc;
213         ScanKey         skey;
214         int                     numIndices;
215         int                     i;
216
217         Pointer    *runtimeKeyInfo;
218         int                     indexPtr;
219         int                *numScanKeys;
220         List       *indxqual;
221         List       *qual;
222         int                     n_keys;
223         ScanKey         scan_keys;
224         int                *run_keys;
225         int                     j;
226         Expr       *clause;
227         Node       *scanexpr;
228         Datum           scanvalue;
229         bool            isNull;
230         bool            isDone;
231
232         indexstate = node->indxstate;
233         estate = node->scan.plan.state;
234         direction = estate->es_direction;
235         numIndices = indexstate->iss_NumIndices;
236         scanDescs = indexstate->iss_ScanDescs;
237         scanKeys = indexstate->iss_ScanKeys;
238
239         runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
240
241         if (runtimeKeyInfo != NULL)
242         {
243
244                 /*
245                  * get the index qualifications and recalculate the appropriate
246                  * values
247                  */
248                 indexPtr = indexstate->iss_IndexPtr;
249                 indxqual = node->indxqual;
250                 qual = nth(indexPtr, indxqual);
251                 numScanKeys = indexstate->iss_NumScanKeys;
252                 n_keys = numScanKeys[indexPtr];
253                 run_keys = (int *) runtimeKeyInfo[indexPtr];
254                 scan_keys = (ScanKey) scanKeys[indexPtr];
255                 
256                 /* it's possible in subselects */
257                 if (exprCtxt == NULL)
258                         exprCtxt = node->scan.scanstate->cstate.cs_ExprContext;
259                 
260                 for (j = 0; j < n_keys; j++)
261                 {
262
263                         /*
264                          * If we have a run-time key, then extract the run-time
265                          * expression and evaluate it with respect to the current
266                          * outer tuple.  We then stick the result into the scan key.
267                          */
268                         if (run_keys[j] != NO_OP)
269                         {
270                                 clause = nth(j, qual);
271                                 scanexpr = (run_keys[j] == RIGHT_OP) ?
272                                         (Node *) get_rightop(clause) : (Node *) get_leftop(clause);
273
274                                 /*
275                                  * pass in isDone but ignore it.  We don't iterate in
276                                  * quals
277                                  */
278                                 scanvalue = (Datum)
279                                         ExecEvalExpr(scanexpr, exprCtxt, &isNull, &isDone);
280                                 scan_keys[j].sk_argument = scanvalue;
281                                 if (isNull)
282                                         scan_keys[j].sk_flags |= SK_ISNULL;
283                                 else
284                                         scan_keys[j].sk_flags &= ~SK_ISNULL;
285                         }
286                 }
287         }
288
289         /*
290          * rescans all indices
291          *
292          * note: AMrescan assumes only one scan key.  This may have to change if
293          * we ever decide to support multiple keys.
294          */
295         for (i = 0; i < numIndices; i++)
296         {
297                 sdesc = scanDescs[i];
298                 skey = scanKeys[i];
299                 index_rescan(sdesc, direction, skey);
300         }
301
302         /* ----------------
303          *      perhaps return something meaningful
304          * ----------------
305          */
306         return;
307 }
308
309 /* ----------------------------------------------------------------
310  *              ExecEndIndexScan
311  *
312  * old comments
313  *              Releases any storage allocated through C routines.
314  *              Returns nothing.
315  * ----------------------------------------------------------------
316  */
317 void
318 ExecEndIndexScan(IndexScan *node)
319 {
320         CommonScanState *scanstate;
321         IndexScanState *indexstate;
322         ScanKey    *scanKeys;
323         int                     numIndices;
324         int                     i;
325
326         scanstate = node->scan.scanstate;
327         indexstate = node->indxstate;
328
329         /* ----------------
330          *      extract information from the node
331          * ----------------
332          */
333         numIndices = indexstate->iss_NumIndices;
334         scanKeys = indexstate->iss_ScanKeys;
335
336         /* ----------------
337          *      Free the projection info and the scan attribute info
338          *
339          *      Note: we don't ExecFreeResultType(scanstate)
340          *                because the rule manager depends on the tupType
341          *                returned by ExecMain().  So for now, this
342          *                is freed at end-transaction time.  -cim 6/2/91
343          * ----------------
344          */
345         ExecFreeProjectionInfo(&scanstate->cstate);
346
347         /* ----------------
348          *      close the heap and index relations
349          * ----------------
350          */
351         ExecCloseR((Plan *) node);
352
353         /* ----------------
354          *      free the scan keys used in scanning the indices
355          * ----------------
356          */
357         for (i = 0; i < numIndices; i++)
358         {
359                 if (scanKeys[i] != NULL)
360                         pfree(scanKeys[i]);
361         }
362
363         /* ----------------
364          *      clear out tuple table slots
365          * ----------------
366          */
367         ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
368         ExecClearTuple(scanstate->css_ScanTupleSlot);
369 /*        ExecClearTuple(scanstate->css_RawTupleSlot); */
370 }
371
372 /* ----------------------------------------------------------------
373  *              ExecIndexMarkPos
374  *
375  * old comments
376  *              Marks scan position by marking the current index.
377  *              Returns nothing.
378  * ----------------------------------------------------------------
379  */
380 void
381 ExecIndexMarkPos(IndexScan *node)
382 {
383         IndexScanState *indexstate;
384         IndexScanDescPtr indexScanDescs;
385         IndexScanDesc scanDesc;
386         int                     indexPtr;
387
388         indexstate = node->indxstate;
389         indexPtr = indexstate->iss_IndexPtr;
390         indexScanDescs = indexstate->iss_ScanDescs;
391         scanDesc = indexScanDescs[indexPtr];
392
393 #if 0
394         IndexScanMarkPosition(scanDesc);
395 #endif
396         index_markpos (scanDesc);
397 }
398
399 /* ----------------------------------------------------------------
400  *              ExecIndexRestrPos
401  *
402  * old comments
403  *              Restores scan position by restoring the current index.
404  *              Returns nothing.
405  *
406  *              XXX Assumes previously marked scan position belongs to current index
407  * ----------------------------------------------------------------
408  */
409 void
410 ExecIndexRestrPos(IndexScan *node)
411 {
412         IndexScanState *indexstate;
413         IndexScanDescPtr indexScanDescs;
414         IndexScanDesc scanDesc;
415         int                     indexPtr;
416
417         indexstate = node->indxstate;
418         indexPtr = indexstate->iss_IndexPtr;
419         indexScanDescs = indexstate->iss_ScanDescs;
420         scanDesc = indexScanDescs[indexPtr];
421
422 #if 0
423         IndexScanRestorePosition(scanDesc);
424 #endif
425         index_restrpos (scanDesc);
426 }
427
428 /* ----------------------------------------------------------------
429  *              ExecInitIndexScan
430  *
431  *              Initializes the index scan's state information, creates
432  *              scan keys, and opens the base and index relations.
433  *
434  *              Note: index scans have 2 sets of state information because
435  *                        we have to keep track of the base relation and the
436  *                        index relations.
437  *
438  * old comments
439  *              Creates the run-time state information for the node and
440  *              sets the relation id to contain relevant decriptors.
441  *
442  *              Parameters:
443  *                node: IndexNode node produced by the planner.
444  *                estate: the execution state initialized in InitPlan.
445  * ----------------------------------------------------------------
446  */
447 bool
448 ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
449 {
450         IndexScanState *indexstate;
451         CommonScanState *scanstate;
452         List       *indxqual;
453         List       *indxid;
454         int                     i;
455         int                     numIndices;
456         int                     indexPtr;
457         ScanKey    *scanKeys;
458         int                *numScanKeys;
459         RelationPtr relationDescs;
460         IndexScanDescPtr scanDescs;
461         Pointer    *runtimeKeyInfo;
462         bool            have_runtime_keys;
463         List       *rangeTable;
464         RangeTblEntry *rtentry;
465         Index           relid;
466         Oid                     reloid;
467
468         Relation        currentRelation;
469         HeapScanDesc currentScanDesc;
470         ScanDirection direction;
471         int                     baseid;
472         
473         List       *execParam = NULL;
474
475         /* ----------------
476          *      assign execution state to node
477          * ----------------
478          */
479         node->scan.plan.state = estate;
480
481         /* --------------------------------
482          *      Part 1)  initialize scan state
483          *
484          *      create new CommonScanState for node
485          * --------------------------------
486          */
487         scanstate = makeNode(CommonScanState);
488 /*
489         scanstate->ss_ProcOuterFlag = false;
490         scanstate->ss_OldRelId = 0;
491 */
492
493         node->scan.scanstate = scanstate;
494
495         /* ----------------
496          *      assign node's base_id .. we don't use AssignNodeBaseid() because
497          *      the increment is done later on after we assign the index scan's
498          *      scanstate.      see below.
499          * ----------------
500          */
501         baseid = estate->es_BaseId;
502 /*        scanstate->csstate.cstate.bnode.base_id = baseid; */
503         scanstate->cstate.cs_base_id = baseid;
504
505         /* ----------------
506          *      create expression context for node
507          * ----------------
508          */
509         ExecAssignExprContext(estate, &scanstate->cstate);
510
511 #define INDEXSCAN_NSLOTS 3
512         /* ----------------
513          *      tuple table initialization
514          * ----------------
515          */
516         ExecInitResultTupleSlot(estate, &scanstate->cstate);
517         ExecInitScanTupleSlot(estate, scanstate);
518 /*        ExecInitRawTupleSlot(estate, scanstate); */
519
520         /* ----------------
521          *      initialize projection info.  result type comes from scan desc
522          *      below..
523          * ----------------
524          */
525         ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
526
527         /* --------------------------------
528           *  Part 2)  initialize index scan state
529           *
530           *  create new IndexScanState for node
531           * --------------------------------
532           */
533         indexstate = makeNode(IndexScanState);
534         indexstate->iss_NumIndices = 0;
535         indexstate->iss_IndexPtr = 0;
536         indexstate->iss_ScanKeys = NULL;
537         indexstate->iss_NumScanKeys = NULL;
538         indexstate->iss_RuntimeKeyInfo = NULL;
539         indexstate->iss_RelationDescs = NULL;
540         indexstate->iss_ScanDescs = NULL;
541
542         node->indxstate = indexstate;
543
544         /* ----------------
545          *      assign base id to index scan state also
546          * ----------------
547          */
548         indexstate->cstate.cs_base_id = baseid;
549         baseid++;
550         estate->es_BaseId = baseid;
551
552         /* ----------------
553          *      get the index node information
554          * ----------------
555          */
556         indxid = node->indxid;
557         indxqual = node->indxqual;
558         numIndices = length(indxid);
559         indexPtr = 0;
560
561         CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);
562
563         /* ----------------
564          *      scanKeys is used to keep track of the ScanKey's. This is needed
565          *      because a single scan may use several indices and each index has
566          *      its own ScanKey.
567          * ----------------
568          */
569         numScanKeys = (int *) palloc(numIndices * sizeof(int));
570         scanKeys = (ScanKey *) palloc(numIndices * sizeof(ScanKey));
571         relationDescs = (RelationPtr) palloc(numIndices * sizeof(Relation));
572         scanDescs = (IndexScanDescPtr) palloc(numIndices * sizeof(IndexScanDesc));
573
574         /* ----------------
575          *      initialize runtime key info.
576          * ----------------
577          */
578         have_runtime_keys = false;
579         runtimeKeyInfo = (Pointer *)
580                 palloc(numIndices * sizeof(Pointer));
581
582         /* ----------------
583          *      build the index scan keys from the index qualification
584          * ----------------
585          */
586         for (i = 0; i < numIndices; i++)
587         {
588                 int                     j;
589                 List       *qual;
590                 int                     n_keys;
591                 ScanKey         scan_keys;
592                 int                *run_keys;
593
594                 qual = nth(i, indxqual);
595                 n_keys = length(qual);
596                 scan_keys = (n_keys <= 0) ? NULL :
597                         (ScanKey) palloc(n_keys * sizeof(ScanKeyData));
598                 run_keys = (n_keys <= 0) ? NULL :
599                         (int *) palloc(n_keys * sizeof(int));
600
601                 CXT1_printf("ExecInitIndexScan: context is %d\n",
602                                         CurrentMemoryContext);
603
604                 /* ----------------
605                  *      for each opclause in the given qual,
606                  *      convert each qual's opclause into a single scan key
607                  * ----------------
608                  */
609                 for (j = 0; j < n_keys; j++)
610                 {
611                         Expr       *clause; /* one part of index qual */
612                         Oper       *op;         /* operator used in scan.. */
613                         Node       *leftop; /* expr on lhs of operator */
614                         Node       *rightop;/* expr on rhs ... */
615                         bits16          flags = 0;
616
617                         int                     scanvar;/* which var identifies varattno */
618                         AttrNumber      varattno = 0;   /* att number used in scan */
619                         Oid                     opid;   /* operator id used in scan */
620                         Datum           scanvalue = 0;  /* value used in scan (if const) */
621
622                         /* ----------------
623                          *      extract clause information from the qualification
624                          * ----------------
625                          */
626                         clause = nth(j, qual);
627
628                         op = (Oper *) clause->oper;
629                         if (!IsA(op, Oper))
630                                 elog(ERROR, "ExecInitIndexScan: op not an Oper!");
631
632                         opid = op->opid;
633
634                         /* ----------------
635                          *      Here we figure out the contents of the index qual.
636                          *      The usual case is (op var const) or (op const var)
637                          *      which means we form a scan key for the attribute
638                          *      listed in the var node and use the value of the const.
639                          *
640                          *      If we don't have a const node, then it means that
641                          *      one of the var nodes refers to the "scan" tuple and
642                          *      is used to determine which attribute to scan, and the
643                          *      other expression is used to calculate the value used in
644                          *      scanning the index.
645                          *
646                          *      This means our index scan's scan key is a function of
647                          *      information obtained during the execution of the plan
648                          *      in which case we need to recalculate the index scan key
649                          *      at run time.
650                          *
651                          *      Hence, we set have_runtime_keys to true and then set
652                          *      the appropriate flag in run_keys to LEFT_OP or RIGHT_OP.
653                          *      The corresponding scan keys are recomputed at run time.
654                          * ----------------
655                          */
656
657                         scanvar = NO_OP;
658
659                         /* ----------------
660                          *      determine information in leftop
661                          * ----------------
662                          */
663                         leftop = (Node *) get_leftop(clause);
664
665                         if (IsA(leftop, Var) &&var_is_rel((Var *) leftop))
666                         {
667                                 /* ----------------
668                                  *      if the leftop is a "rel-var", then it means
669                                  *      that it is a var node which tells us which
670                                  *      attribute to use for our scan key.
671                                  * ----------------
672                                  */
673                                 varattno = ((Var *) leftop)->varattno;
674                                 scanvar = LEFT_OP;
675                         }
676                         else if (IsA(leftop, Const))
677                         {
678                                 /* ----------------
679                                  *      if the leftop is a const node then it means
680                                  *      it identifies the value to place in our scan key.
681                                  * ----------------
682                                  */
683                                 run_keys[j] = NO_OP;
684                                 scanvalue = ((Const *) leftop)->constvalue;
685                         }
686                         else if (IsA(leftop, Param))
687                         {
688                                 bool            isnull;
689
690                                 /* ----------------
691                                  *      if the leftop is a Param node then it means
692                                  *      it identifies the value to place in our scan key.
693                                  * ----------------
694                                  */
695                                 
696                                 /* Life was so easy before ... subselects */
697                                 if ( ((Param *) leftop)->paramkind == PARAM_EXEC )
698                                 {
699                                         have_runtime_keys = true;
700                                         run_keys[j] = LEFT_OP;
701                                         execParam = lappendi (execParam, ((Param*) leftop)->paramid);
702                                 }
703                                 else
704                                 {
705                                         scanvalue = ExecEvalParam((Param *) leftop,
706                                                                                           scanstate->cstate.cs_ExprContext,
707                                                                                           &isnull);
708                                         if (isnull)
709                                                 flags |= SK_ISNULL;
710                                         
711                                         run_keys[j] = NO_OP;
712                                 }
713                         }
714                         else if (leftop != NULL &&
715                                          is_funcclause(leftop) &&
716                                          var_is_rel(lfirst(((Expr *) leftop)->args)))
717                         {
718                                 /* ----------------
719                                  *      if the leftop is a func node then it means
720                                  *      it identifies the value to place in our scan key.
721                                  *      Since functional indices have only one attribute
722                                  *      the attno must always be set to 1.
723                                  * ----------------
724                                  */
725                                 varattno = 1;
726                                 scanvar = LEFT_OP;
727
728                         }
729                         else
730                         {
731                                 /* ----------------
732                                  *      otherwise, the leftop contains information usable
733                                  *      at runtime to figure out the value to place in our
734                                  *      scan key.
735                                  * ----------------
736                                  */
737                                 have_runtime_keys = true;
738                                 run_keys[j] = LEFT_OP;
739                                 scanvalue = Int32GetDatum((int32) true);
740                         }
741
742                         /* ----------------
743                          *      now determine information in rightop
744                          * ----------------
745                          */
746                         rightop = (Node *) get_rightop(clause);
747
748                         if (IsA(rightop, Var) &&var_is_rel((Var *) rightop))
749                         {
750                                 /* ----------------
751                                  *      here we make sure only one op identifies the
752                                  *      scan-attribute...
753                                  * ----------------
754                                  */
755                                 if (scanvar == LEFT_OP)
756                                         elog(ERROR, "ExecInitIndexScan: %s",
757                                                  "both left and right op's are rel-vars");
758
759                                 /* ----------------
760                                  *      if the rightop is a "rel-var", then it means
761                                  *      that it is a var node which tells us which
762                                  *      attribute to use for our scan key.
763                                  * ----------------
764                                  */
765                                 varattno = ((Var *) rightop)->varattno;
766                                 scanvar = RIGHT_OP;
767
768                         }
769                         else if (IsA(rightop, Const))
770                         {
771                                 /* ----------------
772                                  *      if the leftop is a const node then it means
773                                  *      it identifies the value to place in our scan key.
774                                  * ----------------
775                                  */
776                                 run_keys[j] = NO_OP;
777                                 scanvalue = ((Const *) rightop)->constvalue;
778                         }
779                         else if (IsA(rightop, Param))
780                         {
781                                 bool            isnull;
782
783                                 /* ----------------
784                                  *      if the rightop is a Param node then it means
785                                  *      it identifies the value to place in our scan key.
786                                  * ----------------
787                                  */
788                                 
789                                 /* Life was so easy before ... subselects */
790                                 if ( ((Param *) rightop)->paramkind == PARAM_EXEC )
791                                 {
792                                         have_runtime_keys = true;
793                                         run_keys[j] = RIGHT_OP;
794                                         execParam = lappendi (execParam, ((Param*) rightop)->paramid);
795                                 }
796                                 else
797                                 {
798                                         scanvalue = ExecEvalParam((Param *) rightop,
799                                                                                           scanstate->cstate.cs_ExprContext,
800                                                                                           &isnull);
801                                         if (isnull)
802                                                 flags |= SK_ISNULL;
803                                         
804                                         run_keys[j] = NO_OP;
805                                 }
806                         }
807                         else if (rightop != NULL &&
808                                          is_funcclause(rightop) &&
809                                          var_is_rel(lfirst(((Expr *) rightop)->args)))
810                         {
811                                 /* ----------------
812                                  *      if the rightop is a func node then it means
813                                  *      it identifies the value to place in our scan key.
814                                  *      Since functional indices have only one attribute
815                                  *      the attno must always be set to 1.
816                                  * ----------------
817                                  */
818                                 if (scanvar == LEFT_OP)
819                                         elog(ERROR, "ExecInitIndexScan: %s",
820                                                  "both left and right ops are rel-vars");
821
822                                 varattno = 1;
823                                 scanvar = RIGHT_OP;
824
825                         }
826                         else
827                         {
828                                 /* ----------------
829                                  *      otherwise, the leftop contains information usable
830                                  *      at runtime to figure out the value to place in our
831                                  *      scan key.
832                                  * ----------------
833                                  */
834                                 have_runtime_keys = true;
835                                 run_keys[j] = RIGHT_OP;
836                                 scanvalue = Int32GetDatum((int32) true);
837                         }
838
839                         /* ----------------
840                          *      now check that at least one op tells us the scan
841                          *      attribute...
842                          * ----------------
843                          */
844                         if (scanvar == NO_OP)
845                                 elog(ERROR, "ExecInitIndexScan: %s",
846                                          "neither leftop nor rightop refer to scan relation");
847
848                         /* ----------------
849                          *      initialize the scan key's fields appropriately
850                          * ----------------
851                          */
852                         ScanKeyEntryInitialize(&scan_keys[j],
853                                                                    flags,
854                                                                    varattno,    /* attribute number to
855                                                                                                  * scan */
856                                                                    (RegProcedure) opid, /* reg proc to use */
857                                                                    (Datum) scanvalue);  /* constant */
858                 }
859
860                 /* ----------------
861                  *      store the key information into our array.
862                  * ----------------
863                  */
864                 numScanKeys[i] = n_keys;
865                 scanKeys[i] = scan_keys;
866                 runtimeKeyInfo[i] = (Pointer) run_keys;
867         }
868
869         indexstate->iss_NumIndices = numIndices;
870         indexstate->iss_IndexPtr = indexPtr;
871         indexstate->iss_ScanKeys = scanKeys;
872         indexstate->iss_NumScanKeys = numScanKeys;
873
874         /* ----------------
875          *      If all of our keys have the form (op var const) , then we have no
876          *      runtime keys so we store NULL in the runtime key info.
877          *      Otherwise runtime key info contains an array of pointers
878          *      (one for each index) to arrays of flags (one for each key)
879          *      which indicate that the qual needs to be evaluated at runtime.
880          *      -cim 10/24/89
881          * ----------------
882          */
883         if (have_runtime_keys)
884                 indexstate->iss_RuntimeKeyInfo = (Pointer) runtimeKeyInfo;
885         else
886         {
887                 indexstate->iss_RuntimeKeyInfo = NULL;
888                 for (i = 0; i < numIndices; i++)
889                 {
890                         List       *qual;
891                         int                     n_keys;
892
893                         qual = nth(i, indxqual);
894                         n_keys = length(qual);
895                         if (n_keys > 0)
896                                 pfree(runtimeKeyInfo[i]);
897                 }
898                 pfree(runtimeKeyInfo);
899         }
900
901         /* ----------------
902          *      get the range table and direction information
903          *      from the execution state (these are needed to
904          *      open the relations).
905          * ----------------
906          */
907         rangeTable = estate->es_range_table;
908         direction = estate->es_direction;
909
910         /* ----------------
911          *      open the base relation
912          * ----------------
913          */
914         relid = node->scan.scanrelid;
915         rtentry = rt_fetch(relid, rangeTable);
916         reloid = rtentry->relid;
917
918         ExecOpenScanR(reloid,           /* relation */
919                                   0,                    /* nkeys */
920                                   (ScanKey) NULL,               /* scan key */
921                                   0,                    /* is index */
922                                   direction,    /* scan direction */
923                                   &currentRelation,             /* return: rel desc */
924                                   (Pointer *) &currentScanDesc);                /* return: scan desc */
925
926         scanstate->css_currentRelation = currentRelation;
927         scanstate->css_currentScanDesc = currentScanDesc;
928
929
930         /* ----------------
931          *      get the scan type from the relation descriptor.
932          * ----------------
933          */
934         ExecAssignScanType(scanstate, RelationGetTupleDescriptor(currentRelation));
935         ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
936
937         /* ----------------
938          *      index scans don't have subtrees..
939          * ----------------
940          */
941 /*        scanstate->ss_ProcOuterFlag = false; */
942
943         /* ----------------
944          *      open the index relations and initialize
945          *      relation and scan descriptors.
946          * ----------------
947          */
948         for (i = 0; i < numIndices; i++)
949         {
950                 Oid                     indexOid;
951
952                 indexOid = (Oid) nthi(i, indxid);
953
954                 if (indexOid != 0)
955                 {
956                         ExecOpenScanR(indexOid,         /* relation */
957                                                   numScanKeys[i],               /* nkeys */
958                                                   scanKeys[i],  /* scan key */
959                                                   true, /* is index */
960                                                   direction,    /* scan direction */
961                                                   &(relationDescs[i]),  /* return: rel desc */
962                                                   (Pointer *) &(scanDescs[i]));
963                         /* return: scan desc */
964                 }
965         }
966
967         indexstate->iss_RelationDescs = relationDescs;
968         indexstate->iss_ScanDescs = scanDescs;
969
970         indexstate->cstate.cs_TupFromTlist = false;
971         
972         /* 
973          * if there are some PARAM_EXEC in skankeys then
974          * force index rescan on first scan.
975          */
976         ((Plan*) node)->chgParam = execParam;
977         
978         /* ----------------
979          *      all done.
980          * ----------------
981          */
982         return TRUE;
983 }
984
985 int
986 ExecCountSlotsIndexScan(IndexScan *node)
987 {
988         return ExecCountSlotsNode(outerPlan((Plan *) node)) +
989         ExecCountSlotsNode(innerPlan((Plan *) node)) +
990         INDEXSCAN_NSLOTS;
991 }