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

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    seqscan.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    Support routines for sequential scans of relations.
  7.  *
  8.  *   INTERFACE ROUTINES
  9.  *       ExecSeqScan        sequentially scans a relation.
  10.  *        ExecSeqNext         retrieve next tuple in sequential order.
  11.  *       ExecInitSeqScan     creates and initializes a seqscan node.
  12.  *       ExecEndSeqScan        releases any storage allocated.
  13.  *       ExecSeqReScan        rescans the relation
  14.  *       ExecMarkPos        marks scan position
  15.  *       ExecRestrPos        restores scan position
  16.  *
  17.  *   NOTES
  18.  *    
  19.  *   IDENTIFICATION
  20.  *    $Header: /private/postgres/src/executor/RCS/n_seqscan.c,v 1.10 1992/08/04 17:38:02 mer Exp $
  21.  * ----------------------------------------------------------------
  22.  */
  23.  
  24. #include "tcop/slaves.h"
  25. #include "executor/executor.h"
  26.  
  27.  RcsId("$Header: /private/postgres/src/executor/RCS/n_seqscan.c,v 1.10 1992/08/04 17:38:02 mer Exp $");
  28.  
  29. /* ----------------------------------------------------------------
  30.  *               Scan Support
  31.   * ----------------------------------------------------------------
  32.  */
  33. /* ----------------------------------------------------------------
  34.  *    SeqNext
  35.  *
  36.  *|    This is a workhorse for ExecSeqScan
  37.  * ----------------------------------------------------------------
  38.  */
  39. /**** xxref:
  40.  *           <apparently-unused>
  41.  ****/
  42. TupleTableSlot
  43. SeqNext(node)
  44.     SeqScan node;
  45. {
  46.     HeapTuple         tuple;
  47.     HeapScanDesc      scandesc;
  48.     ScanState         scanstate;
  49.     EState         estate;
  50.     ScanDirection    direction;
  51.     TupleTableSlot    slot;
  52.     Buffer        buffer;
  53.     
  54.     /* ----------------
  55.      *    get information from the estate and scan state
  56.      * ----------------
  57.      */
  58.     estate =        (EState) get_state((Plan)node);
  59.     scanstate =     get_scanstate((Scan) node);
  60.     scandesc =      get_css_currentScanDesc((CommonScanState)scanstate);
  61.     direction =     get_es_direction(estate);
  62.  
  63.     /* ----------------
  64.      *    get the next tuple from the access methods
  65.      * ----------------
  66.      */
  67.     tuple = heap_getnext(scandesc,            /* scan desc */
  68.              (direction == EXEC_BKWD), /* backward flag */
  69.              &buffer);                /* return: buffer */
  70.  
  71.     /* ----------------
  72.      *    save the tuple and the buffer returned to us by the access methods
  73.      *  in our scan tuple slot and return the slot.  Note: we pass 'false'
  74.      *  because tuples returned by heap_getnext() are pointers onto
  75.      *  disk pages and were not created with palloc() and so should not
  76.      *  be pfree()'d.
  77.      * ----------------
  78.      */
  79.     slot = (TupleTableSlot)
  80.     get_css_ScanTupleSlot((CommonScanState) scanstate);
  81.  
  82.     slot = (TupleTableSlot)
  83.     ExecStoreTuple((Pointer) tuple,  /* tuple to store */
  84.                (Pointer) slot,   /* slot to store in */
  85.                buffer, /* buffer associated with this tuple */
  86.                false); /* don't pfree this pointer */
  87.     
  88.     /* ----------------
  89.      *  XXX -- mao says:  The sequential scan for heap relations will
  90.      *  automatically unpin the buffer this tuple is on when we cross
  91.      *  a page boundary.  The clearslot code also does this.  We bump
  92.      *  the pin count on the page here, since we actually have two
  93.      *  pointers to it -- one in the scan desc and one in the tuple
  94.      *  table slot.  --mar 20 91
  95.      * ----------------
  96.      */
  97.     ExecIncrSlotBufferRefcnt((Pointer) slot);
  98.  
  99.     return slot;
  100. }
  101.  
  102. /* ----------------------------------------------------------------
  103.  *    ExecSeqScan(node)
  104.  *
  105.  * old comments
  106.  *       Scans the realtion sequentially and returns the next qualifying 
  107.  *       tuple in the direction specified in  execDireciton.
  108.  *       It calls the ExecScan() routine ans passes it the access method
  109.  *       which retrieve tuples sequentially.
  110.  *   
  111.  *       Conditions:
  112.  *         -- the "cursor" maintained by the AMI is positioned at the tuple
  113.  *            returned previously.
  114.  *   
  115.  *       Initial States:
  116.  *         -- the relation indicated is opened for scanning so that the 
  117.  *            "cursor" is positioned before the first qualifying tuple.
  118.  *         -- state variable ruleFlag = nil.
  119.  *
  120.  *    uses SeqNext() as access method
  121.  *
  122.  *    XXX
  123.  *    fix buffer-page stuff. probably put something in state node
  124.  *    sequential scan calling AMI's getnext
  125.  *
  126.  * ----------------------------------------------------------------
  127.  */
  128. #define DEBUG_ExecSeqScan_1 \
  129.     S_printf("ExecSeqScan: scanning node: "); \
  130.     S_lispDisplay(node)
  131.  
  132. #define DEBUG_ExecSeqScan_2 \
  133.     S1_printf("ExecSeqScan: returned tuple slot: %d\n", slot)
  134.  
  135. /**** xxref:
  136.  *           ExecProcNode
  137.  ****/
  138. TupleTableSlot
  139. ExecSeqScan(node)
  140.     SeqScan node;
  141. {
  142.     TupleTableSlot    slot;
  143.     ScanState        scanstate;
  144.     bool        procOuterFlag;
  145.     Plan          outerPlan;
  146.     
  147.     DEBUG_ExecSeqScan_1;
  148.     
  149.     /* ----------------
  150.      *    get information from node
  151.      * ----------------
  152.      */
  153.     scanstate =     get_scanstate((Scan) node);
  154.     procOuterFlag = get_ss_ProcOuterFlag(scanstate);
  155.     
  156.    /* ----------------
  157.     *    get a tuple from either the outer subplan or
  158.     *   from the relation depending on the procOuterFlag.
  159.     * ----------------
  160.     */
  161.     if (procOuterFlag) {
  162.     outerPlan = get_outerPlan((Plan) node);
  163.     slot = ExecProcNode(outerPlan);
  164.     } else {
  165.     slot = ExecScan((Scan) node,
  166.             (VoidFunctionType) SeqNext);
  167.     }
  168.     
  169.     DEBUG_ExecSeqScan_2;
  170.     
  171.     return
  172.     slot;
  173. }
  174.  
  175. /* ----------------------------------------------------------------
  176.  *       InitScanRelation
  177.  *
  178.  *    This does the initialization for scan relations and
  179.  *    subplans of scans.
  180.  * ----------------------------------------------------------------
  181.  */
  182.  
  183. ObjectId
  184. InitScanRelation(node, estate, scanstate, outerPlan)
  185.     Plan         node;
  186.     EState        estate;
  187.     ScanState            scanstate;
  188.     Plan            outerPlan;
  189. {
  190.     Index            relid;
  191.     List            rangeTable;
  192.     List            rtentry;
  193.     ObjectId        reloid;
  194.     TimeQual        timeQual;
  195.     ScanDirection       direction;
  196.     Relation        currentRelation;
  197.     HeapScanDesc        currentScanDesc;
  198.     RelationInfo    resultRelationInfo;
  199.     
  200.     if (outerPlan == NULL) {
  201.     /* ----------------
  202.      * if the outer node is nil then we are doing a simple
  203.      * sequential scan of a relation...
  204.      *
  205.      * get the relation object id from the relid'th entry
  206.      * in the range table, open that relation and initialize
  207.      * the scan state...
  208.      * ----------------
  209.      */
  210.     relid =           get_scanrelid((Scan) node);
  211.     rangeTable =         get_es_range_table(estate);
  212.     rtentry =         rt_fetch(relid, rangeTable);
  213.     reloid =          CInteger(rt_relid(rtentry));
  214.     timeQual =         (TimeQual) CInteger(rt_time(rtentry));
  215.     direction =          get_es_direction(estate);
  216.     resultRelationInfo =     get_es_result_relation_info(estate);
  217.     
  218.     ExecOpenScanR(reloid,          /* relation */
  219.               0,          /* nkeys */
  220.               NULL,              /* scan key */
  221.               0,          /* is index */
  222.               direction,          /* scan direction */
  223.               timeQual,       /* time qual */
  224.               ¤tRelation,   /* return: rel desc */
  225.               (Pointer *) ¤tScanDesc);  /* return: scan desc */
  226.     
  227.     set_css_currentRelation((CommonScanState) scanstate, currentRelation);
  228.     set_css_currentScanDesc((CommonScanState) scanstate, currentScanDesc);
  229.     
  230.     /* ----------------
  231.      *   Initialize rule info for this scan node
  232.      *
  233.      *   Note:  when we have a result relation which is actually
  234.      *        a view managed by the tuple level rule system, the
  235.      *        rule manager needs to be able to get at the raw tuples
  236.      *        associated with the result relation.  To facilitate
  237.      *        this, the estate now contains a pointer to the result
  238.      *        relation's scan state.  -cim 3/17/91
  239.      * ----------------
  240.      */
  241.     set_css_ruleInfo((CommonScanState)scanstate,
  242.         prs2MakeRelationRuleInfo(currentRelation, RETRIEVE));
  243.     
  244.     if (resultRelationInfo != NULL &&
  245.         relid == get_ri_RangeTableIndex(resultRelationInfo)) {
  246.         set_es_result_rel_scanstate(estate, (Pointer) scanstate);
  247.     }
  248.         
  249.     ExecAssignScanType((CommonScanState) scanstate,
  250.                TupDescToExecTupDesc(¤tRelation->rd_att,
  251.                     currentRelation->rd_rel->relnatts),
  252.                ¤tRelation->rd_att);
  253.     
  254.     set_ss_ProcOuterFlag(scanstate, false);
  255.     } else {
  256.     /* ----------------
  257.      *   otherwise we are scanning tuples from the
  258.      *   outer subplan so we initialize the outer plan
  259.      *   and nullify 
  260.      * ----------------
  261.      */
  262.     ExecInitNode(outerPlan, estate, node);
  263.     
  264.     set_scanrelid((Scan) node, 0);
  265.     set_css_currentRelation((CommonScanState) scanstate, NULL);
  266.     set_css_currentScanDesc((CommonScanState) scanstate, NULL);
  267.     set_css_ruleInfo((CommonScanState)scanstate, NULL);
  268.     ExecAssignScanType((CommonScanState)scanstate, NULL, NULL);
  269.     set_ss_ProcOuterFlag((ScanState)scanstate, true);
  270.  
  271.     reloid = InvalidObjectId;
  272.     }
  273.  
  274.     /* ----------------
  275.      *    return the relation
  276.      * ----------------
  277.      */
  278.     return
  279.     reloid;
  280. }
  281.  
  282.  
  283. /* ----------------------------------------------------------------
  284.  *       ExecInitSeqScan
  285.  *
  286.  * old comments
  287.  *       Creates the run-time state information for the seqscan node 
  288.  *       and sets the relation id to contain relevant descriptors.
  289.  *   
  290.  *       If there is a outer subtree (hash or sort), the outer subtree
  291.  *       is initialized and the relation id is set to the descriptors
  292.  *       returned by the subtree.
  293.  * ----------------------------------------------------------------
  294.  */
  295.  
  296. /**** xxref:
  297.  *           ExecInitNode
  298.  ****/
  299. List
  300. ExecInitSeqScan(node, estate, parent)
  301.     Plan     node;
  302.     EState    estate;
  303.     Plan    parent;
  304. {
  305.     ScanState            scanstate;
  306.     Plan            outerPlan;
  307.     ObjectId        reloid;
  308.     HeapScanDesc    scandesc;
  309.     
  310.     /* ----------------
  311.      *  assign the node's execution state
  312.      * ----------------
  313.      */
  314.     set_state((Plan) node,  (EStatePtr)estate);
  315.     
  316.     /* ----------------
  317.      *   create new ScanState for node
  318.      * ----------------
  319.      */
  320.     scanstate = MakeScanState(0, 0);
  321.     set_scanstate((Scan) node, scanstate);
  322.     
  323.     /* ----------------
  324.      *  Miscellanious initialization
  325.      *
  326.      *         +    assign node's base_id
  327.      *       +    assign debugging hooks and
  328.      *       +    create expression context for node
  329.      * ----------------
  330.      */
  331.     ExecAssignNodeBaseInfo(estate, (BaseNode) scanstate, parent);
  332.     ExecAssignDebugHooks(node, (BaseNode) scanstate);
  333.     ExecAssignExprContext(estate, (CommonState) scanstate);
  334.  
  335. #define SEQSCAN_NSLOTS 3
  336.     /* ----------------
  337.      *    tuple table initialization
  338.      * ----------------
  339.      */
  340.     ExecInitResultTupleSlot(estate, (CommonState) scanstate);
  341.     ExecInitScanTupleSlot(estate, (CommonScanState) scanstate);
  342.     ExecInitRawTupleSlot(estate,  (CommonScanState) scanstate);
  343.     
  344.     /* ----------------
  345.      *    initialize scanrelid
  346.      * ----------------
  347.      */
  348.     {
  349.     Index relid;
  350.  
  351.     relid = get_scanrelid((Scan) node);
  352.     set_ss_OldRelId(scanstate, relid);
  353.     }
  354.     
  355.     /* ----------------
  356.      *    initialize scanAttributes (used by rule_manager)
  357.      * ----------------
  358.      */
  359.     ExecInitScanAttributes(node);
  360.     
  361.     /* ----------------
  362.      *    initialize scan relation or outer subplan
  363.      * ----------------
  364.      */
  365.     outerPlan = (Plan) get_outerPlan(node);
  366.     
  367.     reloid = InitScanRelation(node,
  368.                   estate,
  369.                   scanstate,
  370.                   outerPlan);
  371.  
  372.     scandesc = get_css_currentScanDesc((CommonScanState) scanstate);
  373.     if (get_parallel(node)) {
  374.     scandesc->rs_parallel_ok = true;
  375.     SlaveLocalInfoD.heapscandesc = scandesc;
  376.       }
  377.  
  378.     set_cs_TupFromTlist((CommonState) scanstate, false);
  379.  
  380.     /* ----------------
  381.      *     initialize tuple type
  382.      * ----------------
  383.      */
  384.     ExecAssignResultTypeFromTL(node, (CommonState) scanstate);
  385.     ExecAssignProjectionInfo(node, (CommonState) scanstate);
  386.     
  387.     /* ----------------
  388.      * return the object id of the relation
  389.      * (I don't think this is ever used.. -cim 10/16/89)
  390.      * ----------------
  391.      */
  392.     {
  393.     List returnOid = (List)
  394.         MakeList(lispInteger(reloid), -1);
  395.     
  396.     return
  397.         returnOid;
  398.     }
  399. }
  400.  
  401. int
  402. ExecCountSlotsSeqScan(node)
  403.     Plan node;
  404. {
  405.     return ExecCountSlotsNode(get_outerPlan(node)) +
  406.        ExecCountSlotsNode(get_innerPlan(node)) +
  407.        SEQSCAN_NSLOTS;
  408. }
  409.  
  410. /* ----------------------------------------------------------------
  411.  *       ExecEndSeqScan
  412.  *   
  413.  *       frees any storage allocated through C routines.
  414.  *|    ...and also closes relations and/or shuts down outer subplan
  415.  *|    -cim 8/14/89
  416.  * ----------------------------------------------------------------
  417.  */
  418. /**** xxref:
  419.  *           ExecEndNode
  420.  ****/
  421. void
  422. ExecEndSeqScan(node)
  423.     SeqScan node;
  424. {
  425.     ScanState        scanstate;
  426.     Plan        outerPlan;
  427.     AttributeNumberPtr    scanAtts;
  428.     RelationRuleInfo    ruleInfo;
  429.     
  430.     /* ----------------
  431.      *    get information from node
  432.      * ----------------
  433.      */
  434.     scanstate = get_scanstate((Scan) node);
  435.     scanAtts =    get_cs_ScanAttributes((CommonState) scanstate);
  436.  
  437.     /* ----------------
  438.      * Restore the relation level rule stubs.
  439.      * ----------------
  440.      */    
  441.     ruleInfo = get_css_ruleInfo((CommonScanState)scanstate);
  442.     if (ruleInfo != NULL && ruleInfo->relationStubsHaveChanged) {
  443.     ObjectId reloid;
  444.     reloid =
  445.         RelationGetRelationId(
  446.               get_css_currentRelation((CommonScanState)scanstate));
  447.     prs2ReplaceRelationStub(reloid, ruleInfo->relationStubs);
  448.     }
  449.  
  450.     /* ----------------
  451.      *    Free the projection info and the scan attribute info
  452.      *
  453.      *  Note: we don't ExecFreeResultType(scanstate) 
  454.      *        because the rule manager depends on the tupType
  455.      *          returned by ExecMain().  So for now, this
  456.      *          is freed at end-transaction time.  -cim 6/2/91     
  457.      * ----------------
  458.      */    
  459.     ExecFreeProjectionInfo((CommonState) scanstate);
  460.     ExecFreeScanAttributes(scanAtts);
  461.     
  462.     /* ----------------
  463.      * close scan relation
  464.      * ----------------
  465.      */
  466.     ExecCloseR((Plan) node);
  467.     
  468.     /* ----------------
  469.      * clean up outer subtree (does nothing if there is no outerPlan)
  470.      * ----------------
  471.      */
  472.     outerPlan = get_outerPlan((Plan) node);
  473.     ExecEndNode(outerPlan);
  474.   
  475.     /* ----------------
  476.      *    clean out the tuple table
  477.      * ----------------
  478.      */
  479.     ExecClearTuple((Pointer)
  480.            get_cs_ResultTupleSlot((CommonState) scanstate));
  481.     ExecClearTuple((Pointer)
  482.            get_css_ScanTupleSlot((CommonScanState)scanstate));
  483.     ExecClearTuple((Pointer)
  484.            get_css_RawTupleSlot((CommonScanState)scanstate));
  485. }
  486.  
  487. /* ----------------------------------------------------------------
  488.  *               Join Support
  489.  * ----------------------------------------------------------------
  490.  */
  491. /* ----------------------------------------------------------------
  492.  *       ExecSeqReScan(node)
  493.  *   
  494.  *       Rescans the relation.
  495.  * ----------------------------------------------------------------
  496.  */
  497. /**** xxref:
  498.  *           ExecReScan
  499.  ****/
  500. void
  501. ExecSeqReScan(node)
  502.     Plan node;
  503. {
  504.     ScanState       scanstate;
  505.     EState      estate;
  506.     Plan      outerPlan;
  507.     Relation      rdesc;
  508.     HeapScanDesc  sdesc;
  509.     ScanDirection direction;
  510.     
  511.     scanstate = get_scanstate((Scan) node);
  512.     estate =    (EState) get_state(node);
  513.     
  514.     if (get_ss_ProcOuterFlag(scanstate) == false) {
  515.     /* ----------------
  516.      *   if the ProcOuterFlag is false then it means
  517.      *   we are scanning a relation so we use ExecReScanR()
  518.      * ----------------
  519.      */
  520.     rdesc =     get_css_currentRelation((CommonScanState) scanstate);
  521.     sdesc =     get_css_currentScanDesc((CommonScanState) scanstate);
  522.     direction =     get_es_direction(estate);
  523.     sdesc =     ExecReScanR(rdesc, sdesc, direction, 0, NULL);
  524.     set_css_currentScanDesc((CommonScanState) scanstate, sdesc);
  525.     } else {
  526.     /* ----------------
  527.      *   if ProcOuterFlag is true then we are scanning
  528.      *   a subplan so we just call ExecReScan on the subplan.
  529.      * ----------------
  530.      */
  531.     outerPlan = get_outerPlan(node);
  532.     ExecReScan(outerPlan);
  533.     }
  534. }
  535.  
  536. /* ----------------------------------------------------------------
  537.  *       ExecSeqMarkPos(node)
  538.  *   
  539.  *       Marks scan position.
  540.  * ----------------------------------------------------------------
  541.  */
  542. /**** xxref:
  543.  *           ExecMarkPos
  544.  ****/
  545. List
  546. ExecSeqMarkPos(node)
  547.     Plan node;
  548. {
  549.     ScanState      scanstate;
  550.     Plan     outerPlan;
  551.     bool     procOuterFlag;
  552.     HeapScanDesc sdesc;
  553.     
  554.     scanstate =     get_scanstate((Scan) node);
  555.     procOuterFlag = get_ss_ProcOuterFlag(scanstate);
  556.     
  557.     /* ----------------
  558.      *    if we are scanning a subplan then propagate
  559.      *  the ExecMarkPos() request to the subplan
  560.      * ----------------
  561.      */
  562.     if (procOuterFlag) {
  563.     outerPlan = get_outerPlan(node);
  564.     return
  565.         ExecMarkPos(outerPlan);
  566.     }
  567.     
  568.     /* ----------------
  569.      *  otherwise we are scanning a relation so mark the
  570.      *  position using the access methods..
  571.      *
  572.      *  XXX access methods don't return positions yet so
  573.      *      for now we return LispNil.  It's possible that
  574.      *      they will never return positions for all I know -cim 10/16/89
  575.      * ----------------
  576.      */
  577.     sdesc = get_css_currentScanDesc((CommonScanState) scanstate);
  578.     ammarkpos(sdesc);
  579.     
  580.     return LispNil;
  581. }
  582.  
  583. /* ----------------------------------------------------------------
  584.  *       ExecSeqRestrPos
  585.  *   
  586.  *       Restores scan position.
  587.  * ----------------------------------------------------------------
  588.  */
  589. /**** xxref:
  590.  *           ExecRestrPos
  591.  ****/
  592. void
  593. ExecSeqRestrPos(node)
  594.     Plan node;
  595. {
  596.     ScanState     scanstate;
  597.     Plan     outerPlan;
  598.     bool     procOuterFlag;
  599.     HeapScanDesc sdesc;
  600.     
  601.     scanstate = get_scanstate((Scan) node);
  602.     procOuterFlag = get_ss_ProcOuterFlag(scanstate);
  603.     
  604.     /* ----------------
  605.      *    if we are scanning a subplan then propagate
  606.      *  the ExecRestrPos() request to the subplan
  607.      * ----------------
  608.      */
  609.     if (procOuterFlag) {
  610.     outerPlan = get_outerPlan(node);
  611.     ExecRestrPos(outerPlan);
  612.     return;
  613.     }
  614.     
  615.     /* ----------------
  616.      *  otherwise we are scanning a relation so restore the
  617.      *  position using the access methods..
  618.      * ----------------
  619.      */
  620.     sdesc = get_css_currentScanDesc((CommonScanState) scanstate);
  621.     amrestrpos(sdesc);
  622. }
  623.