]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeIndexscan.c
Ye-old pgindent run. Same 4-space tabs.
[postgresql] / src / backend / executor / nodeIndexscan.c
1 /*-------------------------------------------------------------------------
2  *
3  * nodeIndexscan.c
4  *        Routines to support indexes and indexed scans of relations
5  *
6  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.49 2000/04/12 17:15:09 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 /*
16  * INTERFACE ROUTINES
17  *              ExecInsertIndexTuples   inserts tuples into indices on result relation
18  *
19  *              ExecIndexScan                   scans a relation using indices
20  *              ExecIndexNext                   using index to retrieve next tuple
21  *              ExecInitIndexScan               creates and initializes state info.
22  *              ExecIndexReScan                 rescans the indexed relation.
23  *              ExecEndIndexScan                releases all storage.
24  *              ExecIndexMarkPos                marks scan position.
25  *              ExecIndexRestrPos               restores scan position.
26  *
27  *       NOTES
28  *              the code supporting ExecInsertIndexTuples should be
29  *              collected and merged with the genam stuff.
30  *
31  */
32 #include "postgres.h"
33
34
35
36 #include "access/genam.h"
37 #include "access/heapam.h"
38 #include "executor/execdebug.h"
39 #include "executor/executor.h"
40 #include "executor/nodeIndexscan.h"
41 #include "nodes/nodeFuncs.h"
42 #include "optimizer/clauses.h"
43 #include "parser/parsetree.h"
44
45 /* ----------------
46  *              Misc stuff to move to executor.h soon -cim 6/5/90
47  * ----------------
48  */
49 #define NO_OP                   0
50 #define LEFT_OP                 1
51 #define RIGHT_OP                2
52
53 static TupleTableSlot *IndexNext(IndexScan *node);
54
55 /* ----------------------------------------------------------------
56  *              IndexNext
57  *
58  *              Retrieve a tuple from the IndexScan node's currentRelation
59  *              using the indices in the IndexScanState information.
60  *
61  *              note: the old code mentions 'Primary indices'.  to my knowledge
62  *              we only support a single secondary index. -cim 9/11/89
63  *
64  * old comments:
65  *              retrieve a tuple from relation using the indices given.
66  *              The indices are used in the order they appear in 'indices'.
67  *              The indices may be primary or secondary indices:
68  *                * primary index --    scan the relation 'relID' using keys supplied.
69  *                * secondary index --  scan the index relation to get the 'tid' for
70  *                                                              a tuple in the relation 'relID'.
71  *              If the current index(pointed by 'indexPtr') fails to return a
72  *              tuple, the next index in the indices is used.
73  *
74  *                bug fix so that it should retrieve on a null scan key.
75  * ----------------------------------------------------------------
76  */
77 static TupleTableSlot *
78 IndexNext(IndexScan *node)
79 {
80         EState     *estate;
81         CommonScanState *scanstate;
82         IndexScanState *indexstate;
83         ScanDirection direction;
84         Snapshot        snapshot;
85         IndexScanDescPtr scanDescs;
86         IndexScanDesc scandesc;
87         Relation        heapRelation;
88         RetrieveIndexResult result;
89         HeapTuple       tuple;
90         TupleTableSlot *slot;
91         Buffer          buffer = InvalidBuffer;
92         int                     numIndices;
93
94         bool            bBackward;
95         int                     indexNumber;
96
97         /* ----------------
98          *      extract necessary information from index scan node
99          * ----------------
100          */
101         estate = node->scan.plan.state;
102         direction = estate->es_direction;
103         if (ScanDirectionIsBackward(node->indxorderdir))
104         {
105                 if (ScanDirectionIsForward(direction))
106                         direction = BackwardScanDirection;
107                 else if (ScanDirectionIsBackward(direction))
108                         direction = ForwardScanDirection;
109         }
110         snapshot = estate->es_snapshot;
111         scanstate = node->scan.scanstate;
112         indexstate = node->indxstate;
113         scanDescs = indexstate->iss_ScanDescs;
114         heapRelation = scanstate->css_currentRelation;
115         numIndices = indexstate->iss_NumIndices;
116         slot = scanstate->css_ScanTupleSlot;
117
118         /*
119          * Check if we are evaluating PlanQual for tuple of this relation.
120          * Additional checking is not good, but no other way for now. We could
121          * introduce new nodes for this case and handle IndexScan --> NewNode
122          * switching in Init/ReScan plan...
123          */
124         if (estate->es_evTuple != NULL &&
125                 estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
126         {
127                 List       *qual;
128
129                 ExecClearTuple(slot);
130                 if (estate->es_evTupleNull[node->scan.scanrelid - 1])
131                         return slot;            /* return empty slot */
132
133                 /* probably ought to use ExecStoreTuple here... */
134                 slot->val = estate->es_evTuple[node->scan.scanrelid - 1];
135                 slot->ttc_shouldFree = false;
136
137                 scanstate->cstate.cs_ExprContext->ecxt_scantuple = slot;
138
139                 /* Does the tuple meet any of the OR'd indxqual conditions? */
140                 foreach(qual, node->indxqualorig)
141                 {
142                         if (ExecQual((List *) lfirst(qual),
143                                                  scanstate->cstate.cs_ExprContext,
144                                                  false))
145                                 break;
146                 }
147                 if (qual == NIL)                /* would not be returned by indices */
148                         slot->val = NULL;
149
150                 /* Flag for the next call that no more tuples */
151                 estate->es_evTupleNull[node->scan.scanrelid - 1] = true;
152
153                 return slot;
154         }
155
156         tuple = &(indexstate->iss_htup);
157
158         /* ----------------
159          *      ok, now that we have what we need, fetch an index tuple.
160          *      if scanning this index succeeded then return the
161          *      appropriate heap tuple.. else return NULL.
162          * ----------------
163          */
164         bBackward = ScanDirectionIsBackward(direction);
165         if (bBackward)
166         {
167                 indexNumber = numIndices - indexstate->iss_IndexPtr - 1;
168                 if (indexNumber < 0)
169                 {
170                         indexNumber = 0;
171                         indexstate->iss_IndexPtr = numIndices - 1;
172                 }
173         }
174         else
175         {
176                 if ((indexNumber = indexstate->iss_IndexPtr) < 0)
177                 {
178                         indexNumber = 0;
179                         indexstate->iss_IndexPtr = 0;
180                 }
181         }
182         while (indexNumber < numIndices)
183         {
184                 scandesc = scanDescs[indexstate->iss_IndexPtr];
185                 while ((result = index_getnext(scandesc, direction)) != NULL)
186                 {
187                         tuple->t_self = result->heap_iptr;
188                         heap_fetch(heapRelation, snapshot, tuple, &buffer);
189                         pfree(result);
190
191                         if (tuple->t_data != NULL)
192                         {
193                                 bool            prev_matches = false;
194                                 int                     prev_index;
195                                 List       *qual;
196
197                                 /*
198                                  * store the scanned tuple in the scan tuple slot of the
199                                  * scan state.  Eventually we will only do this and not
200                                  * return a tuple.      Note: we pass 'false' because tuples
201                                  * returned by amgetnext are pointers onto disk pages and
202                                  * must not be pfree()'d.
203                                  */
204                                 ExecStoreTuple(tuple,   /* tuple to store */
205                                                            slot,        /* slot to store in */
206                                                            buffer,      /* buffer associated with tuple  */
207                                                            false);      /* don't pfree */
208
209                                 /*
210                                  * At this point we have an extra pin on the buffer,
211                                  * because ExecStoreTuple incremented the pin count. Drop
212                                  * our local pin.
213                                  */
214                                 ReleaseBuffer(buffer);
215
216                                 /*
217                                  * We must check to see if the current tuple was already
218                                  * matched by an earlier index, so we don't double-report
219                                  * it. We do this by passing the tuple through ExecQual
220                                  * and checking for failure with all previous
221                                  * qualifications.
222                                  */
223                                 scanstate->cstate.cs_ExprContext->ecxt_scantuple = slot;
224                                 qual = node->indxqualorig;
225                                 for (prev_index = 0; prev_index < indexstate->iss_IndexPtr;
226                                          prev_index++)
227                                 {
228                                         if (ExecQual((List *) lfirst(qual),
229                                                                  scanstate->cstate.cs_ExprContext,
230                                                                  false))
231                                         {
232                                                 prev_matches = true;
233                                                 break;
234                                         }
235                                         qual = lnext(qual);
236                                 }
237                                 if (!prev_matches)
238                                         return slot;/* OK to return tuple */
239                                 /* Duplicate tuple, so drop it and loop back for another */
240                                 ExecClearTuple(slot);
241                         }
242                 }
243                 if (indexNumber < numIndices)
244                 {
245                         indexNumber++;
246                         if (bBackward)
247                                 indexstate->iss_IndexPtr--;
248                         else
249                                 indexstate->iss_IndexPtr++;
250                 }
251         }
252         /* ----------------
253          *      if we get here it means the index scan failed so we
254          *      are at the end of the scan..
255          * ----------------
256          */
257         return ExecClearTuple(slot);
258 }
259
260 /* ----------------------------------------------------------------
261  *              ExecIndexScan(node)
262  *
263  * old comments:
264  *              Scans the relation using primary or secondary indices and returns
265  *                 the next qualifying tuple in the direction specified.
266  *              It calls ExecScan() and passes it the access methods which returns
267  *              the next tuple using the indices.
268  *
269  *              Conditions:
270  *                -- the "cursor" maintained by the AMI is positioned at the tuple
271  *                       returned previously.
272  *
273  *              Initial States:
274  *                -- the relation indicated is opened for scanning so that the
275  *                       "cursor" is positioned before the first qualifying tuple.
276  *                -- all index realtions are opened for scanning.
277  *                -- indexPtr points to the first index.
278  *                -- state variable ruleFlag = nil.
279  * ----------------------------------------------------------------
280  */
281 TupleTableSlot *
282 ExecIndexScan(IndexScan *node)
283 {
284         /* ----------------
285          *      use IndexNext as access method
286          * ----------------
287          */
288         return ExecScan(&node->scan, IndexNext);
289 }
290
291 /* ----------------------------------------------------------------
292  *              ExecIndexReScan(node)
293  *
294  *              Recalculates the value of the scan keys whose value depends on
295  *              information known at runtime and rescans the indexed relation.
296  *              Updating the scan key was formerly done separately in
297  *              ExecUpdateIndexScanKeys. Integrating it into ReScan
298  *              makes rescans of indices and
299  *              relations/general streams more uniform.
300  *
301  * ----------------------------------------------------------------
302  */
303 void
304 ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
305 {
306         EState     *estate;
307         IndexScanState *indexstate;
308         ScanDirection direction;
309         IndexScanDescPtr scanDescs;
310         ScanKey    *scanKeys;
311         IndexScanDesc scan;
312         ScanKey         skey;
313         int                     numIndices;
314         int                     i;
315
316         Pointer    *runtimeKeyInfo;
317         int                *numScanKeys;
318         List       *indxqual;
319         List       *qual;
320         int                     n_keys;
321         ScanKey         scan_keys;
322         int                *run_keys;
323         int                     j;
324         Expr       *clause;
325         Node       *scanexpr;
326         Datum           scanvalue;
327         bool            isNull;
328         bool            isDone;
329
330         indexstate = node->indxstate;
331         estate = node->scan.plan.state;
332         direction = estate->es_direction;
333         numIndices = indexstate->iss_NumIndices;
334         scanDescs = indexstate->iss_ScanDescs;
335         scanKeys = indexstate->iss_ScanKeys;
336         runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
337         numScanKeys = indexstate->iss_NumScanKeys;
338         indexstate->iss_IndexPtr = -1;
339         if (ScanDirectionIsBackward(node->indxorderdir))
340                 indexstate->iss_IndexPtr = numIndices;
341
342         /* If we are being passed an outer tuple, save it for runtime key calc */
343         if (exprCtxt != NULL)
344                 node->scan.scanstate->cstate.cs_ExprContext->ecxt_outertuple =
345                         exprCtxt->ecxt_outertuple;
346
347         /* If this is re-scanning of PlanQual ... */
348         if (estate->es_evTuple != NULL &&
349                 estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
350         {
351                 estate->es_evTupleNull[node->scan.scanrelid - 1] = false;
352                 return;
353         }
354
355         /*
356          * get the index qualifications and recalculate the appropriate values
357          */
358         indxqual = node->indxqual;
359         for (i = 0; i < numIndices; i++)
360         {
361                 qual = lfirst(indxqual);
362                 indxqual = lnext(indxqual);
363                 n_keys = numScanKeys[i];
364                 scan_keys = (ScanKey) scanKeys[i];
365
366                 if (runtimeKeyInfo)
367                 {
368                         run_keys = (int *) runtimeKeyInfo[i];
369                         for (j = 0; j < n_keys; j++)
370                         {
371
372                                 /*
373                                  * If we have a run-time key, then extract the run-time
374                                  * expression and evaluate it with respect to the current
375                                  * outer tuple.  We then stick the result into the scan
376                                  * key.
377                                  */
378                                 if (run_keys[j] != NO_OP)
379                                 {
380                                         clause = nth(j, qual);
381                                         scanexpr = (run_keys[j] == RIGHT_OP) ?
382                                                 (Node *) get_rightop(clause) :
383                                                 (Node *) get_leftop(clause);
384
385                                         /*
386                                          * pass in isDone but ignore it.  We don't iterate in
387                                          * quals
388                                          */
389                                         scanvalue = (Datum)
390                                                 ExecEvalExpr(scanexpr,
391                                                          node->scan.scanstate->cstate.cs_ExprContext,
392                                                                          &isNull, &isDone);
393                                         scan_keys[j].sk_argument = scanvalue;
394                                         if (isNull)
395                                                 scan_keys[j].sk_flags |= SK_ISNULL;
396                                         else
397                                                 scan_keys[j].sk_flags &= ~SK_ISNULL;
398                                 }
399                         }
400                 }
401                 scan = scanDescs[i];
402                 skey = scanKeys[i];
403                 index_rescan(scan, direction, skey);
404         }
405         /* ----------------
406          *      perhaps return something meaningful
407          * ----------------
408          */
409         return;
410 }
411
412 /* ----------------------------------------------------------------
413  *              ExecEndIndexScan
414  *
415  * old comments
416  *              Releases any storage allocated through C routines.
417  *              Returns nothing.
418  * ----------------------------------------------------------------
419  */
420 void
421 ExecEndIndexScan(IndexScan *node)
422 {
423         CommonScanState *scanstate;
424         IndexScanState *indexstate;
425         Pointer    *runtimeKeyInfo;
426         ScanKey    *scanKeys;
427         List       *indxqual;
428         int                *numScanKeys;
429         int                     numIndices;
430         int                     i;
431
432         scanstate = node->scan.scanstate;
433         indexstate = node->indxstate;
434         indxqual = node->indxqual;
435         runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
436
437         /* ----------------
438          *      extract information from the node
439          * ----------------
440          */
441         numIndices = indexstate->iss_NumIndices;
442         scanKeys = indexstate->iss_ScanKeys;
443         numScanKeys = indexstate->iss_NumScanKeys;
444
445         /* ----------------
446          *      Free the projection info and the scan attribute info
447          *
448          *      Note: we don't ExecFreeResultType(scanstate)
449          *                because the rule manager depends on the tupType
450          *                returned by ExecMain().  So for now, this
451          *                is freed at end-transaction time.  -cim 6/2/91
452          * ----------------
453          */
454         ExecFreeProjectionInfo(&scanstate->cstate);
455
456         /* ----------------
457          *      close the heap and index relations
458          * ----------------
459          */
460         ExecCloseR((Plan *) node);
461
462         /* ----------------
463          *      free the scan keys used in scanning the indices
464          * ----------------
465          */
466         for (i = 0; i < numIndices; i++)
467         {
468                 if (scanKeys[i] != NULL)
469                         pfree(scanKeys[i]);
470         }
471         pfree(scanKeys);
472         pfree(numScanKeys);
473
474         if (runtimeKeyInfo)
475         {
476                 for (i = 0; i < numIndices; i++)
477                 {
478                         List       *qual;
479                         int                     n_keys;
480
481                         qual = nth(i, indxqual);
482                         n_keys = length(qual);
483                         if (n_keys > 0)
484                                 pfree(runtimeKeyInfo[i]);
485                 }
486                 pfree(runtimeKeyInfo);
487         }
488
489         /* ----------------
490          *      clear out tuple table slots
491          * ----------------
492          */
493         ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
494         ExecClearTuple(scanstate->css_ScanTupleSlot);
495 /*        ExecClearTuple(scanstate->css_RawTupleSlot); */
496 }
497
498 /* ----------------------------------------------------------------
499  *              ExecIndexMarkPos
500  *
501  * old comments
502  *              Marks scan position by marking the current index.
503  *              Returns nothing.
504  * ----------------------------------------------------------------
505  */
506 void
507 ExecIndexMarkPos(IndexScan *node)
508 {
509         IndexScanState *indexstate;
510         IndexScanDescPtr indexScanDescs;
511         IndexScanDesc scanDesc;
512         int                     indexPtr;
513
514         indexstate = node->indxstate;
515         indexPtr = indexstate->iss_MarkIndexPtr = indexstate->iss_IndexPtr;
516         indexScanDescs = indexstate->iss_ScanDescs;
517         scanDesc = indexScanDescs[indexPtr];
518
519 #ifdef NOT_USED
520         IndexScanMarkPosition(scanDesc);
521 #endif
522         index_markpos(scanDesc);
523 }
524
525 /* ----------------------------------------------------------------
526  *              ExecIndexRestrPos
527  *
528  * old comments
529  *              Restores scan position by restoring the current index.
530  *              Returns nothing.
531  *
532  *              XXX Assumes previously marked scan position belongs to current index
533  * ----------------------------------------------------------------
534  */
535 void
536 ExecIndexRestrPos(IndexScan *node)
537 {
538         IndexScanState *indexstate;
539         IndexScanDescPtr indexScanDescs;
540         IndexScanDesc scanDesc;
541         int                     indexPtr;
542
543         indexstate = node->indxstate;
544         indexPtr = indexstate->iss_IndexPtr = indexstate->iss_MarkIndexPtr;
545         indexScanDescs = indexstate->iss_ScanDescs;
546         scanDesc = indexScanDescs[indexPtr];
547
548 #ifdef NOT_USED
549         IndexScanRestorePosition(scanDesc);
550 #endif
551         index_restrpos(scanDesc);
552 }
553
554 /* ----------------------------------------------------------------
555  *              ExecInitIndexScan
556   *
557  *              Initializes the index scan's state information, creates
558  *              scan keys, and opens the base and index relations.
559  *
560  *              Note: index scans have 2 sets of state information because
561  *                        we have to keep track of the base relation and the
562  *                        index relations.
563  *
564  * old comments
565  *              Creates the run-time state information for the node and
566  *              sets the relation id to contain relevant decriptors.
567  *
568  *              Parameters:
569  *                node: IndexNode node produced by the planner.
570  *                estate: the execution state initialized in InitPlan.
571  * ----------------------------------------------------------------
572  */
573 bool
574 ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
575 {
576         IndexScanState *indexstate;
577         CommonScanState *scanstate;
578         List       *indxqual;
579         List       *indxid;
580         int                     i;
581         int                     numIndices;
582         int                     indexPtr;
583         ScanKey    *scanKeys;
584         int                *numScanKeys;
585         RelationPtr relationDescs;
586         IndexScanDescPtr scanDescs;
587         Pointer    *runtimeKeyInfo;
588         bool            have_runtime_keys;
589         List       *rangeTable;
590         RangeTblEntry *rtentry;
591         Index           relid;
592         Oid                     reloid;
593
594         Relation        currentRelation;
595         HeapScanDesc currentScanDesc;
596         ScanDirection direction;
597         int                     baseid;
598
599         List       *execParam = NULL;
600
601         /* ----------------
602          *      assign execution state to node
603          * ----------------
604          */
605         node->scan.plan.state = estate;
606
607         /* --------------------------------
608          *      Part 1)  initialize scan state
609          *
610          *      create new CommonScanState for node
611          * --------------------------------
612          */
613         scanstate = makeNode(CommonScanState);
614 /*
615         scanstate->ss_ProcOuterFlag = false;
616         scanstate->ss_OldRelId = 0;
617 */
618
619         node->scan.scanstate = scanstate;
620
621         /* ----------------
622          *      assign node's base_id .. we don't use AssignNodeBaseid() because
623          *      the increment is done later on after we assign the index scan's
624          *      scanstate.      see below.
625          * ----------------
626          */
627         baseid = estate->es_BaseId;
628 /*        scanstate->csstate.cstate.bnode.base_id = baseid; */
629         scanstate->cstate.cs_base_id = baseid;
630
631         /* ----------------
632          *      create expression context for node
633          * ----------------
634          */
635         ExecAssignExprContext(estate, &scanstate->cstate);
636
637 #define INDEXSCAN_NSLOTS 3
638         /* ----------------
639          *      tuple table initialization
640          * ----------------
641          */
642         ExecInitResultTupleSlot(estate, &scanstate->cstate);
643         ExecInitScanTupleSlot(estate, scanstate);
644 /*        ExecInitRawTupleSlot(estate, scanstate); */
645
646         /* ----------------
647          *      initialize projection info.  result type comes from scan desc
648          *      below..
649          * ----------------
650          */
651         ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
652
653         /* --------------------------------
654           *  Part 2)  initialize index scan state
655           *
656           *  create new IndexScanState for node
657           * --------------------------------
658           */
659         indexstate = makeNode(IndexScanState);
660         indexstate->iss_NumIndices = 0;
661         indexstate->iss_IndexPtr = -1;
662         indexstate->iss_ScanKeys = NULL;
663         indexstate->iss_NumScanKeys = NULL;
664         indexstate->iss_RuntimeKeyInfo = NULL;
665         indexstate->iss_RelationDescs = NULL;
666         indexstate->iss_ScanDescs = NULL;
667
668         node->indxstate = indexstate;
669
670         /* ----------------
671          *      assign base id to index scan state also
672          * ----------------
673          */
674         indexstate->cstate.cs_base_id = baseid;
675         baseid++;
676         estate->es_BaseId = baseid;
677
678         /* ----------------
679          *      get the index node information
680          * ----------------
681          */
682         indxid = node->indxid;
683         numIndices = length(indxid);
684         indexPtr = -1;
685
686         CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);
687
688         /* ----------------
689          *      scanKeys is used to keep track of the ScanKey's. This is needed
690          *      because a single scan may use several indices and each index has
691          *      its own ScanKey.
692          * ----------------
693          */
694         numScanKeys = (int *) palloc(numIndices * sizeof(int));
695         scanKeys = (ScanKey *) palloc(numIndices * sizeof(ScanKey));
696         relationDescs = (RelationPtr) palloc(numIndices * sizeof(Relation));
697         scanDescs = (IndexScanDescPtr) palloc(numIndices * sizeof(IndexScanDesc));
698
699         /* ----------------
700          *      initialize runtime key info.
701          * ----------------
702          */
703         have_runtime_keys = false;
704         runtimeKeyInfo = (Pointer *)
705                 palloc(numIndices * sizeof(Pointer));
706
707         /* ----------------
708          *      build the index scan keys from the index qualification
709          * ----------------
710          */
711         indxqual = node->indxqual;
712         for (i = 0; i < numIndices; i++)
713         {
714                 int                     j;
715                 List       *qual;
716                 int                     n_keys;
717                 ScanKey         scan_keys;
718                 int                *run_keys;
719
720                 qual = lfirst(indxqual);
721                 indxqual = lnext(indxqual);
722                 n_keys = length(qual);
723                 scan_keys = (n_keys <= 0) ? NULL :
724                         (ScanKey) palloc(n_keys * sizeof(ScanKeyData));
725                 run_keys = (n_keys <= 0) ? NULL :
726                         (int *) palloc(n_keys * sizeof(int));
727
728                 CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);
729
730                 /* ----------------
731                  *      for each opclause in the given qual,
732                  *      convert each qual's opclause into a single scan key
733                  * ----------------
734                  */
735                 for (j = 0; j < n_keys; j++)
736                 {
737                         Expr       *clause; /* one part of index qual */
738                         Oper       *op;         /* operator used in scan.. */
739                         Node       *leftop; /* expr on lhs of operator */
740                         Node       *rightop;/* expr on rhs ... */
741                         bits16          flags = 0;
742
743                         int                     scanvar;/* which var identifies varattno */
744                         AttrNumber      varattno = 0;   /* att number used in scan */
745                         Oid                     opid;   /* operator id used in scan */
746                         Datum           scanvalue = 0;  /* value used in scan (if const) */
747
748                         /* ----------------
749                          *      extract clause information from the qualification
750                          * ----------------
751                          */
752                         clause = nth(j, qual);
753
754                         op = (Oper *) clause->oper;
755                         if (!IsA(clause, Expr) ||!IsA(op, Oper))
756                                 elog(ERROR, "ExecInitIndexScan: indxqual not an opclause!");
757
758                         opid = op->opid;
759
760                         /* ----------------
761                          *      Here we figure out the contents of the index qual.
762                          *      The usual case is (var op const) or (const op var)
763                          *      which means we form a scan key for the attribute
764                          *      listed in the var node and use the value of the const.
765                          *
766                          *      If we don't have a const node, then it means that
767                          *      one of the var nodes refers to the "scan" tuple and
768                          *      is used to determine which attribute to scan, and the
769                          *      other expression is used to calculate the value used in
770                          *      scanning the index.
771                          *
772                          *      This means our index scan's scan key is a function of
773                          *      information obtained during the execution of the plan
774                          *      in which case we need to recalculate the index scan key
775                          *      at run time.
776                          *
777                          *      Hence, we set have_runtime_keys to true and then set
778                          *      the appropriate flag in run_keys to LEFT_OP or RIGHT_OP.
779                          *      The corresponding scan keys are recomputed at run time.
780                          *
781                          *      XXX Although this code *thinks* it can handle an indexqual
782                          *      with the indexkey on either side, in fact it cannot.
783                          *      Indexscans only work with quals that have the indexkey on
784                          *      the left (the planner/optimizer makes sure it never passes
785                          *      anything else).  The reason: the scankey machinery has no
786                          *      provision for distinguishing which side of the operator is
787                          *      the indexed attribute and which is the compared-to constant.
788                          *      It just assumes that the attribute is on the left :-(
789                          *
790                          *      I am leaving this code able to support both ways, even though
791                          *      half of it is dead code, on the off chance that someone will
792                          *      fix the scankey machinery someday --- tgl 8/11/99.
793                          * ----------------
794                          */
795
796                         scanvar = NO_OP;
797
798                         /* ----------------
799                          *      determine information in leftop
800                          * ----------------
801                          */
802                         leftop = (Node *) get_leftop(clause);
803
804                         Assert(leftop != NULL);
805
806                         if (IsA(leftop, Var) &&var_is_rel((Var *) leftop))
807                         {
808                                 /* ----------------
809                                  *      if the leftop is a "rel-var", then it means
810                                  *      that it is a var node which tells us which
811                                  *      attribute to use for our scan key.
812                                  * ----------------
813                                  */
814                                 varattno = ((Var *) leftop)->varattno;
815                                 scanvar = LEFT_OP;
816                         }
817                         else if (is_funcclause(leftop) &&
818                                          var_is_rel(lfirst(((Expr *) leftop)->args)))
819                         {
820                                 /* ----------------
821                                  *      if the leftop is a func node then it means
822                                  *      it identifies the value to place in our scan key.
823                                  *      Since functional indices have only one attribute
824                                  *      the attno must always be set to 1.
825                                  * ----------------
826                                  */
827                                 varattno = 1;
828                                 scanvar = LEFT_OP;
829                         }
830                         else if (IsA(leftop, Const))
831                         {
832                                 /* ----------------
833                                  *      if the leftop is a const node then it means
834                                  *      it identifies the value to place in our scan key.
835                                  * ----------------
836                                  */
837                                 run_keys[j] = NO_OP;
838                                 scanvalue = ((Const *) leftop)->constvalue;
839                         }
840                         else if (IsA(leftop, Param))
841                         {
842                                 bool            isnull;
843
844                                 /* ----------------
845                                  *      if the leftop is a Param node then it means
846                                  *      it identifies the value to place in our scan key.
847                                  * ----------------
848                                  */
849
850                                 /* Life was so easy before ... subselects */
851                                 if (((Param *) leftop)->paramkind == PARAM_EXEC)
852                                 {
853                                         have_runtime_keys = true;
854                                         run_keys[j] = LEFT_OP;
855                                         execParam = lappendi(execParam, ((Param *) leftop)->paramid);
856                                 }
857                                 else
858                                 {
859                                         scanvalue = ExecEvalParam((Param *) leftop,
860                                                                                 scanstate->cstate.cs_ExprContext,
861                                                                                           &isnull);
862                                         if (isnull)
863                                                 flags |= SK_ISNULL;
864
865                                         run_keys[j] = NO_OP;
866                                 }
867                         }
868                         else
869                         {
870                                 /* ----------------
871                                  *      otherwise, the leftop contains information usable
872                                  *      at runtime to figure out the value to place in our
873                                  *      scan key.
874                                  * ----------------
875                                  */
876                                 have_runtime_keys = true;
877                                 run_keys[j] = LEFT_OP;
878                                 scanvalue = Int32GetDatum((int32) true);
879                         }
880
881                         /* ----------------
882                          *      now determine information in rightop
883                          * ----------------
884                          */
885                         rightop = (Node *) get_rightop(clause);
886
887                         Assert(rightop != NULL);
888
889                         if (IsA(rightop, Var) &&var_is_rel((Var *) rightop))
890                         {
891                                 /* ----------------
892                                  *      here we make sure only one op identifies the
893                                  *      scan-attribute...
894                                  * ----------------
895                                  */
896                                 if (scanvar == LEFT_OP)
897                                         elog(ERROR, "ExecInitIndexScan: %s",
898                                                  "both left and right op's are rel-vars");
899
900                                 /* ----------------
901                                  *      if the rightop is a "rel-var", then it means
902                                  *      that it is a var node which tells us which
903                                  *      attribute to use for our scan key.
904                                  * ----------------
905                                  */
906                                 varattno = ((Var *) rightop)->varattno;
907                                 scanvar = RIGHT_OP;
908                         }
909                         else if (is_funcclause(rightop) &&
910                                          var_is_rel(lfirst(((Expr *) rightop)->args)))
911                         {
912                                 /* ----------------
913                                  *      if the rightop is a func node then it means
914                                  *      it identifies the value to place in our scan key.
915                                  *      Since functional indices have only one attribute
916                                  *      the attno must always be set to 1.
917                                  * ----------------
918                                  */
919                                 if (scanvar == LEFT_OP)
920                                         elog(ERROR, "ExecInitIndexScan: %s",
921                                                  "both left and right ops are rel-vars");
922
923                                 varattno = 1;
924                                 scanvar = RIGHT_OP;
925                         }
926                         else if (IsA(rightop, Const))
927                         {
928                                 /* ----------------
929                                  *      if the rightop is a const node then it means
930                                  *      it identifies the value to place in our scan key.
931                                  * ----------------
932                                  */
933                                 run_keys[j] = NO_OP;
934                                 scanvalue = ((Const *) rightop)->constvalue;
935                         }
936                         else if (IsA(rightop, Param))
937                         {
938                                 bool            isnull;
939
940                                 /* ----------------
941                                  *      if the rightop is a Param node then it means
942                                  *      it identifies the value to place in our scan key.
943                                  * ----------------
944                                  */
945
946                                 /* Life was so easy before ... subselects */
947                                 if (((Param *) rightop)->paramkind == PARAM_EXEC)
948                                 {
949                                         have_runtime_keys = true;
950                                         run_keys[j] = RIGHT_OP;
951                                         execParam = lappendi(execParam, ((Param *) rightop)->paramid);
952                                 }
953                                 else
954                                 {
955                                         scanvalue = ExecEvalParam((Param *) rightop,
956                                                                                 scanstate->cstate.cs_ExprContext,
957                                                                                           &isnull);
958                                         if (isnull)
959                                                 flags |= SK_ISNULL;
960
961                                         run_keys[j] = NO_OP;
962                                 }
963                         }
964                         else
965                         {
966                                 /* ----------------
967                                  *      otherwise, the rightop contains information usable
968                                  *      at runtime to figure out the value to place in our
969                                  *      scan key.
970                                  * ----------------
971                                  */
972                                 have_runtime_keys = true;
973                                 run_keys[j] = RIGHT_OP;
974                                 scanvalue = Int32GetDatum((int32) true);
975                         }
976
977                         /* ----------------
978                          *      now check that at least one op tells us the scan
979                          *      attribute...
980                          * ----------------
981                          */
982                         if (scanvar == NO_OP)
983                                 elog(ERROR, "ExecInitIndexScan: %s",
984                                          "neither leftop nor rightop refer to scan relation");
985
986                         /* ----------------
987                          *      initialize the scan key's fields appropriately
988                          * ----------------
989                          */
990                         ScanKeyEntryInitialize(&scan_keys[j],
991                                                                    flags,
992                                                                    varattno,    /* attribute number to
993                                                                                                  * scan */
994                                                                    (RegProcedure) opid, /* reg proc to use */
995                                                                    (Datum) scanvalue);  /* constant */
996                 }
997
998                 /* ----------------
999                  *      store the key information into our array.
1000                  * ----------------
1001                  */
1002                 numScanKeys[i] = n_keys;
1003                 scanKeys[i] = scan_keys;
1004                 runtimeKeyInfo[i] = (Pointer) run_keys;
1005         }
1006
1007         indexstate->iss_NumIndices = numIndices;
1008         if (ScanDirectionIsBackward(node->indxorderdir))
1009                 indexPtr = numIndices;
1010         indexstate->iss_IndexPtr = indexPtr;
1011         indexstate->iss_ScanKeys = scanKeys;
1012         indexstate->iss_NumScanKeys = numScanKeys;
1013
1014         /* ----------------
1015          *      If all of our keys have the form (op var const) , then we have no
1016          *      runtime keys so we store NULL in the runtime key info.
1017          *      Otherwise runtime key info contains an array of pointers
1018          *      (one for each index) to arrays of flags (one for each key)
1019          *      which indicate that the qual needs to be evaluated at runtime.
1020          *      -cim 10/24/89
1021          * ----------------
1022          */
1023         if (have_runtime_keys)
1024                 indexstate->iss_RuntimeKeyInfo = (Pointer) runtimeKeyInfo;
1025         else
1026                 indexstate->iss_RuntimeKeyInfo = NULL;
1027
1028         /* ----------------
1029          *      get the range table and direction information
1030          *      from the execution state (these are needed to
1031          *      open the relations).
1032          * ----------------
1033          */
1034         rangeTable = estate->es_range_table;
1035         direction = estate->es_direction;
1036
1037         /* ----------------
1038          *      open the base relation
1039          * ----------------
1040          */
1041         relid = node->scan.scanrelid;
1042         rtentry = rt_fetch(relid, rangeTable);
1043         reloid = rtentry->relid;
1044
1045         ExecOpenScanR(reloid,           /* relation */
1046                                   0,                    /* nkeys */
1047                                   (ScanKey) NULL,               /* scan key */
1048                                   0,                    /* is index */
1049                                   direction,    /* scan direction */
1050                                   estate->es_snapshot,  /* */
1051                                   &currentRelation,             /* return: rel desc */
1052                                   (Pointer *) &currentScanDesc);                /* return: scan desc */
1053
1054         if (!RelationGetForm(currentRelation)->relhasindex)
1055                 elog(ERROR, "indexes of the relation %u was inactivated", reloid);
1056         scanstate->css_currentRelation = currentRelation;
1057         scanstate->css_currentScanDesc = currentScanDesc;
1058
1059
1060         /* ----------------
1061          *      get the scan type from the relation descriptor.
1062          * ----------------
1063          */
1064         ExecAssignScanType(scanstate, RelationGetDescr(currentRelation));
1065         ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
1066
1067         /* ----------------
1068          *      index scans don't have subtrees..
1069          * ----------------
1070          */
1071 /*        scanstate->ss_ProcOuterFlag = false; */
1072
1073         /* ----------------
1074          *      open the index relations and initialize
1075          *      relation and scan descriptors.
1076          * ----------------
1077          */
1078         for (i = 0; i < numIndices; i++)
1079         {
1080                 Oid                     indexOid = (Oid) nthi(i, indxid);
1081
1082                 if (indexOid != 0)
1083                 {
1084                         ExecOpenScanR(indexOid,         /* relation */
1085                                                   numScanKeys[i],               /* nkeys */
1086                                                   scanKeys[i],  /* scan key */
1087                                                   true, /* is index */
1088                                                   direction,    /* scan direction */
1089                                                   estate->es_snapshot,
1090                                                   &(relationDescs[i]),  /* return: rel desc */
1091                                                   (Pointer *) &(scanDescs[i]));
1092                         /* return: scan desc */
1093                 }
1094         }
1095
1096         indexstate->iss_RelationDescs = relationDescs;
1097         indexstate->iss_ScanDescs = scanDescs;
1098
1099         indexstate->cstate.cs_TupFromTlist = false;
1100
1101         /*
1102          * if there are some PARAM_EXEC in skankeys then force index rescan on
1103          * first scan.
1104          */
1105         ((Plan *) node)->chgParam = execParam;
1106
1107         /* ----------------
1108          *      all done.
1109          * ----------------
1110          */
1111         return TRUE;
1112 }
1113
1114 int
1115 ExecCountSlotsIndexScan(IndexScan *node)
1116 {
1117         return ExecCountSlotsNode(outerPlan((Plan *) node)) +
1118         ExecCountSlotsNode(innerPlan((Plan *) node)) + INDEXSCAN_NSLOTS;
1119 }