OSDN Git Service

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