execMain.c 53.7 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * execMain.c
4
 *	  top level executor interface routines
5 6
 *
 * INTERFACE ROUTINES
7 8 9
 *	ExecutorStart()
 *	ExecutorRun()
 *	ExecutorEnd()
10
 *
11 12 13 14
 *	The old ExecutorMain() has been replaced by ExecutorStart(),
 *	ExecutorRun() and ExecutorEnd()
 *
 *	These three procedures are the external interfaces to the executor.
15
 *	In each case, the query descriptor is required as an argument.
16
 *
17
 *	ExecutorStart() must be called at the beginning of execution of any
18 19 20
 *	query plan and ExecutorEnd() should always be called at the end of
 *	execution of a plan.
 *
21
 *	ExecutorRun accepts direction and count arguments that specify whether
22
 *	the plan is to be executed forwards, backwards, and for how many tuples.
23
 *
B
Bruce Momjian 已提交
24
 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
B
Add:  
Bruce Momjian 已提交
25
 * Portions Copyright (c) 1994, Regents of the University of California
26 27 28
 *
 *
 * IDENTIFICATION
B
Bruce Momjian 已提交
29
 *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.214 2003/08/04 02:39:58 momjian Exp $
30 31 32
 *
 *-------------------------------------------------------------------------
 */
33 34
#include "postgres.h"

35 36
#include "access/heapam.h"
#include "catalog/heap.h"
37
#include "catalog/namespace.h"
38
#include "commands/tablecmds.h"
39
#include "commands/trigger.h"
B
Bruce Momjian 已提交
40 41 42 43 44 45
#include "executor/execdebug.h"
#include "executor/execdefs.h"
#include "miscadmin.h"
#include "optimizer/var.h"
#include "parser/parsetree.h"
#include "utils/acl.h"
46
#include "utils/lsyscache.h"
47

48

49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
typedef struct execRowMark
{
	Relation	relation;
	Index		rti;
	char		resname[32];
} execRowMark;

typedef struct evalPlanQual
{
	Index		rti;
	EState	   *estate;
	PlanState  *planstate;
	struct evalPlanQual *next;	/* stack of active PlanQual plans */
	struct evalPlanQual *free;	/* list of free PlanQual plans */
} evalPlanQual;

65
/* decls for local routines only used within this module */
66
static void InitPlan(QueryDesc *queryDesc, bool explainOnly);
67
static void initResultRelInfo(ResultRelInfo *resultRelInfo,
B
Bruce Momjian 已提交
68 69 70
				  Index resultRelationIndex,
				  List *rangeTable,
				  CmdType operation);
B
Bruce Momjian 已提交
71
static TupleTableSlot *ExecutePlan(EState *estate, PlanState * planstate,
B
Bruce Momjian 已提交
72 73 74
			CmdType operation,
			long numberTuples,
			ScanDirection direction,
75
			DestReceiver *dest);
76
static void ExecSelect(TupleTableSlot *slot,
77
		   DestReceiver *dest,
B
Bruce Momjian 已提交
78
		   EState *estate);
79
static void ExecInsert(TupleTableSlot *slot, ItemPointer tupleid,
B
Bruce Momjian 已提交
80
		   EState *estate);
81
static void ExecDelete(TupleTableSlot *slot, ItemPointer tupleid,
B
Bruce Momjian 已提交
82
		   EState *estate);
83
static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid,
B
Bruce Momjian 已提交
84
		   EState *estate);
85
static TupleTableSlot *EvalPlanQualNext(EState *estate);
86
static void EndEvalPlanQual(EState *estate);
87
static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation);
88
static void ExecCheckXactReadOnly(Query *parsetree, CmdType operation);
89
static void EvalPlanQualStart(evalPlanQual *epq, EState *estate,
B
Bruce Momjian 已提交
90
				  evalPlanQual *priorepq);
91
static void EvalPlanQualStop(evalPlanQual *epq);
92

93 94
/* end of local decls */

95

96
/* ----------------------------------------------------------------
97 98 99 100 101
 *		ExecutorStart
 *
 *		This routine must be called at the beginning of any execution of any
 *		query plan
 *
102
 * Takes a QueryDesc previously created by CreateQueryDesc (it's not real
B
Bruce Momjian 已提交
103
 * clear why we bother to separate the two functions, but...).	The tupDesc
104 105
 * field of the QueryDesc is filled in to describe the tuples that will be
 * returned, and the internal fields (estate and planstate) are set up.
106
 *
107 108 109
 * If explainOnly is true, we are not actually intending to run the plan,
 * only to set up for EXPLAIN; so skip unwanted side-effects.
 *
110 111
 * NB: the CurrentMemoryContext when this is called will become the parent
 * of the per-query context used for this Executor invocation.
112 113
 * ----------------------------------------------------------------
 */
114
void
115
ExecutorStart(QueryDesc *queryDesc, bool explainOnly)
116
{
117
	EState	   *estate;
118
	MemoryContext oldcontext;
119

120
	/* sanity checks: queryDesc must not be started already */
121
	Assert(queryDesc != NULL);
122 123
	Assert(queryDesc->estate == NULL);

124
	/*
B
Bruce Momjian 已提交
125 126
	 * If the transaction is read-only, we need to check if any writes are
	 * planned to non-temporary tables.
127 128 129 130
	 */
	if (!explainOnly)
		ExecCheckXactReadOnly(queryDesc->parsetree, queryDesc->operation);

131
	/*
132
	 * Build EState, switch into per-query memory context for startup.
133 134 135 136
	 */
	estate = CreateExecutorState();
	queryDesc->estate = estate;

137 138 139 140 141
	oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);

	/*
	 * Fill in parameters, if any, from queryDesc
	 */
142
	estate->es_param_list_info = queryDesc->params;
143

V
Vadim B. Mikheev 已提交
144
	if (queryDesc->plantree->nParamExec > 0)
145
		estate->es_param_exec_vals = (ParamExecData *)
146
			palloc0(queryDesc->plantree->nParamExec * sizeof(ParamExecData));
147

148 149
	estate->es_instrument = queryDesc->doInstrument;

150
	/*
151 152
	 * Make our own private copy of the current query snapshot data.
	 *
B
Bruce Momjian 已提交
153 154 155
	 * This "freezes" our idea of which tuples are good and which are not for
	 * the life of this query, even if it outlives the current command and
	 * current snapshot.
156
	 */
157
	estate->es_snapshot = CopyQuerySnapshot();
158

159
	/*
160
	 * Initialize the plan state tree
161
	 */
162
	InitPlan(queryDesc, explainOnly);
163 164

	MemoryContextSwitchTo(oldcontext);
165 166 167
}

/* ----------------------------------------------------------------
168 169 170 171 172 173 174
 *		ExecutorRun
 *
 *		This is the main routine of the executor module. It accepts
 *		the query descriptor from the traffic cop and executes the
 *		query plan.
 *
 *		ExecutorStart must have been called already.
175
 *
176 177 178
 *		If direction is NoMovementScanDirection then nothing is done
 *		except to start up/shut down the destination.  Otherwise,
 *		we retrieve up to 'count' tuples in the specified direction.
179
 *
180
 *		Note: count = 0 is interpreted as no portal limit, i.e., run to
181
 *		completion.
182
 *
183 184
 * ----------------------------------------------------------------
 */
185
TupleTableSlot *
186
ExecutorRun(QueryDesc *queryDesc,
187
			ScanDirection direction, long count)
188
{
189
	EState	   *estate;
190
	CmdType		operation;
191
	DestReceiver *dest;
192
	TupleTableSlot *result;
193 194 195 196 197 198 199 200
	MemoryContext oldcontext;

	/* sanity checks */
	Assert(queryDesc != NULL);

	estate = queryDesc->estate;

	Assert(estate != NULL);
201

B
Bruce Momjian 已提交
202
	/*
203
	 * Switch into per-query memory context
204
	 */
205
	oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
206

B
Bruce Momjian 已提交
207
	/*
B
Bruce Momjian 已提交
208 209
	 * extract information from the query descriptor and the query
	 * feature.
210
	 */
211 212 213
	operation = queryDesc->operation;
	dest = queryDesc->dest;

B
Bruce Momjian 已提交
214
	/*
215
	 * startup tuple receiver
216
	 */
217 218
	estate->es_processed = 0;
	estate->es_lastoid = InvalidOid;
219

220
	(*dest->startup) (dest, operation, queryDesc->tupDesc);
221

222 223 224 225 226 227 228
	/*
	 * run plan
	 */
	if (direction == NoMovementScanDirection)
		result = NULL;
	else
		result = ExecutePlan(estate,
229
							 queryDesc->planstate,
230 231 232
							 operation,
							 count,
							 direction,
233
							 dest);
234

235 236 237
	/*
	 * shutdown receiver
	 */
238
	(*dest->shutdown) (dest);
239

240 241
	MemoryContextSwitchTo(oldcontext);

242
	return result;
243 244 245
}

/* ----------------------------------------------------------------
246 247
 *		ExecutorEnd
 *
248
 *		This routine must be called at the end of execution of any
249
 *		query plan
250 251 252
 * ----------------------------------------------------------------
 */
void
253
ExecutorEnd(QueryDesc *queryDesc)
254
{
255
	EState	   *estate;
256
	MemoryContext oldcontext;
257

258 259
	/* sanity checks */
	Assert(queryDesc != NULL);
260

261 262
	estate = queryDesc->estate;

263
	Assert(estate != NULL);
264

265
	/*
266
	 * Switch into per-query memory context to run ExecEndPlan
267
	 */
268 269 270
	oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);

	ExecEndPlan(queryDesc->planstate, estate);
271

272
	/*
273
	 * Must switch out of context before destroying it
274
	 */
275
	MemoryContextSwitchTo(oldcontext);
276

277
	/*
278 279
	 * Release EState and per-query memory context.  This should release
	 * everything the executor has allocated.
280
	 */
281 282 283 284 285 286
	FreeExecutorState(estate);

	/* Reset queryDesc fields that no longer point to anything */
	queryDesc->tupDesc = NULL;
	queryDesc->estate = NULL;
	queryDesc->planstate = NULL;
287
}
288

289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
/* ----------------------------------------------------------------
 *		ExecutorRewind
 *
 *		This routine may be called on an open queryDesc to rewind it
 *		to the start.
 * ----------------------------------------------------------------
 */
void
ExecutorRewind(QueryDesc *queryDesc)
{
	EState	   *estate;
	MemoryContext oldcontext;

	/* sanity checks */
	Assert(queryDesc != NULL);

	estate = queryDesc->estate;

	Assert(estate != NULL);

	/* It's probably not sensible to rescan updating queries */
	Assert(queryDesc->operation == CMD_SELECT);

	/*
	 * Switch into per-query memory context
	 */
	oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);

	/*
	 * rescan plan
	 */
	ExecReScan(queryDesc->planstate, NULL);

	MemoryContextSwitchTo(oldcontext);
}

325

326 327 328 329
/*
 * ExecCheckRTPerms
 *		Check access permissions for all relations listed in a range table.
 */
330
void
331
ExecCheckRTPerms(List *rangeTable, CmdType operation)
332 333 334 335
{
	List	   *lp;

	foreach(lp, rangeTable)
336
	{
337 338
		RangeTblEntry *rte = lfirst(lp);

339
		ExecCheckRTEPerms(rte, operation);
340 341 342 343 344 345 346 347
	}
}

/*
 * ExecCheckRTEPerms
 *		Check access permissions for a single RTE.
 */
static void
348
ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
349
{
350
	Oid			relOid;
351
	AclId		userid;
352
	AclResult	aclcheck_result;
353

B
Bruce Momjian 已提交
354
	/*
355 356 357 358 359 360 361 362 363 364
	 * If it's a subquery, recursively examine its rangetable.
	 */
	if (rte->rtekind == RTE_SUBQUERY)
	{
		ExecCheckRTPerms(rte->subquery->rtable, operation);
		return;
	}

	/*
	 * Otherwise, only plain-relation RTEs need to be checked here.
B
Bruce Momjian 已提交
365 366
	 * Function RTEs are checked by init_fcache when the function is
	 * prepared for execution. Join and special RTEs need no checks.
B
Bruce Momjian 已提交
367
	 */
368
	if (rte->rtekind != RTE_RELATION)
369 370
		return;

371
	relOid = rte->relid;
372 373

	/*
B
Bruce Momjian 已提交
374 375
	 * userid to check as: current user unless we have a setuid
	 * indication.
376
	 *
B
Bruce Momjian 已提交
377 378
	 * Note: GetUserId() is presently fast enough that there's no harm in
	 * calling it separately for each RTE.	If that stops being true, we
379
	 * could call it once in ExecCheckRTPerms and pass the userid down
B
Bruce Momjian 已提交
380
	 * from there.	But for now, no need for the extra clutter.
381
	 */
382
	userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
383

384
#define CHECK(MODE)		pg_class_aclcheck(relOid, userid, MODE)
385

386
	if (rte->checkForRead)
387
	{
388
		aclcheck_result = CHECK(ACL_SELECT);
389
		if (aclcheck_result != ACLCHECK_OK)
390 391
			aclcheck_error(aclcheck_result, ACL_KIND_CLASS,
						   get_rel_name(relOid));
392 393 394 395 396 397 398 399 400
	}

	if (rte->checkForWrite)
	{
		/*
		 * Note: write access in a SELECT context means SELECT FOR UPDATE.
		 * Right now we don't distinguish that from true update as far as
		 * permissions checks are concerned.
		 */
401 402 403
		switch (operation)
		{
			case CMD_INSERT:
404
				aclcheck_result = CHECK(ACL_INSERT);
405
				break;
406
			case CMD_SELECT:
407
			case CMD_UPDATE:
408 409 410 411
				aclcheck_result = CHECK(ACL_UPDATE);
				break;
			case CMD_DELETE:
				aclcheck_result = CHECK(ACL_DELETE);
412 413
				break;
			default:
414 415
				elog(ERROR, "unrecognized operation code: %d",
					 (int) operation);
416
				aclcheck_result = ACLCHECK_OK;	/* keep compiler quiet */
417 418
				break;
		}
419
		if (aclcheck_result != ACLCHECK_OK)
420 421
			aclcheck_error(aclcheck_result, ACL_KIND_CLASS,
						   get_rel_name(relOid));
422
	}
423 424
}

425 426 427 428 429 430 431 432 433 434 435 436 437
static void
ExecCheckXactReadOnly(Query *parsetree, CmdType operation)
{
	if (!XactReadOnly)
		return;

	/* CREATE TABLE AS or SELECT INTO */
	if (operation == CMD_SELECT && parsetree->into != NULL)
		goto fail;

	if (operation == CMD_DELETE || operation == CMD_INSERT
		|| operation == CMD_UPDATE)
	{
B
Bruce Momjian 已提交
438
		List	   *lp;
439 440 441 442 443 444 445 446 447 448 449

		foreach(lp, parsetree->rtable)
		{
			RangeTblEntry *rte = lfirst(lp);

			if (rte->rtekind != RTE_RELATION)
				continue;

			if (!rte->checkForWrite)
				continue;

450
			if (isTempNamespace(get_rel_namespace(rte->relid)))
451 452 453 454 455 456 457 458 459
				continue;

			goto fail;
		}
	}

	return;

fail:
460 461 462
	ereport(ERROR,
			(errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
			 errmsg("transaction is read-only")));
463 464 465
}


466
/* ----------------------------------------------------------------
467 468 469 470
 *		InitPlan
 *
 *		Initializes the query plan: open files, allocate storage
 *		and start up the rule manager
471 472
 * ----------------------------------------------------------------
 */
473
static void
474
InitPlan(QueryDesc *queryDesc, bool explainOnly)
475
{
476
	CmdType		operation = queryDesc->operation;
B
Bruce Momjian 已提交
477 478 479
	Query	   *parseTree = queryDesc->parsetree;
	Plan	   *plan = queryDesc->plantree;
	EState	   *estate = queryDesc->estate;
480
	PlanState  *planstate;
B
Bruce Momjian 已提交
481 482
	List	   *rangeTable;
	Relation	intoRelationDesc;
483
	bool		do_select_into;
B
Bruce Momjian 已提交
484
	TupleDesc	tupType;
485

486
	/*
B
Bruce Momjian 已提交
487 488
	 * Do permissions checks.  It's sufficient to examine the query's top
	 * rangetable here --- subplan RTEs will be checked during
489
	 * ExecInitSubPlan().
490
	 */
491
	ExecCheckRTPerms(parseTree->rtable, operation);
492

B
Bruce Momjian 已提交
493
	/*
B
Bruce Momjian 已提交
494
	 * get information from query descriptor
495
	 */
496
	rangeTable = parseTree->rtable;
497

B
Bruce Momjian 已提交
498
	/*
B
Bruce Momjian 已提交
499
	 * initialize the node's execution state
500
	 */
501 502
	estate->es_range_table = rangeTable;

B
Bruce Momjian 已提交
503
	/*
504
	 * if there is a result relation, initialize result relation stuff
505
	 */
506
	if (parseTree->resultRelation != 0 && operation != CMD_SELECT)
507
	{
508 509 510
		List	   *resultRelations = parseTree->resultRelations;
		int			numResultRelations;
		ResultRelInfo *resultRelInfos;
B
Bruce Momjian 已提交
511

512 513 514 515 516 517 518
		if (resultRelations != NIL)
		{
			/*
			 * Multiple result relations (due to inheritance)
			 * parseTree->resultRelations identifies them all
			 */
			ResultRelInfo *resultRelInfo;
519

520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
			numResultRelations = length(resultRelations);
			resultRelInfos = (ResultRelInfo *)
				palloc(numResultRelations * sizeof(ResultRelInfo));
			resultRelInfo = resultRelInfos;
			while (resultRelations != NIL)
			{
				initResultRelInfo(resultRelInfo,
								  lfirsti(resultRelations),
								  rangeTable,
								  operation);
				resultRelInfo++;
				resultRelations = lnext(resultRelations);
			}
		}
		else
		{
			/*
B
Bruce Momjian 已提交
537 538
			 * Single result relation identified by
			 * parseTree->resultRelation
539 540 541 542 543 544 545 546
			 */
			numResultRelations = 1;
			resultRelInfos = (ResultRelInfo *) palloc(sizeof(ResultRelInfo));
			initResultRelInfo(resultRelInfos,
							  parseTree->resultRelation,
							  rangeTable,
							  operation);
		}
547

548 549 550 551
		estate->es_result_relations = resultRelInfos;
		estate->es_num_result_relations = numResultRelations;
		/* Initialize to first or only result rel */
		estate->es_result_relation_info = resultRelInfos;
552
	}
553 554
	else
	{
B
Bruce Momjian 已提交
555
		/*
B
Bruce Momjian 已提交
556
		 * if no result relation, then set state appropriately
557
		 */
558 559
		estate->es_result_relations = NULL;
		estate->es_num_result_relations = 0;
560 561 562
		estate->es_result_relation_info = NULL;
	}

563 564 565 566 567 568 569
	/*
	 * Detect whether we're doing SELECT INTO.  If so, set the force_oids
	 * flag appropriately so that the plan tree will be initialized with
	 * the correct tuple descriptors.
	 */
	do_select_into = false;

570
	if (operation == CMD_SELECT && parseTree->into != NULL)
571 572
	{
		do_select_into = true;
B
Bruce Momjian 已提交
573

574
		/*
B
Bruce Momjian 已提交
575 576 577
		 * For now, always create OIDs in SELECT INTO; this is for
		 * backwards compatibility with pre-7.3 behavior.  Eventually we
		 * might want to allow the user to choose.
578 579 580 581
		 */
		estate->es_force_oids = true;
	}

582 583 584
	/*
	 * Have to lock relations selected for update
	 */
585 586
	estate->es_rowMark = NIL;
	if (parseTree->rowMarks != NIL)
587
	{
B
Bruce Momjian 已提交
588
		List	   *l;
589

590
		foreach(l, parseTree->rowMarks)
591
		{
592 593
			Index		rti = lfirsti(l);
			Oid			relid = getrelid(rti, rangeTable);
594 595 596 597
			Relation	relation;
			execRowMark *erm;

			relation = heap_open(relid, RowShareLock);
B
Bruce Momjian 已提交
598
			erm = (execRowMark *) palloc(sizeof(execRowMark));
599
			erm->relation = relation;
600
			erm->rti = rti;
601
			snprintf(erm->resname, sizeof(erm->resname), "ctid%u", rti);
602 603 604
			estate->es_rowMark = lappend(estate->es_rowMark, erm);
		}
	}
605

B
Bruce Momjian 已提交
606
	/*
607
	 * initialize the executor "tuple" table.  We need slots for all the
608 609 610
	 * plan nodes, plus possibly output slots for the junkfilter(s). At
	 * this point we aren't sure if we need junkfilters, so just add slots
	 * for them unconditionally.
611 612
	 */
	{
613
		int			nSlots = ExecCountSlotsNode(plan);
614

615 616 617 618 619
		if (parseTree->resultRelations != NIL)
			nSlots += length(parseTree->resultRelations);
		else
			nSlots += 1;
		estate->es_tupleTable = ExecCreateTupleTable(nSlots);
620
	}
621

622
	/* mark EvalPlanQual not active */
623
	estate->es_topPlan = plan;
624 625
	estate->es_evalPlanQual = NULL;
	estate->es_evTupleNull = NULL;
626
	estate->es_evTuple = NULL;
627 628
	estate->es_useEvalPlan = false;

B
Bruce Momjian 已提交
629
	/*
B
Bruce Momjian 已提交
630 631
	 * initialize the private state information for all the nodes in the
	 * query tree.	This opens files, allocates storage and leaves us
632
	 * ready to start processing tuples.
633
	 */
634
	planstate = ExecInitNode(plan, estate);
635

B
Bruce Momjian 已提交
636
	/*
637
	 * Get the tuple descriptor describing the type of tuples to return.
B
Bruce Momjian 已提交
638
	 * (this is especially important if we are creating a relation with
639
	 * "SELECT INTO")
640
	 */
641
	tupType = ExecGetResultType(planstate);
642

B
Bruce Momjian 已提交
643
	/*
B
Bruce Momjian 已提交
644 645 646 647 648 649
	 * Initialize the junk filter if needed.  SELECT and INSERT queries
	 * need a filter if there are any junk attrs in the tlist.	INSERT and
	 * SELECT INTO also need a filter if the top plan node is a scan node
	 * that's not doing projection (else we'll be scribbling on the scan
	 * tuple!)	UPDATE and DELETE always need a filter, since there's
	 * always a junk 'ctid' attribute present --- no need to look first.
650 651
	 */
	{
652 653 654
		bool		junk_filter_needed = false;
		List	   *tlist;

655
		switch (operation)
656
		{
657 658
			case CMD_SELECT:
			case CMD_INSERT:
659
				foreach(tlist, plan->targetlist)
660
				{
661 662 663 664 665 666 667
					TargetEntry *tle = (TargetEntry *) lfirst(tlist);

					if (tle->resdom->resjunk)
					{
						junk_filter_needed = true;
						break;
					}
668
				}
669 670 671 672 673 674 675 676 677 678 679 680 681
				if (!junk_filter_needed &&
					(operation == CMD_INSERT || do_select_into))
				{
					if (IsA(planstate, SeqScanState) ||
						IsA(planstate, IndexScanState) ||
						IsA(planstate, TidScanState) ||
						IsA(planstate, SubqueryScanState) ||
						IsA(planstate, FunctionScanState))
					{
						if (planstate->ps_ProjInfo == NULL)
							junk_filter_needed = true;
					}
				}
682 683 684 685 686 687 688
				break;
			case CMD_UPDATE:
			case CMD_DELETE:
				junk_filter_needed = true;
				break;
			default:
				break;
689 690
		}

691
		if (junk_filter_needed)
692
		{
693
			/*
B
Bruce Momjian 已提交
694 695 696 697
			 * If there are multiple result relations, each one needs its
			 * own junk filter.  Note this is only possible for
			 * UPDATE/DELETE, so we can't be fooled by some needing a
			 * filter and some not.
698 699 700
			 */
			if (parseTree->resultRelations != NIL)
			{
701 702
				PlanState **appendplans;
				int			as_nplans;
703
				ResultRelInfo *resultRelInfo;
704
				int			i;
705 706 707 708

				/* Top plan had better be an Append here. */
				Assert(IsA(plan, Append));
				Assert(((Append *) plan)->isTarget);
709 710 711 712
				Assert(IsA(planstate, AppendState));
				appendplans = ((AppendState *) planstate)->appendplans;
				as_nplans = ((AppendState *) planstate)->as_nplans;
				Assert(as_nplans == estate->es_num_result_relations);
713
				resultRelInfo = estate->es_result_relations;
714
				for (i = 0; i < as_nplans; i++)
715
				{
716
					PlanState  *subplan = appendplans[i];
717 718
					JunkFilter *j;

719
					j = ExecInitJunkFilter(subplan->plan->targetlist,
720
										   ExecGetResultType(subplan),
721
							  ExecAllocTableSlot(estate->es_tupleTable));
722 723 724
					resultRelInfo->ri_junkFilter = j;
					resultRelInfo++;
				}
B
Bruce Momjian 已提交
725

726 727 728 729 730 731 732 733 734 735
				/*
				 * Set active junkfilter too; at this point ExecInitAppend
				 * has already selected an active result relation...
				 */
				estate->es_junkFilter =
					estate->es_result_relation_info->ri_junkFilter;
			}
			else
			{
				/* Normal case with just one JunkFilter */
736
				JunkFilter *j;
737

738
				j = ExecInitJunkFilter(planstate->plan->targetlist,
739
									   tupType,
740
							  ExecAllocTableSlot(estate->es_tupleTable));
741 742 743
				estate->es_junkFilter = j;
				if (estate->es_result_relation_info)
					estate->es_result_relation_info->ri_junkFilter = j;
744

745 746 747 748
				/* For SELECT, want to return the cleaned tuple type */
				if (operation == CMD_SELECT)
					tupType = j->jf_cleanTupType;
			}
749 750 751 752
		}
		else
			estate->es_junkFilter = NULL;
	}
753

B
Bruce Momjian 已提交
754
	/*
755
	 * If doing SELECT INTO, initialize the "into" relation.  We must wait
B
Bruce Momjian 已提交
756 757
	 * till now so we have the "clean" result tuple type to create the new
	 * table from.
758 759
	 *
	 * If EXPLAIN, skip creating the "into" relation.
760 761 762
	 */
	intoRelationDesc = (Relation) NULL;

763
	if (do_select_into && !explainOnly)
764
	{
765 766 767 768 769
		char	   *intoName;
		Oid			namespaceId;
		AclResult	aclresult;
		Oid			intoRelationId;
		TupleDesc	tupdesc;
770

771 772 773 774 775
		/*
		 * find namespace to create in, check permissions
		 */
		intoName = parseTree->into->relname;
		namespaceId = RangeVarGetCreationNamespace(parseTree->into);
776

777 778 779
		aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
										  ACL_CREATE);
		if (aclresult != ACLCHECK_OK)
780 781
			aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
						   get_namespace_name(namespaceId));
782

783 784 785 786
		/*
		 * have to copy tupType to get rid of constraints
		 */
		tupdesc = CreateTupleDescCopy(tupType);
787

788 789 790 791 792 793 794
		intoRelationId = heap_create_with_catalog(intoName,
												  namespaceId,
												  tupdesc,
												  RELKIND_RELATION,
												  false,
												  ONCOMMIT_NOOP,
												  allowSystemTableMods);
795

796
		FreeTupleDesc(tupdesc);
797

798
		/*
B
Bruce Momjian 已提交
799 800
		 * Advance command counter so that the newly-created relation's
		 * catalog tuples will be visible to heap_open.
801 802
		 */
		CommandCounterIncrement();
803

804
		/*
B
Bruce Momjian 已提交
805 806 807 808
		 * If necessary, create a TOAST table for the into relation. Note
		 * that AlterTableCreateToastTable ends with
		 * CommandCounterIncrement(), so that the TOAST table will be
		 * visible for insertion.
809 810
		 */
		AlterTableCreateToastTable(intoRelationId, true);
811

812 813 814 815
		/*
		 * And open the constructed table for writing.
		 */
		intoRelationDesc = heap_open(intoRelationId, AccessExclusiveLock);
816 817 818 819
	}

	estate->es_into_relation_descriptor = intoRelationDesc;

820 821
	queryDesc->tupDesc = tupType;
	queryDesc->planstate = planstate;
822 823
}

824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841
/*
 * Initialize ResultRelInfo data for one result relation
 */
static void
initResultRelInfo(ResultRelInfo *resultRelInfo,
				  Index resultRelationIndex,
				  List *rangeTable,
				  CmdType operation)
{
	Oid			resultRelationOid;
	Relation	resultRelationDesc;

	resultRelationOid = getrelid(resultRelationIndex, rangeTable);
	resultRelationDesc = heap_open(resultRelationOid, RowExclusiveLock);

	switch (resultRelationDesc->rd_rel->relkind)
	{
		case RELKIND_SEQUENCE:
842 843 844
			ereport(ERROR,
					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
					 errmsg("cannot change sequence relation \"%s\"",
B
Bruce Momjian 已提交
845
						  RelationGetRelationName(resultRelationDesc))));
846 847
			break;
		case RELKIND_TOASTVALUE:
848 849 850
			ereport(ERROR,
					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
					 errmsg("cannot change toast relation \"%s\"",
B
Bruce Momjian 已提交
851
						  RelationGetRelationName(resultRelationDesc))));
852 853
			break;
		case RELKIND_VIEW:
854 855 856
			ereport(ERROR,
					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
					 errmsg("cannot change view relation \"%s\"",
B
Bruce Momjian 已提交
857
						  RelationGetRelationName(resultRelationDesc))));
858 859 860 861 862 863 864 865 866 867
			break;
	}

	MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
	resultRelInfo->type = T_ResultRelInfo;
	resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
	resultRelInfo->ri_RelationDesc = resultRelationDesc;
	resultRelInfo->ri_NumIndices = 0;
	resultRelInfo->ri_IndexRelationDescs = NULL;
	resultRelInfo->ri_IndexRelationInfo = NULL;
868 869
	/* make a copy so as not to depend on relcache info not changing... */
	resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc);
870
	resultRelInfo->ri_TrigFunctions = NULL;
871 872 873 874 875 876
	resultRelInfo->ri_ConstraintExprs = NULL;
	resultRelInfo->ri_junkFilter = NULL;

	/*
	 * If there are indices on the result relation, open them and save
	 * descriptors in the result relation info, so that we can add new
B
Bruce Momjian 已提交
877 878
	 * index entries for the tuples we add/update.	We need not do this
	 * for a DELETE, however, since deletion doesn't affect indexes.
879 880 881 882 883 884
	 */
	if (resultRelationDesc->rd_rel->relhasindex &&
		operation != CMD_DELETE)
		ExecOpenIndices(resultRelInfo);
}

885
/* ----------------------------------------------------------------
886
 *		ExecEndPlan
887
 *
888
 *		Cleans up the query plan -- closes files and frees up storage
889 890 891 892 893 894
 *
 * NOTE: we are no longer very worried about freeing storage per se
 * in this code; FreeExecutorState should be guaranteed to release all
 * memory that needs to be released.  What we are worried about doing
 * is closing relations and dropping buffer pins.  Thus, for example,
 * tuple tables must be cleared or dropped to ensure pins are released.
895 896
 * ----------------------------------------------------------------
 */
897
void
B
Bruce Momjian 已提交
898
ExecEndPlan(PlanState * planstate, EState *estate)
899
{
900 901
	ResultRelInfo *resultRelInfo;
	int			i;
902
	List	   *l;
903

904 905 906 907 908 909
	/*
	 * shut down any PlanQual processing we were doing
	 */
	if (estate->es_evalPlanQual != NULL)
		EndEvalPlanQual(estate);

B
Bruce Momjian 已提交
910
	/*
911
	 * shut down the node-type-specific query processing
912
	 */
913
	ExecEndNode(planstate);
914

B
Bruce Momjian 已提交
915
	/*
B
Bruce Momjian 已提交
916
	 * destroy the executor "tuple" table.
917
	 */
918 919
	ExecDropTupleTable(estate->es_tupleTable, true);
	estate->es_tupleTable = NULL;
920

B
Bruce Momjian 已提交
921
	/*
B
Bruce Momjian 已提交
922
	 * close the result relation(s) if any, but hold locks until xact
923
	 * commit.
924
	 */
925 926
	resultRelInfo = estate->es_result_relations;
	for (i = estate->es_num_result_relations; i > 0; i--)
927
	{
928 929 930 931
		/* Close indices and then the relation itself */
		ExecCloseIndices(resultRelInfo);
		heap_close(resultRelInfo->ri_RelationDesc, NoLock);
		resultRelInfo++;
932 933
	}

B
Bruce Momjian 已提交
934
	/*
935
	 * close the "into" relation if necessary, again keeping lock
936
	 */
937 938
	if (estate->es_into_relation_descriptor != NULL)
		heap_close(estate->es_into_relation_descriptor, NoLock);
939 940 941 942 943 944 945 946 947 948

	/*
	 * close any relations selected FOR UPDATE, again keeping locks
	 */
	foreach(l, estate->es_rowMark)
	{
		execRowMark *erm = lfirst(l);

		heap_close(erm->relation, NoLock);
	}
949 950 951
}

/* ----------------------------------------------------------------
952 953
 *		ExecutePlan
 *
954
 *		processes the query plan to retrieve 'numberTuples' tuples in the
955
 *		direction specified.
956
 *
957
 *		Retrieves all tuples if numberTuples is 0
958
 *
959
 *		result is either a slot containing the last tuple in the case
960
 *		of a SELECT or NULL otherwise.
961
 *
962 963
 * Note: the ctid attribute is a 'junk' attribute that is removed before the
 * user can see it
964 965 966
 * ----------------------------------------------------------------
 */
static TupleTableSlot *
967
ExecutePlan(EState *estate,
B
Bruce Momjian 已提交
968
			PlanState * planstate,
969
			CmdType operation,
970
			long numberTuples,
971
			ScanDirection direction,
972
			DestReceiver *dest)
973
{
B
Bruce Momjian 已提交
974 975 976 977 978 979
	JunkFilter *junkfilter;
	TupleTableSlot *slot;
	ItemPointer tupleid = NULL;
	ItemPointerData tuple_ctid;
	long		current_tuple_count;
	TupleTableSlot *result;
980

B
Bruce Momjian 已提交
981
	/*
B
Bruce Momjian 已提交
982
	 * initialize local variables
983
	 */
984 985 986 987
	slot = NULL;
	current_tuple_count = 0;
	result = NULL;

B
Bruce Momjian 已提交
988 989
	/*
	 * Set the direction.
990
	 */
991 992
	estate->es_direction = direction;

993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
	/*
	 * Process BEFORE EACH STATEMENT triggers
	 */
	switch (operation)
	{
		case CMD_UPDATE:
			ExecBSUpdateTriggers(estate, estate->es_result_relation_info);
			break;
		case CMD_DELETE:
			ExecBSDeleteTriggers(estate, estate->es_result_relation_info);
			break;
		case CMD_INSERT:
			ExecBSInsertTriggers(estate, estate->es_result_relation_info);
			break;
		default:
			/* do nothing */
1009
			break;
1010 1011
	}

B
Bruce Momjian 已提交
1012
	/*
B
Bruce Momjian 已提交
1013
	 * Loop until we've processed the proper number of tuples from the
1014
	 * plan.
1015 1016 1017 1018
	 */

	for (;;)
	{
1019 1020
		/* Reset the per-output-tuple exprcontext */
		ResetPerTupleExprContext(estate);
B
Bruce Momjian 已提交
1021

B
Bruce Momjian 已提交
1022
		/*
B
Bruce Momjian 已提交
1023
		 * Execute the plan and obtain a tuple
1024
		 */
B
Bruce Momjian 已提交
1025
lnext:	;
1026 1027 1028 1029
		if (estate->es_useEvalPlan)
		{
			slot = EvalPlanQualNext(estate);
			if (TupIsNull(slot))
1030
				slot = ExecProcNode(planstate);
1031 1032
		}
		else
1033
			slot = ExecProcNode(planstate);
1034

B
Bruce Momjian 已提交
1035
		/*
B
Bruce Momjian 已提交
1036 1037
		 * if the tuple is null, then we assume there is nothing more to
		 * process so we just return null...
1038 1039 1040 1041 1042
		 */
		if (TupIsNull(slot))
		{
			result = NULL;
			break;
1043 1044
		}

B
Bruce Momjian 已提交
1045
		/*
B
Bruce Momjian 已提交
1046 1047
		 * if we have a junk filter, then project a new tuple with the
		 * junk removed.
1048
		 *
1049 1050 1051
		 * Store this new "clean" tuple in the junkfilter's resultSlot.
		 * (Formerly, we stored it back over the "dirty" tuple, which is
		 * WRONG because that tuple slot has the wrong descriptor.)
1052
		 *
B
Bruce Momjian 已提交
1053
		 * Also, extract all the junk information we need.
1054 1055 1056
		 */
		if ((junkfilter = estate->es_junkFilter) != (JunkFilter *) NULL)
		{
1057 1058 1059
			Datum		datum;
			HeapTuple	newTuple;
			bool		isNull;
1060

B
Bruce Momjian 已提交
1061
			/*
1062 1063 1064 1065 1066 1067 1068 1069 1070
			 * extract the 'ctid' junk attribute.
			 */
			if (operation == CMD_UPDATE || operation == CMD_DELETE)
			{
				if (!ExecGetJunkAttribute(junkfilter,
										  slot,
										  "ctid",
										  &datum,
										  &isNull))
1071
					elog(ERROR, "could not find junk ctid column");
1072

1073
				/* shouldn't ever get a null result... */
1074
				if (isNull)
1075
					elog(ERROR, "ctid is NULL");
1076 1077 1078 1079 1080 1081

				tupleid = (ItemPointer) DatumGetPointer(datum);
				tuple_ctid = *tupleid;	/* make sure we don't free the
										 * ctid!! */
				tupleid = &tuple_ctid;
			}
1082
			else if (estate->es_rowMark != NIL)
1083
			{
B
Bruce Momjian 已提交
1084
				List	   *l;
1085

B
Bruce Momjian 已提交
1086 1087
		lmark:	;
				foreach(l, estate->es_rowMark)
1088
				{
1089 1090 1091 1092 1093 1094
					execRowMark *erm = lfirst(l);
					Buffer		buffer;
					HeapTupleData tuple;
					TupleTableSlot *newSlot;
					int			test;

1095 1096 1097 1098 1099
					if (!ExecGetJunkAttribute(junkfilter,
											  slot,
											  erm->resname,
											  &datum,
											  &isNull))
1100
						elog(ERROR, "could not find junk \"%s\" column",
1101
							 erm->resname);
1102

1103
					/* shouldn't ever get a null result... */
1104
					if (isNull)
1105
						elog(ERROR, "\"%s\" is NULL", erm->resname);
1106 1107

					tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
1108 1109
					test = heap_mark4update(erm->relation, &tuple, &buffer,
											estate->es_snapshot->curcid);
1110 1111 1112 1113
					ReleaseBuffer(buffer);
					switch (test)
					{
						case HeapTupleSelfUpdated:
1114 1115 1116
							/* treat it as deleted; do not process */
							goto lnext;

1117 1118 1119 1120 1121
						case HeapTupleMayBeUpdated:
							break;

						case HeapTupleUpdated:
							if (XactIsoLevel == XACT_SERIALIZABLE)
1122 1123
								ereport(ERROR,
										(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
1124
										 errmsg("could not serialize access due to concurrent update")));
1125
							if (!(ItemPointerEquals(&(tuple.t_self),
B
Bruce Momjian 已提交
1126
								  (ItemPointer) DatumGetPointer(datum))))
1127
							{
B
Bruce Momjian 已提交
1128
								newSlot = EvalPlanQual(estate, erm->rti, &(tuple.t_self));
1129 1130 1131 1132 1133 1134 1135
								if (!(TupIsNull(newSlot)))
								{
									slot = newSlot;
									estate->es_useEvalPlan = true;
									goto lmark;
								}
							}
B
Bruce Momjian 已提交
1136 1137 1138

							/*
							 * if tuple was deleted or PlanQual failed for
1139
							 * updated tuple - we must not return this
B
Bruce Momjian 已提交
1140
							 * tuple!
1141 1142
							 */
							goto lnext;
1143 1144

						default:
1145 1146
							elog(ERROR, "unrecognized heap_mark4update status: %u",
								 test);
B
Bruce Momjian 已提交
1147
							return (NULL);
1148 1149 1150
					}
				}
			}
1151

B
Bruce Momjian 已提交
1152
			/*
1153 1154 1155 1156 1157 1158
			 * Finally create a new "clean" tuple with all junk attributes
			 * removed
			 */
			newTuple = ExecRemoveJunk(junkfilter, slot);

			slot = ExecStoreTuple(newTuple,		/* tuple to store */
1159
								  junkfilter->jf_resultSlot,	/* dest slot */
B
Bruce Momjian 已提交
1160 1161
								  InvalidBuffer,		/* this tuple has no
														 * buffer */
1162
								  true);		/* tuple should be pfreed */
1163
		}
1164

B
Bruce Momjian 已提交
1165
		/*
B
Bruce Momjian 已提交
1166 1167
		 * now that we have a tuple, do the appropriate thing with it..
		 * either return it to the user, add it to a relation someplace,
B
Bruce Momjian 已提交
1168
		 * delete it from a relation, or modify some of its attributes.
1169 1170 1171
		 */
		switch (operation)
		{
1172
			case CMD_SELECT:
B
Bruce Momjian 已提交
1173
				ExecSelect(slot,	/* slot containing tuple */
1174
						   dest,	/* destination's tuple-receiver obj */
1175
						   estate);
1176 1177
				result = slot;
				break;
1178

1179
			case CMD_INSERT:
1180
				ExecInsert(slot, tupleid, estate);
1181 1182
				result = NULL;
				break;
1183

1184 1185 1186 1187
			case CMD_DELETE:
				ExecDelete(slot, tupleid, estate);
				result = NULL;
				break;
1188

1189
			case CMD_UPDATE:
1190
				ExecUpdate(slot, tupleid, estate);
1191 1192
				result = NULL;
				break;
1193

1194
			default:
1195 1196
				elog(ERROR, "unrecognized operation code: %d",
					 (int) operation);
1197
				result = NULL;
1198
				break;
1199
		}
B
Bruce Momjian 已提交
1200

B
Bruce Momjian 已提交
1201
		/*
1202
		 * check our tuple count.. if we've processed the proper number
B
Bruce Momjian 已提交
1203
		 * then quit, else loop again and process more tuples.	Zero
1204
		 * numberTuples means no limit.
1205
		 */
1206
		current_tuple_count++;
1207
		if (numberTuples && numberTuples == current_tuple_count)
1208
			break;
1209
	}
1210

1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226
	/*
	 * Process AFTER EACH STATEMENT triggers
	 */
	switch (operation)
	{
		case CMD_UPDATE:
			ExecASUpdateTriggers(estate, estate->es_result_relation_info);
			break;
		case CMD_DELETE:
			ExecASDeleteTriggers(estate, estate->es_result_relation_info);
			break;
		case CMD_INSERT:
			ExecASInsertTriggers(estate, estate->es_result_relation_info);
			break;
		default:
			/* do nothing */
1227
			break;
1228 1229
	}

B
Bruce Momjian 已提交
1230
	/*
B
Bruce Momjian 已提交
1231
	 * here, result is either a slot containing a tuple in the case of a
1232
	 * SELECT or NULL otherwise.
1233
	 */
1234
	return result;
1235 1236 1237
}

/* ----------------------------------------------------------------
1238
 *		ExecSelect
1239
 *
1240
 *		SELECTs are easy.. we just pass the tuple to the appropriate
1241
 *		print function.  The only complexity is when we do a
1242
 *		"SELECT INTO", in which case we insert the tuple into
1243 1244
 *		the appropriate relation (note: this is a newly created relation
 *		so we don't need to worry about indices or locks.)
1245 1246 1247
 * ----------------------------------------------------------------
 */
static void
1248
ExecSelect(TupleTableSlot *slot,
1249
		   DestReceiver *dest,
1250
		   EState *estate)
1251
{
1252 1253
	HeapTuple	tuple;
	TupleDesc	attrtype;
1254

B
Bruce Momjian 已提交
1255
	/*
B
Bruce Momjian 已提交
1256
	 * get the heap tuple out of the tuple table slot
1257 1258 1259 1260
	 */
	tuple = slot->val;
	attrtype = slot->ttc_tupleDescriptor;

B
Bruce Momjian 已提交
1261
	/*
B
Bruce Momjian 已提交
1262
	 * insert the tuple into the "into relation"
1263 1264
	 *
	 * XXX this probably ought to be replaced by a separate destination
1265 1266 1267
	 */
	if (estate->es_into_relation_descriptor != NULL)
	{
1268 1269
		heap_insert(estate->es_into_relation_descriptor, tuple,
					estate->es_snapshot->curcid);
1270 1271 1272
		IncrAppended();
	}

B
Bruce Momjian 已提交
1273
	/*
1274
	 * send the tuple to the destination
1275
	 */
1276
	(*dest->receiveTuple) (tuple, attrtype, dest);
1277 1278
	IncrRetrieved();
	(estate->es_processed)++;
1279 1280 1281
}

/* ----------------------------------------------------------------
1282
 *		ExecInsert
1283
 *
1284
 *		INSERTs are trickier.. we have to insert the tuple into
1285 1286
 *		the base relation and insert appropriate tuples into the
 *		index relations.
1287 1288 1289
 * ----------------------------------------------------------------
 */
static void
1290
ExecInsert(TupleTableSlot *slot,
1291
		   ItemPointer tupleid,
1292
		   EState *estate)
1293
{
1294
	HeapTuple	tuple;
1295
	ResultRelInfo *resultRelInfo;
1296 1297 1298
	Relation	resultRelationDesc;
	int			numIndices;
	Oid			newId;
1299

B
Bruce Momjian 已提交
1300
	/*
B
Bruce Momjian 已提交
1301
	 * get the heap tuple out of the tuple table slot
1302 1303 1304
	 */
	tuple = slot->val;

B
Bruce Momjian 已提交
1305
	/*
1306
	 * get information on the (current) result relation
1307
	 */
1308 1309
	resultRelInfo = estate->es_result_relation_info;
	resultRelationDesc = resultRelInfo->ri_RelationDesc;
1310 1311

	/* BEFORE ROW INSERT Triggers */
1312
	if (resultRelInfo->ri_TrigDesc &&
B
Bruce Momjian 已提交
1313
	  resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
1314
	{
1315
		HeapTuple	newtuple;
1316

1317
		newtuple = ExecBRInsertTriggers(estate, resultRelInfo, tuple);
1318 1319 1320 1321 1322 1323

		if (newtuple == NULL)	/* "do nothing" */
			return;

		if (newtuple != tuple)	/* modified by Trigger(s) */
		{
1324 1325 1326
			/*
			 * Insert modified tuple into tuple table slot, replacing the
			 * original.  We assume that it was allocated in per-tuple
B
Bruce Momjian 已提交
1327 1328
			 * memory context, and therefore will go away by itself. The
			 * tuple table slot should not try to clear it.
1329 1330 1331
			 */
			ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
			tuple = newtuple;
1332 1333 1334
		}
	}

B
Bruce Momjian 已提交
1335
	/*
1336
	 * Check the constraints of the tuple
1337 1338
	 */
	if (resultRelationDesc->rd_att->constr)
1339
		ExecConstraints(resultRelInfo, slot, estate);
1340

B
Bruce Momjian 已提交
1341
	/*
B
Bruce Momjian 已提交
1342
	 * insert the tuple
1343
	 */
1344 1345
	newId = heap_insert(resultRelationDesc, tuple,
						estate->es_snapshot->curcid);
1346

1347
	IncrAppended();
1348 1349
	(estate->es_processed)++;
	estate->es_lastoid = newId;
T
Tom Lane 已提交
1350
	setLastTid(&(tuple->t_self));
1351

B
Bruce Momjian 已提交
1352
	/*
B
Bruce Momjian 已提交
1353
	 * process indices
1354
	 *
B
Bruce Momjian 已提交
1355 1356 1357
	 * Note: heap_insert adds a new tuple to a relation.  As a side effect,
	 * the tupleid of the new tuple is placed in the new tuple's t_ctid
	 * field.
1358
	 */
1359
	numIndices = resultRelInfo->ri_NumIndices;
1360
	if (numIndices > 0)
1361
		ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
1362 1363

	/* AFTER ROW INSERT Triggers */
1364
	ExecARInsertTriggers(estate, resultRelInfo, tuple);
1365 1366 1367
}

/* ----------------------------------------------------------------
1368
 *		ExecDelete
1369
 *
1370
 *		DELETE is like UPDATE, we delete the tuple and its
1371
 *		index tuples.
1372 1373 1374
 * ----------------------------------------------------------------
 */
static void
1375
ExecDelete(TupleTableSlot *slot,
1376
		   ItemPointer tupleid,
1377
		   EState *estate)
1378
{
1379
	ResultRelInfo *resultRelInfo;
B
Bruce Momjian 已提交
1380 1381 1382
	Relation	resultRelationDesc;
	ItemPointerData ctid;
	int			result;
1383

B
Bruce Momjian 已提交
1384
	/*
1385
	 * get information on the (current) result relation
1386
	 */
1387 1388
	resultRelInfo = estate->es_result_relation_info;
	resultRelationDesc = resultRelInfo->ri_RelationDesc;
1389 1390

	/* BEFORE ROW DELETE Triggers */
1391
	if (resultRelInfo->ri_TrigDesc &&
1392
	  resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_DELETE] > 0)
1393
	{
1394
		bool		dodelete;
1395

1396 1397
		dodelete = ExecBRDeleteTriggers(estate, resultRelInfo, tupleid,
										estate->es_snapshot->curcid);
1398 1399 1400 1401 1402

		if (!dodelete)			/* "do nothing" */
			return;
	}

V
Vadim B. Mikheev 已提交
1403
	/*
B
Bruce Momjian 已提交
1404
	 * delete the tuple
1405
	 */
1406
ldelete:;
1407 1408 1409
	result = heap_delete(resultRelationDesc, tupleid,
						 &ctid,
						 estate->es_snapshot->curcid);
V
Vadim B. Mikheev 已提交
1410 1411 1412
	switch (result)
	{
		case HeapTupleSelfUpdated:
1413
			/* already deleted by self; nothing to do */
V
Vadim B. Mikheev 已提交
1414 1415 1416 1417 1418 1419
			return;

		case HeapTupleMayBeUpdated:
			break;

		case HeapTupleUpdated:
1420
			if (XactIsoLevel == XACT_SERIALIZABLE)
1421 1422
				ereport(ERROR,
						(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
1423
						 errmsg("could not serialize access due to concurrent update")));
1424 1425
			else if (!(ItemPointerEquals(tupleid, &ctid)))
			{
B
Bruce Momjian 已提交
1426
				TupleTableSlot *epqslot = EvalPlanQual(estate,
B
Bruce Momjian 已提交
1427
							   resultRelInfo->ri_RangeTableIndex, &ctid);
1428

V
Vadim B. Mikheev 已提交
1429
				if (!TupIsNull(epqslot))
1430 1431 1432 1433 1434
				{
					*tupleid = ctid;
					goto ldelete;
				}
			}
1435
			/* tuple already deleted; nothing to do */
V
Vadim B. Mikheev 已提交
1436 1437 1438
			return;

		default:
1439
			elog(ERROR, "unrecognized heap_delete status: %u", result);
V
Vadim B. Mikheev 已提交
1440 1441
			return;
	}
1442 1443 1444 1445

	IncrDeleted();
	(estate->es_processed)++;

B
Bruce Momjian 已提交
1446
	/*
B
Bruce Momjian 已提交
1447 1448
	 * Note: Normally one would think that we have to delete index tuples
	 * associated with the heap tuple now..
1449
	 *
B
Bruce Momjian 已提交
1450 1451 1452
	 * ... but in POSTGRES, we have no need to do this because the vacuum
	 * daemon automatically opens an index scan and deletes index tuples
	 * when it finds deleted heap tuples. -cim 9/27/89
1453 1454 1455
	 */

	/* AFTER ROW DELETE Triggers */
1456
	ExecARDeleteTriggers(estate, resultRelInfo, tupleid);
1457 1458 1459
}

/* ----------------------------------------------------------------
1460
 *		ExecUpdate
1461
 *
1462 1463 1464 1465
 *		note: we can't run UPDATE queries with transactions
 *		off because UPDATEs are actually INSERTs and our
 *		scan will mistakenly loop forever, updating the tuple
 *		it just inserted..	This should be fixed but until it
1466 1467
 *		is, we don't want to get stuck in an infinite loop
 *		which corrupts your database..
1468 1469 1470
 * ----------------------------------------------------------------
 */
static void
1471
ExecUpdate(TupleTableSlot *slot,
B
Bruce Momjian 已提交
1472 1473
		   ItemPointer tupleid,
		   EState *estate)
1474
{
B
Bruce Momjian 已提交
1475
	HeapTuple	tuple;
1476
	ResultRelInfo *resultRelInfo;
B
Bruce Momjian 已提交
1477 1478 1479 1480
	Relation	resultRelationDesc;
	ItemPointerData ctid;
	int			result;
	int			numIndices;
1481

B
Bruce Momjian 已提交
1482
	/*
B
Bruce Momjian 已提交
1483
	 * abort the operation if not running transactions
1484 1485
	 */
	if (IsBootstrapProcessingMode())
1486
		elog(ERROR, "cannot UPDATE during bootstrap");
1487

B
Bruce Momjian 已提交
1488
	/*
B
Bruce Momjian 已提交
1489
	 * get the heap tuple out of the tuple table slot
1490 1491 1492
	 */
	tuple = slot->val;

B
Bruce Momjian 已提交
1493
	/*
1494
	 * get information on the (current) result relation
1495
	 */
1496 1497
	resultRelInfo = estate->es_result_relation_info;
	resultRelationDesc = resultRelInfo->ri_RelationDesc;
1498 1499

	/* BEFORE ROW UPDATE Triggers */
1500
	if (resultRelInfo->ri_TrigDesc &&
1501
	  resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0)
1502
	{
1503
		HeapTuple	newtuple;
1504

1505
		newtuple = ExecBRUpdateTriggers(estate, resultRelInfo,
1506 1507
										tupleid, tuple,
										estate->es_snapshot->curcid);
1508 1509 1510 1511 1512 1513

		if (newtuple == NULL)	/* "do nothing" */
			return;

		if (newtuple != tuple)	/* modified by Trigger(s) */
		{
1514 1515 1516
			/*
			 * Insert modified tuple into tuple table slot, replacing the
			 * original.  We assume that it was allocated in per-tuple
B
Bruce Momjian 已提交
1517 1518
			 * memory context, and therefore will go away by itself. The
			 * tuple table slot should not try to clear it.
1519 1520 1521
			 */
			ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
			tuple = newtuple;
1522 1523 1524
		}
	}

B
Bruce Momjian 已提交
1525
	/*
1526
	 * Check the constraints of the tuple
1527
	 *
1528 1529 1530 1531 1532
	 * If we generate a new candidate tuple after EvalPlanQual testing, we
	 * must loop back here and recheck constraints.  (We don't need to
	 * redo triggers, however.	If there are any BEFORE triggers then
	 * trigger.c will have done mark4update to lock the correct tuple, so
	 * there's no need to do them again.)
1533
	 */
1534
lreplace:;
1535
	if (resultRelationDesc->rd_att->constr)
1536
		ExecConstraints(resultRelInfo, slot, estate);
1537

V
Vadim B. Mikheev 已提交
1538
	/*
B
Bruce Momjian 已提交
1539
	 * replace the heap tuple
1540
	 */
1541 1542 1543
	result = heap_update(resultRelationDesc, tupleid, tuple,
						 &ctid,
						 estate->es_snapshot->curcid);
V
Vadim B. Mikheev 已提交
1544 1545 1546
	switch (result)
	{
		case HeapTupleSelfUpdated:
1547
			/* already deleted by self; nothing to do */
V
Vadim B. Mikheev 已提交
1548 1549 1550 1551 1552 1553
			return;

		case HeapTupleMayBeUpdated:
			break;

		case HeapTupleUpdated:
1554
			if (XactIsoLevel == XACT_SERIALIZABLE)
1555 1556
				ereport(ERROR,
						(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
1557
						 errmsg("could not serialize access due to concurrent update")));
1558 1559
			else if (!(ItemPointerEquals(tupleid, &ctid)))
			{
B
Bruce Momjian 已提交
1560
				TupleTableSlot *epqslot = EvalPlanQual(estate,
B
Bruce Momjian 已提交
1561
							   resultRelInfo->ri_RangeTableIndex, &ctid);
1562

V
Vadim B. Mikheev 已提交
1563
				if (!TupIsNull(epqslot))
1564 1565
				{
					*tupleid = ctid;
V
Vadim B. Mikheev 已提交
1566
					tuple = ExecRemoveJunk(estate->es_junkFilter, epqslot);
1567
					slot = ExecStoreTuple(tuple,
1568
									estate->es_junkFilter->jf_resultSlot,
1569
										  InvalidBuffer, true);
1570 1571 1572
					goto lreplace;
				}
			}
1573
			/* tuple already deleted; nothing to do */
V
Vadim B. Mikheev 已提交
1574 1575 1576
			return;

		default:
1577
			elog(ERROR, "unrecognized heap_update status: %u", result);
V
Vadim B. Mikheev 已提交
1578
			return;
1579 1580 1581 1582 1583
	}

	IncrReplaced();
	(estate->es_processed)++;

B
Bruce Momjian 已提交
1584
	/*
B
Bruce Momjian 已提交
1585
	 * Note: instead of having to update the old index tuples associated
B
Bruce Momjian 已提交
1586
	 * with the heap tuple, all we do is form and insert new index tuples.
1587
	 * This is because UPDATEs are actually DELETEs and INSERTs and index
B
Bruce Momjian 已提交
1588 1589
	 * tuple deletion is done automagically by the vacuum daemon. All we
	 * do is insert new index tuples.  -cim 9/27/89
1590 1591
	 */

B
Bruce Momjian 已提交
1592
	/*
B
Bruce Momjian 已提交
1593
	 * process indices
1594
	 *
1595
	 * heap_update updates a tuple in the base relation by invalidating it
1596
	 * and then inserting a new tuple to the relation.	As a side effect,
B
Bruce Momjian 已提交
1597 1598 1599
	 * the tupleid of the new tuple is placed in the new tuple's t_ctid
	 * field.  So we now insert index tuples using the new tupleid stored
	 * there.
1600 1601
	 */

1602
	numIndices = resultRelInfo->ri_NumIndices;
1603
	if (numIndices > 0)
1604
		ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
1605 1606

	/* AFTER ROW UPDATE Triggers */
1607
	ExecARUpdateTriggers(estate, resultRelInfo, tupleid, tuple);
1608
}
V
Vadim B. Mikheev 已提交
1609

1610
static const char *
1611 1612
ExecRelCheck(ResultRelInfo *resultRelInfo,
			 TupleTableSlot *slot, EState *estate)
V
Vadim B. Mikheev 已提交
1613
{
1614
	Relation	rel = resultRelInfo->ri_RelationDesc;
1615 1616
	int			ncheck = rel->rd_att->constr->num_check;
	ConstrCheck *check = rel->rd_att->constr->check;
1617
	ExprContext *econtext;
1618
	MemoryContext oldContext;
1619 1620
	List	   *qual;
	int			i;
1621

1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634
	/*
	 * If first time through for this result relation, build expression
	 * nodetrees for rel's constraint expressions.  Keep them in the
	 * per-query memory context so they'll survive throughout the query.
	 */
	if (resultRelInfo->ri_ConstraintExprs == NULL)
	{
		oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
		resultRelInfo->ri_ConstraintExprs =
			(List **) palloc(ncheck * sizeof(List *));
		for (i = 0; i < ncheck; i++)
		{
			qual = (List *) stringToNode(check[i].ccbin);
1635
			resultRelInfo->ri_ConstraintExprs[i] = (List *)
1636
				ExecPrepareExpr((Expr *) qual, estate);
1637 1638 1639 1640
		}
		MemoryContextSwitchTo(oldContext);
	}

1641
	/*
B
Bruce Momjian 已提交
1642 1643
	 * We will use the EState's per-tuple context for evaluating
	 * constraint expressions (creating it if it's not already there).
1644
	 */
1645
	econtext = GetPerTupleExprContext(estate);
1646

1647 1648 1649 1650
	/* Arrange for econtext's scan tuple to be the tuple under test */
	econtext->ecxt_scantuple = slot;

	/* And evaluate the constraints */
1651 1652
	for (i = 0; i < ncheck; i++)
	{
1653
		qual = resultRelInfo->ri_ConstraintExprs[i];
1654

1655 1656
		/*
		 * NOTE: SQL92 specifies that a NULL result from a constraint
1657 1658
		 * expression is not to be treated as a failure.  Therefore, tell
		 * ExecQual to return TRUE for NULL.
1659
		 */
1660
		if (!ExecQual(qual, econtext, true))
1661
			return check[i].ccname;
1662 1663
	}

1664
	/* NULL result means no error */
1665
	return NULL;
V
Vadim B. Mikheev 已提交
1666 1667
}

1668
void
1669
ExecConstraints(ResultRelInfo *resultRelInfo,
1670
				TupleTableSlot *slot, EState *estate)
V
Vadim B. Mikheev 已提交
1671
{
1672
	Relation	rel = resultRelInfo->ri_RelationDesc;
1673 1674 1675 1676
	HeapTuple	tuple = slot->val;
	TupleConstr *constr = rel->rd_att->constr;

	Assert(constr);
1677

1678
	if (constr->has_not_null)
V
Vadim B. Mikheev 已提交
1679
	{
1680
		int			natts = rel->rd_att->natts;
1681
		int			attrChk;
1682

1683
		for (attrChk = 1; attrChk <= natts; attrChk++)
1684
		{
B
Bruce Momjian 已提交
1685
			if (rel->rd_att->attrs[attrChk - 1]->attnotnull &&
1686
				heap_attisnull(tuple, attrChk))
1687 1688 1689
				ereport(ERROR,
						(errcode(ERRCODE_NOT_NULL_VIOLATION),
						 errmsg("null value for attribute \"%s\" violates NOT NULL constraint",
B
Bruce Momjian 已提交
1690
					NameStr(rel->rd_att->attrs[attrChk - 1]->attname))));
1691 1692 1693
		}
	}

1694
	if (constr->num_check > 0)
1695
	{
B
Bruce Momjian 已提交
1696
		const char *failed;
1697

1698
		if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
1699 1700 1701 1702
			ereport(ERROR,
					(errcode(ERRCODE_CHECK_VIOLATION),
					 errmsg("new row for relation \"%s\" violates CHECK constraint \"%s\"",
							RelationGetRelationName(rel), failed)));
1703
	}
V
Vadim B. Mikheev 已提交
1704
}
1705

1706 1707 1708 1709 1710 1711
/*
 * Check a modified tuple to see if we want to process its updated version
 * under READ COMMITTED rules.
 *
 * See backend/executor/README for some info about how this works.
 */
B
Bruce Momjian 已提交
1712
TupleTableSlot *
1713 1714
EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
{
1715 1716
	evalPlanQual *epq;
	EState	   *epqstate;
B
Bruce Momjian 已提交
1717 1718
	Relation	relation;
	HeapTupleData tuple;
1719 1720
	HeapTuple	copyTuple = NULL;
	bool		endNode;
1721 1722 1723

	Assert(rti != 0);

1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743
	/*
	 * find relation containing target tuple
	 */
	if (estate->es_result_relation_info != NULL &&
		estate->es_result_relation_info->ri_RangeTableIndex == rti)
		relation = estate->es_result_relation_info->ri_RelationDesc;
	else
	{
		List	   *l;

		relation = NULL;
		foreach(l, estate->es_rowMark)
		{
			if (((execRowMark *) lfirst(l))->rti == rti)
			{
				relation = ((execRowMark *) lfirst(l))->relation;
				break;
			}
		}
		if (relation == NULL)
1744
			elog(ERROR, "could not find RowMark for RT index %u", rti);
1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756
	}

	/*
	 * fetch tid tuple
	 *
	 * Loop here to deal with updated or busy tuples
	 */
	tuple.t_self = *tid;
	for (;;)
	{
		Buffer		buffer;

1757
		if (heap_fetch(relation, SnapshotDirty, &tuple, &buffer, false, NULL))
1758 1759 1760
		{
			TransactionId xwait = SnapshotDirty->xmax;

1761
			/* xmin should not be dirty... */
1762
			if (TransactionIdIsValid(SnapshotDirty->xmin))
1763
				elog(ERROR, "t_xmin is uncommitted in tuple to be updated");
1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809

			/*
			 * If tuple is being updated by other transaction then we have
			 * to wait for its commit/abort.
			 */
			if (TransactionIdIsValid(xwait))
			{
				ReleaseBuffer(buffer);
				XactLockTableWait(xwait);
				continue;
			}

			/*
			 * We got tuple - now copy it for use by recheck query.
			 */
			copyTuple = heap_copytuple(&tuple);
			ReleaseBuffer(buffer);
			break;
		}

		/*
		 * Oops! Invalid tuple. Have to check is it updated or deleted.
		 * Note that it's possible to get invalid SnapshotDirty->tid if
		 * tuple updated by this transaction. Have we to check this ?
		 */
		if (ItemPointerIsValid(&(SnapshotDirty->tid)) &&
			!(ItemPointerEquals(&(tuple.t_self), &(SnapshotDirty->tid))))
		{
			/* updated, so look at the updated copy */
			tuple.t_self = SnapshotDirty->tid;
			continue;
		}

		/*
		 * Deleted or updated by this transaction; forget it.
		 */
		return NULL;
	}

	/*
	 * For UPDATE/DELETE we have to return tid of actual row we're
	 * executing PQ for.
	 */
	*tid = tuple.t_self;

	/*
1810
	 * Need to run a recheck subquery.	Find or create a PQ stack entry.
1811
	 */
1812
	epq = estate->es_evalPlanQual;
1813 1814
	endNode = true;

1815 1816
	if (epq != NULL && epq->rti == 0)
	{
1817
		/* Top PQ stack entry is idle, so re-use it */
1818
		Assert(!(estate->es_useEvalPlan) && epq->next == NULL);
1819 1820 1821 1822 1823 1824
		epq->rti = rti;
		endNode = false;
	}

	/*
	 * If this is request for another RTE - Ra, - then we have to check
B
Bruce Momjian 已提交
1825 1826 1827
	 * wasn't PlanQual requested for Ra already and if so then Ra' row was
	 * updated again and we have to re-start old execution for Ra and
	 * forget all what we done after Ra was suspended. Cool? -:))
1828
	 */
B
Bruce Momjian 已提交
1829
	if (epq != NULL && epq->rti != rti &&
1830
		epq->estate->es_evTuple[rti - 1] != NULL)
1831 1832 1833
	{
		do
		{
1834 1835
			evalPlanQual *oldepq;

1836
			/* stop execution */
1837 1838 1839 1840
			EvalPlanQualStop(epq);
			/* pop previous PlanQual from the stack */
			oldepq = epq->next;
			Assert(oldepq && oldepq->rti != 0);
1841 1842 1843
			/* push current PQ to freePQ stack */
			oldepq->free = epq;
			epq = oldepq;
1844
			estate->es_evalPlanQual = epq;
1845 1846 1847
		} while (epq->rti != rti);
	}

B
Bruce Momjian 已提交
1848
	/*
1849 1850 1851 1852 1853 1854
	 * If we are requested for another RTE then we have to suspend
	 * execution of current PlanQual and start execution for new one.
	 */
	if (epq == NULL || epq->rti != rti)
	{
		/* try to reuse plan used previously */
B
Bruce Momjian 已提交
1855
		evalPlanQual *newepq = (epq != NULL) ? epq->free : NULL;
1856

1857
		if (newepq == NULL)		/* first call or freePQ stack is empty */
1858
		{
1859
			newepq = (evalPlanQual *) palloc0(sizeof(evalPlanQual));
1860
			newepq->free = NULL;
1861 1862
			newepq->estate = NULL;
			newepq->planstate = NULL;
1863 1864
		}
		else
1865
		{
1866 1867 1868
			/* recycle previously used PlanQual */
			Assert(newepq->estate == NULL);
			epq->free = NULL;
1869
		}
1870
		/* push current PQ to the stack */
1871
		newepq->next = epq;
1872
		epq = newepq;
1873
		estate->es_evalPlanQual = epq;
1874 1875 1876 1877
		epq->rti = rti;
		endNode = false;
	}

1878
	Assert(epq->rti == rti);
1879 1880

	/*
1881 1882
	 * Ok - we're requested for the same RTE.  Unfortunately we still have
	 * to end and restart execution of the plan, because ExecReScan
1883
	 * wouldn't ensure that upper plan nodes would reset themselves.  We
1884 1885 1886
	 * could make that work if insertion of the target tuple were
	 * integrated with the Param mechanism somehow, so that the upper plan
	 * nodes know that their children's outputs have changed.
1887
	 *
B
Bruce Momjian 已提交
1888 1889
	 * Note that the stack of free evalPlanQual nodes is quite useless at the
	 * moment, since it only saves us from pallocing/releasing the
1890
	 * evalPlanQual nodes themselves.  But it will be useful once we
B
Bruce Momjian 已提交
1891 1892
	 * implement ReScan instead of end/restart for re-using PlanQual
	 * nodes.
1893 1894
	 */
	if (endNode)
1895
	{
1896
		/* stop execution */
1897
		EvalPlanQualStop(epq);
1898
	}
1899

1900 1901 1902
	/*
	 * Initialize new recheck query.
	 *
B
Bruce Momjian 已提交
1903 1904 1905 1906 1907
	 * Note: if we were re-using PlanQual plans via ExecReScan, we'd need to
	 * instead copy down changeable state from the top plan (including
	 * es_result_relation_info, es_junkFilter) and reset locally
	 * changeable state in the epq (including es_param_exec_vals,
	 * es_evTupleNull).
1908 1909 1910
	 */
	EvalPlanQualStart(epq, estate, epq->next);

1911
	/*
1912 1913
	 * free old RTE' tuple, if any, and store target tuple where
	 * relation's scan node will see it
1914
	 */
1915
	epqstate = epq->estate;
1916 1917 1918
	if (epqstate->es_evTuple[rti - 1] != NULL)
		heap_freetuple(epqstate->es_evTuple[rti - 1]);
	epqstate->es_evTuple[rti - 1] = copyTuple;
1919

1920
	return EvalPlanQualNext(estate);
1921 1922
}

B
Bruce Momjian 已提交
1923
static TupleTableSlot *
1924 1925
EvalPlanQualNext(EState *estate)
{
1926 1927
	evalPlanQual *epq = estate->es_evalPlanQual;
	MemoryContext oldcontext;
B
Bruce Momjian 已提交
1928
	TupleTableSlot *slot;
1929 1930 1931 1932

	Assert(epq->rti != 0);

lpqnext:;
1933
	oldcontext = MemoryContextSwitchTo(epq->estate->es_query_cxt);
1934
	slot = ExecProcNode(epq->planstate);
1935
	MemoryContextSwitchTo(oldcontext);
1936 1937 1938 1939 1940 1941

	/*
	 * No more tuples for this PQ. Continue previous one.
	 */
	if (TupIsNull(slot))
	{
1942 1943
		evalPlanQual *oldepq;

1944
		/* stop execution */
1945
		EvalPlanQualStop(epq);
1946
		/* pop old PQ from the stack */
1947 1948
		oldepq = epq->next;
		if (oldepq == NULL)
1949
		{
1950 1951 1952 1953 1954
			/* this is the first (oldest) PQ - mark as free */
			epq->rti = 0;
			estate->es_useEvalPlan = false;
			/* and continue Query execution */
			return (NULL);
1955 1956 1957 1958 1959
		}
		Assert(oldepq->rti != 0);
		/* push current PQ to freePQ stack */
		oldepq->free = epq;
		epq = oldepq;
1960
		estate->es_evalPlanQual = epq;
1961 1962 1963 1964 1965
		goto lpqnext;
	}

	return (slot);
}
1966 1967 1968 1969

static void
EndEvalPlanQual(EState *estate)
{
1970
	evalPlanQual *epq = estate->es_evalPlanQual;
1971

1972 1973
	if (epq->rti == 0)			/* plans already shutdowned */
	{
1974
		Assert(epq->next == NULL);
1975
		return;
1976
	}
1977 1978 1979

	for (;;)
	{
1980 1981
		evalPlanQual *oldepq;

1982
		/* stop execution */
1983
		EvalPlanQualStop(epq);
1984
		/* pop old PQ from the stack */
1985 1986
		oldepq = epq->next;
		if (oldepq == NULL)
1987
		{
1988 1989 1990
			/* this is the first (oldest) PQ - mark as free */
			epq->rti = 0;
			estate->es_useEvalPlan = false;
1991 1992 1993 1994 1995 1996
			break;
		}
		Assert(oldepq->rti != 0);
		/* push current PQ to freePQ stack */
		oldepq->free = epq;
		epq = oldepq;
1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021
		estate->es_evalPlanQual = epq;
	}
}

/*
 * Start execution of one level of PlanQual.
 *
 * This is a cut-down version of ExecutorStart(): we copy some state from
 * the top-level estate rather than initializing it fresh.
 */
static void
EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
{
	EState	   *epqstate;
	int			rtsize;
	MemoryContext oldcontext;

	rtsize = length(estate->es_range_table);

	epq->estate = epqstate = CreateExecutorState();

	oldcontext = MemoryContextSwitchTo(epqstate->es_query_cxt);

	/*
	 * The epqstates share the top query's copy of unchanging state such
B
Bruce Momjian 已提交
2022 2023 2024
	 * as the snapshot, rangetable, result-rel info, and external Param
	 * info. They need their own copies of local state, including a tuple
	 * table, es_param_exec_vals, etc.
2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039
	 */
	epqstate->es_direction = ForwardScanDirection;
	epqstate->es_snapshot = estate->es_snapshot;
	epqstate->es_range_table = estate->es_range_table;
	epqstate->es_result_relations = estate->es_result_relations;
	epqstate->es_num_result_relations = estate->es_num_result_relations;
	epqstate->es_result_relation_info = estate->es_result_relation_info;
	epqstate->es_junkFilter = estate->es_junkFilter;
	epqstate->es_into_relation_descriptor = estate->es_into_relation_descriptor;
	epqstate->es_param_list_info = estate->es_param_list_info;
	if (estate->es_topPlan->nParamExec > 0)
		epqstate->es_param_exec_vals = (ParamExecData *)
			palloc0(estate->es_topPlan->nParamExec * sizeof(ParamExecData));
	epqstate->es_rowMark = estate->es_rowMark;
	epqstate->es_instrument = estate->es_instrument;
2040
	epqstate->es_force_oids = estate->es_force_oids;
2041
	epqstate->es_topPlan = estate->es_topPlan;
B
Bruce Momjian 已提交
2042

2043
	/*
B
Bruce Momjian 已提交
2044 2045 2046
	 * Each epqstate must have its own es_evTupleNull state, but all the
	 * stack entries share es_evTuple state.  This allows sub-rechecks to
	 * inherit the value being examined by an outer recheck.
2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088
	 */
	epqstate->es_evTupleNull = (bool *) palloc0(rtsize * sizeof(bool));
	if (priorepq == NULL)
		/* first PQ stack entry */
		epqstate->es_evTuple = (HeapTuple *)
			palloc0(rtsize * sizeof(HeapTuple));
	else
		/* later stack entries share the same storage */
		epqstate->es_evTuple = priorepq->estate->es_evTuple;

	epqstate->es_tupleTable =
		ExecCreateTupleTable(estate->es_tupleTable->size);

	epq->planstate = ExecInitNode(estate->es_topPlan, epqstate);

	MemoryContextSwitchTo(oldcontext);
}

/*
 * End execution of one level of PlanQual.
 *
 * This is a cut-down version of ExecutorEnd(); basically we want to do most
 * of the normal cleanup, but *not* close result relations (which we are
 * just sharing from the outer query).
 */
static void
EvalPlanQualStop(evalPlanQual *epq)
{
	EState	   *epqstate = epq->estate;
	MemoryContext oldcontext;

	oldcontext = MemoryContextSwitchTo(epqstate->es_query_cxt);

	ExecEndNode(epq->planstate);

	ExecDropTupleTable(epqstate->es_tupleTable, true);
	epqstate->es_tupleTable = NULL;

	if (epqstate->es_evTuple[epq->rti - 1] != NULL)
	{
		heap_freetuple(epqstate->es_evTuple[epq->rti - 1]);
		epqstate->es_evTuple[epq->rti - 1] = NULL;
2089
	}
2090 2091 2092 2093 2094 2095 2096

	MemoryContextSwitchTo(oldcontext);

	FreeExecutorState(epqstate);

	epq->estate = NULL;
	epq->planstate = NULL;
2097
}