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