execProcnode.c 16.3 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
B
Bruce Momjian 已提交
15
 *	  $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.30 2002/06/20 20:29:27 momjian Exp $
16 17 18 19
 *
 *-------------------------------------------------------------------------
 */
/*
20
 *	 INTERFACE ROUTINES
B
Bruce Momjian 已提交
21
 *		ExecInitNode	-		initialize a plan node and its subplans
22
 *		ExecProcNode	-		get a tuple by executing the plan node
B
Bruce Momjian 已提交
23
 *		ExecEndNode		-		shut down a plan node and its subplans
24 25
 *		ExecCountSlotsNode -	count tuple slots needed by plan tree
 *		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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
 *						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
 *		and so forth until the entire plan is initialized.
 *
 *	  * Then when ExecRun() is called, it calls ExecutePlan() which
 *		calls ExecProcNode() repeatedly on the top node of the plan.
 *		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.
76 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 84 85 86
#include "executor/nodeAppend.h"
#include "executor/nodeGroup.h"
#include "executor/nodeHash.h"
#include "executor/nodeHashjoin.h"
B
Bruce Momjian 已提交
87
#include "executor/nodeIndexscan.h"
88
#include "executor/nodeTidscan.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/nodeFunctionscan.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 112 113
 *		ExecInitNode
 *
 *		Recursively initializes all the nodes in the plan rooted
 *		at 'node'.
 *
 *		Initial States:
 *		  'node' is the plan produced by the query planner
 *
 *		returns TRUE/FALSE on whether the plan was successfully initialized
114 115 116
 * ------------------------------------------------------------------------
 */
bool
117
ExecInitNode(Plan *node, EState *estate, Plan *parent)
118
{
119
	bool		result;
V
Vadim B. Mikheev 已提交
120
	List	   *subp;
121

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

128 129 130 131
	/* Set up instrumentation for this node if the parent has it */
	if (!node->instrument && parent && parent->instrument)
		node->instrument = InstrAlloc();

132
	foreach(subp, node->initPlan)
V
Vadim B. Mikheev 已提交
133
	{
134 135
		result = ExecInitSubPlan((SubPlan *) lfirst(subp), estate, node);
		if (result == FALSE)
136
			return FALSE;
V
Vadim B. Mikheev 已提交
137
	}
138

139 140
	switch (nodeTag(node))
	{
141 142
			/*
			 * control nodes
143 144 145 146 147 148 149 150 151
			 */
		case T_Result:
			result = ExecInitResult((Result *) node, estate, parent);
			break;

		case T_Append:
			result = ExecInitAppend((Append *) node, estate, parent);
			break;

152 153
			/*
			 * scan nodes
154 155 156 157 158 159 160 161 162
			 */
		case T_SeqScan:
			result = ExecInitSeqScan((SeqScan *) node, estate, parent);
			break;

		case T_IndexScan:
			result = ExecInitIndexScan((IndexScan *) node, estate, parent);
			break;

163 164 165 166 167 168 169 170 171
		case T_TidScan:
			result = ExecInitTidScan((TidScan *) node, estate, parent);
			break;

		case T_SubqueryScan:
			result = ExecInitSubqueryScan((SubqueryScan *) node, estate,
										  parent);
			break;

172 173 174 175 176
		case T_FunctionScan:
			result = ExecInitFunctionScan((FunctionScan *) node, estate,
										  parent);
			break;

177 178
			/*
			 * join nodes
179 180 181 182 183 184 185 186 187
			 */
		case T_NestLoop:
			result = ExecInitNestLoop((NestLoop *) node, estate, parent);
			break;

		case T_MergeJoin:
			result = ExecInitMergeJoin((MergeJoin *) node, estate, parent);
			break;

188 189 190 191 192 193 194 195
		case T_Hash:
			result = ExecInitHash((Hash *) node, estate, parent);
			break;

		case T_HashJoin:
			result = ExecInitHashJoin((HashJoin *) node, estate, parent);
			break;

196 197
			/*
			 * materialization nodes
198 199 200 201 202 203 204 205 206 207 208 209 210
			 */
		case T_Material:
			result = ExecInitMaterial((Material *) node, estate, parent);
			break;

		case T_Sort:
			result = ExecInitSort((Sort *) node, estate, parent);
			break;

		case T_Unique:
			result = ExecInitUnique((Unique *) node, estate, parent);
			break;

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

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

219 220 221 222 223 224 225 226 227
		case T_Group:
			result = ExecInitGroup((Group *) node, estate, parent);
			break;

		case T_Agg:
			result = ExecInitAgg((Agg *) node, estate, parent);
			break;

		default:
228 229
			elog(ERROR, "ExecInitNode: node type %d unsupported",
				 (int) nodeTag(node));
230
			result = FALSE;
231
			break;
232
	}
233 234

	if (result != FALSE)
V
Vadim B. Mikheev 已提交
235
	{
236
		foreach(subp, node->subPlan)
V
Vadim B. Mikheev 已提交
237
		{
238 239
			result = ExecInitSubPlan((SubPlan *) lfirst(subp), estate, node);
			if (result == FALSE)
240
				return FALSE;
V
Vadim B. Mikheev 已提交
241 242
		}
	}
243 244

	return result;
245 246 247 248
}


/* ----------------------------------------------------------------
249 250 251 252
 *		ExecProcNode
 *
 *		Initial States:
 *		  the query tree must be initialized once by calling ExecInit.
253 254 255
 * ----------------------------------------------------------------
 */
TupleTableSlot *
256
ExecProcNode(Plan *node, Plan *parent)
257
{
258 259
	TupleTableSlot *result;

260 261
	CHECK_FOR_INTERRUPTS();

262 263
	/*
	 * deal with NULL nodes..
264
	 */
265 266
	if (node == NULL)
		return NULL;
267 268 269 270

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

271 272 273
	if (node->instrument)
		InstrStartNode(node->instrument);

274 275
	switch (nodeTag(node))
	{
276 277 278
			/*
			 * control nodes
			 */
279 280 281 282 283 284 285 286
		case T_Result:
			result = ExecResult((Result *) node);
			break;

		case T_Append:
			result = ExecProcAppend((Append *) node);
			break;

287 288
			/*
			 * scan nodes
289 290 291 292 293 294 295 296 297
			 */
		case T_SeqScan:
			result = ExecSeqScan((SeqScan *) node);
			break;

		case T_IndexScan:
			result = ExecIndexScan((IndexScan *) node);
			break;

298 299 300 301 302 303 304 305
		case T_TidScan:
			result = ExecTidScan((TidScan *) node);
			break;

		case T_SubqueryScan:
			result = ExecSubqueryScan((SubqueryScan *) node);
			break;

306 307 308 309
		case T_FunctionScan:
			result = ExecFunctionScan((FunctionScan *) node);
			break;

310 311
			/*
			 * join nodes
312 313
			 */
		case T_NestLoop:
314
			result = ExecNestLoop((NestLoop *) node);
315 316 317 318 319 320
			break;

		case T_MergeJoin:
			result = ExecMergeJoin((MergeJoin *) node);
			break;

321 322 323 324 325 326 327 328
		case T_Hash:
			result = ExecHash((Hash *) node);
			break;

		case T_HashJoin:
			result = ExecHashJoin((HashJoin *) node);
			break;

329 330
			/*
			 * materialization nodes
331 332 333 334 335 336 337 338 339 340 341 342 343
			 */
		case T_Material:
			result = ExecMaterial((Material *) node);
			break;

		case T_Sort:
			result = ExecSort((Sort *) node);
			break;

		case T_Unique:
			result = ExecUnique((Unique *) node);
			break;

344 345 346 347
		case T_SetOp:
			result = ExecSetOp((SetOp *) node);
			break;

348 349 350 351
		case T_Limit:
			result = ExecLimit((Limit *) node);
			break;

352 353 354 355 356 357 358 359 360
		case T_Group:
			result = ExecGroup((Group *) node);
			break;

		case T_Agg:
			result = ExecAgg((Agg *) node);
			break;

		default:
361 362
			elog(ERROR, "ExecProcNode: node type %d unsupported",
				 (int) nodeTag(node));
V
Vadim B. Mikheev 已提交
363
			result = NULL;
364
			break;
365 366
	}

367 368 369
	if (node->instrument)
		InstrStopNode(node->instrument, !TupIsNull(result));

370
	return result;
371 372 373
}

int
374
ExecCountSlotsNode(Plan *node)
375
{
376 377
	if (node == (Plan *) NULL)
		return 0;
378

379 380
	switch (nodeTag(node))
	{
381 382
			/*
			 * control nodes
383 384 385 386 387 388 389
			 */
		case T_Result:
			return ExecCountSlotsResult((Result *) node);

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

390 391
			/*
			 * scan nodes
392 393 394 395 396 397 398
			 */
		case T_SeqScan:
			return ExecCountSlotsSeqScan((SeqScan *) node);

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

399 400 401 402 403 404
		case T_TidScan:
			return ExecCountSlotsTidScan((TidScan *) node);

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

405 406 407
		case T_FunctionScan:
			return ExecCountSlotsFunctionScan((FunctionScan *) node);

408 409
			/*
			 * join nodes
410 411 412 413 414 415 416
			 */
		case T_NestLoop:
			return ExecCountSlotsNestLoop((NestLoop *) node);

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

417 418 419 420 421 422
		case T_Hash:
			return ExecCountSlotsHash((Hash *) node);

		case T_HashJoin:
			return ExecCountSlotsHashJoin((HashJoin *) node);

423 424
			/*
			 * materialization nodes
425 426 427 428 429 430 431 432 433 434
			 */
		case T_Material:
			return ExecCountSlotsMaterial((Material *) node);

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

		case T_Unique:
			return ExecCountSlotsUnique((Unique *) node);

435 436 437
		case T_SetOp:
			return ExecCountSlotsSetOp((SetOp *) node);

438 439 440
		case T_Limit:
			return ExecCountSlotsLimit((Limit *) node);

441 442 443 444 445 446 447
		case T_Group:
			return ExecCountSlotsGroup((Group *) node);

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

		default:
448 449
			elog(ERROR, "ExecCountSlotsNode: node type %d unsupported",
				 (int) nodeTag(node));
450
			break;
451 452
	}
	return 0;
453 454
}

455 456
/* ----------------------------------------------------------------
 *		ExecEndNode
457
 *
458 459 460 461 462 463 464
 *		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.
 * ----------------------------------------------------------------
465 466
 */
void
467
ExecEndNode(Plan *node, Plan *parent)
468
{
V
Vadim B. Mikheev 已提交
469
	List	   *subp;
470

471 472
	/*
	 * do nothing when we get to the end of a leaf on tree.
473
	 */
474 475
	if (node == NULL)
		return;
476 477 478 479 480 481

	foreach(subp, node->initPlan)
		ExecEndSubPlan((SubPlan *) lfirst(subp));
	foreach(subp, node->subPlan)
		ExecEndSubPlan((SubPlan *) lfirst(subp));
	if (node->chgParam != NULL)
V
Vadim B. Mikheev 已提交
482
	{
483
		freeList(node->chgParam);
V
Vadim B. Mikheev 已提交
484 485
		node->chgParam = NULL;
	}
486 487 488

	switch (nodeTag(node))
	{
489 490 491
			/*
			 * control nodes
			 */
492 493 494 495 496 497 498 499
		case T_Result:
			ExecEndResult((Result *) node);
			break;

		case T_Append:
			ExecEndAppend((Append *) node);
			break;

500 501
			/*
			 * scan nodes
502 503 504 505 506 507 508 509 510
			 */
		case T_SeqScan:
			ExecEndSeqScan((SeqScan *) node);
			break;

		case T_IndexScan:
			ExecEndIndexScan((IndexScan *) node);
			break;

511 512 513 514 515 516 517 518
		case T_TidScan:
			ExecEndTidScan((TidScan *) node);
			break;

		case T_SubqueryScan:
			ExecEndSubqueryScan((SubqueryScan *) node);
			break;

519 520 521 522
		case T_FunctionScan:
			ExecEndFunctionScan((FunctionScan *) node);
			break;

523 524
			/*
			 * join nodes
525 526 527 528 529 530 531 532 533
			 */
		case T_NestLoop:
			ExecEndNestLoop((NestLoop *) node);
			break;

		case T_MergeJoin:
			ExecEndMergeJoin((MergeJoin *) node);
			break;

534 535 536 537 538 539 540 541
		case T_Hash:
			ExecEndHash((Hash *) node);
			break;

		case T_HashJoin:
			ExecEndHashJoin((HashJoin *) node);
			break;

542 543
			/*
			 * materialization nodes
544 545 546 547 548 549 550 551 552 553 554 555 556
			 */
		case T_Material:
			ExecEndMaterial((Material *) node);
			break;

		case T_Sort:
			ExecEndSort((Sort *) node);
			break;

		case T_Unique:
			ExecEndUnique((Unique *) node);
			break;

557 558 559 560
		case T_SetOp:
			ExecEndSetOp((SetOp *) node);
			break;

561 562 563 564
		case T_Limit:
			ExecEndLimit((Limit *) node);
			break;

565 566 567 568 569 570 571 572 573
		case T_Group:
			ExecEndGroup((Group *) node);
			break;

		case T_Agg:
			ExecEndAgg((Agg *) node);
			break;

		default:
574 575
			elog(ERROR, "ExecEndNode: node type %d unsupported",
				 (int) nodeTag(node));
576
			break;
577
	}
578 579 580

	if (node->instrument)
		InstrEndLoop(node->instrument);
581
}
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659


/* ----------------------------------------------------------------
 *		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
ExecGetTupType(Plan *node)
{
	TupleTableSlot *slot;

	if (node == NULL)
		return NULL;

	switch (nodeTag(node))
	{
		case T_Result:
			{
				ResultState *resstate = ((Result *) node)->resstate;

				slot = resstate->cstate.cs_ResultTupleSlot;
			}
			break;

		case T_SeqScan:
			{
				CommonScanState *scanstate = ((SeqScan *) node)->scanstate;

				slot = scanstate->cstate.cs_ResultTupleSlot;
			}
			break;

		case T_NestLoop:
			{
				NestLoopState *nlstate = ((NestLoop *) node)->nlstate;

				slot = nlstate->jstate.cs_ResultTupleSlot;
			}
			break;

		case T_Append:
			{
				AppendState *appendstate = ((Append *) node)->appendstate;

				slot = appendstate->cstate.cs_ResultTupleSlot;
			}
			break;

		case T_IndexScan:
			{
				CommonScanState *scanstate = ((IndexScan *) node)->scan.scanstate;

				slot = scanstate->cstate.cs_ResultTupleSlot;
			}
			break;

		case T_TidScan:
			{
				CommonScanState *scanstate = ((TidScan *) node)->scan.scanstate;

				slot = scanstate->cstate.cs_ResultTupleSlot;
			}
			break;

		case T_SubqueryScan:
			{
				CommonScanState *scanstate = ((SubqueryScan *) node)->scan.scanstate;

				slot = scanstate->cstate.cs_ResultTupleSlot;
			}
			break;

660 661 662 663 664 665 666 667
		case T_FunctionScan:
			{
				CommonScanState *scanstate = ((FunctionScan *) node)->scan.scanstate;

				slot = scanstate->cstate.cs_ResultTupleSlot;
			}
			break;

668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
		case T_Material:
			{
				MaterialState *matstate = ((Material *) node)->matstate;

				slot = matstate->csstate.css_ScanTupleSlot;
			}
			break;

		case T_Sort:
			{
				SortState  *sortstate = ((Sort *) node)->sortstate;

				slot = sortstate->csstate.css_ScanTupleSlot;
			}
			break;

		case T_Agg:
			{
				AggState   *aggstate = ((Agg *) node)->aggstate;

				slot = aggstate->csstate.cstate.cs_ResultTupleSlot;
			}
			break;

		case T_Group:
			{
				GroupState *grpstate = ((Group *) node)->grpstate;

				slot = grpstate->csstate.cstate.cs_ResultTupleSlot;
			}
			break;

		case T_Hash:
			{
				HashState  *hashstate = ((Hash *) node)->hashstate;

				slot = hashstate->cstate.cs_ResultTupleSlot;
			}
			break;

		case T_Unique:
			{
				UniqueState *uniquestate = ((Unique *) node)->uniquestate;

				slot = uniquestate->cstate.cs_ResultTupleSlot;
			}
			break;

		case T_SetOp:
			{
				SetOpState *setopstate = ((SetOp *) node)->setopstate;

				slot = setopstate->cstate.cs_ResultTupleSlot;
			}
			break;

		case T_Limit:
			{
				LimitState *limitstate = ((Limit *) node)->limitstate;

				slot = limitstate->cstate.cs_ResultTupleSlot;
			}
			break;

		case T_MergeJoin:
			{
				MergeJoinState *mergestate = ((MergeJoin *) node)->mergestate;

				slot = mergestate->jstate.cs_ResultTupleSlot;
			}
			break;

		case T_HashJoin:
			{
				HashJoinState *hashjoinstate = ((HashJoin *) node)->hashjoinstate;

				slot = hashjoinstate->jstate.cs_ResultTupleSlot;
			}
			break;

		default:
749 750 751

			/*
			 * should never get here
752 753 754 755 756 757 758 759
			 */
			elog(ERROR, "ExecGetTupType: node type %d unsupported",
				 (int) nodeTag(node));
			return NULL;
	}

	return slot->ttc_tupleDescriptor;
}