nodeSeqscan.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:13k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * nodeSeqscan.c
  4.  *   Support routines for sequential scans of relations.
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.18 1999/05/25 16:08:46 momjian Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. /*
  15.  * INTERFACE ROUTINES
  16.  * ExecSeqScan sequentially scans a relation.
  17.  * ExecSeqNext retrieve next tuple in sequential order.
  18.  * ExecInitSeqScan creates and initializes a seqscan node.
  19.  * ExecEndSeqScan releases any storage allocated.
  20.  * ExecSeqReScan rescans the relation
  21.  * ExecMarkPos marks scan position
  22.  * ExecRestrPos restores scan position
  23.  *
  24.  */
  25. #include "postgres.h"
  26. #include "executor/executor.h"
  27. #include "executor/execdebug.h"
  28. #include "executor/nodeSeqscan.h"
  29. #include "access/heapam.h"
  30. #include "parser/parsetree.h"
  31. #include "nodes/print.h"
  32. static Oid InitScanRelation(SeqScan *node, EState *estate,
  33.  CommonScanState *scanstate, Plan *outerPlan);
  34. static TupleTableSlot *SeqNext(SeqScan *node);
  35. /* ----------------------------------------------------------------
  36.  * Scan Support
  37.  * ----------------------------------------------------------------
  38.  */
  39. /* ----------------------------------------------------------------
  40.  * SeqNext
  41.  *
  42.  * This is a workhorse for ExecSeqScan
  43.  * ----------------------------------------------------------------
  44.  */
  45. static TupleTableSlot *
  46. SeqNext(SeqScan *node)
  47. {
  48. HeapTuple tuple;
  49. HeapScanDesc scandesc;
  50. CommonScanState *scanstate;
  51. EState    *estate;
  52. ScanDirection direction;
  53. TupleTableSlot *slot;
  54. /* ----------------
  55.  * get information from the estate and scan state
  56.  * ----------------
  57.  */
  58. estate = node->plan.state;
  59. scanstate = node->scanstate;
  60. scandesc = scanstate->css_currentScanDesc;
  61. direction = estate->es_direction;
  62. slot = scanstate->css_ScanTupleSlot;
  63. /*
  64.  * Check if we are evaluating PlanQual for tuple of this relation.
  65.  * Additional checking is not good, but no other way for now. We could
  66.  * introduce new nodes for this case and handle SeqScan --> NewNode
  67.  * switching in Init/ReScan plan...
  68.  */
  69. if (estate->es_evTuple != NULL &&
  70. estate->es_evTuple[node->scanrelid - 1] != NULL)
  71. {
  72. slot->ttc_buffer = InvalidBuffer;
  73. slot->ttc_shouldFree = false;
  74. if (estate->es_evTupleNull[node->scanrelid - 1])
  75. {
  76. slot->val = NULL; /* must not free tuple! */
  77. return (slot);
  78. }
  79. slot->val = estate->es_evTuple[node->scanrelid - 1];
  80. /*
  81.  * Note that unlike IndexScan, SeqScan never use keys in
  82.  * heap_beginscan (and this is very bad) - so, here we have not
  83.  * check are keys ok or not.
  84.  */
  85. /* Flag for the next call that no more tuples */
  86. estate->es_evTupleNull[node->scanrelid - 1] = true;
  87. return (slot);
  88. }
  89. /* ----------------
  90.  * get the next tuple from the access methods
  91.  * ----------------
  92.  */
  93. tuple = heap_getnext(scandesc, ScanDirectionIsBackward(direction));
  94. /* ----------------
  95.  * save the tuple and the buffer returned to us by the access methods
  96.  * in our scan tuple slot and return the slot.  Note: we pass 'false'
  97.  * because tuples returned by heap_getnext() are pointers onto
  98.  * disk pages and were not created with palloc() and so should not
  99.  * be pfree()'d.
  100.  * ----------------
  101.  */
  102. slot = ExecStoreTuple(tuple,/* tuple to store */
  103.   slot, /* slot to store in */
  104.   scandesc->rs_cbuf, /* buffer associated with
  105.  * this tuple */
  106.   false); /* don't pfree this pointer */
  107. /* ----------------
  108.  * XXX -- mao says:  The sequential scan for heap relations will
  109.  * automatically unpin the buffer this tuple is on when we cross
  110.  * a page boundary.  The clearslot code also does this.  We bump
  111.  * the pin count on the page here, since we actually have two
  112.  * pointers to it -- one in the scan desc and one in the tuple
  113.  * table slot.  --mar 20 91
  114.  * ----------------
  115.  */
  116. ExecIncrSlotBufferRefcnt(slot);
  117. return slot;
  118. }
  119. /* ----------------------------------------------------------------
  120.  * ExecSeqScan(node)
  121.  *
  122.  * Scans the relation sequentially and returns the next qualifying
  123.  * tuple.
  124.  * It calls the ExecScan() routine and passes it the access method
  125.  * which retrieve tuples sequentially.
  126.  *
  127.  */
  128. TupleTableSlot *
  129. ExecSeqScan(SeqScan *node)
  130. {
  131. TupleTableSlot *slot;
  132. Plan    *outerPlan;
  133. S_printf("ExecSeqScan: scanning node: ");
  134. S_nodeDisplay(node);
  135. /* ----------------
  136.  * if there is an outer subplan, get a tuple from it
  137.  * else, scan the relation
  138.  * ----------------
  139.  */
  140. if ((outerPlan = outerPlan((Plan *) node)) != NULL)
  141. slot = ExecProcNode(outerPlan, (Plan *) node);
  142. else
  143. slot = ExecScan(node, SeqNext);
  144. S1_printf("ExecSeqScan: returned tuple slot: %dn", slot);
  145. return slot;
  146. }
  147. /* ----------------------------------------------------------------
  148.  * InitScanRelation
  149.  *
  150.  * This does the initialization for scan relations and
  151.  * subplans of scans.
  152.  * ----------------------------------------------------------------
  153.  */
  154. static Oid
  155. InitScanRelation(SeqScan *node, EState *estate,
  156.  CommonScanState *scanstate, Plan *outerPlan)
  157. {
  158. Index relid;
  159. List    *rangeTable;
  160. RangeTblEntry *rtentry;
  161. Oid reloid;
  162. ScanDirection direction;
  163. Relation currentRelation;
  164. HeapScanDesc currentScanDesc;
  165. RelationInfo *resultRelationInfo;
  166. if (outerPlan == NULL)
  167. {
  168. /* ----------------
  169.  * if the outer node is nil then we are doing a simple
  170.  * sequential scan of a relation...
  171.  *
  172.  * get the relation object id from the relid'th entry
  173.  * in the range table, open that relation and initialize
  174.  * the scan state...
  175.  * ----------------
  176.  */
  177. relid = node->scanrelid;
  178. rangeTable = estate->es_range_table;
  179. rtentry = rt_fetch(relid, rangeTable);
  180. reloid = rtentry->relid;
  181. direction = estate->es_direction;
  182. resultRelationInfo = estate->es_result_relation_info;
  183. ExecOpenScanR(reloid, /* relation */
  184.   0, /* nkeys */
  185.   NULL, /* scan key */
  186.   0, /* is index */
  187.   direction,/* scan direction */
  188.   estate->es_snapshot,
  189.   &currentRelation, /* return: rel desc */
  190.   (Pointer *) &currentScanDesc); /* return: scan desc */
  191. scanstate->css_currentRelation = currentRelation;
  192. scanstate->css_currentScanDesc = currentScanDesc;
  193. ExecAssignScanType(scanstate,
  194.    RelationGetDescr(currentRelation));
  195. }
  196. else
  197. {
  198. /* ----------------
  199.  *  otherwise we are scanning tuples from the
  200.  *  outer subplan so we initialize the outer plan
  201.  *  and nullify
  202.  * ----------------
  203.  */
  204. ExecInitNode(outerPlan, estate, (Plan *) node);
  205. node->scanrelid = 0;
  206. scanstate->css_currentRelation = NULL;
  207. scanstate->css_currentScanDesc = NULL;
  208. ExecAssignScanType(scanstate, NULL);
  209. reloid = InvalidOid;
  210. }
  211. /* ----------------
  212.  * return the relation
  213.  * ----------------
  214.  */
  215. return reloid;
  216. }
  217. /* ----------------------------------------------------------------
  218.  * ExecInitSeqScan
  219.  *
  220.  * old comments
  221.  * Creates the run-time state information for the seqscan node
  222.  * and sets the relation id to contain relevant descriptors.
  223.  *
  224.  * If there is a outer subtree (sort), the outer subtree
  225.  * is initialized and the relation id is set to the descriptors
  226.  * returned by the subtree.
  227.  * ----------------------------------------------------------------
  228.  */
  229. bool
  230. ExecInitSeqScan(SeqScan *node, EState *estate, Plan *parent)
  231. {
  232. CommonScanState *scanstate;
  233. Plan    *outerPlan;
  234. Oid reloid;
  235. HeapScanDesc scandesc;
  236. /* ----------------
  237.  * assign the node's execution state
  238.  * ----------------
  239.  */
  240. node->plan.state = estate;
  241. /* ----------------
  242.  *  create new CommonScanState for node
  243.  * ----------------
  244.  */
  245. scanstate = makeNode(CommonScanState);
  246. node->scanstate = scanstate;
  247. /* ----------------
  248.  * Miscellanious initialization
  249.  *
  250.  *  + assign node's base_id
  251.  *  + create expression context for node
  252.  * ----------------
  253.  */
  254. ExecAssignNodeBaseInfo(estate, &scanstate->cstate, parent);
  255. ExecAssignExprContext(estate, &scanstate->cstate);
  256. #define SEQSCAN_NSLOTS 3
  257. /* ----------------
  258.  * tuple table initialization
  259.  * ----------------
  260.  */
  261. ExecInitResultTupleSlot(estate, &scanstate->cstate);
  262. ExecInitScanTupleSlot(estate, scanstate);
  263. /* ----------------
  264.  * initialize scan relation or outer subplan
  265.  * ----------------
  266.  */
  267. outerPlan = outerPlan((Plan *) node);
  268. reloid = InitScanRelation(node, estate, scanstate, outerPlan);
  269. scandesc = scanstate->css_currentScanDesc;
  270. scanstate->cstate.cs_TupFromTlist = false;
  271. /* ----------------
  272.  * initialize tuple type
  273.  * ----------------
  274.  */
  275. ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
  276. ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
  277. return TRUE;
  278. }
  279. int
  280. ExecCountSlotsSeqScan(SeqScan *node)
  281. {
  282. return ExecCountSlotsNode(outerPlan(node)) +
  283. ExecCountSlotsNode(innerPlan(node)) +
  284. SEQSCAN_NSLOTS;
  285. }
  286. /* ----------------------------------------------------------------
  287.  * ExecEndSeqScan
  288.  *
  289.  * frees any storage allocated through C routines.
  290.  *| ...and also closes relations and/or shuts down outer subplan
  291.  *| -cim 8/14/89
  292.  * ----------------------------------------------------------------
  293.  */
  294. void
  295. ExecEndSeqScan(SeqScan *node)
  296. {
  297. CommonScanState *scanstate;
  298. Plan    *outerPlan;
  299. /* ----------------
  300.  * get information from node
  301.  * ----------------
  302.  */
  303. scanstate = node->scanstate;
  304. /* ----------------
  305.  * Free the projection info and the scan attribute info
  306.  *
  307.  * Note: we don't ExecFreeResultType(scanstate)
  308.  *   because the rule manager depends on the tupType
  309.  *   returned by ExecMain().  So for now, this
  310.  *   is freed at end-transaction time.  -cim 6/2/91
  311.  * ----------------
  312.  */
  313. ExecFreeProjectionInfo(&scanstate->cstate);
  314. /* ----------------
  315.  * close scan relation
  316.  * ----------------
  317.  */
  318. ExecCloseR((Plan *) node);
  319. /* ----------------
  320.  * clean up outer subtree (does nothing if there is no outerPlan)
  321.  * ----------------
  322.  */
  323. outerPlan = outerPlan((Plan *) node);
  324. ExecEndNode(outerPlan, (Plan *) node);
  325. /* ----------------
  326.  * clean out the tuple table
  327.  * ----------------
  328.  */
  329. ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
  330. ExecClearTuple(scanstate->css_ScanTupleSlot);
  331. }
  332. /* ----------------------------------------------------------------
  333.  * Join Support
  334.  * ----------------------------------------------------------------
  335.  */
  336. /* ----------------------------------------------------------------
  337.  * ExecSeqReScan
  338.  *
  339.  * Rescans the relation.
  340.  * ----------------------------------------------------------------
  341.  */
  342. void
  343. ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent)
  344. {
  345. CommonScanState *scanstate;
  346. EState    *estate;
  347. Plan    *outerPlan;
  348. Relation rel;
  349. HeapScanDesc scan;
  350. ScanDirection direction;
  351. scanstate = node->scanstate;
  352. estate = node->plan.state;
  353. if ((outerPlan = outerPlan((Plan *) node)) != NULL)
  354. {
  355. /* we are scanning a subplan */
  356. outerPlan = outerPlan((Plan *) node);
  357. ExecReScan(outerPlan, exprCtxt, parent);
  358. }
  359. else
  360. /* otherwise, we are scanning a relation */
  361. {
  362. /* If this is re-scanning of PlanQual ... */
  363. if (estate->es_evTuple != NULL &&
  364. estate->es_evTuple[node->scanrelid - 1] != NULL)
  365. {
  366. estate->es_evTupleNull[node->scanrelid - 1] = false;
  367. return;
  368. }
  369. rel = scanstate->css_currentRelation;
  370. scan = scanstate->css_currentScanDesc;
  371. direction = estate->es_direction;
  372. scan = ExecReScanR(rel, scan, direction, 0, NULL);
  373. scanstate->css_currentScanDesc = scan;
  374. }
  375. }
  376. /* ----------------------------------------------------------------
  377.  * ExecSeqMarkPos(node)
  378.  *
  379.  * Marks scan position.
  380.  * ----------------------------------------------------------------
  381.  */
  382. void
  383. ExecSeqMarkPos(SeqScan *node)
  384. {
  385. CommonScanState *scanstate;
  386. Plan    *outerPlan;
  387. HeapScanDesc scan;
  388. scanstate = node->scanstate;
  389. /* ----------------
  390.  * if we are scanning a subplan then propagate
  391.  * the ExecMarkPos() request to the subplan
  392.  * ----------------
  393.  */
  394. outerPlan = outerPlan((Plan *) node);
  395. if (outerPlan)
  396. {
  397. ExecMarkPos(outerPlan);
  398. return;
  399. }
  400. /* ----------------
  401.  * otherwise we are scanning a relation so mark the
  402.  * position using the access methods..
  403.  *
  404.  * ----------------
  405.  */
  406. scan = scanstate->css_currentScanDesc;
  407. heap_markpos(scan);
  408. return;
  409. }
  410. /* ----------------------------------------------------------------
  411.  * ExecSeqRestrPos
  412.  *
  413.  * Restores scan position.
  414.  * ----------------------------------------------------------------
  415.  */
  416. void
  417. ExecSeqRestrPos(SeqScan *node)
  418. {
  419. CommonScanState *scanstate;
  420. Plan    *outerPlan;
  421. HeapScanDesc scan;
  422. scanstate = node->scanstate;
  423. /* ----------------
  424.  * if we are scanning a subplan then propagate
  425.  * the ExecRestrPos() request to the subplan
  426.  * ----------------
  427.  */
  428. outerPlan = outerPlan((Plan *) node);
  429. if (outerPlan)
  430. {
  431. ExecRestrPos(outerPlan);
  432. return;
  433. }
  434. /* ----------------
  435.  * otherwise we are scanning a relation so restore the
  436.  * position using the access methods..
  437.  * ----------------
  438.  */
  439. scan = scanstate->css_currentScanDesc;
  440. heap_restrpos(scan);
  441. }