execProcnode.c 15.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
 *
10
 * Portions Copyright (c) 1996-2001, 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.26 2001/03/22 06:16:12 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"
B
Bruce Momjian 已提交
81
#include "executor/nodeAgg.h"
82 83 84 85
#include "executor/nodeAppend.h"
#include "executor/nodeGroup.h"
#include "executor/nodeHash.h"
#include "executor/nodeHashjoin.h"
B
Bruce Momjian 已提交
86
#include "executor/nodeIndexscan.h"
87
#include "executor/nodeTidscan.h"
88
#include "executor/nodeLimit.h"
B
Bruce Momjian 已提交
89 90 91 92 93
#include "executor/nodeMaterial.h"
#include "executor/nodeMergejoin.h"
#include "executor/nodeNestloop.h"
#include "executor/nodeResult.h"
#include "executor/nodeSeqscan.h"
94
#include "executor/nodeSetOp.h"
B
Bruce Momjian 已提交
95
#include "executor/nodeSort.h"
V
Vadim B. Mikheev 已提交
96
#include "executor/nodeSubplan.h"
97
#include "executor/nodeSubqueryscan.h"
B
Bruce Momjian 已提交
98 99 100
#include "executor/nodeUnique.h"
#include "miscadmin.h"
#include "tcop/tcopprot.h"
101 102

/* ------------------------------------------------------------------------
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
 *
 *		returns TRUE/FALSE on whether the plan was successfully initialized
112 113 114
 * ------------------------------------------------------------------------
 */
bool
115
ExecInitNode(Plan *node, EState *estate, Plan *parent)
116
{
117
	bool		result;
V
Vadim B. Mikheev 已提交
118
	List	   *subp;
119

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

	foreach(subp, node->initPlan)
V
Vadim B. Mikheev 已提交
127
	{
128 129
		result = ExecInitSubPlan((SubPlan *) lfirst(subp), estate, node);
		if (result == FALSE)
130
			return FALSE;
V
Vadim B. Mikheev 已提交
131
	}
132

133 134
	switch (nodeTag(node))
	{
135 136 137

			/*
			 * control nodes
138 139 140 141 142 143 144 145 146
			 */
		case T_Result:
			result = ExecInitResult((Result *) node, estate, parent);
			break;

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

147 148
			/*
			 * scan nodes
149 150 151 152 153 154 155 156 157
			 */
		case T_SeqScan:
			result = ExecInitSeqScan((SeqScan *) node, estate, parent);
			break;

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

158 159 160 161 162 163 164 165 166
		case T_TidScan:
			result = ExecInitTidScan((TidScan *) node, estate, parent);
			break;

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

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

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

178 179 180 181 182 183 184 185
		case T_Hash:
			result = ExecInitHash((Hash *) node, estate, parent);
			break;

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

186 187
			/*
			 * materialization nodes
188 189 190 191 192 193 194 195 196 197 198 199 200
			 */
		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;

201 202 203 204
		case T_SetOp:
			result = ExecInitSetOp((SetOp *) node, estate, parent);
			break;

205 206 207 208
		case T_Limit:
			result = ExecInitLimit((Limit *) node, estate, parent);
			break;

209 210 211 212 213 214 215 216 217
		case T_Group:
			result = ExecInitGroup((Group *) node, estate, parent);
			break;

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

		default:
218 219
			elog(ERROR, "ExecInitNode: node type %d unsupported",
				 (int) nodeTag(node));
220
			result = FALSE;
221
	}
222 223

	if (result != FALSE)
V
Vadim B. Mikheev 已提交
224
	{
225
		foreach(subp, node->subPlan)
V
Vadim B. Mikheev 已提交
226
		{
227 228
			result = ExecInitSubPlan((SubPlan *) lfirst(subp), estate, node);
			if (result == FALSE)
229
				return FALSE;
V
Vadim B. Mikheev 已提交
230 231
		}
	}
232 233

	return result;
234 235 236 237
}


/* ----------------------------------------------------------------
238 239 240 241
 *		ExecProcNode
 *
 *		Initial States:
 *		  the query tree must be initialized once by calling ExecInit.
242 243 244
 * ----------------------------------------------------------------
 */
TupleTableSlot *
245
ExecProcNode(Plan *node, Plan *parent)
246
{
247 248
	TupleTableSlot *result;

249 250
	CHECK_FOR_INTERRUPTS();

251 252
	/*
	 * deal with NULL nodes..
253
	 */
254 255
	if (node == NULL)
		return NULL;
256 257 258 259

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

260 261
	switch (nodeTag(node))
	{
262 263 264

			/*
			 * control nodes
265 266 267 268 269 270 271 272 273
			 */
		case T_Result:
			result = ExecResult((Result *) node);
			break;

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

274 275
			/*
			 * scan nodes
276 277 278 279 280 281 282 283 284
			 */
		case T_SeqScan:
			result = ExecSeqScan((SeqScan *) node);
			break;

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

285 286 287 288 289 290 291 292
		case T_TidScan:
			result = ExecTidScan((TidScan *) node);
			break;

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

293 294
			/*
			 * join nodes
295 296
			 */
		case T_NestLoop:
297
			result = ExecNestLoop((NestLoop *) node);
298 299 300 301 302 303
			break;

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

304 305 306 307 308 309 310 311
		case T_Hash:
			result = ExecHash((Hash *) node);
			break;

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

312 313
			/*
			 * materialization nodes
314 315 316 317 318 319 320 321 322 323 324 325 326
			 */
		case T_Material:
			result = ExecMaterial((Material *) node);
			break;

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

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

327 328 329 330
		case T_SetOp:
			result = ExecSetOp((SetOp *) node);
			break;

331 332 333 334
		case T_Limit:
			result = ExecLimit((Limit *) node);
			break;

335 336 337 338 339 340 341 342 343
		case T_Group:
			result = ExecGroup((Group *) node);
			break;

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

		default:
344 345
			elog(ERROR, "ExecProcNode: node type %d unsupported",
				 (int) nodeTag(node));
V
Vadim B. Mikheev 已提交
346
			result = NULL;
347 348 349
	}

	return result;
350 351 352
}

int
353
ExecCountSlotsNode(Plan *node)
354
{
355 356
	if (node == (Plan *) NULL)
		return 0;
357

358 359
	switch (nodeTag(node))
	{
360 361 362

			/*
			 * control nodes
363 364 365 366 367 368 369
			 */
		case T_Result:
			return ExecCountSlotsResult((Result *) node);

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

370 371
			/*
			 * scan nodes
372 373 374 375 376 377 378
			 */
		case T_SeqScan:
			return ExecCountSlotsSeqScan((SeqScan *) node);

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

379 380 381 382 383 384
		case T_TidScan:
			return ExecCountSlotsTidScan((TidScan *) node);

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

385 386
			/*
			 * join nodes
387 388 389 390 391 392 393
			 */
		case T_NestLoop:
			return ExecCountSlotsNestLoop((NestLoop *) node);

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

394 395 396 397 398 399
		case T_Hash:
			return ExecCountSlotsHash((Hash *) node);

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

400 401
			/*
			 * materialization nodes
402 403 404 405 406 407 408 409 410 411
			 */
		case T_Material:
			return ExecCountSlotsMaterial((Material *) node);

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

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

412 413 414
		case T_SetOp:
			return ExecCountSlotsSetOp((SetOp *) node);

415 416 417
		case T_Limit:
			return ExecCountSlotsLimit((Limit *) node);

418 419 420 421 422 423 424
		case T_Group:
			return ExecCountSlotsGroup((Group *) node);

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

		default:
425 426
			elog(ERROR, "ExecCountSlotsNode: node type %d unsupported",
				 (int) nodeTag(node));
427
			break;
428 429
	}
	return 0;
430 431
}

432 433
/* ----------------------------------------------------------------
 *		ExecEndNode
434
 *
435 436 437 438 439 440 441
 *		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.
 * ----------------------------------------------------------------
442 443
 */
void
444
ExecEndNode(Plan *node, Plan *parent)
445
{
V
Vadim B. Mikheev 已提交
446
	List	   *subp;
447

448 449
	/*
	 * do nothing when we get to the end of a leaf on tree.
450
	 */
451 452
	if (node == NULL)
		return;
453 454 455 456 457 458

	foreach(subp, node->initPlan)
		ExecEndSubPlan((SubPlan *) lfirst(subp));
	foreach(subp, node->subPlan)
		ExecEndSubPlan((SubPlan *) lfirst(subp));
	if (node->chgParam != NULL)
V
Vadim B. Mikheev 已提交
459
	{
460
		freeList(node->chgParam);
V
Vadim B. Mikheev 已提交
461 462
		node->chgParam = NULL;
	}
463 464 465

	switch (nodeTag(node))
	{
466 467 468

			/*
			 * control nodes
469 470 471 472 473 474 475 476 477
			 */
		case T_Result:
			ExecEndResult((Result *) node);
			break;

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

478 479
			/*
			 * scan nodes
480 481 482 483 484 485 486 487 488
			 */
		case T_SeqScan:
			ExecEndSeqScan((SeqScan *) node);
			break;

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

489 490 491 492 493 494 495 496
		case T_TidScan:
			ExecEndTidScan((TidScan *) node);
			break;

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

497 498
			/*
			 * join nodes
499 500 501 502 503 504 505 506 507
			 */
		case T_NestLoop:
			ExecEndNestLoop((NestLoop *) node);
			break;

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

508 509 510 511 512 513 514 515
		case T_Hash:
			ExecEndHash((Hash *) node);
			break;

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

516 517
			/*
			 * materialization nodes
518 519 520 521 522 523 524 525 526 527 528 529 530
			 */
		case T_Material:
			ExecEndMaterial((Material *) node);
			break;

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

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

531 532 533 534
		case T_SetOp:
			ExecEndSetOp((SetOp *) node);
			break;

535 536 537 538
		case T_Limit:
			ExecEndLimit((Limit *) node);
			break;

539 540 541 542 543 544 545 546 547
		case T_Group:
			ExecEndGroup((Group *) node);
			break;

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

		default:
548 549
			elog(ERROR, "ExecEndNode: node type %d unsupported",
				 (int) nodeTag(node));
550
			break;
551
	}
552
}
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 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 660 661 662 663 664 665 666 667 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


/* ----------------------------------------------------------------
 *		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;

		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:
712 713 714

			/*
			 * should never get here
715 716 717 718 719 720 721 722
			 */
			elog(ERROR, "ExecGetTupType: node type %d unsupported",
				 (int) nodeTag(node));
			return NULL;
	}

	return slot->ttc_tupleDescriptor;
}