execProcnode.c 14.1 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * execProcnode.c
4 5 6
 *	 contains dispatch functions which call the appropriate "initialize",
 *	 "get a tuple", and "cleanup" routines for the given node type.
 *	 If the node has children, then it will presumably call ExecInitNode,
B
Bruce Momjian 已提交
7
 *	 ExecProcNode, or ExecEndNode on its subnodes and do the appropriate
8
 *	 processing.
9
 *
B
Bruce Momjian 已提交
10
 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
B
Add:  
Bruce Momjian 已提交
11
 * Portions Copyright (c) 1994, Regents of the University of California
12 13 14
 *
 *
 * IDENTIFICATION
15
 *	  $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.37 2003/07/21 17:05:08 tgl Exp $
16 17 18 19
 *
 *-------------------------------------------------------------------------
 */
/*
20
 *	 INTERFACE ROUTINES
21
 *		ExecCountSlotsNode -	count tuple slots needed by plan tree
B
Bruce Momjian 已提交
22
 *		ExecInitNode	-		initialize a plan node and its subplans
23
 *		ExecProcNode	-		get a tuple by executing the plan node
B
Bruce Momjian 已提交
24
 *		ExecEndNode		-		shut down a plan node and its subplans
25
 *
26 27 28 29
 *	 NOTES
 *		This used to be three files.  It is now all combined into
 *		one file so that it is easier to keep ExecInitNode, ExecProcNode,
 *		and ExecEndNode in sync when new nodes are added.
30
 *
31 32 33
 *	 EXAMPLE
 *		suppose we want the age of the manager of the shoe department and
 *		the number of employees in that department.  so we have the query:
34
 *
35 36 37
 *				retrieve (DEPT.no_emps, EMP.age)
 *				where EMP.name = DEPT.mgr and
 *					  DEPT.name = "shoe"
38
 *
39
 *		Suppose the planner gives us the following plan:
40
 *
41 42 43 44 45 46 47 48 49 50 51 52 53 54
 *						Nest Loop (DEPT.mgr = EMP.name)
 *						/		\
 *					   /		 \
 *				   Seq Scan		Seq Scan
 *					DEPT		  EMP
 *				(name = "shoe")
 *
 *		ExecStart() is called first.
 *		It calls InitPlan() which calls ExecInitNode() on
 *		the root of the plan -- the nest loop node.
 *
 *	  * ExecInitNode() notices that it is looking at a nest loop and
 *		as the code below demonstrates, it calls ExecInitNestLoop().
 *		Eventually this calls ExecInitNode() on the right and left subplans
55 56 57
 *		and so forth until the entire plan is initialized.  The result
 *		of ExecInitNode() is a plan state tree built with the same structure
 *		as the underlying plan tree.
58
 *
59 60
 *	  * Then when ExecRun() is called, it calls ExecutePlan() which calls
 *		ExecProcNode() repeatedly on the top node of the plan state tree.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
 *		Each time this happens, ExecProcNode() will end up calling
 *		ExecNestLoop(), which calls ExecProcNode() on its subplans.
 *		Each of these subplans is a sequential scan so ExecSeqScan() is
 *		called.  The slots returned by ExecSeqScan() may contain
 *		tuples which contain the attributes ExecNestLoop() uses to
 *		form the tuples it returns.
 *
 *	  * Eventually ExecSeqScan() stops returning tuples and the nest
 *		loop join ends.  Lastly, ExecEnd() calls ExecEndNode() which
 *		calls ExecEndNestLoop() which in turn calls ExecEndNode() on
 *		its subplans which result in ExecEndSeqScan().
 *
 *		This should show how the executor works by having
 *		ExecInitNode(), ExecProcNode() and ExecEndNode() dispatch
 *		their work to the appopriate node support routines which may
 *		in turn call these routines themselves on their subplans.
77
 */
78 79
#include "postgres.h"

80
#include "executor/executor.h"
81
#include "executor/instrument.h"
B
Bruce Momjian 已提交
82
#include "executor/nodeAgg.h"
83
#include "executor/nodeAppend.h"
84
#include "executor/nodeFunctionscan.h"
85 86 87
#include "executor/nodeGroup.h"
#include "executor/nodeHash.h"
#include "executor/nodeHashjoin.h"
B
Bruce Momjian 已提交
88
#include "executor/nodeIndexscan.h"
89
#include "executor/nodeLimit.h"
B
Bruce Momjian 已提交
90 91 92 93 94
#include "executor/nodeMaterial.h"
#include "executor/nodeMergejoin.h"
#include "executor/nodeNestloop.h"
#include "executor/nodeResult.h"
#include "executor/nodeSeqscan.h"
95
#include "executor/nodeSetOp.h"
B
Bruce Momjian 已提交
96
#include "executor/nodeSort.h"
V
Vadim B. Mikheev 已提交
97
#include "executor/nodeSubplan.h"
98
#include "executor/nodeSubqueryscan.h"
99
#include "executor/nodeTidscan.h"
B
Bruce Momjian 已提交
100 101 102
#include "executor/nodeUnique.h"
#include "miscadmin.h"
#include "tcop/tcopprot.h"
103 104

/* ------------------------------------------------------------------------
105 106 107 108 109 110 111
 *		ExecInitNode
 *
 *		Recursively initializes all the nodes in the plan rooted
 *		at 'node'.
 *
 *		Initial States:
 *		  'node' is the plan produced by the query planner
112
 *		  'estate' is the shared execution state for the query tree
113
 *
114
 *		Returns a PlanState node corresponding to the given Plan node.
115 116
 * ------------------------------------------------------------------------
 */
117 118
PlanState *
ExecInitNode(Plan *node, EState *estate)
119
{
120 121
	PlanState  *result;
	List	   *subps;
V
Vadim B. Mikheev 已提交
122
	List	   *subp;
123

124 125
	/*
	 * do nothing when we get to the end of a leaf on tree.
126
	 */
127
	if (node == NULL)
128
		return NULL;
129

130 131
	switch (nodeTag(node))
	{
132 133
			/*
			 * control nodes
134 135
			 */
		case T_Result:
136
			result = (PlanState *) ExecInitResult((Result *) node, estate);
137 138 139
			break;

		case T_Append:
140
			result = (PlanState *) ExecInitAppend((Append *) node, estate);
141 142
			break;

143 144
			/*
			 * scan nodes
145 146
			 */
		case T_SeqScan:
147
			result = (PlanState *) ExecInitSeqScan((SeqScan *) node, estate);
148 149 150
			break;

		case T_IndexScan:
151
			result = (PlanState *) ExecInitIndexScan((IndexScan *) node, estate);
152 153
			break;

154
		case T_TidScan:
155
			result = (PlanState *) ExecInitTidScan((TidScan *) node, estate);
156 157 158
			break;

		case T_SubqueryScan:
159
			result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node, estate);
160 161
			break;

162
		case T_FunctionScan:
163
			result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node, estate);
164 165
			break;

166 167
			/*
			 * join nodes
168 169
			 */
		case T_NestLoop:
170
			result = (PlanState *) ExecInitNestLoop((NestLoop *) node, estate);
171 172 173
			break;

		case T_MergeJoin:
174
			result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node, estate);
175 176 177
			break;

		case T_HashJoin:
178
			result = (PlanState *) ExecInitHashJoin((HashJoin *) node, estate);
179 180
			break;

181 182
			/*
			 * materialization nodes
183 184
			 */
		case T_Material:
185
			result = (PlanState *) ExecInitMaterial((Material *) node, estate);
186 187 188
			break;

		case T_Sort:
189
			result = (PlanState *) ExecInitSort((Sort *) node, estate);
190 191
			break;

192 193
		case T_Group:
			result = (PlanState *) ExecInitGroup((Group *) node, estate);
194 195
			break;

196 197
		case T_Agg:
			result = (PlanState *) ExecInitAgg((Agg *) node, estate);
198 199
			break;

200 201
		case T_Unique:
			result = (PlanState *) ExecInitUnique((Unique *) node, estate);
202 203
			break;

204 205
		case T_Hash:
			result = (PlanState *) ExecInitHash((Hash *) node, estate);
206 207
			break;

208 209 210 211 212 213
		case T_SetOp:
			result = (PlanState *) ExecInitSetOp((SetOp *) node, estate);
			break;

		case T_Limit:
			result = (PlanState *) ExecInitLimit((Limit *) node, estate);
214 215 216
			break;

		default:
217
			elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
218
			result = NULL;		/* keep compiler quiet */
219
			break;
220
	}
221

222 223 224 225 226 227
	/*
	 * Initialize any initPlans present in this node.  The planner put
	 * them in a separate list for us.
	 */
	subps = NIL;
	foreach(subp, node->initPlan)
V
Vadim B. Mikheev 已提交
228
	{
229 230
		SubPlan	   *subplan = (SubPlan *) lfirst(subp);
		SubPlanState *sstate;
231

232
		Assert(IsA(subplan, SubPlan));
233 234 235
		sstate = ExecInitExprInitPlan(subplan, result);
		ExecInitSubPlan(sstate, estate);
		subps = lappend(subps, sstate);
V
Vadim B. Mikheev 已提交
236
	}
237 238 239 240
	result->initPlan = subps;

	/*
	 * Initialize any subPlans present in this node.  These were found
241 242 243
	 * by ExecInitExpr during initialization of the PlanState.  Note we
	 * must do this after initializing initPlans, in case their arguments
	 * contain subPlans (is that actually possible? perhaps not).
244 245 246 247
	 */
	subps = NIL;
	foreach(subp, result->subPlan)
	{
248
		SubPlanState *sstate = (SubPlanState *) lfirst(subp);
249

250
		Assert(IsA(sstate, SubPlanState));
251 252
		ExecInitSubPlan(sstate, estate);
		subps = lappend(subps, sstate);
253 254 255 256 257 258
	}
	result->subPlan = subps;

	/* Set up instrumentation for this node if requested */
	if (estate->es_instrument)
		result->instrument = InstrAlloc();
259 260

	return result;
261 262 263 264
}


/* ----------------------------------------------------------------
265 266
 *		ExecProcNode
 *
267
 *		Execute the given node to return a(nother) tuple.
268 269 270
 * ----------------------------------------------------------------
 */
TupleTableSlot *
271
ExecProcNode(PlanState *node)
272
{
273 274
	TupleTableSlot *result;

275 276
	CHECK_FOR_INTERRUPTS();

277 278
	/*
	 * deal with NULL nodes..
279
	 */
280 281
	if (node == NULL)
		return NULL;
282

283
	if (node->chgParam != NULL)	/* something changed */
284
		ExecReScan(node, NULL); /* let ReScan handle this */
285

286 287 288
	if (node->instrument)
		InstrStartNode(node->instrument);

289 290
	switch (nodeTag(node))
	{
291 292 293
			/*
			 * control nodes
			 */
294 295
		case T_ResultState:
			result = ExecResult((ResultState *) node);
296 297
			break;

298 299
		case T_AppendState:
			result = ExecProcAppend((AppendState *) node);
300 301
			break;

302 303
			/*
			 * scan nodes
304
			 */
305 306
		case T_SeqScanState:
			result = ExecSeqScan((SeqScanState *) node);
307 308
			break;

309 310
		case T_IndexScanState:
			result = ExecIndexScan((IndexScanState *) node);
311 312
			break;

313 314
		case T_TidScanState:
			result = ExecTidScan((TidScanState *) node);
315 316
			break;

317 318
		case T_SubqueryScanState:
			result = ExecSubqueryScan((SubqueryScanState *) node);
319 320
			break;

321 322
		case T_FunctionScanState:
			result = ExecFunctionScan((FunctionScanState *) node);
323 324
			break;

325 326
			/*
			 * join nodes
327
			 */
328 329
		case T_NestLoopState:
			result = ExecNestLoop((NestLoopState *) node);
330 331
			break;

332 333
		case T_MergeJoinState:
			result = ExecMergeJoin((MergeJoinState *) node);
334 335
			break;

336 337
		case T_HashJoinState:
			result = ExecHashJoin((HashJoinState *) node);
338 339
			break;

340 341
			/*
			 * materialization nodes
342
			 */
343 344
		case T_MaterialState:
			result = ExecMaterial((MaterialState *) node);
345 346
			break;

347 348
		case T_SortState:
			result = ExecSort((SortState *) node);
349 350
			break;

351 352
		case T_GroupState:
			result = ExecGroup((GroupState *) node);
353 354
			break;

355 356
		case T_AggState:
			result = ExecAgg((AggState *) node);
357 358
			break;

359 360
		case T_UniqueState:
			result = ExecUnique((UniqueState *) node);
361 362
			break;

363 364
		case T_HashState:
			result = ExecHash((HashState *) node);
365 366
			break;

367 368 369 370 371 372
		case T_SetOpState:
			result = ExecSetOp((SetOpState *) node);
			break;

		case T_LimitState:
			result = ExecLimit((LimitState *) node);
373 374 375
			break;

		default:
376
			elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
V
Vadim B. Mikheev 已提交
377
			result = NULL;
378
			break;
379 380
	}

381 382 383
	if (node->instrument)
		InstrStopNode(node->instrument, !TupIsNull(result));

384
	return result;
385 386
}

387 388 389 390 391 392
/*
 * ExecCountSlotsNode - count up the number of tuple table slots needed
 *
 * Note that this scans a Plan tree, not a PlanState tree, because we
 * haven't built the PlanState tree yet ...
 */
393
int
394
ExecCountSlotsNode(Plan *node)
395
{
396
	if (node == NULL)
397
		return 0;
398

399 400
	switch (nodeTag(node))
	{
401 402
			/*
			 * control nodes
403 404 405 406 407 408 409
			 */
		case T_Result:
			return ExecCountSlotsResult((Result *) node);

		case T_Append:
			return ExecCountSlotsAppend((Append *) node);

410 411
			/*
			 * scan nodes
412 413 414 415 416 417 418
			 */
		case T_SeqScan:
			return ExecCountSlotsSeqScan((SeqScan *) node);

		case T_IndexScan:
			return ExecCountSlotsIndexScan((IndexScan *) node);

419 420 421 422 423 424
		case T_TidScan:
			return ExecCountSlotsTidScan((TidScan *) node);

		case T_SubqueryScan:
			return ExecCountSlotsSubqueryScan((SubqueryScan *) node);

425 426 427
		case T_FunctionScan:
			return ExecCountSlotsFunctionScan((FunctionScan *) node);

428 429
			/*
			 * join nodes
430 431 432 433 434 435 436
			 */
		case T_NestLoop:
			return ExecCountSlotsNestLoop((NestLoop *) node);

		case T_MergeJoin:
			return ExecCountSlotsMergeJoin((MergeJoin *) node);

437 438 439
		case T_HashJoin:
			return ExecCountSlotsHashJoin((HashJoin *) node);

440 441
			/*
			 * materialization nodes
442 443 444 445 446 447 448
			 */
		case T_Material:
			return ExecCountSlotsMaterial((Material *) node);

		case T_Sort:
			return ExecCountSlotsSort((Sort *) node);

449 450 451 452 453 454
		case T_Group:
			return ExecCountSlotsGroup((Group *) node);

		case T_Agg:
			return ExecCountSlotsAgg((Agg *) node);

455 456 457
		case T_Unique:
			return ExecCountSlotsUnique((Unique *) node);

458 459 460
		case T_Hash:
			return ExecCountSlotsHash((Hash *) node);

461 462 463
		case T_SetOp:
			return ExecCountSlotsSetOp((SetOp *) node);

464 465 466
		case T_Limit:
			return ExecCountSlotsLimit((Limit *) node);

467
		default:
468
			elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
469
			break;
470
	}
471

472
	return 0;
473 474
}

475 476
/* ----------------------------------------------------------------
 *		ExecEndNode
477
 *
478 479 480 481 482 483 484
 *		Recursively cleans up all the nodes in the plan rooted
 *		at 'node'.
 *
 *		After this operation, the query plan will not be able to
 *		processed any further.	This should be called only after
 *		the query plan has been fully executed.
 * ----------------------------------------------------------------
485 486
 */
void
487
ExecEndNode(PlanState *node)
488
{
V
Vadim B. Mikheev 已提交
489
	List	   *subp;
490

491 492
	/*
	 * do nothing when we get to the end of a leaf on tree.
493
	 */
494 495
	if (node == NULL)
		return;
496

497
	/* Clean up initPlans and subPlans */
498
	foreach(subp, node->initPlan)
499
		ExecEndSubPlan((SubPlanState *) lfirst(subp));
500
	foreach(subp, node->subPlan)
501
		ExecEndSubPlan((SubPlanState *) lfirst(subp));
502

503
	if (node->chgParam != NULL)
V
Vadim B. Mikheev 已提交
504
	{
505 506
		bms_free(node->chgParam);
		node->chgParam = NULL;
V
Vadim B. Mikheev 已提交
507
	}
508 509 510

	switch (nodeTag(node))
	{
511 512 513
			/*
			 * control nodes
			 */
514 515
		case T_ResultState:
			ExecEndResult((ResultState *) node);
516 517
			break;

518 519
		case T_AppendState:
			ExecEndAppend((AppendState *) node);
520 521
			break;

522 523
			/*
			 * scan nodes
524
			 */
525 526
		case T_SeqScanState:
			ExecEndSeqScan((SeqScanState *) node);
527 528
			break;

529 530
		case T_IndexScanState:
			ExecEndIndexScan((IndexScanState *) node);
531 532
			break;

533 534
		case T_TidScanState:
			ExecEndTidScan((TidScanState *) node);
535 536
			break;

537 538
		case T_SubqueryScanState:
			ExecEndSubqueryScan((SubqueryScanState *) node);
539 540
			break;

541 542
		case T_FunctionScanState:
			ExecEndFunctionScan((FunctionScanState *) node);
543 544
			break;

545 546
			/*
			 * join nodes
547
			 */
548 549
		case T_NestLoopState:
			ExecEndNestLoop((NestLoopState *) node);
550 551
			break;

552 553
		case T_MergeJoinState:
			ExecEndMergeJoin((MergeJoinState *) node);
554 555
			break;

556 557
		case T_HashJoinState:
			ExecEndHashJoin((HashJoinState *) node);
558 559
			break;

560 561
			/*
			 * materialization nodes
562
			 */
563 564
		case T_MaterialState:
			ExecEndMaterial((MaterialState *) node);
565 566
			break;

567 568
		case T_SortState:
			ExecEndSort((SortState *) node);
569 570
			break;

571 572
		case T_GroupState:
			ExecEndGroup((GroupState *) node);
573 574
			break;

575 576
		case T_AggState:
			ExecEndAgg((AggState *) node);
577 578
			break;

579 580
		case T_UniqueState:
			ExecEndUnique((UniqueState *) node);
581 582
			break;

583 584
		case T_HashState:
			ExecEndHash((HashState *) node);
585 586
			break;

587 588 589 590 591 592
		case T_SetOpState:
			ExecEndSetOp((SetOpState *) node);
			break;

		case T_LimitState:
			ExecEndLimit((LimitState *) node);
593 594 595
			break;

		default:
596
			elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
597
			break;
598
	}
599
}