execUtils.c 41.2 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * execUtils.c
4
 *	  miscellaneous executor utility routines
5
 *
6
 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
B
Add:  
Bruce Momjian 已提交
7
 * Portions Copyright (c) 1994, Regents of the University of California
8 9 10
 *
 *
 * IDENTIFICATION
11
 *	  $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.170 2010/02/08 04:33:54 tgl Exp $
12 13 14 15 16
 *
 *-------------------------------------------------------------------------
 */
/*
 * INTERFACE ROUTINES
17 18 19
 *		CreateExecutorState		Create/delete executor working state
 *		FreeExecutorState
 *		CreateExprContext
20
 *		CreateStandaloneExprContext
21
 *		FreeExprContext
22
 *		ReScanExprContext
23
 *
24
 *		ExecAssignExprContext	Common code for plan node init routines.
25 26
 *		ExecAssignResultType
 *		etc
27
 *
28 29 30
 *		ExecOpenScanRelation	Common code for scan node init routines.
 *		ExecCloseScanRelation
 *
31 32
 *		ExecOpenIndices			\
 *		ExecCloseIndices		 | referenced by InitPlan, EndPlan,
33
 *		ExecInsertIndexTuples	/  ExecInsert, ExecUpdate
34
 *
35 36 37
 *		RegisterExprContextCallback    Register function shutdown callback
 *		UnregisterExprContextCallback  Deregister function shutdown callback
 *
38 39 40
 *	 NOTES
 *		This file has traditionally been the place to stick misc.
 *		executor support stuff that doesn't really go anyplace else.
41 42
 */

43 44
#include "postgres.h"

45
#include "access/genam.h"
B
Bruce Momjian 已提交
46
#include "access/heapam.h"
47 48
#include "access/relscan.h"
#include "access/transam.h"
49
#include "catalog/index.h"
B
Bruce Momjian 已提交
50
#include "executor/execdebug.h"
51
#include "nodes/nodeFuncs.h"
52
#include "parser/parsetree.h"
53
#include "storage/lmgr.h"
54
#include "utils/memutils.h"
55
#include "utils/relcache.h"
56
#include "utils/tqual.h"
57

58

59
static bool get_last_attnums(Node *node, ProjectionInfo *projInfo);
60 61 62
static bool index_recheck_constraint(Relation index, Oid *constr_procs,
						 Datum *existing_values, bool *existing_isnull,
						 Datum *new_values);
63
static void ShutdownExprContext(ExprContext *econtext, bool isCommit);
64

65

66
/* ----------------------------------------------------------------
67
 *				 Executor state and memory management functions
68 69 70 71
 * ----------------------------------------------------------------
 */

/* ----------------
72
 *		CreateExecutorState
73
 *
74 75
 *		Create and initialize an EState node, which is the root of
 *		working storage for an entire Executor invocation.
76
 *
77 78 79 80
 * Principally, this creates the per-query memory context that will be
 * used to hold all working data that lives till the end of the query.
 * Note that the per-query context will become a child of the caller's
 * CurrentMemoryContext.
81 82
 * ----------------
 */
83 84
EState *
CreateExecutorState(void)
85
{
86
	EState	   *estate;
87
	MemoryContext qcontext;
88
	MemoryContext oldcontext;
89

90 91 92 93 94 95 96 97
	/*
	 * Create the per-query context for this Executor run.
	 */
	qcontext = AllocSetContextCreate(CurrentMemoryContext,
									 "ExecutorState",
									 ALLOCSET_DEFAULT_MINSIZE,
									 ALLOCSET_DEFAULT_INITSIZE,
									 ALLOCSET_DEFAULT_MAXSIZE);
B
Bruce Momjian 已提交
98

99
	/*
B
Bruce Momjian 已提交
100 101
	 * Make the EState node within the per-query context.  This way, we don't
	 * need a separate pfree() operation for it at shutdown.
102
	 */
103 104 105 106 107 108 109 110 111
	oldcontext = MemoryContextSwitchTo(qcontext);

	estate = makeNode(EState);

	/*
	 * Initialize all fields of the Executor State structure
	 */
	estate->es_direction = ForwardScanDirection;
	estate->es_snapshot = SnapshotNow;
112
	estate->es_crosscheck_snapshot = InvalidSnapshot;	/* no crosscheck */
113
	estate->es_range_table = NIL;
114
	estate->es_plannedstmt = NULL;
115

116 117
	estate->es_junkFilter = NULL;

118 119
	estate->es_output_cid = (CommandId) 0;

120 121 122 123
	estate->es_result_relations = NULL;
	estate->es_num_result_relations = 0;
	estate->es_result_relation_info = NULL;

124
	estate->es_trig_target_relations = NIL;
125
	estate->es_trig_tuple_slot = NULL;
126
	estate->es_trig_oldtup_slot = NULL;
127

128 129 130 131 132
	estate->es_param_list_info = NULL;
	estate->es_param_exec_vals = NULL;

	estate->es_query_cxt = qcontext;

133
	estate->es_tupleTable = NIL;
134

135 136
	estate->es_rowMarks = NIL;

137 138 139 140
	estate->es_processed = 0;
	estate->es_lastoid = InvalidOid;

	estate->es_instrument = false;
141 142
	estate->es_select_into = false;
	estate->es_into_oids = false;
143 144 145

	estate->es_exprcontexts = NIL;

146 147
	estate->es_subplanstates = NIL;

148 149
	estate->es_per_tuple_exprcontext = NULL;

150 151 152
	estate->es_epqTuple = NULL;
	estate->es_epqTupleSet = NULL;
	estate->es_epqScanDone = NULL;
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180

	/*
	 * Return the executor state structure
	 */
	MemoryContextSwitchTo(oldcontext);

	return estate;
}

/* ----------------
 *		FreeExecutorState
 *
 *		Release an EState along with all remaining working storage.
 *
 * Note: this is not responsible for releasing non-memory resources,
 * such as open relations or buffer pins.  But it will shut down any
 * still-active ExprContexts within the EState.  That is sufficient
 * cleanup for situations where the EState has only been used for expression
 * evaluation, and not to run a complete Plan.
 *
 * This can be called in any memory context ... so long as it's not one
 * of the ones to be freed.
 * ----------------
 */
void
FreeExecutorState(EState *estate)
{
	/*
B
Bruce Momjian 已提交
181 182 183 184
	 * Shut down and free any remaining ExprContexts.  We do this explicitly
	 * to ensure that any remaining shutdown callbacks get called (since they
	 * might need to release resources that aren't simply memory within the
	 * per-query memory context).
185 186 187
	 */
	while (estate->es_exprcontexts)
	{
B
Bruce Momjian 已提交
188
		/*
B
Bruce Momjian 已提交
189 190
		 * XXX: seems there ought to be a faster way to implement this than
		 * repeated list_delete(), no?
191
		 */
192 193
		FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts),
						true);
194 195
		/* FreeExprContext removed the list link for us */
	}
B
Bruce Momjian 已提交
196

197 198
	/*
	 * Free the per-query memory context, thereby releasing all working
199
	 * memory, including the EState node itself.
200
	 */
201
	MemoryContextDelete(estate->es_query_cxt);
202 203 204
}

/* ----------------
205 206 207 208 209 210 211 212
 *		CreateExprContext
 *
 *		Create a context for expression evaluation within an EState.
 *
 * An executor run may require multiple ExprContexts (we usually make one
 * for each Plan node, and a separate one for per-output-tuple processing
 * such as constraint checking).  Each ExprContext has its own "per-tuple"
 * memory context.
213
 *
214
 * Note we make no assumption about the caller's memory context.
215 216
 * ----------------
 */
217
ExprContext *
218
CreateExprContext(EState *estate)
219
{
220 221
	ExprContext *econtext;
	MemoryContext oldcontext;
222

223 224 225 226 227 228 229
	/* Create the ExprContext node within the per-query memory context */
	oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);

	econtext = makeNode(ExprContext);

	/* Initialize fields of ExprContext */
	econtext->ecxt_scantuple = NULL;
230 231
	econtext->ecxt_innertuple = NULL;
	econtext->ecxt_outertuple = NULL;
232 233

	econtext->ecxt_per_query_memory = estate->es_query_cxt;
B
Bruce Momjian 已提交
234

235
	/*
236
	 * Create working memory for expression evaluation in this context.
237 238
	 */
	econtext->ecxt_per_tuple_memory =
239 240 241
		AllocSetContextCreate(estate->es_query_cxt,
							  "ExprContext",
							  ALLOCSET_DEFAULT_MINSIZE,
242 243
							  ALLOCSET_DEFAULT_INITSIZE,
							  ALLOCSET_DEFAULT_MAXSIZE);
244 245 246 247

	econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
	econtext->ecxt_param_list_info = estate->es_param_list_info;

248 249
	econtext->ecxt_aggvalues = NULL;
	econtext->ecxt_aggnulls = NULL;
250

251 252 253
	econtext->caseValue_datum = (Datum) 0;
	econtext->caseValue_isNull = true;

254 255 256 257 258
	econtext->domainValue_datum = (Datum) 0;
	econtext->domainValue_isNull = true;

	econtext->ecxt_estate = estate;

259
	econtext->ecxt_callbacks = NULL;
260

261
	/*
B
Bruce Momjian 已提交
262 263 264
	 * Link the ExprContext into the EState to ensure it is shut down when the
	 * EState is freed.  Because we use lcons(), shutdowns will occur in
	 * reverse order of creation, which may not be essential but can't hurt.
265 266 267 268 269
	 */
	estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);

	MemoryContextSwitchTo(oldcontext);

270 271
	return econtext;
}
272

273 274 275 276 277 278 279 280 281 282 283 284 285 286 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 325 326 327 328 329 330 331 332 333 334
/* ----------------
 *		CreateStandaloneExprContext
 *
 *		Create a context for standalone expression evaluation.
 *
 * An ExprContext made this way can be used for evaluation of expressions
 * that contain no Params, subplans, or Var references (it might work to
 * put tuple references into the scantuple field, but it seems unwise).
 *
 * The ExprContext struct is allocated in the caller's current memory
 * context, which also becomes its "per query" context.
 *
 * It is caller's responsibility to free the ExprContext when done,
 * or at least ensure that any shutdown callbacks have been called
 * (ReScanExprContext() is suitable).  Otherwise, non-memory resources
 * might be leaked.
 * ----------------
 */
ExprContext *
CreateStandaloneExprContext(void)
{
	ExprContext *econtext;

	/* Create the ExprContext node within the caller's memory context */
	econtext = makeNode(ExprContext);

	/* Initialize fields of ExprContext */
	econtext->ecxt_scantuple = NULL;
	econtext->ecxt_innertuple = NULL;
	econtext->ecxt_outertuple = NULL;

	econtext->ecxt_per_query_memory = CurrentMemoryContext;

	/*
	 * Create working memory for expression evaluation in this context.
	 */
	econtext->ecxt_per_tuple_memory =
		AllocSetContextCreate(CurrentMemoryContext,
							  "ExprContext",
							  ALLOCSET_DEFAULT_MINSIZE,
							  ALLOCSET_DEFAULT_INITSIZE,
							  ALLOCSET_DEFAULT_MAXSIZE);

	econtext->ecxt_param_exec_vals = NULL;
	econtext->ecxt_param_list_info = NULL;

	econtext->ecxt_aggvalues = NULL;
	econtext->ecxt_aggnulls = NULL;

	econtext->caseValue_datum = (Datum) 0;
	econtext->caseValue_isNull = true;

	econtext->domainValue_datum = (Datum) 0;
	econtext->domainValue_isNull = true;

	econtext->ecxt_estate = NULL;

	econtext->ecxt_callbacks = NULL;

	return econtext;
}

335 336 337 338 339 340 341 342 343
/* ----------------
 *		FreeExprContext
 *
 *		Free an expression context, including calling any remaining
 *		shutdown callbacks.
 *
 * Since we free the temporary context used for expression evaluation,
 * any previously computed pass-by-reference expression result will go away!
 *
344 345 346 347 348
 * If isCommit is false, we are being called in error cleanup, and should
 * not call callbacks but only release memory.  (It might be better to call
 * the callbacks and pass the isCommit flag to them, but that would require
 * more invasive code changes than currently seems justified.)
 *
349 350
 * Note we make no assumption about the caller's memory context.
 * ----------------
351 352
 */
void
353
FreeExprContext(ExprContext *econtext, bool isCommit)
354
{
355 356
	EState	   *estate;

357
	/* Call any registered callbacks */
358
	ShutdownExprContext(econtext, isCommit);
359
	/* And clean up the memory used */
360
	MemoryContextDelete(econtext->ecxt_per_tuple_memory);
361
	/* Unlink self from owning EState, if any */
362
	estate = econtext->ecxt_estate;
363 364 365
	if (estate)
		estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts,
												  econtext);
366
	/* And delete the ExprContext node */
367
	pfree(econtext);
368 369
}

370 371 372 373
/*
 * ReScanExprContext
 *
 *		Reset an expression context in preparation for a rescan of its
B
Bruce Momjian 已提交
374
 *		plan node.	This requires calling any registered shutdown callbacks,
375 376 377 378 379 380 381 382
 *		since any partially complete set-returning-functions must be canceled.
 *
 * Note we make no assumption about the caller's memory context.
 */
void
ReScanExprContext(ExprContext *econtext)
{
	/* Call any registered callbacks */
383
	ShutdownExprContext(econtext, true);
384 385 386 387
	/* And clean up the memory used */
	MemoryContextReset(econtext->ecxt_per_tuple_memory);
}

388 389 390
/*
 * Build a per-output-tuple ExprContext for an EState.
 *
391 392
 * This is normally invoked via GetPerTupleExprContext() macro,
 * not directly.
393 394 395 396 397
 */
ExprContext *
MakePerTupleExprContext(EState *estate)
{
	if (estate->es_per_tuple_exprcontext == NULL)
398
		estate->es_per_tuple_exprcontext = CreateExprContext(estate);
399 400 401 402

	return estate->es_per_tuple_exprcontext;
}

403

404
/* ----------------------------------------------------------------
405 406 407 408
 *				 miscellaneous node-init support functions
 *
 * Note: all of these are expected to be called with CurrentMemoryContext
 * equal to the per-query memory context.
409 410 411
 * ----------------------------------------------------------------
 */

412 413 414
/* ----------------
 *		ExecAssignExprContext
 *
B
Bruce Momjian 已提交
415
 *		This initializes the ps_ExprContext field.	It is only necessary
416
 *		to do this for nodes which use ExecQual or ExecProject
B
Bruce Momjian 已提交
417
 *		because those routines require an econtext. Other nodes that
418 419 420 421
 *		don't have to evaluate expressions don't need to do this.
 * ----------------
 */
void
422
ExecAssignExprContext(EState *estate, PlanState *planstate)
423 424 425 426
{
	planstate->ps_ExprContext = CreateExprContext(estate);
}

427
/* ----------------
428
 *		ExecAssignResultType
429 430 431
 * ----------------
 */
void
432
ExecAssignResultType(PlanState *planstate, TupleDesc tupDesc)
433
{
434
	TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
435

436
	ExecSetSlotDescriptor(slot, tupDesc);
437 438 439
}

/* ----------------
440
 *		ExecAssignResultTypeFromTL
441 442 443
 * ----------------
 */
void
444
ExecAssignResultTypeFromTL(PlanState *planstate)
445
{
446
	bool		hasoid;
447
	TupleDesc	tupDesc;
448

449 450 451 452
	if (ExecContextForcesOids(planstate, &hasoid))
	{
		/* context forces OID choice; hasoid is now set correctly */
	}
453
	else
454
	{
455 456
		/* given free choice, don't leave space for OIDs in result tuples */
		hasoid = false;
457
	}
B
Bruce Momjian 已提交
458

459
	/*
B
Bruce Momjian 已提交
460 461 462
	 * ExecTypeFromTL needs the parse-time representation of the tlist, not a
	 * list of ExprStates.	This is good because some plan nodes don't bother
	 * to set up planstate->targetlist ...
463 464
	 */
	tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
465
	ExecAssignResultType(planstate, tupDesc);
466 467 468
}

/* ----------------
469
 *		ExecGetResultType
470 471 472
 * ----------------
 */
TupleDesc
473
ExecGetResultType(PlanState *planstate)
474
{
475
	TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
476

477
	return slot->tts_tupleDescriptor;
478 479 480
}

/* ----------------
481 482 483 484 485 486
 *		ExecBuildProjectionInfo
 *
 * Build a ProjectionInfo node for evaluating the given tlist in the given
 * econtext, and storing the result into the tuple slot.  (Caller must have
 * ensured that tuple slot has a descriptor matching the tlist!)  Note that
 * the given tlist should be a list of ExprState nodes, not Expr nodes.
487 488
 *
 * inputDesc can be NULL, but if it is not, we check to see whether simple
B
Bruce Momjian 已提交
489
 * Vars in the tlist match the descriptor.	It is important to provide
490 491 492
 * inputDesc for relation-scan plan nodes, as a cross check that the relation
 * hasn't been changed since the plan was made.  At higher levels of a plan,
 * there is no need to recheck.
493 494
 * ----------------
 */
495 496 497
ProjectionInfo *
ExecBuildProjectionInfo(List *targetList,
						ExprContext *econtext,
498 499
						TupleTableSlot *slot,
						TupleDesc inputDesc)
500
{
501
	ProjectionInfo *projInfo = makeNode(ProjectionInfo);
502 503 504 505 506 507 508 509
	int			len = ExecTargetListLength(targetList);
	int		   *workspace;
	int		   *varSlotOffsets;
	int		   *varNumbers;
	int		   *varOutputCols;
	List	   *exprlist;
	int			numSimpleVars;
	bool		directMap;
510
	ListCell   *tl;
511

512 513
	projInfo->pi_exprContext = econtext;
	projInfo->pi_slot = slot;
514 515 516 517 518 519 520 521
	/* since these are all int arrays, we need do just one palloc */
	workspace = (int *) palloc(len * 3 * sizeof(int));
	projInfo->pi_varSlotOffsets = varSlotOffsets = workspace;
	projInfo->pi_varNumbers = varNumbers = workspace + len;
	projInfo->pi_varOutputCols = varOutputCols = workspace + len * 2;
	projInfo->pi_lastInnerVar = 0;
	projInfo->pi_lastOuterVar = 0;
	projInfo->pi_lastScanVar = 0;
522 523

	/*
524
	 * We separate the target list elements into simple Var references and
525 526
	 * expressions which require the full ExecTargetList machinery.  To be a
	 * simple Var, a Var has to be a user attribute and not mismatch the
527 528
	 * inputDesc.  (Note: if there is a type mismatch then ExecEvalVar will
	 * probably throw an error at runtime, but we leave that to it.)
529
	 */
530 531 532
	exprlist = NIL;
	numSimpleVars = 0;
	directMap = true;
533 534 535 536
	foreach(tl, targetList)
	{
		GenericExprState *gstate = (GenericExprState *) lfirst(tl);
		Var		   *variable = (Var *) gstate->arg->expr;
537
		bool		isSimpleVar = false;
538

539 540 541
		if (variable != NULL &&
			IsA(variable, Var) &&
			variable->varattno > 0)
542
		{
543 544 545 546 547
			if (!inputDesc)
				isSimpleVar = true;		/* can't check type, assume OK */
			else if (variable->varattno <= inputDesc->natts)
			{
				Form_pg_attribute attr;
548

549 550 551 552 553
				attr = inputDesc->attrs[variable->varattno - 1];
				if (!attr->attisdropped && variable->vartype == attr->atttypid)
					isSimpleVar = true;
			}
		}
554

555
		if (isSimpleVar)
556 557
		{
			TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
558
			AttrNumber	attnum = variable->varattno;
559

560 561
			varNumbers[numSimpleVars] = attnum;
			varOutputCols[numSimpleVars] = tle->resno;
562
			if (tle->resno != numSimpleVars + 1)
563
				directMap = false;
564 565 566 567

			switch (variable->varno)
			{
				case INNER:
568 569 570 571
					varSlotOffsets[numSimpleVars] = offsetof(ExprContext,
															 ecxt_innertuple);
					if (projInfo->pi_lastInnerVar < attnum)
						projInfo->pi_lastInnerVar = attnum;
572 573 574
					break;

				case OUTER:
575 576 577 578
					varSlotOffsets[numSimpleVars] = offsetof(ExprContext,
															 ecxt_outertuple);
					if (projInfo->pi_lastOuterVar < attnum)
						projInfo->pi_lastOuterVar = attnum;
579 580 581
					break;

				default:
582 583 584 585
					varSlotOffsets[numSimpleVars] = offsetof(ExprContext,
															 ecxt_scantuple);
					if (projInfo->pi_lastScanVar < attnum)
						projInfo->pi_lastScanVar = attnum;
586 587
					break;
			}
588 589 590 591 592 593 594 595
			numSimpleVars++;
		}
		else
		{
			/* Not a simple variable, add it to generic targetlist */
			exprlist = lappend(exprlist, gstate);
			/* Examine expr to include contained Vars in lastXXXVar counts */
			get_last_attnums((Node *) variable, projInfo);
596 597
		}
	}
598 599 600 601 602 603
	projInfo->pi_targetlist = exprlist;
	projInfo->pi_numSimpleVars = numSimpleVars;
	projInfo->pi_directMap = directMap;

	if (exprlist == NIL)
		projInfo->pi_itemIsDone = NULL; /* not needed */
604 605 606
	else
		projInfo->pi_itemIsDone = (ExprDoneCond *)
			palloc(len * sizeof(ExprDoneCond));
607 608 609

	return projInfo;
}
610

611 612 613 614 615 616 617 618 619 620 621 622 623
/*
 * get_last_attnums: expression walker for ExecBuildProjectionInfo
 *
 *	Update the lastXXXVar counts to be at least as large as the largest
 *	attribute numbers found in the expression
 */
static bool
get_last_attnums(Node *node, ProjectionInfo *projInfo)
{
	if (node == NULL)
		return false;
	if (IsA(node, Var))
	{
624
		Var		   *variable = (Var *) node;
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645
		AttrNumber	attnum = variable->varattno;

		switch (variable->varno)
		{
			case INNER:
				if (projInfo->pi_lastInnerVar < attnum)
					projInfo->pi_lastInnerVar = attnum;
				break;

			case OUTER:
				if (projInfo->pi_lastOuterVar < attnum)
					projInfo->pi_lastOuterVar = attnum;
				break;

			default:
				if (projInfo->pi_lastScanVar < attnum)
					projInfo->pi_lastScanVar = attnum;
				break;
		}
		return false;
	}
646

647
	/*
648 649
	 * Don't examine the arguments of Aggrefs or WindowFuncs, because those do
	 * not represent expressions to be evaluated within the overall
650 651 652 653 654 655 656 657 658 659
	 * targetlist's econtext.
	 */
	if (IsA(node, Aggref))
		return false;
	if (IsA(node, WindowFunc))
		return false;
	return expression_tree_walker(node, get_last_attnums,
								  (void *) projInfo);
}

660 661 662 663
/* ----------------
 *		ExecAssignProjectionInfo
 *
 * forms the projection information from the node's targetlist
664 665 666
 *
 * Notes for inputDesc are same as for ExecBuildProjectionInfo: supply it
 * for a relation-scan node, can pass NULL for upper-level nodes
667 668 669
 * ----------------
 */
void
670 671
ExecAssignProjectionInfo(PlanState *planstate,
						 TupleDesc inputDesc)
672 673 674 675
{
	planstate->ps_ProjInfo =
		ExecBuildProjectionInfo(planstate->targetlist,
								planstate->ps_ExprContext,
676 677
								planstate->ps_ResultTupleSlot,
								inputDesc);
678 679 680
}


681 682
/* ----------------
 *		ExecFreeExprContext
683
 *
684 685 686
 * A plan node's ExprContext should be freed explicitly during executor
 * shutdown because there may be shutdown callbacks to call.  (Other resources
 * made by the above routines, such as projection info, don't need to be freed
687
 * explicitly because they're just memory in the per-query memory context.)
688 689 690
 *
 * However ... there is no particular need to do it during ExecEndNode,
 * because FreeExecutorState will free any remaining ExprContexts within
B
Bruce Momjian 已提交
691
 * the EState.	Letting FreeExecutorState do it allows the ExprContexts to
692 693 694
 * be freed in reverse order of creation, rather than order of creation as
 * will happen if we delete them here, which saves O(N^2) work in the list
 * cleanup inside FreeExprContext.
695 696 697
 * ----------------
 */
void
698
ExecFreeExprContext(PlanState *planstate)
699
{
700
	/*
B
Bruce Momjian 已提交
701 702
	 * Per above discussion, don't actually delete the ExprContext. We do
	 * unlink it from the plan node, though.
703
	 */
704
	planstate->ps_ExprContext = NULL;
705 706
}

707
/* ----------------------------------------------------------------
708 709 710 711 712 713
 *		the following scan type support functions are for
 *		those nodes which are stubborn and return tuples in
 *		their Scan tuple slot instead of their Result tuple
 *		slot..	luck fur us, these nodes do not do projections
 *		so we don't have to worry about getting the ProjectionInfo
 *		right for them...  -cim 6/3/91
714 715 716 717
 * ----------------------------------------------------------------
 */

/* ----------------
718
 *		ExecGetScanType
719 720 721
 * ----------------
 */
TupleDesc
722
ExecGetScanType(ScanState *scanstate)
723
{
724
	TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
725

726
	return slot->tts_tupleDescriptor;
727 728 729
}

/* ----------------
730
 *		ExecAssignScanType
731 732 733
 * ----------------
 */
void
734
ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
735
{
736
	TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
737

738
	ExecSetSlotDescriptor(slot, tupDesc);
739 740 741
}

/* ----------------
742
 *		ExecAssignScanTypeFromOuterPlan
743 744 745
 * ----------------
 */
void
746
ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
747
{
748
	PlanState  *outerPlan;
749
	TupleDesc	tupDesc;
750

751
	outerPlan = outerPlanState(scanstate);
752
	tupDesc = ExecGetResultType(outerPlan);
753

754
	ExecAssignScanType(scanstate, tupDesc);
755 756 757
}


758 759 760 761 762
/* ----------------------------------------------------------------
 *				  Scan node support
 * ----------------------------------------------------------------
 */

763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
/* ----------------------------------------------------------------
 *		ExecRelationIsTargetRelation
 *
 *		Detect whether a relation (identified by rangetable index)
 *		is one of the target relations of the query.
 * ----------------------------------------------------------------
 */
bool
ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
{
	ResultRelInfo *resultRelInfos;
	int			i;

	resultRelInfos = estate->es_result_relations;
	for (i = 0; i < estate->es_num_result_relations; i++)
	{
		if (resultRelInfos[i].ri_RangeTableIndex == scanrelid)
			return true;
	}
	return false;
}

785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802
/* ----------------------------------------------------------------
 *		ExecOpenScanRelation
 *
 *		Open the heap relation to be scanned by a base-level scan plan node.
 *		This should be called during the node's ExecInit routine.
 *
 * By default, this acquires AccessShareLock on the relation.  However,
 * if the relation was already locked by InitPlan, we don't need to acquire
 * any additional lock.  This saves trips to the shared lock manager.
 * ----------------------------------------------------------------
 */
Relation
ExecOpenScanRelation(EState *estate, Index scanrelid)
{
	Oid			reloid;
	LOCKMODE	lockmode;

	/*
803 804 805
	 * Determine the lock type we need.  First, scan to see if target relation
	 * is a result relation.  If not, check if it's a FOR UPDATE/FOR SHARE
	 * relation.  In either of those cases, we got the lock already.
806 807
	 */
	lockmode = AccessShareLock;
808 809
	if (ExecRelationIsTargetRelation(estate, scanrelid))
		lockmode = NoLock;
810
	else
811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826
	{
		ListCell   *l;

		foreach(l, estate->es_rowMarks)
		{
			ExecRowMark *erm = lfirst(l);

			if (erm->rti == scanrelid)
			{
				lockmode = NoLock;
				break;
			}
		}
	}

	/* OK, open the relation and acquire lock as needed */
827
	reloid = getrelid(scanrelid, estate->es_range_table);
828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851
	return heap_open(reloid, lockmode);
}

/* ----------------------------------------------------------------
 *		ExecCloseScanRelation
 *
 *		Close the heap relation scanned by a base-level scan plan node.
 *		This should be called during the node's ExecEnd routine.
 *
 * Currently, we do not release the lock acquired by ExecOpenScanRelation.
 * This lock should be held till end of transaction.  (There is a faction
 * that considers this too much locking, however.)
 *
 * If we did want to release the lock, we'd have to repeat the logic in
 * ExecOpenScanRelation in order to figure out what to release.
 * ----------------------------------------------------------------
 */
void
ExecCloseScanRelation(Relation scanrel)
{
	heap_close(scanrel, NoLock);
}


852
/* ----------------------------------------------------------------
853
 *				  ExecInsertIndexTuples support
854 855
 * ----------------------------------------------------------------
 */
856 857 858 859

/* ----------------------------------------------------------------
 *		ExecOpenIndices
 *
860
 *		Find the indices associated with a result relation, open them,
861
 *		and save information about them in the result ResultRelInfo.
862
 *
863
 *		At entry, caller has already opened and locked
864
 *		resultRelInfo->ri_RelationDesc.
865 866 867
 * ----------------------------------------------------------------
 */
void
868
ExecOpenIndices(ResultRelInfo *resultRelInfo)
869
{
870
	Relation	resultRelation = resultRelInfo->ri_RelationDesc;
871 872
	List	   *indexoidlist;
	ListCell   *l;
873 874
	int			len,
				i;
875 876
	RelationPtr relationDescs;
	IndexInfo **indexInfoArray;
877

878
	resultRelInfo->ri_NumIndices = 0;
879

880
	/* fast path if no indexes */
B
Bruce Momjian 已提交
881
	if (!RelationGetForm(resultRelation)->relhasindex)
H
Hiroshi Inoue 已提交
882
		return;
883

884 885
	/*
	 * Get cached list of index OIDs
886
	 */
887
	indexoidlist = RelationGetIndexList(resultRelation);
888
	len = list_length(indexoidlist);
889 890
	if (len == 0)
		return;
891

892 893
	/*
	 * allocate space for result arrays
894
	 */
895 896 897
	relationDescs = (RelationPtr) palloc(len * sizeof(Relation));
	indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *));

898 899 900
	resultRelInfo->ri_NumIndices = len;
	resultRelInfo->ri_IndexRelationDescs = relationDescs;
	resultRelInfo->ri_IndexRelationInfo = indexInfoArray;
901

902
	/*
B
Bruce Momjian 已提交
903 904
	 * For each index, open the index relation and save pg_index info. We
	 * acquire RowExclusiveLock, signifying we will update the index.
905
	 */
906
	i = 0;
907
	foreach(l, indexoidlist)
908
	{
909
		Oid			indexOid = lfirst_oid(l);
910 911
		Relation	indexDesc;
		IndexInfo  *ii;
912

913
		indexDesc = index_open(indexOid, RowExclusiveLock);
914

915 916
		/* extract index key information from the index's pg_index info */
		ii = BuildIndexInfo(indexDesc);
917

918 919 920
		relationDescs[i] = indexDesc;
		indexInfoArray[i] = ii;
		i++;
921
	}
922

923
	list_free(indexoidlist);
924 925 926
}

/* ----------------------------------------------------------------
927
 *		ExecCloseIndices
928
 *
929
 *		Close the index relations stored in resultRelInfo
930 931 932
 * ----------------------------------------------------------------
 */
void
933
ExecCloseIndices(ResultRelInfo *resultRelInfo)
934
{
935 936
	int			i;
	int			numIndices;
937
	RelationPtr indexDescs;
938

939
	numIndices = resultRelInfo->ri_NumIndices;
940
	indexDescs = resultRelInfo->ri_IndexRelationDescs;
941 942

	for (i = 0; i < numIndices; i++)
V
Vadim B. Mikheev 已提交
943
	{
944
		if (indexDescs[i] == NULL)
945
			continue;			/* shouldn't happen? */
B
Bruce Momjian 已提交
946

947
		/* Drop lock acquired by ExecOpenIndices */
948
		index_close(indexDescs[i], RowExclusiveLock);
V
Vadim B. Mikheev 已提交
949
	}
B
Bruce Momjian 已提交
950

951
	/*
952 953
	 * XXX should free indexInfo array here too?  Currently we assume that
	 * such stuff will be cleaned up automatically in FreeExecutorState.
954
	 */
955 956 957
}

/* ----------------------------------------------------------------
958
 *		ExecInsertIndexTuples
959
 *
960 961 962 963 964 965 966
 *		This routine takes care of inserting index tuples
 *		into all the relations indexing the result relation
 *		when a heap tuple is inserted into the result relation.
 *		Much of this code should be moved into the genam
 *		stuff as it only exists here because the genam stuff
 *		doesn't provide the functionality needed by the
 *		executor.. -cim 9/27/89
967
 *
968 969
 *		This returns a list of index OIDs for any unique or exclusion
 *		constraints that are deferred and that had
970 971
 *		potential (unconfirmed) conflicts.
 *
972 973 974
 *		CAUTION: this must not be called for a HOT update.
 *		We can't defend against that here for lack of info.
 *		Should we change the API to make it safer?
975 976
 * ----------------------------------------------------------------
 */
977
List *
978
ExecInsertIndexTuples(TupleTableSlot *slot,
979
					  ItemPointer tupleid,
980
					  EState *estate)
981
{
982
	List	   *result = NIL;
983
	ResultRelInfo *resultRelInfo;
984 985 986 987 988 989
	int			i;
	int			numIndices;
	RelationPtr relationDescs;
	Relation	heapRelation;
	IndexInfo **indexInfoArray;
	ExprContext *econtext;
990 991
	Datum		values[INDEX_MAX_KEYS];
	bool		isnull[INDEX_MAX_KEYS];
992

993 994
	/*
	 * Get information from the result relation info structure.
995
	 */
996 997 998 999 1000
	resultRelInfo = estate->es_result_relation_info;
	numIndices = resultRelInfo->ri_NumIndices;
	relationDescs = resultRelInfo->ri_IndexRelationDescs;
	indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
	heapRelation = resultRelInfo->ri_RelationDesc;
1001

1002
	/*
B
Bruce Momjian 已提交
1003 1004
	 * We will use the EState's per-tuple context for evaluating predicates
	 * and index expressions (creating it if it's not already there).
1005
	 */
1006
	econtext = GetPerTupleExprContext(estate);
1007 1008 1009

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

1011 1012
	/*
	 * for each index, form and insert the index tuple
1013
	 */
1014 1015
	for (i = 0; i < numIndices; i++)
	{
1016
		Relation	indexRelation = relationDescs[i];
1017
		IndexInfo  *indexInfo;
1018
		IndexUniqueCheck checkUnique;
1019
		bool		satisfiesConstraint;
1020

1021
		if (indexRelation == NULL)
1022 1023 1024
			continue;

		indexInfo = indexInfoArray[i];
1025

1026 1027 1028 1029
		/* If the index is marked as read-only, ignore it */
		if (!indexInfo->ii_ReadyForInserts)
			continue;

1030 1031
		/* Check for partial index */
		if (indexInfo->ii_Predicate != NIL)
1032
		{
1033 1034 1035
			List	   *predicate;

			/*
B
Bruce Momjian 已提交
1036 1037
			 * If predicate state not set up yet, create it (in the estate's
			 * per-query context)
1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
			 */
			predicate = indexInfo->ii_PredicateState;
			if (predicate == NIL)
			{
				predicate = (List *)
					ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
									estate);
				indexInfo->ii_PredicateState = predicate;
			}

1048
			/* Skip this index-update if the predicate isn't satisfied */
1049
			if (!ExecQual(predicate, econtext, false))
1050 1051 1052
				continue;
		}

1053
		/*
B
Bruce Momjian 已提交
1054 1055
		 * FormIndexDatum fills in its values and isnull parameters with the
		 * appropriate values for the column(s) of the index.
1056
		 */
1057
		FormIndexDatum(indexInfo,
1058
					   slot,
1059
					   estate,
1060 1061
					   values,
					   isnull);
1062

1063
		/*
1064
		 * The index AM does the actual insertion, plus uniqueness checking.
1065 1066 1067 1068 1069 1070 1071
		 *
		 * For an immediate-mode unique index, we just tell the index AM to
		 * throw error if not unique.
		 *
		 * For a deferrable unique index, we tell the index AM to just detect
		 * possible non-uniqueness, and we add the index OID to the result
		 * list if further checking is needed.
1072
		 */
1073
		if (!indexRelation->rd_index->indisunique)
1074 1075 1076 1077 1078 1079
			checkUnique = UNIQUE_CHECK_NO;
		else if (indexRelation->rd_index->indimmediate)
			checkUnique = UNIQUE_CHECK_YES;
		else
			checkUnique = UNIQUE_CHECK_PARTIAL;

1080
		satisfiesConstraint =
1081 1082 1083 1084 1085 1086 1087
			index_insert(indexRelation,	/* index relation */
						 values,		/* array of index Datums */
						 isnull,		/* null flags */
						 tupleid,		/* tid of heap tuple */
						 heapRelation,	/* heap relation */
						 checkUnique);	/* type of uniqueness check to do */

1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
		/*
		 * If the index has an associated exclusion constraint, check that.
		 * This is simpler than the process for uniqueness checks since we
		 * always insert first and then check.  If the constraint is deferred,
		 * we check now anyway, but don't throw error on violation; instead
		 * we'll queue a recheck event.
		 *
		 * An index for an exclusion constraint can't also be UNIQUE (not an
		 * essential property, we just don't allow it in the grammar), so no
		 * need to preserve the prior state of satisfiesConstraint.
		 */
		if (indexInfo->ii_ExclusionOps != NULL)
		{
			bool errorOK = !indexRelation->rd_index->indimmediate;

			satisfiesConstraint =
				check_exclusion_constraint(heapRelation,
										   indexRelation, indexInfo,
										   tupleid, values, isnull,
										   estate, false, errorOK);
		}

		if ((checkUnique == UNIQUE_CHECK_PARTIAL ||
			 indexInfo->ii_ExclusionOps != NULL) &&
			!satisfiesConstraint)
1113 1114
		{
			/*
1115 1116 1117
			 * The tuple potentially violates the uniqueness or exclusion
			 * constraint, so make a note of the index so that we can re-check
			 * it later.
1118 1119 1120
			 */
			result = lappend_oid(result, RelationGetRelid(indexRelation));
		}
1121
	}
1122 1123

	return result;
1124
}
V
Vadim B. Mikheev 已提交
1125

1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
/*
 * Check for violation of an exclusion constraint
 *
 * heap: the table containing the new tuple
 * index: the index supporting the exclusion constraint
 * indexInfo: info about the index, including the exclusion properties
 * tupleid: heap TID of the new tuple we have just inserted
 * values, isnull: the *index* column values computed for the new tuple
 * estate: an EState we can do evaluation in
 * newIndex: if true, we are trying to build a new index (this affects
 *		only the wording of error messages)
 * errorOK: if true, don't throw error for violation
 *
 * Returns true if OK, false if actual or potential violation
 *
 * When errorOK is true, we report violation without waiting to see if any
 * concurrent transaction has committed or not; so the violation is only
 * potential, and the caller must recheck sometime later.  This behavior
 * is convenient for deferred exclusion checks; we need not bother queuing
 * a deferred event if there is definitely no conflict at insertion time.
 *
 * When errorOK is false, we'll throw error on violation, so a false result
 * is impossible.
 */
bool
check_exclusion_constraint(Relation heap, Relation index, IndexInfo *indexInfo,
						   ItemPointer tupleid, Datum *values, bool *isnull,
						   EState *estate, bool newIndex, bool errorOK)
{
	Oid			*constr_procs = indexInfo->ii_ExclusionProcs;
	uint16		*constr_strats = indexInfo->ii_ExclusionStrats;
	int			 index_natts = index->rd_index->indnatts;
	IndexScanDesc	index_scan;
	HeapTuple		tup;
	ScanKeyData		scankeys[INDEX_MAX_KEYS];
	SnapshotData	DirtySnapshot;
	int				i;
	bool			conflict;
	bool			found_self;
1165
	ExprContext	   *econtext;
1166
	TupleTableSlot *existing_slot;
1167
	TupleTableSlot *save_scantuple;
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193

	/*
	 * If any of the input values are NULL, the constraint check is assumed
	 * to pass (i.e., we assume the operators are strict).
	 */
	for (i = 0; i < index_natts; i++)
	{
		if (isnull[i])
			return true;
	}

	/*
	 * Search the tuples that are in the index for any violations,
	 * including tuples that aren't visible yet.
	 */
	InitDirtySnapshot(DirtySnapshot);

	for (i = 0; i < index_natts; i++)
	{
		ScanKeyInit(&scankeys[i],
					i + 1,
					constr_strats[i],
					constr_procs[i],
					values[i]);
	}

1194 1195 1196 1197 1198 1199 1200
	/*
	 * Need a TupleTableSlot to put existing tuples in.
	 *
	 * To use FormIndexDatum, we have to make the econtext's scantuple point
	 * to this slot.  Be sure to save and restore caller's value for
	 * scantuple.
	 */
1201 1202
	existing_slot = MakeSingleTupleTableSlot(RelationGetDescr(heap));

1203 1204 1205 1206
	econtext = GetPerTupleExprContext(estate);
	save_scantuple = econtext->ecxt_scantuple;
	econtext->ecxt_scantuple = existing_slot;

1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320
	/*
	 * May have to restart scan from this point if a potential
	 * conflict is found.
	 */
retry:
	conflict = false;
	found_self = false;
	index_scan = index_beginscan(heap, index, &DirtySnapshot,
								 index_natts, scankeys);

	while ((tup = index_getnext(index_scan,
								ForwardScanDirection)) != NULL)
	{
		TransactionId	 xwait;
		Datum		existing_values[INDEX_MAX_KEYS];
		bool		existing_isnull[INDEX_MAX_KEYS];
		char		*error_new;
		char		*error_existing;

		/*
		 * Ignore the entry for the tuple we're trying to check.
		 */
		if (ItemPointerEquals(tupleid, &tup->t_self))
		{
			if (found_self)		/* should not happen */
				elog(ERROR, "found self tuple multiple times in index \"%s\"",
					 RelationGetRelationName(index));
			found_self = true;
			continue;
		}

		/*
		 * Extract the index column values and isnull flags from the existing
		 * tuple.
		 */
		ExecStoreTuple(tup,	existing_slot, InvalidBuffer, false);
		FormIndexDatum(indexInfo, existing_slot, estate,
					   existing_values, existing_isnull);

		/* If lossy indexscan, must recheck the condition */
		if (index_scan->xs_recheck)
		{
			if (!index_recheck_constraint(index,
										  constr_procs,
										  existing_values,
										  existing_isnull,
										  values))
				continue; /* tuple doesn't actually match, so no conflict */
		}

		/*
		 * At this point we have either a conflict or a potential conflict.
		 * If we're not supposed to raise error, just return the fact of the
		 * potential conflict without waiting to see if it's real.
		 */
		if (errorOK)
		{
			conflict = true;
			break;
		}

		/*
		 * If an in-progress transaction is affecting the visibility of this
		 * tuple, we need to wait for it to complete and then recheck.  For
		 * simplicity we do rechecking by just restarting the whole scan ---
		 * this case probably doesn't happen often enough to be worth trying
		 * harder, and anyway we don't want to hold any index internal locks
		 * while waiting.
		 */
		xwait = TransactionIdIsValid(DirtySnapshot.xmin) ?
			DirtySnapshot.xmin : DirtySnapshot.xmax;

		if (TransactionIdIsValid(xwait))
		{
			index_endscan(index_scan);
			XactLockTableWait(xwait);
			goto retry;
		}

		/*
		 * We have a definite conflict.  Report it.
		 */
		error_new = BuildIndexValueDescription(index, values, isnull);
		error_existing = BuildIndexValueDescription(index, existing_values,
													existing_isnull);
		if (newIndex)
			ereport(ERROR,
					(errcode(ERRCODE_EXCLUSION_VIOLATION),
					 errmsg("could not create exclusion constraint \"%s\"",
							RelationGetRelationName(index)),
					 errdetail("Key %s conflicts with key %s.",
							   error_new, error_existing)));
		else
			ereport(ERROR,
					(errcode(ERRCODE_EXCLUSION_VIOLATION),
					 errmsg("conflicting key value violates exclusion constraint \"%s\"",
							RelationGetRelationName(index)),
					 errdetail("Key %s conflicts with existing key %s.",
							   error_new, error_existing)));
	}

	index_endscan(index_scan);

	/*
	 * We should have found our tuple in the index, unless we exited the
	 * loop early because of conflict.  Complain if not.
	 */
	if (!found_self && !conflict)
		ereport(ERROR,
				(errcode(ERRCODE_INTERNAL_ERROR),
				 errmsg("failed to re-find tuple within index \"%s\"",
						RelationGetRelationName(index)),
				 errhint("This may be because of a non-immutable index expression.")));

1321 1322
	econtext->ecxt_scantuple = save_scantuple;

1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354
	ExecDropSingleTupleTableSlot(existing_slot);

	return !conflict;
}

/*
 * Check existing tuple's index values to see if it really matches the
 * exclusion condition against the new_values.  Returns true if conflict.
 */
static bool
index_recheck_constraint(Relation index, Oid *constr_procs,
						 Datum *existing_values, bool *existing_isnull,
						 Datum *new_values)
{
	int			index_natts = index->rd_index->indnatts;
	int			i;

	for (i = 0; i < index_natts; i++)
	{
		/* Assume the exclusion operators are strict */
		if (existing_isnull[i])
			return false;

		if (!DatumGetBool(OidFunctionCall2(constr_procs[i],
										   existing_values[i],
										   new_values[i])))
			return false;
	}

	return true;
}

1355 1356 1357 1358
/*
 * UpdateChangedParamSet
 *		Add changed parameters to a plan node's chgParam set
 */
1359
void
1360
UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
V
Vadim B. Mikheev 已提交
1361
{
1362
	Bitmapset  *parmset;
1363

1364
	/*
B
Bruce Momjian 已提交
1365 1366
	 * The plan node only depends on params listed in its allParam set. Don't
	 * include anything else into its chgParam set.
1367 1368
	 */
	parmset = bms_intersect(node->plan->allParam, newchg);
B
Bruce Momjian 已提交
1369

1370
	/*
B
Bruce Momjian 已提交
1371 1372
	 * Keep node->chgParam == NULL if there's not actually any members; this
	 * allows the simplest possible tests in executor node files.
1373 1374 1375 1376 1377
	 */
	if (!bms_is_empty(parmset))
		node->chgParam = bms_join(node->chgParam, parmset);
	else
		bms_free(parmset);
V
Vadim B. Mikheev 已提交
1378
}
1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394

/*
 * Register a shutdown callback in an ExprContext.
 *
 * Shutdown callbacks will be called (in reverse order of registration)
 * when the ExprContext is deleted or rescanned.  This provides a hook
 * for functions called in the context to do any cleanup needed --- it's
 * particularly useful for functions returning sets.  Note that the
 * callback will *not* be called in the event that execution is aborted
 * by an error.
 */
void
RegisterExprContextCallback(ExprContext *econtext,
							ExprContextCallbackFunction function,
							Datum arg)
{
B
Bruce Momjian 已提交
1395
	ExprContext_CB *ecxt_callback;
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420

	/* Save the info in appropriate memory context */
	ecxt_callback = (ExprContext_CB *)
		MemoryContextAlloc(econtext->ecxt_per_query_memory,
						   sizeof(ExprContext_CB));

	ecxt_callback->function = function;
	ecxt_callback->arg = arg;

	/* link to front of list for appropriate execution order */
	ecxt_callback->next = econtext->ecxt_callbacks;
	econtext->ecxt_callbacks = ecxt_callback;
}

/*
 * Deregister a shutdown callback in an ExprContext.
 *
 * Any list entries matching the function and arg will be removed.
 * This can be used if it's no longer necessary to call the callback.
 */
void
UnregisterExprContextCallback(ExprContext *econtext,
							  ExprContextCallbackFunction function,
							  Datum arg)
{
B
Bruce Momjian 已提交
1421 1422
	ExprContext_CB **prev_callback;
	ExprContext_CB *ecxt_callback;
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442

	prev_callback = &econtext->ecxt_callbacks;

	while ((ecxt_callback = *prev_callback) != NULL)
	{
		if (ecxt_callback->function == function && ecxt_callback->arg == arg)
		{
			*prev_callback = ecxt_callback->next;
			pfree(ecxt_callback);
		}
		else
			prev_callback = &ecxt_callback->next;
	}
}

/*
 * Call all the shutdown callbacks registered in an ExprContext.
 *
 * The callback list is emptied (important in case this is only a rescan
 * reset, and not deletion of the ExprContext).
1443 1444 1445
 *
 * If isCommit is false, just clean the callback list but don't call 'em.
 * (See comment for FreeExprContext.)
1446 1447
 */
static void
1448
ShutdownExprContext(ExprContext *econtext, bool isCommit)
1449
{
B
Bruce Momjian 已提交
1450
	ExprContext_CB *ecxt_callback;
1451 1452 1453 1454 1455 1456 1457
	MemoryContext oldcontext;

	/* Fast path in normal case where there's nothing to do. */
	if (econtext->ecxt_callbacks == NULL)
		return;

	/*
B
Bruce Momjian 已提交
1458 1459
	 * Call the callbacks in econtext's per-tuple context.  This ensures that
	 * any memory they might leak will get cleaned up.
1460 1461
	 */
	oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
1462 1463 1464 1465 1466 1467 1468

	/*
	 * Call each callback function in reverse registration order.
	 */
	while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
	{
		econtext->ecxt_callbacks = ecxt_callback->next;
1469 1470
		if (isCommit)
			(*ecxt_callback->function) (ecxt_callback->arg);
1471 1472
		pfree(ecxt_callback);
	}
1473 1474

	MemoryContextSwitchTo(oldcontext);
1475
}