execProcnode.c 17.5 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.33 2002/12/13 19:45:52 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
 *		ExecGetTupType	-		get result tuple type of a plan node
26
 *
27 28 29 30
 *	 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.
31
 *
32 33 34
 *	 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:
35
 *
36 37 38
 *				retrieve (DEPT.no_emps, EMP.age)
 *				where EMP.name = DEPT.mgr and
 *					  DEPT.name = "shoe"
39
 *
40
 *		Suppose the planner gives us the following plan:
41
 *
42 43 44 45 46 47 48 49 50 51 52 53 54 55
 *						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
56 57 58
 *		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.
59
 *
60 61
 *	  * Then when ExecRun() is called, it calls ExecutePlan() which calls
 *		ExecProcNode() repeatedly on the top node of the plan state tree.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
 *		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.
78
 */
79 80
#include "postgres.h"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

224 225 226 227 228 229
	/*
	 * 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 已提交
230
	{
231
		SubPlanExpr *subplan = (SubPlanExpr *) lfirst(subp);
232
		SubPlanExprState *sstate;
233

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

	/*
	 * Initialize any subPlans present in this node.  These were found
243 244 245
	 * 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).
246 247 248 249
	 */
	subps = NIL;
	foreach(subp, result->subPlan)
	{
250
		SubPlanExprState *sstate = (SubPlanExprState *) lfirst(subp);
251

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

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

	return result;
263 264 265 266
}


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

277 278
	CHECK_FOR_INTERRUPTS();

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

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

288 289 290
	if (node->instrument)
		InstrStartNode(node->instrument);

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

300 301
		case T_AppendState:
			result = ExecProcAppend((AppendState *) node);
302 303
			break;

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

311 312
		case T_IndexScanState:
			result = ExecIndexScan((IndexScanState *) node);
313 314
			break;

315 316
		case T_TidScanState:
			result = ExecTidScan((TidScanState *) node);
317 318
			break;

319 320
		case T_SubqueryScanState:
			result = ExecSubqueryScan((SubqueryScanState *) node);
321 322
			break;

323 324
		case T_FunctionScanState:
			result = ExecFunctionScan((FunctionScanState *) node);
325 326
			break;

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

334 335
		case T_MergeJoinState:
			result = ExecMergeJoin((MergeJoinState *) node);
336 337
			break;

338 339
		case T_HashJoinState:
			result = ExecHashJoin((HashJoinState *) node);
340 341
			break;

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

349 350
		case T_SortState:
			result = ExecSort((SortState *) node);
351 352
			break;

353 354
		case T_GroupState:
			result = ExecGroup((GroupState *) node);
355 356
			break;

357 358
		case T_AggState:
			result = ExecAgg((AggState *) node);
359 360
			break;

361 362
		case T_UniqueState:
			result = ExecUnique((UniqueState *) node);
363 364
			break;

365 366
		case T_HashState:
			result = ExecHash((HashState *) node);
367 368
			break;

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

		case T_LimitState:
			result = ExecLimit((LimitState *) node);
375 376 377
			break;

		default:
378 379
			elog(ERROR, "ExecProcNode: node type %d unsupported",
				 (int) nodeTag(node));
V
Vadim B. Mikheev 已提交
380
			result = NULL;
381
			break;
382 383
	}

384 385 386
	if (node->instrument)
		InstrStopNode(node->instrument, !TupIsNull(result));

387
	return result;
388 389
}

390 391 392 393 394 395
/*
 * 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 ...
 */
396
int
397
ExecCountSlotsNode(Plan *node)
398
{
399
	if (node == NULL)
400
		return 0;
401

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

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

413 414
			/*
			 * scan nodes
415 416 417 418 419 420 421
			 */
		case T_SeqScan:
			return ExecCountSlotsSeqScan((SeqScan *) node);

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

422 423 424 425 426 427
		case T_TidScan:
			return ExecCountSlotsTidScan((TidScan *) node);

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

428 429 430
		case T_FunctionScan:
			return ExecCountSlotsFunctionScan((FunctionScan *) node);

431 432
			/*
			 * join nodes
433 434 435 436 437 438 439
			 */
		case T_NestLoop:
			return ExecCountSlotsNestLoop((NestLoop *) node);

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

440 441 442
		case T_HashJoin:
			return ExecCountSlotsHashJoin((HashJoin *) node);

443 444
			/*
			 * materialization nodes
445 446 447 448 449 450 451
			 */
		case T_Material:
			return ExecCountSlotsMaterial((Material *) node);

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

452 453 454 455 456 457
		case T_Group:
			return ExecCountSlotsGroup((Group *) node);

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

458 459 460
		case T_Unique:
			return ExecCountSlotsUnique((Unique *) node);

461 462 463
		case T_Hash:
			return ExecCountSlotsHash((Hash *) node);

464 465 466
		case T_SetOp:
			return ExecCountSlotsSetOp((SetOp *) node);

467 468 469
		case T_Limit:
			return ExecCountSlotsLimit((Limit *) node);

470
		default:
471 472
			elog(ERROR, "ExecCountSlotsNode: node type %d unsupported",
				 (int) nodeTag(node));
473
			break;
474
	}
475

476
	return 0;
477 478
}

479 480
/* ----------------------------------------------------------------
 *		ExecEndNode
481
 *
482 483 484 485 486 487 488
 *		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.
 * ----------------------------------------------------------------
489 490
 */
void
491
ExecEndNode(PlanState *node)
492
{
V
Vadim B. Mikheev 已提交
493
	List	   *subp;
494

495 496
	/*
	 * do nothing when we get to the end of a leaf on tree.
497
	 */
498 499
	if (node == NULL)
		return;
500

501
	/* Clean up initPlans and subPlans */
502
	foreach(subp, node->initPlan)
503
		ExecEndSubPlan((SubPlanExprState *) lfirst(subp));
504
	foreach(subp, node->subPlan)
505
		ExecEndSubPlan((SubPlanExprState *) lfirst(subp));
506 507

	if (node->chgParam != NIL)
V
Vadim B. Mikheev 已提交
508
	{
509
		freeList(node->chgParam);
510
		node->chgParam = NIL;
V
Vadim B. Mikheev 已提交
511
	}
512 513 514

	switch (nodeTag(node))
	{
515 516 517
			/*
			 * control nodes
			 */
518 519
		case T_ResultState:
			ExecEndResult((ResultState *) node);
520 521
			break;

522 523
		case T_AppendState:
			ExecEndAppend((AppendState *) node);
524 525
			break;

526 527
			/*
			 * scan nodes
528
			 */
529 530
		case T_SeqScanState:
			ExecEndSeqScan((SeqScanState *) node);
531 532
			break;

533 534
		case T_IndexScanState:
			ExecEndIndexScan((IndexScanState *) node);
535 536
			break;

537 538
		case T_TidScanState:
			ExecEndTidScan((TidScanState *) node);
539 540
			break;

541 542
		case T_SubqueryScanState:
			ExecEndSubqueryScan((SubqueryScanState *) node);
543 544
			break;

545 546
		case T_FunctionScanState:
			ExecEndFunctionScan((FunctionScanState *) node);
547 548
			break;

549 550
			/*
			 * join nodes
551
			 */
552 553
		case T_NestLoopState:
			ExecEndNestLoop((NestLoopState *) node);
554 555
			break;

556 557
		case T_MergeJoinState:
			ExecEndMergeJoin((MergeJoinState *) node);
558 559
			break;

560 561
		case T_HashJoinState:
			ExecEndHashJoin((HashJoinState *) node);
562 563
			break;

564 565
			/*
			 * materialization nodes
566
			 */
567 568
		case T_MaterialState:
			ExecEndMaterial((MaterialState *) node);
569 570
			break;

571 572
		case T_SortState:
			ExecEndSort((SortState *) node);
573 574
			break;

575 576
		case T_GroupState:
			ExecEndGroup((GroupState *) node);
577 578
			break;

579 580
		case T_AggState:
			ExecEndAgg((AggState *) node);
581 582
			break;

583 584
		case T_UniqueState:
			ExecEndUnique((UniqueState *) node);
585 586
			break;

587 588
		case T_HashState:
			ExecEndHash((HashState *) node);
589 590
			break;

591 592 593 594 595 596
		case T_SetOpState:
			ExecEndSetOp((SetOpState *) node);
			break;

		case T_LimitState:
			ExecEndLimit((LimitState *) node);
597 598 599
			break;

		default:
600 601
			elog(ERROR, "ExecEndNode: node type %d unsupported",
				 (int) nodeTag(node));
602
			break;
603
	}
604
}
605 606 607 608 609 610 611 612 613 614 615 616 617


/* ----------------------------------------------------------------
 *		ExecGetTupType
 *
 *		this gives you the tuple descriptor for tuples returned
 *		by this node.  I really wish I could ditch this routine,
 *		but since not all nodes store their type info in the same
 *		place, we have to do something special for each node type.
 *
 * ----------------------------------------------------------------
 */
TupleDesc
618
ExecGetTupType(PlanState *node)
619 620 621 622 623 624 625 626
{
	TupleTableSlot *slot;

	if (node == NULL)
		return NULL;

	switch (nodeTag(node))
	{
627
		case T_ResultState:
628
			{
629
				ResultState *resstate = (ResultState *) node;
630

631
				slot = resstate->ps.ps_ResultTupleSlot;
632 633 634
			}
			break;

635
		case T_AppendState:
636
			{
637
				AppendState *appendstate = (AppendState *) node;
638

639
				slot = appendstate->ps.ps_ResultTupleSlot;
640 641 642
			}
			break;

643
		case T_SeqScanState:
644
			{
645
				SeqScanState *scanstate = (SeqScanState *) node;
646

647
				slot = scanstate->ps.ps_ResultTupleSlot;
648 649 650
			}
			break;

651
		case T_IndexScanState:
652
			{
653
				IndexScanState *scanstate = (IndexScanState *) node;
654

655
				slot = scanstate->ss.ps.ps_ResultTupleSlot;
656 657 658
			}
			break;

659
		case T_TidScanState:
660
			{
661
				TidScanState *scanstate = (TidScanState *) node;
662

663
				slot = scanstate->ss.ps.ps_ResultTupleSlot;
664 665 666
			}
			break;

667
		case T_SubqueryScanState:
668
			{
669
				SubqueryScanState *scanstate = (SubqueryScanState *) node;
670

671
				slot = scanstate->ss.ps.ps_ResultTupleSlot;
672 673 674
			}
			break;

675
		case T_FunctionScanState:
676
			{
677
				FunctionScanState *scanstate = (FunctionScanState *) node;
678

679
				slot = scanstate->ss.ps.ps_ResultTupleSlot;
680 681 682
			}
			break;

683
		case T_NestLoopState:
684
			{
685
				NestLoopState *nlstate = (NestLoopState *) node;
686

687
				slot = nlstate->js.ps.ps_ResultTupleSlot;
688 689 690
			}
			break;

691
		case T_MergeJoinState:
692
			{
693
				MergeJoinState *mergestate = (MergeJoinState *) node;
694

695
				slot = mergestate->js.ps.ps_ResultTupleSlot;
696 697 698
			}
			break;

699
		case T_HashJoinState:
700
			{
701
				HashJoinState *hashjoinstate = (HashJoinState *) node;
702

703
				slot = hashjoinstate->js.ps.ps_ResultTupleSlot;
704 705 706
			}
			break;

707
		case T_MaterialState:
708
			{
709
				MaterialState *matstate = (MaterialState *) node;
710

711
				slot = matstate->ss.ss_ScanTupleSlot;
712 713 714
			}
			break;

715
		case T_SortState:
716
			{
717
				SortState  *sortstate = (SortState *) node;
718

719
				slot = sortstate->ss.ss_ScanTupleSlot;
720 721 722
			}
			break;

723
		case T_GroupState:
724
			{
725
				GroupState *grpstate = (GroupState *) node;
726

727
				slot = grpstate->ss.ps.ps_ResultTupleSlot;
728 729 730
			}
			break;

731
		case T_AggState:
732
			{
733
				AggState   *aggstate = (AggState *) node;
734

735
				slot = aggstate->ss.ps.ps_ResultTupleSlot;
736 737 738
			}
			break;

739
		case T_UniqueState:
740
			{
741
				UniqueState *uniquestate = (UniqueState *) node;
742

743
				slot = uniquestate->ps.ps_ResultTupleSlot;
744 745 746
			}
			break;

747
		case T_HashState:
748
			{
749
				HashState  *hashstate = (HashState *) node;
750

751
				slot = hashstate->ps.ps_ResultTupleSlot;
752 753 754
			}
			break;

755
		case T_SetOpState:
756
			{
757
				SetOpState *setopstate = (SetOpState *) node;
758

759
				slot = setopstate->ps.ps_ResultTupleSlot;
760 761 762
			}
			break;

763
		case T_LimitState:
764
			{
765
				LimitState *limitstate = (LimitState *) node;
766

767
				slot = limitstate->ps.ps_ResultTupleSlot;
768 769 770 771
			}
			break;

		default:
772 773 774

			/*
			 * should never get here
775 776 777 778 779 780 781 782
			 */
			elog(ERROR, "ExecGetTupType: node type %d unsupported",
				 (int) nodeTag(node));
			return NULL;
	}

	return slot->ttc_tupleDescriptor;
}