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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * execProcnode.c
  4.  *  contains dispatch functions which call the appropriate "initialize",
  5.  *  "get a tuple", and "cleanup" routines for the given node type.
  6.  *  If the node has children, then it will presumably call ExecInitNode,
  7.  *  ExecProcNode, or ExecEndNode on it's subnodes and do the appropriate
  8.  *  processing..
  9.  *
  10.  * Copyright (c) 1994, Regents of the University of California
  11.  *
  12.  *
  13.  * IDENTIFICATION
  14.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.14 1999/03/23 16:50:48 momjian Exp $
  15.  *
  16.  *-------------------------------------------------------------------------
  17.  */
  18. /*
  19.  *  INTERFACE ROUTINES
  20.  * ExecInitNode - initialize a plan node and it's subplans
  21.  * ExecProcNode - get a tuple by executing the plan node
  22.  * ExecEndNode - shut down a plan node and it's subplans
  23.  *
  24.  *  NOTES
  25.  * This used to be three files.  It is now all combined into
  26.  * one file so that it is easier to keep ExecInitNode, ExecProcNode,
  27.  * and ExecEndNode in sync when new nodes are added.
  28.  *
  29.  *  EXAMPLE
  30.  * suppose we want the age of the manager of the shoe department and
  31.  * the number of employees in that department.  so we have the query:
  32.  *
  33.  * retrieve (DEPT.no_emps, EMP.age)
  34.  * where EMP.name = DEPT.mgr and
  35.  *   DEPT.name = "shoe"
  36.  *
  37.  * Suppose the planner gives us the following plan:
  38.  *
  39.  * Nest Loop (DEPT.mgr = EMP.name)
  40.  * /
  41.  *    /  
  42.  *    Seq Scan Seq Scan
  43.  * DEPT   EMP
  44.  * (name = "shoe")
  45.  *
  46.  * ExecStart() is called first.
  47.  * It calls InitPlan() which calls ExecInitNode() on
  48.  * the root of the plan -- the nest loop node.
  49.  *
  50.  *   * ExecInitNode() notices that it is looking at a nest loop and
  51.  * as the code below demonstrates, it calls ExecInitNestLoop().
  52.  * Eventually this calls ExecInitNode() on the right and left subplans
  53.  * and so forth until the entire plan is initialized.
  54.  *
  55.  *   * Then when ExecRun() is called, it calls ExecutePlan() which
  56.  * calls ExecProcNode() repeatedly on the top node of the plan.
  57.  * Each time this happens, ExecProcNode() will end up calling
  58.  * ExecNestLoop(), which calls ExecProcNode() on its subplans.
  59.  * Each of these subplans is a sequential scan so ExecSeqScan() is
  60.  * called.  The slots returned by ExecSeqScan() may contain
  61.  * tuples which contain the attributes ExecNestLoop() uses to
  62.  * form the tuples it returns.
  63.  *
  64.  *   * Eventually ExecSeqScan() stops returning tuples and the nest
  65.  * loop join ends.  Lastly, ExecEnd() calls ExecEndNode() which
  66.  * calls ExecEndNestLoop() which in turn calls ExecEndNode() on
  67.  * its subplans which result in ExecEndSeqScan().
  68.  *
  69.  * This should show how the executor works by having
  70.  * ExecInitNode(), ExecProcNode() and ExecEndNode() dispatch
  71.  * their work to the appopriate node support routines which may
  72.  * in turn call these routines themselves on their subplans.
  73.  *
  74.  */
  75. #include "postgres.h"
  76. #include "miscadmin.h"
  77. #include "tcop/tcopprot.h"
  78. #include "executor/executor.h"
  79. #include "executor/nodeResult.h"
  80. #include "executor/nodeAppend.h"
  81. #include "executor/nodeSeqscan.h"
  82. #include "executor/nodeIndexscan.h"
  83. #include "executor/nodeNestloop.h"
  84. #include "executor/nodeMergejoin.h"
  85. #include "executor/nodeMaterial.h"
  86. #include "executor/nodeSort.h"
  87. #include "executor/nodeUnique.h"
  88. #include "executor/nodeGroup.h"
  89. #include "executor/nodeAgg.h"
  90. #include "executor/nodeHash.h"
  91. #include "executor/nodeHashjoin.h"
  92. #include "executor/nodeSubplan.h"
  93. /* ------------------------------------------------------------------------
  94.  * ExecInitNode
  95.  *
  96.  * Recursively initializes all the nodes in the plan rooted
  97.  * at 'node'.
  98.  *
  99.  * Initial States:
  100.  *   'node' is the plan produced by the query planner
  101.  *
  102.  * returns TRUE/FALSE on whether the plan was successfully initialized
  103.  * ------------------------------------------------------------------------
  104.  */
  105. bool
  106. ExecInitNode(Plan *node, EState *estate, Plan *parent)
  107. {
  108. bool result;
  109. List    *subp;
  110. /* ----------------
  111.  * do nothing when we get to the end
  112.  * of a leaf on tree.
  113.  * ----------------
  114.  */
  115. if (node == NULL)
  116. return FALSE;
  117. foreach(subp, node->initPlan)
  118. {
  119. result = ExecInitSubPlan((SubPlan *) lfirst(subp), estate, node);
  120. if (result == FALSE)
  121. return FALSE;
  122. }
  123. switch (nodeTag(node))
  124. {
  125. /* ----------------
  126.  * control nodes
  127.  * ----------------
  128.  */
  129. case T_Result:
  130. result = ExecInitResult((Result *) node, estate, parent);
  131. break;
  132. case T_Append:
  133. result = ExecInitAppend((Append *) node, estate, parent);
  134. break;
  135. /* ----------------
  136.  * scan nodes
  137.  * ----------------
  138.  */
  139. case T_SeqScan:
  140. result = ExecInitSeqScan((SeqScan *) node, estate, parent);
  141. break;
  142. case T_IndexScan:
  143. result = ExecInitIndexScan((IndexScan *) node, estate, parent);
  144. break;
  145. /* ----------------
  146.  * join nodes
  147.  * ----------------
  148.  */
  149. case T_NestLoop:
  150. result = ExecInitNestLoop((NestLoop *) node, estate, parent);
  151. break;
  152. case T_MergeJoin:
  153. result = ExecInitMergeJoin((MergeJoin *) node, estate, parent);
  154. break;
  155. /* ----------------
  156.  * materialization nodes
  157.  * ----------------
  158.  */
  159. case T_Material:
  160. result = ExecInitMaterial((Material *) node, estate, parent);
  161. break;
  162. case T_Sort:
  163. result = ExecInitSort((Sort *) node, estate, parent);
  164. break;
  165. case T_Unique:
  166. result = ExecInitUnique((Unique *) node, estate, parent);
  167. break;
  168. case T_Group:
  169. result = ExecInitGroup((Group *) node, estate, parent);
  170. break;
  171. case T_Agg:
  172. result = ExecInitAgg((Agg *) node, estate, parent);
  173. break;
  174. case T_Hash:
  175. result = ExecInitHash((Hash *) node, estate, parent);
  176. break;
  177. case T_HashJoin:
  178. result = ExecInitHashJoin((HashJoin *) node, estate, parent);
  179. break;
  180. default:
  181. elog(ERROR, "ExecInitNode: node %d unsupported", nodeTag(node));
  182. result = FALSE;
  183. }
  184. if (result != FALSE)
  185. {
  186. foreach(subp, node->subPlan)
  187. {
  188. result = ExecInitSubPlan((SubPlan *) lfirst(subp), estate, node);
  189. if (result == FALSE)
  190. return FALSE;
  191. }
  192. }
  193. return result;
  194. }
  195. /* ----------------------------------------------------------------
  196.  * ExecProcNode
  197.  *
  198.  * Initial States:
  199.  *   the query tree must be initialized once by calling ExecInit.
  200.  * ----------------------------------------------------------------
  201.  */
  202. TupleTableSlot *
  203. ExecProcNode(Plan *node, Plan *parent)
  204. {
  205. TupleTableSlot *result;
  206. /* ----------------
  207.  * deal with NULL nodes..
  208.  * ----------------
  209.  */
  210. if (QueryCancel)
  211. CancelQuery();
  212. if (node == NULL)
  213. return NULL;
  214. if (node->chgParam != NULL) /* something changed */
  215. ExecReScan(node, NULL, parent); /* let ReScan handle this */
  216. switch (nodeTag(node))
  217. {
  218. /* ----------------
  219.  * control nodes
  220.  * ----------------
  221.  */
  222. case T_Result:
  223. result = ExecResult((Result *) node);
  224. break;
  225. case T_Append:
  226. result = ExecProcAppend((Append *) node);
  227. break;
  228. /* ----------------
  229.  * scan nodes
  230.  * ----------------
  231.  */
  232. case T_SeqScan:
  233. result = ExecSeqScan((SeqScan *) node);
  234. break;
  235. case T_IndexScan:
  236. result = ExecIndexScan((IndexScan *) node);
  237. break;
  238. /* ----------------
  239.  * join nodes
  240.  * ----------------
  241.  */
  242. case T_NestLoop:
  243. result = ExecNestLoop((NestLoop *) node, parent);
  244. break;
  245. case T_MergeJoin:
  246. result = ExecMergeJoin((MergeJoin *) node);
  247. break;
  248. /* ----------------
  249.  * materialization nodes
  250.  * ----------------
  251.  */
  252. case T_Material:
  253. result = ExecMaterial((Material *) node);
  254. break;
  255. case T_Sort:
  256. result = ExecSort((Sort *) node);
  257. break;
  258. case T_Unique:
  259. result = ExecUnique((Unique *) node);
  260. break;
  261. case T_Group:
  262. result = ExecGroup((Group *) node);
  263. break;
  264. case T_Agg:
  265. result = ExecAgg((Agg *) node);
  266. break;
  267. case T_Hash:
  268. result = ExecHash((Hash *) node);
  269. break;
  270. case T_HashJoin:
  271. result = ExecHashJoin((HashJoin *) node);
  272. break;
  273. default:
  274. elog(ERROR, "ExecProcNode: node %d unsupported", nodeTag(node));
  275. result = NULL;
  276. }
  277. return result;
  278. }
  279. int
  280. ExecCountSlotsNode(Plan *node)
  281. {
  282. if (node == (Plan *) NULL)
  283. return 0;
  284. switch (nodeTag(node))
  285. {
  286. /* ----------------
  287.  * control nodes
  288.  * ----------------
  289.  */
  290. case T_Result:
  291. return ExecCountSlotsResult((Result *) node);
  292. case T_Append:
  293. return ExecCountSlotsAppend((Append *) node);
  294. /* ----------------
  295.  * scan nodes
  296.  * ----------------
  297.  */
  298. case T_SeqScan:
  299. return ExecCountSlotsSeqScan((SeqScan *) node);
  300. case T_IndexScan:
  301. return ExecCountSlotsIndexScan((IndexScan *) node);
  302. /* ----------------
  303.  * join nodes
  304.  * ----------------
  305.  */
  306. case T_NestLoop:
  307. return ExecCountSlotsNestLoop((NestLoop *) node);
  308. case T_MergeJoin:
  309. return ExecCountSlotsMergeJoin((MergeJoin *) node);
  310. /* ----------------
  311.  * materialization nodes
  312.  * ----------------
  313.  */
  314. case T_Material:
  315. return ExecCountSlotsMaterial((Material *) node);
  316. case T_Sort:
  317. return ExecCountSlotsSort((Sort *) node);
  318. case T_Unique:
  319. return ExecCountSlotsUnique((Unique *) node);
  320. case T_Group:
  321. return ExecCountSlotsGroup((Group *) node);
  322. case T_Agg:
  323. return ExecCountSlotsAgg((Agg *) node);
  324. case T_Hash:
  325. return ExecCountSlotsHash((Hash *) node);
  326. case T_HashJoin:
  327. return ExecCountSlotsHashJoin((HashJoin *) node);
  328. default:
  329. elog(ERROR, "ExecCountSlotsNode: node not yet supported: %d",
  330.  nodeTag(node));
  331. break;
  332. }
  333. return 0;
  334. }
  335. /* ----------------------------------------------------------------
  336.  * ExecEndNode
  337.  *
  338.  * Recursively cleans up all the nodes in the plan rooted
  339.  * at 'node'.
  340.  *
  341.  * After this operation, the query plan will not be able to
  342.  * processed any further. This should be called only after
  343.  * the query plan has been fully executed.
  344.  * ----------------------------------------------------------------
  345.  */
  346. void
  347. ExecEndNode(Plan *node, Plan *parent)
  348. {
  349. List    *subp;
  350. /* ----------------
  351.  * do nothing when we get to the end
  352.  * of a leaf on tree.
  353.  * ----------------
  354.  */
  355. if (node == NULL)
  356. return;
  357. foreach(subp, node->initPlan)
  358. ExecEndSubPlan((SubPlan *) lfirst(subp));
  359. foreach(subp, node->subPlan)
  360. ExecEndSubPlan((SubPlan *) lfirst(subp));
  361. if (node->chgParam != NULL)
  362. {
  363. freeList(node->chgParam);
  364. node->chgParam = NULL;
  365. }
  366. switch (nodeTag(node))
  367. {
  368. /* ----------------
  369.  * control nodes
  370.  * ----------------
  371.  */
  372. case T_Result:
  373. ExecEndResult((Result *) node);
  374. break;
  375. case T_Append:
  376. ExecEndAppend((Append *) node);
  377. break;
  378. /* ----------------
  379.  * scan nodes
  380.  * ----------------
  381.  */
  382. case T_SeqScan:
  383. ExecEndSeqScan((SeqScan *) node);
  384. break;
  385. case T_IndexScan:
  386. ExecEndIndexScan((IndexScan *) node);
  387. break;
  388. /* ----------------
  389.  * join nodes
  390.  * ----------------
  391.  */
  392. case T_NestLoop:
  393. ExecEndNestLoop((NestLoop *) node);
  394. break;
  395. case T_MergeJoin:
  396. ExecEndMergeJoin((MergeJoin *) node);
  397. break;
  398. /* ----------------
  399.  * materialization nodes
  400.  * ----------------
  401.  */
  402. case T_Material:
  403. ExecEndMaterial((Material *) node);
  404. break;
  405. case T_Sort:
  406. ExecEndSort((Sort *) node);
  407. break;
  408. case T_Unique:
  409. ExecEndUnique((Unique *) node);
  410. break;
  411. case T_Group:
  412. ExecEndGroup((Group *) node);
  413. break;
  414. case T_Agg:
  415. ExecEndAgg((Agg *) node);
  416. break;
  417. /* ----------------
  418.  * XXX add hooks to these
  419.  * ----------------
  420.  */
  421. case T_Hash:
  422. ExecEndHash((Hash *) node);
  423. break;
  424. case T_HashJoin:
  425. ExecEndHashJoin((HashJoin *) node);
  426. break;
  427. default:
  428. elog(ERROR, "ExecEndNode: node %d unsupported", nodeTag(node));
  429. break;
  430. }
  431. }