]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeIndexscan.c
Cleanup of OR fix.
[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.21 1998/08/01 22:44:52 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         Snapshot                snapshot;
90         IndexScanDescPtr scanDescs;
91         IndexScanDesc scandesc;
92         Relation        heapRelation;
93         RetrieveIndexResult result;
94         HeapTuple       tuple;
95         TupleTableSlot *slot;
96         Buffer          buffer = InvalidBuffer;
97         int                     numIndices;
98         
99         /* ----------------
100          *      extract necessary information from index scan node
101          * ----------------
102          */
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;
112
113         /* ----------------
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.
117          * ----------------
118          */
119         while (indexstate->iss_IndexPtr < numIndices)
120         {
121                 scandesc = scanDescs[indexstate->iss_IndexPtr];
122                 while ((result = index_getnext(scandesc, direction)) != NULL)
123                 {
124                         tuple = heap_fetch(heapRelation, snapshot,
125                                                                 &result->heap_iptr, &buffer);
126                         /* be tidy */
127                         pfree(result);
128
129                         if (tuple != NULL)
130                         {
131                                 bool            prev_matches = false;
132                                 int                     prev_index;
133
134                                 /* ----------------
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.
140                                  * ----------------
141                                  */
142                                 ExecStoreTuple(tuple,           /* tuple to store */
143                                                                 slot,           /* slot to store in */
144                                                                 buffer,         /* buffer associated with tuple  */
145                                                                 false);         /* don't pfree */
146  
147                                 for (prev_index = 0; prev_index < indexstate->iss_IndexPtr;
148                                                                                                                                 prev_index++)
149                                 {
150                                         if (ExecQual(nth(prev_index, node->indxqual),
151                                                 scanstate->cstate.cs_ExprContext))
152                                         {
153                                                 prev_matches = true;
154                                                 break;
155                                         }
156                                 }
157                                 if (!prev_matches)
158                                         return slot;
159                                 else
160                                         ExecClearTuple(slot);
161                         }
162                         if (BufferIsValid(buffer))
163                                 ReleaseBuffer(buffer);
164                 }
165                 if (indexstate->iss_IndexPtr < numIndices)
166                         indexstate->iss_IndexPtr++;
167         }
168         /* ----------------
169          *      if we get here it means the index scan failed so we
170          *      are at the end of the scan..
171          * ----------------
172          */
173         return ExecClearTuple(slot);
174 }
175
176 /* ----------------------------------------------------------------
177  *              ExecIndexScan(node)
178  *
179  * old comments:
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.
184  *
185  *              Conditions:
186  *                -- the "cursor" maintained by the AMI is positioned at the tuple
187  *                       returned previously.
188  *
189  *              Initial States:
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  * ----------------------------------------------------------------
196  */
197 TupleTableSlot *
198 ExecIndexScan(IndexScan *node)
199 {
200         /* ----------------
201          *      use IndexNext as access method
202          * ----------------
203          */
204         return ExecScan(&node->scan, IndexNext);
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                *numScanKeys;
234         List       *indxqual;
235         List       *qual;
236         int                     n_keys;
237         ScanKey         scan_keys;
238         int                *run_keys;
239         int                     j;
240         Expr       *clause;
241         Node       *scanexpr;
242         Datum           scanvalue;
243         bool            isNull;
244         bool            isDone;
245
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;
256         
257         /* it's possible in subselects */
258         if (exprCtxt == NULL)
259                 exprCtxt = node->scan.scanstate->cstate.cs_ExprContext;
260
261         if (exprCtxt != NULL)
262                 node->scan.scanstate->cstate.cs_ExprContext->ecxt_outertuple =
263                         exprCtxt->ecxt_outertuple;
264                 
265         /*
266          * get the index qualifications and recalculate the appropriate
267          * values
268          */
269         for (i = 0; i < numIndices; i++)
270         {
271                 if (runtimeKeyInfo && runtimeKeyInfo[i] != NULL)
272                 {
273                         qual = nth(i, indxqual);
274                         n_keys = numScanKeys[i];
275                         run_keys = (int *) runtimeKeyInfo[i];
276                         scan_keys = (ScanKey) scanKeys[i];
277                 
278                         for (j = 0; j < n_keys; j++)
279                         {
280                                 /*
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.
284                                  */
285                                 if (run_keys[j] != NO_OP)
286                                 {
287                                         clause = nth(j, qual);
288                                         scanexpr = (run_keys[j] == RIGHT_OP) ?
289                                                 (Node *) get_rightop(clause) : (Node *) get_leftop(clause);
290         
291                                         /*
292                                          * pass in isDone but ignore it.  We don't iterate in
293                                          * quals
294                                          */
295                                         scanvalue = (Datum)
296                                                 ExecEvalExpr(scanexpr, exprCtxt, &isNull, &isDone);
297                                         scan_keys[j].sk_argument = scanvalue;
298                                         if (isNull)
299                                                 scan_keys[j].sk_flags |= SK_ISNULL;
300                                         else
301                                                 scan_keys[j].sk_flags &= ~SK_ISNULL;
302                                 }
303                         }
304                         sdesc = scanDescs[i];
305                         skey = scanKeys[i];
306                         index_rescan(sdesc, direction, skey);
307                 }
308         }
309         /* ----------------
310          *      perhaps return something meaningful
311          * ----------------
312          */
313         return;
314 }
315
316 /* ----------------------------------------------------------------
317  *              ExecEndIndexScan
318  *
319  * old comments
320  *              Releases any storage allocated through C routines.
321  *              Returns nothing.
322  * ----------------------------------------------------------------
323  */
324 void
325 ExecEndIndexScan(IndexScan *node)
326 {
327         CommonScanState *scanstate;
328         IndexScanState *indexstate;
329         Pointer    *runtimeKeyInfo;
330         ScanKey    *scanKeys;
331         List       *indxqual;
332         int                *numScanKeys;
333         int                     numIndices;
334         int                     i;
335
336         scanstate = node->scan.scanstate;
337         indexstate = node->indxstate;
338         indxqual = node->indxqual;
339         runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
340         
341         /* ----------------
342          *      extract information from the node
343          * ----------------
344          */
345         numIndices = indexstate->iss_NumIndices;
346         scanKeys = indexstate->iss_ScanKeys;
347         numScanKeys = indexstate->iss_NumScanKeys;
348
349         /* ----------------
350          *      Free the projection info and the scan attribute info
351          *
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
356          * ----------------
357          */
358         ExecFreeProjectionInfo(&scanstate->cstate);
359
360         /* ----------------
361          *      close the heap and index relations
362          * ----------------
363          */
364         ExecCloseR((Plan *) node);
365
366         /* ----------------
367          *      free the scan keys used in scanning the indices
368          * ----------------
369          */
370         for (i = 0; i < numIndices; i++)
371         {
372                 if (scanKeys[i] != NULL)
373                         pfree(scanKeys[i]);
374         }
375         pfree(scanKeys);
376         pfree(numScanKeys);
377
378         if (runtimeKeyInfo)
379         {       
380                 for (i = 0; i < numIndices; i++)
381                 {
382                         List       *qual;
383                         int                     n_keys;
384
385                         qual = nth(i, indxqual);
386                         n_keys = length(qual);
387                         if (n_keys > 0)
388                                 pfree(runtimeKeyInfo[i]);
389                 }
390                 pfree(runtimeKeyInfo);
391         }
392         
393         /* ----------------
394          *      clear out tuple table slots
395          * ----------------
396          */
397         ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
398         ExecClearTuple(scanstate->css_ScanTupleSlot);
399 /*        ExecClearTuple(scanstate->css_RawTupleSlot); */
400 }
401
402 /* ----------------------------------------------------------------
403  *              ExecIndexMarkPos
404  *
405  * old comments
406  *              Marks scan position by marking the current index.
407  *              Returns nothing.
408  * ----------------------------------------------------------------
409  */
410 void
411 ExecIndexMarkPos(IndexScan *node)
412 {
413         IndexScanState *indexstate;
414         IndexScanDescPtr indexScanDescs;
415         IndexScanDesc scanDesc;
416         int                     indexPtr;
417
418         indexstate = node->indxstate;
419         indexPtr = indexstate->iss_IndexPtr;
420         indexScanDescs = indexstate->iss_ScanDescs;
421         scanDesc = indexScanDescs[indexPtr];
422
423 #if 0
424         IndexScanMarkPosition(scanDesc);
425 #endif
426         index_markpos (scanDesc);
427 }
428
429 /* ----------------------------------------------------------------
430  *              ExecIndexRestrPos
431  *
432  * old comments
433  *              Restores scan position by restoring the current index.
434  *              Returns nothing.
435  *
436  *              XXX Assumes previously marked scan position belongs to current index
437  * ----------------------------------------------------------------
438  */
439 void
440 ExecIndexRestrPos(IndexScan *node)
441 {
442         IndexScanState *indexstate;
443         IndexScanDescPtr indexScanDescs;
444         IndexScanDesc scanDesc;
445         int                     indexPtr;
446
447         indexstate = node->indxstate;
448         indexPtr = indexstate->iss_IndexPtr;
449         indexScanDescs = indexstate->iss_ScanDescs;
450         scanDesc = indexScanDescs[indexPtr];
451
452 #if 0
453         IndexScanRestorePosition(scanDesc);
454 #endif
455         index_restrpos (scanDesc);
456 }
457
458 /* ----------------------------------------------------------------
459  *              ExecInitIndexScan
460   *
461  *              Initializes the index scan's state information, creates
462  *              scan keys, and opens the base and index relations.
463  *
464  *              Note: index scans have 2 sets of state information because
465  *                        we have to keep track of the base relation and the
466  *                        index relations.
467  *
468  * old comments
469  *              Creates the run-time state information for the node and
470  *              sets the relation id to contain relevant decriptors.
471  *
472  *              Parameters:
473  *                node: IndexNode node produced by the planner.
474  *                estate: the execution state initialized in InitPlan.
475  * ----------------------------------------------------------------
476  */
477 bool
478 ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
479 {
480         IndexScanState *indexstate;
481         CommonScanState *scanstate;
482         List       *indxqual;
483         List       *indxid;
484         int                     i;
485         int                     numIndices;
486         int                     indexPtr;
487         ScanKey    *scanKeys;
488         int                *numScanKeys;
489         RelationPtr relationDescs;
490         IndexScanDescPtr scanDescs;
491         Pointer    *runtimeKeyInfo;
492         bool            have_runtime_keys;
493         List       *rangeTable;
494         RangeTblEntry *rtentry;
495         Index           relid;
496         Oid                     reloid;
497
498         Relation        currentRelation;
499         HeapScanDesc currentScanDesc;
500         ScanDirection direction;
501         int                     baseid;
502         
503         List       *execParam = NULL;
504
505         /* ----------------
506          *      assign execution state to node
507          * ----------------
508          */
509         node->scan.plan.state = estate;
510
511         /* --------------------------------
512          *      Part 1)  initialize scan state
513          *
514          *      create new CommonScanState for node
515          * --------------------------------
516          */
517         scanstate = makeNode(CommonScanState);
518 /*
519         scanstate->ss_ProcOuterFlag = false;
520         scanstate->ss_OldRelId = 0;
521 */
522
523         node->scan.scanstate = scanstate;
524
525         /* ----------------
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.
529          * ----------------
530          */
531         baseid = estate->es_BaseId;
532 /*        scanstate->csstate.cstate.bnode.base_id = baseid; */
533         scanstate->cstate.cs_base_id = baseid;
534
535         /* ----------------
536          *      create expression context for node
537          * ----------------
538          */
539         ExecAssignExprContext(estate, &scanstate->cstate);
540
541 #define INDEXSCAN_NSLOTS 3
542         /* ----------------
543          *      tuple table initialization
544          * ----------------
545          */
546         ExecInitResultTupleSlot(estate, &scanstate->cstate);
547         ExecInitScanTupleSlot(estate, scanstate);
548 /*        ExecInitRawTupleSlot(estate, scanstate); */
549
550         /* ----------------
551          *      initialize projection info.  result type comes from scan desc
552          *      below..
553          * ----------------
554          */
555         ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
556
557         /* --------------------------------
558           *  Part 2)  initialize index scan state
559           *
560           *  create new IndexScanState for node
561           * --------------------------------
562           */
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;
571
572         node->indxstate = indexstate;
573
574         /* ----------------
575          *      assign base id to index scan state also
576          * ----------------
577          */
578         indexstate->cstate.cs_base_id = baseid;
579         baseid++;
580         estate->es_BaseId = baseid;
581
582         /* ----------------
583          *      get the index node information
584          * ----------------
585          */
586         indxid = node->indxid;
587         indxqual = node->indxqual;
588         numIndices = length(indxid);
589         indexPtr = 0;
590
591         CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);
592
593         /* ----------------
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
596          *      its own ScanKey.
597          * ----------------
598          */
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));
603
604         /* ----------------
605          *      initialize runtime key info.
606          * ----------------
607          */
608         have_runtime_keys = false;
609         runtimeKeyInfo = (Pointer *)
610                 palloc(numIndices * sizeof(Pointer));
611
612         /* ----------------
613          *      build the index scan keys from the index qualification
614          * ----------------
615          */
616         for (i = 0; i < numIndices; i++)
617         {
618                 int                     j;
619                 List       *qual;
620                 int                     n_keys;
621                 ScanKey         scan_keys;
622                 int                *run_keys;
623
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));
630
631                 CXT1_printf("ExecInitIndexScan: context is %d\n",
632                                         CurrentMemoryContext);
633
634                 /* ----------------
635                  *      for each opclause in the given qual,
636                  *      convert each qual's opclause into a single scan key
637                  * ----------------
638                  */
639                 for (j = 0; j < n_keys; j++)
640                 {
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 ... */
645                         bits16          flags = 0;
646
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) */
651
652                         /* ----------------
653                          *      extract clause information from the qualification
654                          * ----------------
655                          */
656                         clause = nth(j, qual);
657
658                         op = (Oper *) clause->oper;
659                         if (!IsA(op, Oper))
660                                 elog(ERROR, "ExecInitIndexScan: op not an Oper!");
661
662                         opid = op->opid;
663
664                         /* ----------------
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.
669                          *
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.
675                          *
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
679                          *      at run time.
680                          *
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.
684                          * ----------------
685                          */
686
687                         scanvar = NO_OP;
688
689                         /* ----------------
690                          *      determine information in leftop
691                          * ----------------
692                          */
693                         leftop = (Node *) get_leftop(clause);
694
695                         if (IsA(leftop, Var) &&var_is_rel((Var *) leftop))
696                         {
697                                 /* ----------------
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.
701                                  * ----------------
702                                  */
703                                 varattno = ((Var *) leftop)->varattno;
704                                 scanvar = LEFT_OP;
705                         }
706                         else if (IsA(leftop, Const))
707                         {
708                                 /* ----------------
709                                  *      if the leftop is a const node then it means
710                                  *      it identifies the value to place in our scan key.
711                                  * ----------------
712                                  */
713                                 run_keys[j] = NO_OP;
714                                 scanvalue = ((Const *) leftop)->constvalue;
715                         }
716                         else if (IsA(leftop, Param))
717                         {
718                                 bool            isnull;
719
720                                 /* ----------------
721                                  *      if the leftop is a Param node then it means
722                                  *      it identifies the value to place in our scan key.
723                                  * ----------------
724                                  */
725                                 
726                                 /* Life was so easy before ... subselects */
727                                 if ( ((Param *) leftop)->paramkind == PARAM_EXEC )
728                                 {
729                                         have_runtime_keys = true;
730                                         run_keys[j] = LEFT_OP;
731                                         execParam = lappendi (execParam, ((Param*) leftop)->paramid);
732                                 }
733                                 else
734                                 {
735                                         scanvalue = ExecEvalParam((Param *) leftop,
736                                                                                           scanstate->cstate.cs_ExprContext,
737                                                                                           &isnull);
738                                         if (isnull)
739                                                 flags |= SK_ISNULL;
740                                         
741                                         run_keys[j] = NO_OP;
742                                 }
743                         }
744                         else if (leftop != NULL &&
745                                          is_funcclause(leftop) &&
746                                          var_is_rel(lfirst(((Expr *) leftop)->args)))
747                         {
748                                 /* ----------------
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.
753                                  * ----------------
754                                  */
755                                 varattno = 1;
756                                 scanvar = LEFT_OP;
757
758                         }
759                         else
760                         {
761                                 /* ----------------
762                                  *      otherwise, the leftop contains information usable
763                                  *      at runtime to figure out the value to place in our
764                                  *      scan key.
765                                  * ----------------
766                                  */
767                                 have_runtime_keys = true;
768                                 run_keys[j] = LEFT_OP;
769                                 scanvalue = Int32GetDatum((int32) true);
770                         }
771
772                         /* ----------------
773                          *      now determine information in rightop
774                          * ----------------
775                          */
776                         rightop = (Node *) get_rightop(clause);
777
778                         if (IsA(rightop, Var) &&var_is_rel((Var *) rightop))
779                         {
780                                 /* ----------------
781                                  *      here we make sure only one op identifies the
782                                  *      scan-attribute...
783                                  * ----------------
784                                  */
785                                 if (scanvar == LEFT_OP)
786                                         elog(ERROR, "ExecInitIndexScan: %s",
787                                                  "both left and right op's are rel-vars");
788
789                                 /* ----------------
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.
793                                  * ----------------
794                                  */
795                                 varattno = ((Var *) rightop)->varattno;
796                                 scanvar = RIGHT_OP;
797
798                         }
799                         else if (IsA(rightop, Const))
800                         {
801                                 /* ----------------
802                                  *      if the leftop is a const node then it means
803                                  *      it identifies the value to place in our scan key.
804                                  * ----------------
805                                  */
806                                 run_keys[j] = NO_OP;
807                                 scanvalue = ((Const *) rightop)->constvalue;
808                         }
809                         else if (IsA(rightop, Param))
810                         {
811                                 bool            isnull;
812
813                                 /* ----------------
814                                  *      if the rightop is a Param node then it means
815                                  *      it identifies the value to place in our scan key.
816                                  * ----------------
817                                  */
818                                 
819                                 /* Life was so easy before ... subselects */
820                                 if ( ((Param *) rightop)->paramkind == PARAM_EXEC )
821                                 {
822                                         have_runtime_keys = true;
823                                         run_keys[j] = RIGHT_OP;
824                                         execParam = lappendi (execParam, ((Param*) rightop)->paramid);
825                                 }
826                                 else
827                                 {
828                                         scanvalue = ExecEvalParam((Param *) rightop,
829                                                                                           scanstate->cstate.cs_ExprContext,
830                                                                                           &isnull);
831                                         if (isnull)
832                                                 flags |= SK_ISNULL;
833                                         
834                                         run_keys[j] = NO_OP;
835                                 }
836                         }
837                         else if (rightop != NULL &&
838                                          is_funcclause(rightop) &&
839                                          var_is_rel(lfirst(((Expr *) rightop)->args)))
840                         {
841                                 /* ----------------
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.
846                                  * ----------------
847                                  */
848                                 if (scanvar == LEFT_OP)
849                                         elog(ERROR, "ExecInitIndexScan: %s",
850                                                  "both left and right ops are rel-vars");
851
852                                 varattno = 1;
853                                 scanvar = RIGHT_OP;
854
855                         }
856                         else
857                         {
858                                 /* ----------------
859                                  *      otherwise, the leftop contains information usable
860                                  *      at runtime to figure out the value to place in our
861                                  *      scan key.
862                                  * ----------------
863                                  */
864                                 have_runtime_keys = true;
865                                 run_keys[j] = RIGHT_OP;
866                                 scanvalue = Int32GetDatum((int32) true);
867                         }
868
869                         /* ----------------
870                          *      now check that at least one op tells us the scan
871                          *      attribute...
872                          * ----------------
873                          */
874                         if (scanvar == NO_OP)
875                                 elog(ERROR, "ExecInitIndexScan: %s",
876                                          "neither leftop nor rightop refer to scan relation");
877
878                         /* ----------------
879                          *      initialize the scan key's fields appropriately
880                          * ----------------
881                          */
882                         ScanKeyEntryInitialize(&scan_keys[j],
883                                                                    flags,
884                                                                    varattno,    /* attribute number to
885                                                                                                  * scan */
886                                                                    (RegProcedure) opid, /* reg proc to use */
887                                                                    (Datum) scanvalue);  /* constant */
888                 }
889
890                 /* ----------------
891                  *      store the key information into our array.
892                  * ----------------
893                  */
894                 numScanKeys[i] = n_keys;
895                 scanKeys[i] = scan_keys;
896                 runtimeKeyInfo[i] = (Pointer) run_keys;
897         }
898
899         indexstate->iss_NumIndices = numIndices;
900         indexstate->iss_IndexPtr = indexPtr;
901         indexstate->iss_ScanKeys = scanKeys;
902         indexstate->iss_NumScanKeys = numScanKeys;
903
904         /* ----------------
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.
910          *      -cim 10/24/89
911          * ----------------
912          */
913         if (have_runtime_keys)
914                 indexstate->iss_RuntimeKeyInfo = (Pointer) runtimeKeyInfo;
915         else
916                 indexstate->iss_RuntimeKeyInfo = NULL;
917
918         /* ----------------
919          *      get the range table and direction information
920          *      from the execution state (these are needed to
921          *      open the relations).
922          * ----------------
923          */
924         rangeTable = estate->es_range_table;
925         direction = estate->es_direction;
926
927         /* ----------------
928          *      open the base relation
929          * ----------------
930          */
931         relid = node->scan.scanrelid;
932         rtentry = rt_fetch(relid, rangeTable);
933         reloid = rtentry->relid;
934
935         ExecOpenScanR(reloid,           /* relation */
936                                   0,                    /* nkeys */
937                                   (ScanKey) NULL,               /* scan key */
938                                   0,                    /* is index */
939                                   direction,    /* scan direction */
940                                   estate->es_snapshot,  /* */
941                                   &currentRelation,             /* return: rel desc */
942                                   (Pointer *) &currentScanDesc);                /* return: scan desc */
943
944         scanstate->css_currentRelation = currentRelation;
945         scanstate->css_currentScanDesc = currentScanDesc;
946
947
948         /* ----------------
949          *      get the scan type from the relation descriptor.
950          * ----------------
951          */
952         ExecAssignScanType(scanstate, RelationGetTupleDescriptor(currentRelation));
953         ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
954
955         /* ----------------
956          *      index scans don't have subtrees..
957          * ----------------
958          */
959 /*        scanstate->ss_ProcOuterFlag = false; */
960
961         /* ----------------
962          *      open the index relations and initialize
963          *      relation and scan descriptors.
964          * ----------------
965          */
966         for (i = 0; i < numIndices; i++)
967         {
968                 Oid                     indexOid;
969
970                 indexOid = (Oid) nthi(i, indxid);
971
972                 if (indexOid != 0)
973                 {
974                         ExecOpenScanR(indexOid,         /* relation */
975                                                   numScanKeys[i],               /* nkeys */
976                                                   scanKeys[i],  /* scan key */
977                                                   true, /* is index */
978                                                   direction,    /* scan direction */
979                                                   estate->es_snapshot,
980                                                   &(relationDescs[i]),  /* return: rel desc */
981                                                   (Pointer *) &(scanDescs[i]));
982                         /* return: scan desc */
983                 }
984         }
985
986         indexstate->iss_RelationDescs = relationDescs;
987         indexstate->iss_ScanDescs = scanDescs;
988
989         indexstate->cstate.cs_TupFromTlist = false;
990         
991         /* 
992          * if there are some PARAM_EXEC in skankeys then
993          * force index rescan on first scan.
994          */
995         ((Plan*) node)->chgParam = execParam;
996         
997         /* ----------------
998          *      all done.
999          * ----------------
1000          */
1001         return TRUE;
1002 }
1003
1004 int
1005 ExecCountSlotsIndexScan(IndexScan *node)
1006 {
1007         return ExecCountSlotsNode(outerPlan((Plan *) node)) +
1008                    ExecCountSlotsNode(innerPlan((Plan *) node)) + INDEXSCAN_NSLOTS;
1009 }