home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / executor / n_indexscan.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  47.3 KB  |  1,643 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    indexscan.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    Routines to support indexes and indexed scans of relations
  7.  *
  8.  *   INTERFACE ROUTINES
  9.  *    ExecInsertIndexTuples    inserts tuples into indices on result relation
  10.  *
  11.  *       ExecIndexScan         scans a relation using indices
  12.  *       ExecIndexNext         using index to retrieve next tuple
  13.  *       ExecInitIndexScan    creates and initializes state info. 
  14.  *       ExecIndexReScan        rescans the indexed relation.
  15.  *       ExecEndIndexScan     releases all storage.
  16.  *       ExecIndexMarkPos    marks scan position.
  17.  *       ExecIndexRestrPos    restores scan position.
  18.  *
  19.  *   NOTES
  20.  *    the code supporting ExecInsertIndexTuples should be
  21.  *    collected and merged with the genam stuff.
  22.  *
  23.  *   IDENTIFICATION
  24.  *    $Header: /private/postgres/src/executor/RCS/n_indexscan.c,v 1.15 1992/08/26 19:41:12 mer Exp $
  25.  * ----------------------------------------------------------------
  26.  */
  27.  
  28. #include "tcop/slaves.h"
  29. #include "executor/executor.h"
  30.  
  31.  RcsId("$Header: /private/postgres/src/executor/RCS/n_indexscan.c,v 1.15 1992/08/26 19:41:12 mer Exp $");
  32.  
  33. /* ----------------
  34.  *    Misc stuff to move to executor.h soon -cim 6/5/90
  35.  * ----------------
  36.  */
  37. #define NO_OP        0
  38. #define LEFT_OP        1
  39. #define RIGHT_OP    2
  40.  
  41. /* ----------------------------------------------------------------
  42.  *          ExecInsertIndexTuples support
  43.  * ----------------------------------------------------------------
  44.  */
  45. /* ----------------------------------------------------------------
  46.  *    ExecGetIndexKeyInfo
  47.  *
  48.  *    Extracts the index key attribute numbers from
  49.  *    an index tuple form (i.e. a tuple from the pg_index relation)
  50.  *    into an array of attribute numbers.  The array and the
  51.  *    size of the array are returned to the caller via return
  52.  *    parameters.
  53.  * ----------------------------------------------------------------
  54.  */
  55. /**** xxref:
  56.  *           ExecOpenIndices
  57.  ****/
  58. void
  59. ExecGetIndexKeyInfo(indexTuple, numAttsOutP, attsOutP, fInfoP)
  60.     IndexTupleForm    indexTuple;
  61.     int            *numAttsOutP;
  62.     AttributeNumberPtr    *attsOutP;
  63.     FuncIndexInfoPtr    fInfoP;
  64. {
  65.     int            i;
  66.     int         numKeys;
  67.     AttributeNumberPtr     attKeys;
  68.     
  69.     /* ----------------
  70.      *    check parameters
  71.      * ----------------
  72.      */
  73.     if (numAttsOutP == NULL && attsOutP == NULL) {
  74.     elog(DEBUG, "ExecGetIndexKeyInfo: %s",
  75.          "invalid parameters: numAttsOutP and attsOutP must be non-NULL");
  76.     }
  77.     
  78.     /* ----------------
  79.      * set the procid for a possible functional index.
  80.      * ----------------
  81.      */
  82.     FIsetProcOid(fInfoP, indexTuple->indproc);
  83.  
  84.     /* ----------------
  85.      *    count the number of keys..
  86.      * ----------------
  87.      */
  88.     numKeys = 0;
  89.     for (i=0; i<8 && indexTuple->indkey[i] != 0; i++)
  90.     numKeys++;
  91.     
  92.     /* ----------------
  93.      *    place number keys in callers return area
  94.      *  or the number of arguments for a functional index.
  95.      *
  96.      *  If we have a functional index then the number of 
  97.      *  attributes defined in the index must 1 (the function's 
  98.      *  single return value).
  99.      * ----------------
  100.      */
  101.     if (FIgetProcOid(fInfoP) != InvalidObjectId) {
  102.     FIsetnArgs(fInfoP, numKeys);
  103.     (*numAttsOutP) = 1;
  104.     }
  105.     else
  106.     (*numAttsOutP) = numKeys;
  107.  
  108.     if (numKeys < 1) {
  109.     elog(DEBUG, "ExecGetIndexKeyInfo: %s",
  110.          "all index key attribute numbers are zero!");
  111.     (*attsOutP) = NULL;
  112.     return;
  113.     }
  114.     
  115.     /* ----------------
  116.      *    allocate and fill in array of key attribute numbers
  117.      * ----------------
  118.      */
  119.     CXT1_printf("ExecGetIndexKeyInfo: context is %d\n", CurrentMemoryContext);
  120.     
  121.     attKeys = (AttributeNumberPtr)
  122.     palloc(numKeys * sizeof(AttributeNumber));
  123.     
  124.     for (i=0; i<numKeys; i++)
  125.     attKeys[i] = indexTuple->indkey[i];
  126.     
  127.     /* ----------------
  128.      *    return array to caller.
  129.      * ----------------
  130.      */
  131.     (*attsOutP) = attKeys;
  132. }
  133.  
  134. /* ----------------------------------------------------------------
  135.  *    ExecOpenIndices
  136.  *
  137.  *    Here we scan the pg_index relation to find indices
  138.  *    associated with a given heap relation oid.  Since we
  139.  *    don't know in advance how many indices we have, we
  140.  *    form lists containing the information we need from
  141.  *    pg_index and then process these lists.
  142.  *
  143.  *    Note: much of this code duplicates effort done by
  144.  *    the IndexCatalogInformation function in plancat.c
  145.  *    because IndexCatalogInformation is poorly written.
  146.  *
  147.  *    It would be much better the functionality provided
  148.  *    by this function and IndexCatalogInformation was
  149.  *    in the form of a small set of orthogonal routines..
  150.  *    If you are trying to understand this, I suggest you
  151.  *    look at the code to IndexCatalogInformation and
  152.  *    FormIndexTuple.. -cim 9/27/89
  153.  * ----------------------------------------------------------------
  154.  */
  155. /**** xxref:
  156.  *           InitPlan
  157.  ****/
  158. void
  159. ExecOpenIndices(resultRelationOid, resultRelationInfo)
  160.     ObjectId        resultRelationOid;
  161.     RelationInfo    resultRelationInfo;
  162. {
  163.     Relation        indexRd;
  164.     HeapScanDesc    indexSd;
  165.     ScanKeyData        key;
  166.     HeapTuple        tuple;
  167.     IndexTupleForm    indexStruct;
  168.     ObjectId             indexOid;
  169.     List        oidList;
  170.     List        nkeyList;
  171.     List        keyList;
  172.     List        fiList;
  173.     List        indexoid;
  174.     List        numkeys;
  175.     List        indexkeys;
  176.     List        indexfuncs;
  177.     int            len;
  178.     
  179.     RelationPtr        relationDescs;
  180.     IndexInfoPtr    indexInfoArray;
  181.     FuncIndexInfoPtr    fInfoP;
  182.     int               numKeyAtts;
  183.     AttributeNumberPtr     indexKeyAtts;
  184.     int            i;
  185.     
  186.     /* ----------------
  187.      *    open pg_index
  188.      * ----------------
  189.      */
  190.     indexRd = amopenr(IndexRelationName);
  191.     
  192.     /* ----------------
  193.      *    form a scan key
  194.      * ----------------
  195.      */
  196.     ScanKeyEntryInitialize(&key.data[0], 0, IndexHeapRelationIdAttributeNumber,
  197.                            ObjectIdEqualRegProcedure,
  198.                            ObjectIdGetDatum(resultRelationOid));
  199.     
  200.     /* ----------------
  201.      *    scan the index relation, looking for indices for our
  202.      *  result relation..
  203.      * ----------------
  204.      */
  205.     indexSd = ambeginscan(indexRd,         /* scan desc */
  206.               false,         /* scan backward flag */
  207.               NowTimeQual,         /* time qual */
  208.               1,            /* number scan keys */
  209.               &key);         /* scan keys */
  210.     
  211.     oidList =  LispNil;
  212.     nkeyList = LispNil;
  213.     keyList =  LispNil;
  214.     fiList =   LispNil;
  215.     
  216.     while(tuple = amgetnext(indexSd,         /* scan desc */
  217.                 false,        /* scan backward flag */
  218.                 NULL),            /* return: buffer */
  219.       HeapTupleIsValid(tuple)) {
  220.     
  221.     /* ----------------
  222.      *  For each index relation we find, extract the information
  223.      *  we need and store it in a list..
  224.      * 
  225.      *  first get the oid of the index relation from the tuple
  226.      * ----------------
  227.      */
  228.     indexStruct = (IndexTupleForm) GETSTRUCT(tuple);
  229.     indexOid = indexStruct->indexrelid;
  230.     
  231.     /* ----------------
  232.      * allocate space for functional index information.
  233.      * ----------------
  234.      */
  235.     fInfoP = (FuncIndexInfoPtr)palloc( sizeof(*fInfoP) );
  236.  
  237.     /* ----------------
  238.      *  next get the index key information from the tuple
  239.      * ----------------
  240.      */
  241.     ExecGetIndexKeyInfo(indexStruct,
  242.                 &numKeyAtts,
  243.                 &indexKeyAtts,
  244.                 fInfoP);
  245.     
  246.     /* ----------------
  247.      *  save the index information into lists
  248.      * ----------------
  249.      */
  250.     oidList =  lispCons(lispInteger(indexOid), oidList);
  251.     nkeyList = lispCons(lispInteger(numKeyAtts), nkeyList);
  252.     keyList =  lispCons((LispValue)indexKeyAtts, keyList);
  253.     fiList =   lispCons((LispValue)fInfoP, fiList);
  254.     }
  255.     
  256.     /* ----------------
  257.      *    we have the info we need so close the pg_index relation..
  258.      * ----------------
  259.      */
  260.     amendscan(indexSd);
  261.     amclose(indexRd);
  262.     
  263.     /* ----------------
  264.      *    Now that we've collected the index information into three
  265.      *  lists, we open the index relations and store the descriptors
  266.      *  and the key information into arrays.
  267.      * ----------------
  268.      */
  269.     len = length(oidList);
  270.     if (len > 0) {
  271.     /* ----------------
  272.      *   allocate space for relation descs
  273.      * ----------------
  274.      */
  275.     CXT1_printf("ExecOpenIndices: context is %d\n", CurrentMemoryContext);
  276.     relationDescs = (RelationPtr)
  277.         palloc(len * sizeof(Relation));
  278.     
  279.     /* ----------------
  280.      *   initialize index info array
  281.      * ----------------
  282.      */
  283.     CXT1_printf("ExecOpenIndices: context is %d\n", CurrentMemoryContext);
  284.     indexInfoArray = (IndexInfoPtr)
  285.         palloc(len * sizeof(IndexInfo));
  286.     
  287.     for (i=0; i<len; i++)
  288.         indexInfoArray[i] = MakeIndexInfo(0,NULL);
  289.     
  290.     /* ----------------
  291.      *   attempt to open each of the indices.  If we succeed,
  292.      *   then store the index relation descriptor into the
  293.      *   relation descriptor array.
  294.      * ----------------
  295.      */
  296.     i = 0;
  297.     foreach (indexoid, oidList) {
  298.         Relation  indexDesc;
  299.         
  300.         indexOid =  CInteger(CAR(indexoid));
  301.         indexDesc = AMopen(indexOid);
  302.         if (indexDesc != NULL)
  303.         relationDescs[i++] = indexDesc;
  304.     }
  305.     
  306.     /* ----------------
  307.      *   store the relation descriptor array and number of
  308.      *   descs into the result relation info.
  309.      * ----------------
  310.      */
  311.     set_ri_NumIndices(resultRelationInfo, i);
  312.     set_ri_IndexRelationDescs(resultRelationInfo, relationDescs);
  313.     
  314.     /* ----------------
  315.      *   store the index key information collected in our
  316.      *   lists into the index info array
  317.      * ----------------
  318.      */
  319.     i = 0;
  320.     foreach (numkeys, nkeyList) {
  321.         numKeyAtts = CInteger(CAR(numkeys));
  322.         set_ii_NumKeyAttributes(indexInfoArray[i++], numKeyAtts);
  323.     }
  324.     
  325.     i = 0;
  326.     foreach (indexkeys, keyList) {
  327.         indexKeyAtts = (AttributeNumberPtr) CAR(indexkeys);
  328.         set_ii_KeyAttributeNumbers(indexInfoArray[i++], indexKeyAtts);
  329.     }
  330.     
  331.     i = 0;
  332.     foreach (indexfuncs, fiList) {
  333.         FuncIndexInfoPtr fiP = (FuncIndexInfoPtr)CAR(indexfuncs);
  334.         set_ii_FuncIndexInfo(indexInfoArray[i++], fiP);
  335.     }
  336.     /* ----------------
  337.      *   store the index info array into relation info
  338.      * ----------------
  339.      */
  340.     set_ri_IndexRelationInfo(resultRelationInfo, indexInfoArray);
  341.     }
  342.     
  343.     /* ----------------
  344.      *    All done,  resultRelationInfo now contains complete information
  345.      *  on the indices associated with the result relation.
  346.      * ----------------
  347.      */
  348.     
  349.     /* should free oidList, nkeyList and keyList here */
  350. }
  351.  
  352. /* ----------------------------------------------------------------
  353.  *    ExecCloseIndices
  354.  *
  355.  *    Close the index relations stored in resultRelationInfo
  356.  * ----------------------------------------------------------------
  357.  */
  358.  
  359. /**** xxref:
  360.  *           EndPlan
  361.  ****/
  362. void
  363. ExecCloseIndices(resultRelationInfo)
  364.     RelationInfo    resultRelationInfo;
  365. {
  366.     int     i;
  367.     int     numIndices;
  368.     RelationPtr    relationDescs;
  369.     
  370.     numIndices = get_ri_NumIndices(resultRelationInfo);
  371.     relationDescs = get_ri_IndexRelationDescs(resultRelationInfo);
  372.     
  373.     for (i=0; i<numIndices; i++)
  374.     if (relationDescs[i] != NULL)
  375.         AMclose(relationDescs[i]);
  376.     /*
  377.      * XXX should free indexInfo array here too.
  378.      */
  379. }
  380.  
  381. /* ----------------------------------------------------------------
  382.  *    ExecFormIndexTuple
  383.  *
  384.  *    Most of this code is cannabilized from DefaultBuild().
  385.  *    As said in the comments for ExecOpenIndices, most of
  386.  *    this functionality should be rearranged into a proper
  387.  *    set of routines..
  388.  * ----------------------------------------------------------------
  389.  */
  390. /**** xxref:
  391.  *           ExecInsertIndexTuples
  392.  ****/
  393. IndexTuple
  394. ExecFormIndexTuple(heapTuple, heapRelation, indexRelation, indexInfo)
  395.     HeapTuple    heapTuple;
  396.     Relation    heapRelation;
  397.     Relation    indexRelation;
  398.     IndexInfo    indexInfo;
  399. {
  400.     IndexTuple        indexTuple;
  401.     TupleDescriptor    heapDescriptor;
  402.     TupleDescriptor    indexDescriptor;
  403.     Datum        *datum;
  404.     char        *nulls;
  405.     
  406.     int            numberOfAttributes;
  407.     AttributeNumberPtr  keyAttributeNumbers;
  408.     FuncIndexInfoPtr    fInfoP;
  409.     
  410.     /* ----------------
  411.      *    get information from index info structure
  412.      * ----------------
  413.      */
  414.     numberOfAttributes =  get_ii_NumKeyAttributes(indexInfo);
  415.     keyAttributeNumbers = get_ii_KeyAttributeNumbers(indexInfo);
  416.     fInfoP =              get_ii_FuncIndexInfo(indexInfo);
  417.     
  418.     /* ----------------
  419.      *    datum and null are arrays in which we collect the index attributes
  420.      *  when forming a new index tuple.
  421.      * ----------------
  422.      */
  423.     CXT1_printf("ExecFormIndexTuple: context is %d\n", CurrentMemoryContext);
  424.     datum = (Datum *)    palloc(numberOfAttributes * sizeof *datum);
  425.     nulls =  (char *)    palloc(numberOfAttributes * sizeof *nulls);
  426.     
  427.     /* ----------------
  428.      *    get the tuple descriptors from the relations so we know
  429.      *  how to form the index tuples..
  430.      * ----------------
  431.      */
  432.     heapDescriptor =  RelationGetTupleDescriptor(heapRelation);
  433.     indexDescriptor = RelationGetTupleDescriptor(indexRelation);
  434.     
  435.     /* ----------------
  436.      *  FormIndexDatum fills in its datum and null parameters
  437.      *  with attribute information taken from the given heap tuple.
  438.      * ----------------
  439.      */
  440.     FormIndexDatum(numberOfAttributes,  /* num attributes */
  441.            keyAttributeNumbers,    /* array of att nums to extract */
  442.            heapTuple,            /* tuple from base relation */
  443.            heapDescriptor,    /* heap tuple's descriptor */
  444.            InvalidBuffer,    /* buffer associated with heap tuple */
  445.            datum,        /* return: array of attributes */
  446.            nulls,        /* return: array of char's */
  447.            fInfoP);        /* functional index information */
  448.     
  449.     indexTuple = FormIndexTuple(numberOfAttributes,
  450.                 indexDescriptor,
  451.                 datum,
  452.                 nulls);
  453.     
  454.     /* ----------------
  455.      *    free temporary arrays
  456.      *
  457.      *  XXX should store these in the IndexInfo instead of allocating
  458.      *     and freeing on every insertion, but efficency here is not
  459.      *     that important and FormIndexTuple is wasteful anyways..
  460.      *     -cim 9/27/89
  461.      * ----------------
  462.      */
  463.     pfree(nulls);
  464.     pfree(datum);
  465.     
  466.     return indexTuple;
  467. }
  468.  
  469. /* ----------------------------------------------------------------
  470.  *    ExecInsertIndexTuples
  471.  *
  472.  *    This routine takes care of inserting index tuples
  473.  *    into all the relations indexing the result relation
  474.  *    when a heap tuple is inserted into the result relation.
  475.  *    Much of this code should be moved into the genam
  476.  *    stuff as it only exists here because the genam stuff
  477.  *    doesn't provide the functionality needed by the
  478.  *    executor.. -cim 9/27/89
  479.  * ----------------------------------------------------------------
  480.  */
  481.  
  482. /**** xxref:
  483.  *           ExecAppend
  484.  *           ExecReplace
  485.  ****/
  486. RuleLock
  487. ExecInsertIndexTuples(heapTuple, tupleid, estate)
  488.     HeapTuple        heapTuple;
  489.     ItemPointer     tupleid;
  490.     EState        estate;
  491. {
  492.     RelationInfo            resultRelationInfo;
  493.     int             i;
  494.     int             numIndices;
  495.     RelationPtr                relationDescs;
  496.     Relation            heapRelation;
  497.     IndexInfoPtr        indexInfoArray;
  498.     IndexTuple                 indexTuple;
  499.     GeneralInsertIndexResult     result;
  500.     
  501.     /* ----------------
  502.      *    get information from the result relation info structure.
  503.      * ----------------
  504.      */
  505.     resultRelationInfo = get_es_result_relation_info(estate);
  506.     numIndices =         get_ri_NumIndices(resultRelationInfo);
  507.     relationDescs =      get_ri_IndexRelationDescs(resultRelationInfo);
  508.     indexInfoArray =     get_ri_IndexRelationInfo(resultRelationInfo);
  509.     heapRelation =       get_ri_RelationDesc(resultRelationInfo);
  510.     
  511.     /* ----------------
  512.      *    for each index, form and insert the index tuple
  513.      * ----------------
  514.      */
  515.     for (i=0; i<numIndices; i++) {
  516.     if (relationDescs[i] != NULL) {
  517.         
  518.         indexTuple = ExecFormIndexTuple(heapTuple,
  519.                         heapRelation,
  520.                         relationDescs[i],
  521.                         indexInfoArray[i]);
  522.         
  523.         indexTuple->t_tid = (*tupleid);     /* structure assignment */
  524.         
  525.         result = AMinsert(relationDescs[i], /* index relation */
  526.                   indexTuple,     /* index tuple */
  527.                   0,        /* scan (not used) */
  528.                   0);        /* return: offset */
  529.         
  530.         /* XXX should inspect result for locks */
  531.         
  532.         /* ----------------
  533.          *    keep track of index inserts for debugging
  534.          * ----------------
  535.          */
  536.         IncrIndexInserted();
  537.         
  538.         /* ----------------
  539.          *    free index tuple after insertion
  540.          * ----------------
  541.          */
  542.         pfree(indexTuple);
  543.     }
  544.     }
  545.     
  546.     /* ----------------
  547.      *    return rule locks from insertion.. (someday)
  548.      * ----------------
  549.      */
  550.     return NULL;
  551. }
  552.  
  553. /* ----------------------------------------------------------------
  554.  *            index scan support
  555.  * ----------------------------------------------------------------
  556.  */
  557.  
  558. /* ----------------------------------------------------------------
  559.  *       IndexNext
  560.  *
  561.  *    Retrieve a tuple from the IndexScan node's currentRelation
  562.  *    using the indices in the IndexScanState information.
  563.  *
  564.  *    note: the old code mentions 'Primary indices'.  to my knowledge
  565.  *    we only support a single secondary index. -cim 9/11/89
  566.  *
  567.  * old comments:
  568.  *       retrieve a tuple from relation using the indices given.
  569.  *       The indices are used in the order they appear in 'indices'.
  570.  *       The indices may be primary or secondary indices:
  571.  *         * primary index --     scan the relation 'relID' using keys supplied.
  572.  *         * secondary index --     scan the index relation to get the 'tid' for
  573.  *                          a tuple in the relation 'relID'.
  574.  *       If the current index(pointed by 'indexPtr') fails to return a
  575.  *       tuple, the next index in the indices is used.
  576.  *   
  577.  *        bug fix so that it should retrieve on a null scan key.
  578.  * ----------------------------------------------------------------
  579.  */
  580. /**** xxref:
  581.  *           UseNextIndex
  582.  ****/
  583. TupleTableSlot
  584. IndexNext(node)
  585.     IndexScan node;
  586. {
  587.     EState               estate;
  588.     ScanState               scanstate;
  589.     IndexScanState         indexstate;
  590.     ScanDirection          direction;
  591.     int                   indexPtr;
  592.     IndexScanDescPtr         scanDescs;
  593.     IndexScanDesc          scandesc;
  594.     Relation               heapRelation;
  595.     GeneralRetrieveIndexResult  result;
  596.     ItemPointer               iptr;
  597.     HeapTuple               tuple;
  598.     TupleTableSlot        returnTuple;
  599.     TupleTableSlot        slot;
  600.     Buffer            buffer = InvalidBuffer;
  601.     
  602.     /* ----------------
  603.      *    extract necessary information from index scan node
  604.      * ----------------
  605.      */
  606.     estate =         (EState) get_state((Plan) node);
  607.     direction =      get_es_direction(estate);
  608.     scanstate =      get_scanstate((Scan) node);
  609.     indexstate =     get_indxstate(node);
  610.     indexPtr =       get_iss_IndexPtr(indexstate);
  611.     scanDescs =     get_iss_ScanDescs(indexstate);
  612.     scandesc =      scanDescs[ indexPtr ];
  613.     heapRelation =    get_css_currentRelation((CommonScanState) scanstate);
  614.     
  615.     slot = (TupleTableSlot)
  616.     get_css_ScanTupleSlot((CommonScanState) scanstate);
  617.     
  618.     /* ----------------
  619.      *    ok, now that we have what we need, fetch an index tuple.
  620.      * ----------------
  621.      */
  622.     
  623.     for(;;) {
  624.     result = AMgettuple(scandesc, direction);
  625.     /* ----------------
  626.      *  if scanning this index succeeded then return the
  627.      *  appropriate heap tuple.. else return LispNil.
  628.      * ----------------
  629.      */
  630.     if (GeneralRetrieveIndexResultIsValid(result)) {
  631.         iptr =  GeneralRetrieveIndexResultGetHeapItemPointer(result);
  632.         tuple = heap_fetch(heapRelation,
  633.                    NowTimeQual,
  634.                    iptr,
  635.                    &buffer);
  636.         /* be tidy */
  637.         pfree(result);
  638.  
  639.         if (tuple == NULL) {
  640.         /* ----------------
  641.          *   we found a deleted tuple, so keep on scanning..
  642.          * ----------------
  643.          */
  644.         if (BufferIsValid(buffer))
  645.             ReleaseBuffer(buffer);
  646.         continue;
  647.         }
  648.  
  649.         /* ----------------
  650.          *    store the scanned tuple in the scan tuple slot of
  651.          *  the scan state.  Eventually we will only do this and not
  652.          *  return a tuple.  Note: we pass 'false' because tuples
  653.          *  returned by amgetnext are pointers onto disk pages and
  654.          *  were not created with palloc() and so should not be pfree()'d.
  655.          * ----------------
  656.          */
  657.         ExecStoreTuple((Pointer) tuple,      /* tuple to store */
  658.                (Pointer) slot,       /* slot to store in */
  659.                buffer,       /* buffer associated with tuple  */
  660.                false);         /* don't pfree */
  661.         
  662.         return slot;
  663.     }
  664.     
  665.     /* ----------------
  666.      *  if we get here it means the index scan failed so we
  667.      *  are at the end of the scan..
  668.      * ----------------
  669.      */
  670.     return (TupleTableSlot)
  671.         ExecClearTuple((Pointer) slot);
  672.     }
  673. }
  674.  
  675. /* ----------------------------------------------------------------
  676.  *    ExecIndexScan(node)
  677.  *
  678.  * old comments:
  679.  *       Scans the relation using primary or secondary indices and returns 
  680.  *         the next qualifying tuple in the direction specified.
  681.  *       It calls ExecScan() and passes it the access methods which returns
  682.  *       the next tuple using the indices.
  683.  *       
  684.  *       Conditions:
  685.  *         -- the "cursor" maintained by the AMI is positioned at the tuple
  686.  *            returned previously.
  687.  *   
  688.  *       Initial States:
  689.  *         -- the relation indicated is opened for scanning so that the 
  690.  *            "cursor" is positioned before the first qualifying tuple.
  691.  *         -- all index realtions are opened for scanning.
  692.  *         -- indexPtr points to the first index.
  693.  *         -- state variable ruleFlag = nil.
  694.  * ----------------------------------------------------------------
  695.  */
  696. /**** xxref:
  697.  *           ExecProcNode
  698.  ****/
  699. TupleTableSlot
  700. ExecIndexScan(node)
  701.     IndexScan node;
  702. {
  703.     TupleTableSlot returnTuple;
  704.     
  705.     /* ----------------
  706.      *    use IndexNext as access method
  707.      * ----------------
  708.      */
  709.     returnTuple = ExecScan((Scan) node, (VoidFunctionType)IndexNext);
  710.     return
  711.     returnTuple;
  712. }    
  713.  
  714. /* ----------------------------------------------------------------
  715.  *        ExecIndexReScan(node)
  716.  *
  717.  * old comments
  718.  *        Rescans the indexed relation.
  719.  * ----------------------------------------------------------------
  720.  */
  721. /**** xxref:
  722.  *           ExecReScan
  723.  ****/
  724. List
  725. ExecIndexReScan(node)
  726.     IndexScan node;
  727. {
  728.     EState        estate;
  729.     IndexScanState  indexstate;
  730.     ScanDirection   direction;
  731.     
  732.     IndexScanDescPtr scanDescs;
  733.     ScanKeyPtr        scanKeys;
  734.     IndexScanDesc   sdesc;
  735.     ScanKey        skey;
  736.     int            numIndices;
  737.     int         i;
  738.     
  739.     /* ----------------
  740.      *    get information from the node..
  741.      * ----------------
  742.      */
  743.     estate =     (EState) get_state((Plan) node);
  744.     direction =  get_es_direction(estate);
  745.     
  746.     indexstate = get_indxstate(node);
  747.     numIndices = get_iss_NumIndices(indexstate);
  748.     scanDescs =  get_iss_ScanDescs(indexstate);
  749.     scanKeys =   get_iss_ScanKeys(indexstate);
  750.     
  751.     /* ----------------
  752.      * rescans all indices
  753.      *
  754.      * note: AMrescan assumes only one scan key.  This may have
  755.      *         to change if we ever decide to support multiple keys.
  756.      *         (actually I doubt the thing is even used -cim 9/11/89)
  757.      *
  758.      *      this is actually necessary because the index scan keys are
  759.      *    copied into the scan desc in AMrescan() and when we call
  760.      *    ExecUpdateIndexScanKeys() we create a new set of keys which
  761.      *    have to be copied into the scan desc.
  762.      * ----------------
  763.      */
  764.     for (i = 0; i < numIndices; i++) {
  765.     sdesc = scanDescs[ i ];
  766.     skey =  scanKeys[ i ];
  767.     AMrescan(sdesc, direction, skey);
  768.     }
  769.  
  770.     /* ----------------
  771.      *    perhaps return something meaningful
  772.      * ----------------
  773.      */
  774.     return LispNil;
  775. }
  776.  
  777. /* ----------------------------------------------------------------
  778.  *        ExecEndIndexScan
  779.  *
  780.  * old comments
  781.  *        Releases any storage allocated through C routines.
  782.  *        Returns nothing.
  783.  * ----------------------------------------------------------------
  784.  */
  785. /**** xxref:
  786.  *           ExecEndNode
  787.  ****/
  788. void
  789. ExecEndIndexScan(node)
  790.     IndexScan node;
  791. {
  792.     ScanState            scanstate;
  793.     IndexScanState      indexstate;
  794.     ScanKeyPtr            scanKeys;
  795.     ScanKey            skey;
  796.     int                numIndices;
  797.     int             i;
  798.     AttributeNumberPtr    scanAtts;
  799.     RelationRuleInfo    ruleInfo;
  800.  
  801.     scanstate =  get_scanstate((Scan) node);
  802.     indexstate = get_indxstate(node);
  803.     
  804.     /* ----------------
  805.      *    extract information from the node
  806.      * ----------------
  807.      */
  808.     numIndices = get_iss_NumIndices(indexstate);
  809.     scanKeys =   get_iss_ScanKeys(indexstate);
  810.     scanAtts =     get_cs_ScanAttributes((CommonState) scanstate);
  811.     
  812.     /* ----------------
  813.      * Restore the relation level rule stubs.
  814.      * ----------------
  815.      */
  816.     ruleInfo = get_css_ruleInfo((CommonScanState)scanstate);
  817.     if (ruleInfo != NULL && ruleInfo->relationStubsHaveChanged) {
  818.     ObjectId reloid;
  819.     reloid =
  820.         RelationGetRelationId(
  821.               get_css_currentRelation((CommonScanState)scanstate));
  822.         prs2ReplaceRelationStub(reloid, ruleInfo->relationStubs);
  823.     }
  824.  
  825.     /* ----------------
  826.      *    Free the projection info and the scan attribute info
  827.      *
  828.      *  Note: we don't ExecFreeResultType(scanstate) 
  829.      *        because the rule manager depends on the tupType
  830.      *          returned by ExecMain().  So for now, this
  831.      *          is freed at end-transaction time.  -cim 6/2/91     
  832.      * ----------------
  833.      */    
  834.     ExecFreeProjectionInfo((CommonState)scanstate);
  835.     ExecFreeScanAttributes(scanAtts);
  836.     
  837.     /* ----------------
  838.      *    close the heap and index relations
  839.      * ----------------
  840.      */
  841.     ExecCloseR((Plan) node);
  842.     
  843.     /* ----------------
  844.      *    free the scan keys used in scanning the indices
  845.      * ----------------
  846.      */
  847.     for (i=0; i<numIndices; i++) { 
  848.     skey = scanKeys[ i ];
  849.     ExecFreeSkeys(skey);
  850.     }
  851.  
  852.     /* ----------------
  853.      *    clear out tuple table slots
  854.      * ----------------
  855.      */
  856.     ExecClearTuple((Pointer)
  857.            get_cs_ResultTupleSlot((CommonState)scanstate));    
  858.     ExecClearTuple((Pointer)
  859.            get_css_ScanTupleSlot((CommonScanState)scanstate));    
  860.     ExecClearTuple((Pointer)
  861.            get_css_RawTupleSlot((CommonScanState)scanstate));    
  862. }
  863.  
  864. /* ----------------------------------------------------------------
  865.  *        ExecIndexMarkPos
  866.  *
  867.  * old comments
  868.  *        Marks scan position by marking the current index.
  869.  *        Returns nothing.
  870.  * ----------------------------------------------------------------
  871.  */
  872. /**** xxref:
  873.  *           ExecMarkPos
  874.  ****/
  875. List
  876. ExecIndexMarkPos(node)
  877.     IndexScan node;
  878. {
  879.     IndexScanState    indexstate;
  880.     IndexScanDescPtr    indexScanDescs;
  881.     IndexScanDesc    scanDesc;
  882.     int            indexPtr;
  883.     
  884.     indexstate =     get_indxstate(node);
  885.     indexPtr =       get_iss_IndexPtr(indexstate);
  886.     indexScanDescs = get_iss_ScanDescs(indexstate);
  887.     scanDesc = indexScanDescs[ indexPtr ];
  888.     
  889.     /* ----------------
  890.      *    XXX access methods don't return marked positions so
  891.      *        we return LispNil.
  892.      * ----------------
  893.      */
  894.     IndexScanMarkPosition( scanDesc );
  895.     return LispNil;
  896.     
  897.  /* was:   
  898.   * IndexScanMarkPosition( SGetIScanDesc( SGetIndexID( SGetIndexPtr(node),
  899.   *                               node)));
  900.   */
  901. }
  902.  
  903. /* ----------------------------------------------------------------
  904.  *        ExecIndexRestrPos
  905.  *
  906.  * old comments
  907.  *        Restores scan position by restoring the current index.
  908.  *        Returns nothing.
  909.  *    
  910.  *        XXX Assumes previously marked scan position belongs to current index
  911.  * ----------------------------------------------------------------
  912.  */
  913. /**** xxref:
  914.  *           ExecRestrPos
  915.  ****/
  916. void
  917. ExecIndexRestrPos(node)
  918.     IndexScan node;
  919. {
  920.     IndexScanState    indexstate;
  921.     IndexScanDescPtr    indexScanDescs;
  922.     IndexScanDesc    scanDesc;
  923.     int            indexPtr;
  924.     
  925.     indexstate =     get_indxstate(node);
  926.     indexPtr =       get_iss_IndexPtr(indexstate);
  927.     indexScanDescs = get_iss_ScanDescs(indexstate);
  928.     scanDesc = indexScanDescs[ indexPtr ];
  929.     
  930.     IndexScanRestorePosition( scanDesc );
  931.     
  932.  /* was:
  933.   * IndexScanRestorePosition( SGetIScanDesc( SGetIndexID( SGetIndexPtr(node),
  934.   *                             node)));
  935.   */
  936. }
  937.  
  938. /* ----------------------------------------------------------------
  939.  *    ExecUpdateIndexScanKeys
  940.  *
  941.  *    This recalculates the value of the scan keys whose
  942.  *    value depends on information known at runtime.
  943.  * ----------------------------------------------------------------
  944.  */
  945. /**** xxref:
  946.  *           ExecIndexReScan
  947.  *           ExecNestLoop
  948.  ****/
  949. void
  950. ExecUpdateIndexScanKeys(node, econtext)
  951.     IndexScan    node;
  952.     ExprContext econtext;
  953. {
  954.     IndexScanState    indexstate;
  955.     Pointer        *runtimeKeyInfo;
  956.     
  957.     int                indexPtr;
  958.     ScanKeyPtr            scanKeys;
  959.     IntPtr            numScanKeys;
  960.     
  961.     List            indxqual;
  962.     List        qual;
  963.     int         n_keys;
  964.     ScanKey        scan_keys;
  965.     int            *run_keys;
  966.     int            j;
  967.     
  968.     List        clause;
  969.     Node        scanexpr;
  970.     Const        scanconst;
  971.     Datum        scanvalue;
  972.     Boolean        isNull;
  973.     Boolean        isDone;
  974.     
  975.     /* ----------------
  976.      *    get info from the node
  977.      * ----------------
  978.      */
  979.     indexstate =     get_indxstate(node);
  980.     runtimeKeyInfo =     (Pointer *) get_iss_RuntimeKeyInfo(indexstate);
  981.     
  982.     /* ----------------
  983.      *    if runtimeKeyInfo is null, then it means all our
  984.      *  scan keys are constant so we don't have to recompute
  985.      *  anything.
  986.      * ----------------
  987.      */
  988.     if (runtimeKeyInfo == NULL)
  989.     return;
  990.     
  991.     /* ----------------
  992.      *    otherwise get the index qualifications and
  993.      *  recalculate the appropriate values.
  994.      * ----------------
  995.      */
  996.     indexPtr =        get_iss_IndexPtr(indexstate);
  997.     
  998.     indxqual =         get_indxqual(node);
  999.     qual =        nth(indexPtr, indxqual);
  1000.     
  1001.     scanKeys =      get_iss_ScanKeys(indexstate);
  1002.     numScanKeys =    get_iss_NumScanKeys(indexstate);
  1003.     
  1004.     n_keys =         numScanKeys[ indexPtr ];
  1005.     run_keys =         (int *)   runtimeKeyInfo[ indexPtr ];
  1006.     scan_keys =     (ScanKey) scanKeys[ indexPtr ];
  1007.     
  1008.     for (j=0; j < n_keys; j++) {
  1009.     /* ----------------
  1010.      *   if we have a run-time key, then extract the run-time
  1011.      *   expression and evautate it with respect to the current
  1012.      *   outer tuple.  We then stick the result into the scan
  1013.      *   key.
  1014.      * ----------------
  1015.      */
  1016.     if (run_keys[j] != NO_OP) {
  1017.         clause =    nth(j, qual);
  1018.         
  1019.         scanexpr =  (run_keys[j] == RIGHT_OP) ?
  1020.         (Node) get_rightop(clause) : (Node) get_leftop(clause) ;
  1021.         
  1022.         /* -------------
  1023.          *  Pass in isDone but ignore it.  We don't iterate in quals
  1024.          * -------------
  1025.          */
  1026.         scanvalue = (Datum)
  1027.         ExecEvalExpr(scanexpr, econtext, &isNull, &isDone);
  1028.         
  1029.         ExecSetSkeysValue(j,      /* index into scan_keys array */
  1030.                   scan_keys,  /* array of scan keys */
  1031.                   scanvalue); /* const computed from outerTuple */
  1032.     }
  1033.     }
  1034. }
  1035.  
  1036. /* ----------------------------------------------------------------
  1037.  *        ExecInitIndexScan
  1038.  *
  1039.  *    Initializes the index scan's state information, creates
  1040.  *    scan keys, and opens the base and index relations.
  1041.  *
  1042.  *    Note: index scans have 2 sets of state information because
  1043.  *          we have to keep track of the base relation and the
  1044.  *          index relations.
  1045.  *          
  1046.  * old comments
  1047.  *        Creates the run-time state information for the node and 
  1048.  *        sets the relation id to contain relevant decriptors.
  1049.  *    
  1050.  *        Parameters: 
  1051.  *          node: IndexNode node produced by the planner.
  1052.  *      estate: the execution state initialized in InitPlan.
  1053.  * ----------------------------------------------------------------
  1054.  */
  1055. /**** xxref:
  1056.  *           ExecInitNode
  1057.  ****/
  1058. List
  1059. ExecInitIndexScan(node, estate, parent)
  1060.     IndexScan     node;
  1061.     EState     estate;
  1062.     Plan    parent;
  1063. {
  1064.     IndexScanState      indexstate;
  1065.     ScanState        scanstate;
  1066.     List            indxqual;
  1067.     List            indxid;
  1068.     int            i;
  1069.     int                numIndices;
  1070.     int                indexPtr;
  1071.     ScanKeyPtr            scanKeys;
  1072.     IntPtr            numScanKeys;
  1073.     RelationPtr            relationDescs;
  1074.     IndexScanDescPtr    scanDescs;
  1075.     Pointer        *runtimeKeyInfo;
  1076.     bool        have_runtime_keys;
  1077.     List           rangeTable;
  1078.     List            rtentry;
  1079.     Index            relid;
  1080.     ObjectId           reloid;
  1081.     TimeQual        timeQual;
  1082.     
  1083.     Relation            currentRelation;
  1084.     HeapScanDesc        currentScanDesc;
  1085.     ScanDirection       direction;
  1086.     ParamListInfo       paraminfo;
  1087.     ExprContext            econtext;
  1088.     int            baseid;
  1089.     
  1090.     /* ----------------
  1091.      *    assign execution state to node
  1092.      * ----------------
  1093.      */
  1094.     set_state((Plan) node, (EStatePtr)estate);
  1095.     
  1096.     /* --------------------------------
  1097.      *  Part 1)  initialize scan state
  1098.      *
  1099.      *    create new ScanState for node
  1100.      * --------------------------------
  1101.      */
  1102.     scanstate = MakeScanState(false, 0);
  1103.     set_scanstate((Scan) node, scanstate);
  1104.     
  1105.     /* ----------------
  1106.      *    assign node's base_id .. we don't use AssignNodeBaseid() because
  1107.      *  the increment is done later on after we assign the index scan's
  1108.      *  scanstate.  see below. 
  1109.      * ----------------
  1110.      */
  1111.     baseid = get_es_BaseId(estate);
  1112.     set_base_id((BaseNode) scanstate, baseid);
  1113.     
  1114.     /* ----------------
  1115.      *  create expression context for node
  1116.      * ----------------
  1117.      */
  1118.     ExecAssignExprContext(estate, (CommonState) scanstate);
  1119.  
  1120. #define INDEXSCAN_NSLOTS 3
  1121.     /* ----------------
  1122.      *    tuple table initialization
  1123.      * ----------------
  1124.      */
  1125.     ExecInitResultTupleSlot(estate, (CommonState) scanstate);
  1126.     ExecInitScanTupleSlot(estate, (CommonScanState)scanstate);
  1127.     ExecInitRawTupleSlot(estate, (CommonScanState)scanstate);
  1128.   
  1129.     /* ----------------
  1130.      *     initialize projection info.  result type comes from scan desc
  1131.      *  below..
  1132.      * ----------------
  1133.      */
  1134.     ExecAssignProjectionInfo((Plan) node, (CommonState)scanstate);
  1135.  
  1136.     /* ----------------
  1137.      *    initialize scanAttributes (used by rule manager)
  1138.      * ----------------
  1139.      */
  1140.     ExecInitScanAttributes((Plan) node);
  1141.     
  1142.     /* --------------------------------
  1143.      *  Part 2)  initialize index scan state
  1144.      *
  1145.      *    create new IndexScanState for node
  1146.      * --------------------------------
  1147.      */
  1148.     indexstate = MakeIndexScanState(0, 0, NULL, NULL, NULL, NULL, NULL);
  1149.     set_indxstate(node, indexstate);
  1150.     
  1151.     /* ----------------
  1152.      *    assign base id to index scan state also
  1153.      * ----------------
  1154.      */
  1155.     set_base_id((BaseNode) indexstate, baseid);
  1156.     baseid++;
  1157.     set_es_BaseId(estate, baseid);
  1158.     
  1159.     /* ----------------
  1160.      *    assign debugging hooks
  1161.      * ----------------
  1162.      */
  1163.     ExecAssignDebugHooks((Plan) node, (BaseNode) indexstate);
  1164.             
  1165.     /* ----------------
  1166.      *    get the index node information
  1167.      * ----------------
  1168.      */
  1169.     indxid =     get_indxid(node);
  1170.     indxqual =     get_indxqual(node);
  1171.     numIndices = length(indxid);
  1172.     indexPtr =      0;
  1173.     
  1174.     CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);
  1175.     
  1176.     numScanKeys = (IntPtr)    palloc(numIndices * sizeof(int));
  1177.     scanKeys = (ScanKeyPtr)    palloc(numIndices * sizeof(ScanKey));
  1178.     relationDescs = (RelationPtr) palloc(numIndices * sizeof(Relation));
  1179.     scanDescs =  (IndexScanDescPtr) palloc(numIndices * sizeof(IndexScanDesc));
  1180.     
  1181.     /* ----------------
  1182.      *    initialize runtime key info.
  1183.      * ----------------
  1184.      */
  1185.     have_runtime_keys = false;
  1186.     runtimeKeyInfo = (Pointer *)
  1187.     palloc(numIndices * sizeof(Pointer));
  1188.     
  1189.     /* ----------------
  1190.      *    build the index scan keys from the index qualification
  1191.      * ----------------
  1192.      */
  1193.     for (i=0; i < numIndices; i++) {
  1194.     int         j;
  1195.     List        qual;
  1196.     int         n_keys;
  1197.     ScanKey        scan_keys;
  1198.     int        *run_keys;
  1199.     
  1200.     qual =        nth(i, indxqual);
  1201.     n_keys =     length(qual);
  1202.     scan_keys =    (ScanKey) ExecMakeSkeys(n_keys);
  1203.     
  1204.     CXT1_printf("ExecInitIndexScan: context is %d\n",
  1205.             CurrentMemoryContext);
  1206.     
  1207.     if (n_keys > 0) {
  1208.         run_keys = (int *)    palloc(n_keys * sizeof(int));
  1209.     }
  1210.     
  1211.     /* ----------------
  1212.      *  for each opclause in the given qual,
  1213.      *  convert each qual's opclause into a single scan key
  1214.      * ----------------
  1215.      */
  1216.     for (j=0; j < n_keys; j++) {
  1217.         List    clause;        /* one part of index qual */
  1218.         Oper    op;        /* operator used in scan.. */
  1219.         Node    leftop;        /* expr on lhs of operator */
  1220.         Node    rightop;     /* expr on rhs ... */
  1221.         
  1222.         int        scanvar;     /* which var identifies varattno */
  1223.         int        varattno;     /* att number used in scan */
  1224.         ObjectId    opid;        /* operator id used in scan */
  1225.         Datum    scanvalue;     /* value used in scan (if const) */
  1226.         
  1227.         /* ----------------
  1228.          *    extract clause information from the qualification
  1229.          * ----------------
  1230.          */
  1231.         clause =     nth(j, qual);
  1232.         
  1233.         op = (Oper)  get_op(clause);
  1234.         if (! ExactNodeType(op,Oper))
  1235.         elog(WARN, "ExecInitIndexScan: op not an Oper!");
  1236.         
  1237.         opid = get_opid(op);
  1238.  
  1239.         /* ----------------
  1240.          *  Here we figure out the contents of the index qual.
  1241.          *  The usual case is (op var const) or (op const var)
  1242.          *  which means we form a scan key for the attribute
  1243.          *  listed in the var node and use the value of the const.
  1244.          *
  1245.          *  If we don't have a const node, then it means that
  1246.          *  one of the var nodes refers to the "scan" tuple and
  1247.          *  is used to determine which attribute to scan, and the
  1248.          *  other expression is used to calculate the value used in
  1249.          *  scanning the index.
  1250.          *
  1251.          *  This means our index scan's scan key is a function of
  1252.          *  information obtained during the execution of the plan
  1253.          *  in which case we need to recalculate the index scan key
  1254.          *  at run time.
  1255.          *  
  1256.          *  Hence, we set have_runtime_keys to true and then set
  1257.          *  the appropriate flag in run_keys to LEFT_OP or RIGHT_OP.
  1258.          *  The corresponding scan keys are recomputed at run time.
  1259.          * ----------------
  1260.          */
  1261.  
  1262.         scanvar = NO_OP;
  1263.         
  1264.         /* ----------------
  1265.          *    determine information in leftop
  1266.          * ----------------
  1267.          */
  1268.         leftop =     (Node) get_leftop(clause);
  1269.         
  1270.         if (ExactNodeType(leftop,Var) && var_is_rel(leftop)) {
  1271.         /* ----------------
  1272.          *  if the leftop is a "rel-var", then it means
  1273.          *  that it is a var node which tells us which
  1274.          *  attribute to use for our scan key.
  1275.          * ----------------
  1276.          */
  1277.         varattno =     get_varattno((Var) leftop);
  1278.         scanvar =     LEFT_OP;
  1279.         } else if (ExactNodeType(leftop,Const)) {
  1280.         /* ----------------
  1281.          *  if the leftop is a const node then it means
  1282.          *  it identifies the value to place in our scan key.
  1283.          * ----------------
  1284.          */
  1285.         run_keys[ j ] = NO_OP;
  1286.         scanvalue = get_constvalue((Const) leftop);
  1287.         } else if (consp(leftop) && 
  1288.                ExactNodeType(CAR((List)leftop),Func) &&
  1289.                var_is_rel(CADR((List)leftop))) {
  1290.         /* ----------------
  1291.          *  if the leftop is a func node then it means
  1292.          *  it identifies the value to place in our scan key.
  1293.          *  Since functional indices have only one attribute
  1294.          *  the attno must always be set to 1.
  1295.          * ----------------
  1296.          */
  1297.         varattno =     1;
  1298.         scanvar =     LEFT_OP;
  1299.  
  1300.         } else {
  1301.         /* ----------------
  1302.          *  otherwise, the leftop contains information usable
  1303.          *  at runtime to figure out the value to place in our
  1304.          *  scan key.
  1305.          * ----------------
  1306.          */
  1307.         have_runtime_keys = true;
  1308.         run_keys[ j ] = LEFT_OP;
  1309.         scanvalue = get_constvalue(ConstTrue);
  1310.         }
  1311.  
  1312.         /* ----------------
  1313.          *    now determine information in rightop
  1314.          * ----------------
  1315.          */
  1316.         rightop =     (Node) get_rightop(clause);
  1317.         
  1318.         if (ExactNodeType(rightop,Var) && var_is_rel(rightop)) {
  1319.         /* ----------------
  1320.          *  here we make sure only one op identifies the
  1321.          *  scan-attribute...
  1322.          * ----------------
  1323.          */
  1324.         if (scanvar == LEFT_OP)
  1325.             elog(WARN, "ExecInitIndexScan: %s",
  1326.              "both left and right op's are rel-vars");
  1327.         
  1328.         /* ----------------
  1329.          *  if the rightop is a "rel-var", then it means
  1330.          *  that it is a var node which tells us which
  1331.          *  attribute to use for our scan key.
  1332.          * ----------------
  1333.          */
  1334.         varattno =     get_varattno((Var) rightop);
  1335.         scanvar =     RIGHT_OP;
  1336.         
  1337.         } else if (ExactNodeType(rightop,Const)) {
  1338.         /* ----------------
  1339.          *  if the leftop is a const node then it means
  1340.          *  it identifies the value to place in our scan key.
  1341.          * ----------------
  1342.          */
  1343.         run_keys[ j ] = NO_OP;
  1344.         scanvalue = get_constvalue((Const) rightop);
  1345.  
  1346.         } else if (consp(rightop) &&
  1347.                ExactNodeType(CAR((List)rightop),Func) &&
  1348.                var_is_rel(CADR((List)rightop))) {
  1349.         /* ----------------
  1350.          *  if the rightop is a func node then it means
  1351.          *  it identifies the value to place in our scan key.
  1352.          *  Since functional indices have only one attribute
  1353.          *  the attno must always be set to 1.
  1354.          * ----------------
  1355.          */
  1356.         if (scanvar == LEFT_OP)
  1357.             elog(WARN, "ExecInitIndexScan: %s",
  1358.              "both left and right ops are rel-vars");
  1359.  
  1360.         varattno =     1;
  1361.         scanvar =     RIGHT_OP;
  1362.  
  1363.         } else {
  1364.         /* ----------------
  1365.          *  otherwise, the leftop contains information usable
  1366.          *  at runtime to figure out the value to place in our
  1367.          *  scan key.
  1368.          * ----------------
  1369.          */
  1370.         have_runtime_keys = true;
  1371.         run_keys[ j ] = RIGHT_OP;
  1372.         scanvalue = get_constvalue(ConstTrue);
  1373.         }
  1374.  
  1375.         /* ----------------
  1376.          *    now check that at least one op tells us the scan
  1377.          *  attribute...
  1378.          * ----------------
  1379.          */
  1380.         if (scanvar == NO_OP) 
  1381.         elog(WARN, "ExecInitIndexScan: %s",
  1382.              "neither leftop nor rightop refer to scan relation");
  1383.         
  1384.         /* ----------------
  1385.          *    initialize the scan key's fields appropriately
  1386.          *
  1387.          * XXX UGLY, UGLY, UGLY cast here. scan_keys is an array of
  1388.          * pointers to ScanKeyData structs and the macro first
  1389.          * dereferences then takes address of it and passes this
  1390.          * off as a ScanKeyEntry. It works but its not right.
  1391.          * -- mer 16 Nov. 1991
  1392.          * ----------------
  1393.          */
  1394.         ExecSetSkeys(j,        /* index into scan_keys array */
  1395.                     /* array in which to plug scan key */
  1396.              (ScanKeyEntry)scan_keys,
  1397.                      /* attribute number to scan */
  1398.              (AttributeNumber) varattno,
  1399.              (RegProcedure) opid,        /* reg proc to use */
  1400.              (Datum) scanvalue);        /* constant */
  1401.     }
  1402.     
  1403.     /* ----------------
  1404.      *  store the key information into our array.
  1405.      * ----------------
  1406.      */
  1407.     numScanKeys[ i ] =     n_keys;
  1408.     scanKeys[ i ] =     scan_keys;
  1409.     runtimeKeyInfo[ i ] =   (Pointer) run_keys;
  1410.     }
  1411.     
  1412.     set_iss_NumIndices(indexstate, numIndices);
  1413.     set_iss_IndexPtr(indexstate, indexPtr);
  1414.     set_iss_ScanKeys(indexstate, scanKeys);
  1415.     set_iss_NumScanKeys(indexstate, numScanKeys);
  1416.     
  1417.     /* ----------------
  1418.      *    If all of our keys have the form (op var const) , then we have no
  1419.      *  runtime keys so we store NULL in the runtime key info.
  1420.      *  Otherwise runtime key info contains an array of pointers
  1421.      *  (one for each index) to arrays of flags (one for each key)
  1422.      *  which indicate that the qual needs to be evaluated at runtime.
  1423.      *  -cim 10/24/89
  1424.      * ----------------
  1425.      */
  1426.     if (have_runtime_keys)
  1427.     {
  1428.     set_iss_RuntimeKeyInfo(indexstate, (Pointer) runtimeKeyInfo);
  1429.     }
  1430.     else {
  1431.     set_iss_RuntimeKeyInfo(indexstate, NULL);
  1432.     for (i=0; i < numIndices; i++) {
  1433.         List qual;
  1434.         int n_keys;
  1435.         qual = nth(i, indxqual);
  1436.         n_keys = length(qual);
  1437.         if (n_keys > 0)
  1438.             pfree(runtimeKeyInfo[i]);
  1439.       }
  1440.     pfree(runtimeKeyInfo);
  1441.     }
  1442.     
  1443.     /* ----------------
  1444.      *    get the range table and direction information
  1445.      *  from the execution state (these are needed to
  1446.      *  open the relations).
  1447.      * ----------------
  1448.      */
  1449.     rangeTable = get_es_range_table(estate);
  1450.     direction =  get_es_direction(estate);
  1451.     
  1452.     /* ----------------
  1453.      *    open the base relation
  1454.      * ----------------
  1455.      */
  1456.     relid =   get_scanrelid((Scan) node);
  1457.     rtentry = rt_fetch(relid, rangeTable);
  1458.     reloid =  CInteger(rt_relid(rtentry));
  1459.     timeQual = (TimeQual) CInteger(rt_time(rtentry));
  1460.     
  1461.     ExecOpenScanR(reloid,          /* relation */
  1462.           0,              /* nkeys */
  1463.           (ScanKey) NULL,     /* scan key */
  1464.           0,              /* is index */
  1465.           direction,          /* scan direction */
  1466.           timeQual,          /* time qual */
  1467.           ¤tRelation,   /* return: rel desc */
  1468.           (Pointer *) ¤tScanDesc);  /* return: scan desc */
  1469.     
  1470.     set_css_currentRelation((CommonScanState) scanstate, currentRelation);
  1471.     set_css_currentScanDesc((CommonScanState)scanstate, currentScanDesc);
  1472.     /*
  1473.      * intialize scan state rule info
  1474.      */
  1475.     set_css_ruleInfo((CommonScanState)scanstate,
  1476.         prs2MakeRelationRuleInfo(currentRelation, RETRIEVE));
  1477.  
  1478.  
  1479.     /* ----------------
  1480.      *    XXX temporary hack to prevent tuple level locks
  1481.      *      from exhausting our semaphores.   Remove this
  1482.      *        when the tuple level lock stuff is fixed.
  1483.      * ----------------
  1484.      */
  1485.     RelationSetLockForRead(currentRelation);
  1486.     
  1487.     /* ----------------
  1488.      *    get the scan type from the relation descriptor.
  1489.      * ----------------
  1490.      */
  1491.     ExecAssignScanType((CommonScanState)scanstate,
  1492.                TupDescToExecTupDesc(¤tRelation->rd_att,
  1493.                     currentRelation->rd_rel->relnatts),
  1494.                ¤tRelation->rd_att); /* bug -- glass */
  1495.     ExecAssignResultTypeFromTL((Plan) node, (CommonState)scanstate);
  1496.     
  1497.     /* ----------------
  1498.      *    index scans don't have subtrees..
  1499.      * ----------------
  1500.      */
  1501.     set_ss_ProcOuterFlag(scanstate, false);
  1502.     
  1503.     /* ----------------
  1504.      *    open the index relations and initialize
  1505.      *  relation and scan descriptors.
  1506.      * ----------------
  1507.      */
  1508.     for (i=0; i < numIndices; i++) {
  1509.     List     index;
  1510.     ObjectId indexOid;
  1511.     
  1512.     index =     nth(i, indxid);
  1513.     indexOid =  CInteger(index);
  1514.     
  1515.     if (indexOid != 0) {
  1516.         ExecOpenScanR(indexOid,           /* relation */
  1517.               numScanKeys[ i ],      /* nkeys */
  1518.               scanKeys[ i ],      /* scan key */
  1519.               true,              /* is index */
  1520.               direction,          /* scan direction */
  1521.               timeQual,           /* time qual */
  1522.               &(relationDescs[ i ]),  /* return: rel desc */
  1523.               (Pointer *) &(scanDescs[ i ]));
  1524.                                               /* return: scan desc */
  1525.     }
  1526.     }
  1527.     
  1528.     set_iss_RelationDescs(indexstate, relationDescs);
  1529.     if (ParallelExecutorEnabled() && SlaveLocalInfoD.nparallel > 1)
  1530.        partition_indexscan(numIndices, scanDescs, SlaveLocalInfoD.nparallel);
  1531.     set_iss_ScanDescs(indexstate, scanDescs);
  1532.     
  1533.     set_cs_TupFromTlist((CommonState)indexstate, false);
  1534.  
  1535.     /* ----------------
  1536.      *    all done.
  1537.      * ----------------
  1538.      */
  1539.     return
  1540.     LispTrue;
  1541. }
  1542.  
  1543. int
  1544. ExecCountSlotsIndexScan(node)
  1545.     Plan node;
  1546. {
  1547.     return ExecCountSlotsNode(get_outerPlan(node)) +
  1548.        ExecCountSlotsNode(get_innerPlan(node)) +
  1549.        INDEXSCAN_NSLOTS;
  1550. }
  1551.  
  1552. /* ---------------------------------------------------------
  1553.  *    partition_indexscan
  1554.  *
  1555.  *    XXXXXX this function now only works for indexes on
  1556.  *    int2 and int4 and does handle skewed data distribution.
  1557.  *    more elaborate schemes will be implemented later.
  1558.  *
  1559.  * --------------------------------------------------------
  1560.  */
  1561.  
  1562. #define INT4LT  66
  1563. #define INT4LE  149
  1564. #define INT4GT  147
  1565. #define INT4GE  150
  1566. #define INT2LT  64
  1567. #define INT2LE  148
  1568. #define INT2GT  146
  1569. #define INT2GE  151
  1570.  
  1571. void
  1572. partition_indexscan(numIndices, scanDescs, parallel)
  1573.     int                     numIndices;
  1574.     IndexScanDescPtr        scanDescs;
  1575.     int                     parallel;
  1576. {
  1577.     int         i;
  1578.     IndexScanDesc     scanDesc;
  1579.     ScanKeyEntryData     lowKeyEntry;
  1580.     ScanKeyEntryData     highKeyEntry;
  1581.     int32         lowKey, newlowkey;
  1582.     int32         highKey, newhighkey;
  1583.     int         delt;
  1584.  
  1585.     for (i=0; i<numIndices; i++) {
  1586.         scanDesc = scanDescs[i];
  1587.         if (scanDesc->numberOfKeys < 2) {
  1588.        /* -------------------------------------
  1589.         *  don't know how to partition, just return
  1590.         * -------------------------------------
  1591.         */
  1592.            return;
  1593.        }
  1594.         lowKeyEntry = scanDesc->keyData.data[0];
  1595.     
  1596.         switch (lowKeyEntry.procedure) {
  1597.         case INT4GT:
  1598.         case INT4GE:
  1599.            highKeyEntry = scanDesc->keyData.data[1];
  1600.            break;
  1601.        
  1602.         case INT4LT:
  1603.         case INT4LE:
  1604.            highKeyEntry = lowKeyEntry;
  1605.            lowKeyEntry = scanDesc->keyData.data[1];
  1606.            break;
  1607.        
  1608.         defaults:
  1609.        /* -------------------------------------
  1610.         *  don't know how to partition, just return
  1611.         * -------------------------------------
  1612.         */
  1613.            return;
  1614.         }
  1615.     
  1616.         lowKey = DatumGetInt32(lowKeyEntry.argument);
  1617.         highKey = DatumGetInt32(highKeyEntry.argument);
  1618.         delt = highKey - lowKey;
  1619.     
  1620.         Assert(delt > 0);
  1621.     
  1622.         newlowkey = lowKey + SlaveInfoP[MyPid].groupPid * delt / parallel;
  1623.         newhighkey = lowKey + (SlaveInfoP[MyPid].groupPid + 1) * delt/parallel;
  1624.     
  1625.         lowKeyEntry.argument = Int32GetDatum(newlowkey);
  1626.     
  1627.         if (SlaveInfoP[MyPid].groupPid > 0) {
  1628.            lowKeyEntry.procedure = INT4GE;
  1629.        fmgr_info(INT4GE, &lowKeyEntry.func, &lowKeyEntry.nargs);
  1630.       }
  1631.     
  1632.         highKeyEntry.argument = Int32GetDatum(newhighkey);
  1633.     
  1634.         if (SlaveInfoP[MyPid].groupPid < parallel - 1) {
  1635.            highKeyEntry.procedure = INT4LT;
  1636.        fmgr_info(INT4LT, &highKeyEntry.func, &highKeyEntry.nargs);
  1637.       }
  1638.     
  1639.         scanDesc->keyData.data[0] = lowKeyEntry;
  1640.         scanDesc->keyData.data[1] = highKeyEntry;
  1641.       }
  1642. }
  1643.