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

39 40
#include "postgres.h"

41
#include "access/genam.h"
B
Bruce Momjian 已提交
42 43
#include "access/heapam.h"
#include "catalog/index.h"
H
Hiroshi Inoue 已提交
44
#include "catalog/catalog.h"
B
Bruce Momjian 已提交
45
#include "catalog/pg_index.h"
B
Bruce Momjian 已提交
46
#include "executor/execdebug.h"
H
Hiroshi Inoue 已提交
47
#include "miscadmin.h"
48 49
#include "utils/builtins.h"
#include "utils/fmgroids.h"
50
#include "utils/memutils.h"
51 52
#include "utils/relcache.h"
#include "utils/syscache.h"
53

54

55
/* ----------------------------------------------------------------
56 57
 *		global counters for number of tuples processed, retrieved,
 *		appended, replaced, deleted.
58 59
 * ----------------------------------------------------------------
 */
60 61 62 63 64 65
int			NTupleProcessed;
int			NTupleRetrieved;
int			NTupleReplaced;
int			NTupleAppended;
int			NTupleDeleted;
int			NIndexTupleInserted;
B
Bruce Momjian 已提交
66 67
extern int	NIndexTupleProcessed;		/* have to be defined in the access
										 * method level so that the
68
										 * cinterface.a will link ok. */
69

70 71 72

static void ShutdownExprContext(ExprContext *econtext);

73

74
/* ----------------------------------------------------------------
75
 *						statistic functions
76 77 78 79
 * ----------------------------------------------------------------
 */

/* ----------------------------------------------------------------
80
 *		ResetTupleCount
81 82
 * ----------------------------------------------------------------
 */
83
#ifdef NOT_USED
84
void
85
ResetTupleCount(void)
86
{
87 88 89 90 91 92
	NTupleProcessed = 0;
	NTupleRetrieved = 0;
	NTupleAppended = 0;
	NTupleDeleted = 0;
	NTupleReplaced = 0;
	NIndexTupleProcessed = 0;
93
}
94
#endif
95 96

/* ----------------------------------------------------------------
97
 *		PrintTupleCount
98 99
 * ----------------------------------------------------------------
 */
100
#ifdef NOT_USED
101
void
102
DisplayTupleCount(FILE *statfp)
103
{
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
	if (NTupleProcessed > 0)
		fprintf(statfp, "!\t%d tuple%s processed, ", NTupleProcessed,
				(NTupleProcessed == 1) ? "" : "s");
	else
	{
		fprintf(statfp, "!\tno tuples processed.\n");
		return;
	}
	if (NIndexTupleProcessed > 0)
		fprintf(statfp, "%d indextuple%s processed, ", NIndexTupleProcessed,
				(NIndexTupleProcessed == 1) ? "" : "s");
	if (NIndexTupleInserted > 0)
		fprintf(statfp, "%d indextuple%s inserted, ", NIndexTupleInserted,
				(NIndexTupleInserted == 1) ? "" : "s");
	if (NTupleRetrieved > 0)
		fprintf(statfp, "%d tuple%s retrieved. ", NTupleRetrieved,
				(NTupleRetrieved == 1) ? "" : "s");
	if (NTupleAppended > 0)
		fprintf(statfp, "%d tuple%s appended. ", NTupleAppended,
				(NTupleAppended == 1) ? "" : "s");
	if (NTupleDeleted > 0)
		fprintf(statfp, "%d tuple%s deleted. ", NTupleDeleted,
				(NTupleDeleted == 1) ? "" : "s");
	if (NTupleReplaced > 0)
		fprintf(statfp, "%d tuple%s replaced. ", NTupleReplaced,
				(NTupleReplaced == 1) ? "" : "s");
	fprintf(statfp, "\n");
131
}
132
#endif
133

134

135
/* ----------------------------------------------------------------
136
 *				 Executor state and memory management functions
137 138 139 140
 * ----------------------------------------------------------------
 */

/* ----------------
141
 *		CreateExecutorState
142
 *
143 144
 *		Create and initialize an EState node, which is the root of
 *		working storage for an entire Executor invocation.
145
 *
146 147 148 149
 * 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.
150 151
 * ----------------
 */
152 153
EState *
CreateExecutorState(void)
154
{
155 156 157
	EState	   *estate;
	MemoryContext qcontext;
	MemoryContext oldcontext;
158

159 160 161 162 163 164 165 166
	/*
	 * 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 已提交
167

168
	/*
B
Bruce Momjian 已提交
169 170
	 * Make the EState node within the per-query context.  This way, we don't
	 * need a separate pfree() operation for it at shutdown.
171
	 */
172 173 174 175 176 177 178 179 180
	oldcontext = MemoryContextSwitchTo(qcontext);

	estate = makeNode(EState);

	/*
	 * Initialize all fields of the Executor State structure
	 */
	estate->es_direction = ForwardScanDirection;
	estate->es_snapshot = SnapshotNow;
181
	estate->es_crosscheck_snapshot = InvalidSnapshot;	/* no crosscheck */
182 183 184 185 186 187 188
	estate->es_range_table = NIL;

	estate->es_result_relations = NULL;
	estate->es_num_result_relations = 0;
	estate->es_result_relation_info = NULL;

	estate->es_junkFilter = NULL;
189

190
	estate->es_into_relation_descriptor = NULL;
191
	estate->es_into_relation_use_wal = false;
192 193 194 195 196 197 198

	estate->es_param_list_info = NULL;
	estate->es_param_exec_vals = NULL;

	estate->es_query_cxt = qcontext;

	estate->es_tupleTable = NULL;
199

200 201
	estate->es_processed = 0;
	estate->es_lastoid = InvalidOid;
202
	estate->es_rowMarks = NIL;
203
	estate->es_forUpdate = false;
204
	estate->es_rowNoWait = false;
205 206

	estate->es_instrument = false;
207 208
	estate->es_select_into = false;
	estate->es_into_oids = false;
209 210 211 212 213

	estate->es_exprcontexts = NIL;

	estate->es_per_tuple_exprcontext = NULL;

214
	estate->es_topPlan = NULL;
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
	estate->es_evalPlanQual = NULL;
	estate->es_evTupleNull = NULL;
	estate->es_evTuple = NULL;
	estate->es_useEvalPlan = false;

	/*
	 * 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 已提交
247 248 249 250
	 * 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).
251 252 253
	 */
	while (estate->es_exprcontexts)
	{
B
Bruce Momjian 已提交
254
		/*
B
Bruce Momjian 已提交
255 256
		 * XXX: seems there ought to be a faster way to implement this than
		 * repeated list_delete(), no?
257 258
		 */
		FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts));
259 260
		/* FreeExprContext removed the list link for us */
	}
B
Bruce Momjian 已提交
261

262 263 264 265 266
	/*
	 * Free the per-query memory context, thereby releasing all working
	 * memory, including the EState node itself.
	 */
	MemoryContextDelete(estate->es_query_cxt);
267 268 269
}

/* ----------------
270 271 272 273 274 275 276 277
 *		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.
278
 *
279
 * Note we make no assumption about the caller's memory context.
280 281
 * ----------------
 */
282
ExprContext *
283
CreateExprContext(EState *estate)
284
{
285 286
	ExprContext *econtext;
	MemoryContext oldcontext;
287

288 289 290 291 292 293 294
	/* 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;
295 296
	econtext->ecxt_innertuple = NULL;
	econtext->ecxt_outertuple = NULL;
297 298

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

300
	/*
301
	 * Create working memory for expression evaluation in this context.
302 303
	 */
	econtext->ecxt_per_tuple_memory =
304 305 306
		AllocSetContextCreate(estate->es_query_cxt,
							  "ExprContext",
							  ALLOCSET_DEFAULT_MINSIZE,
307 308
							  ALLOCSET_DEFAULT_INITSIZE,
							  ALLOCSET_DEFAULT_MAXSIZE);
309 310 311 312

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

313 314
	econtext->ecxt_aggvalues = NULL;
	econtext->ecxt_aggnulls = NULL;
315

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

319 320 321 322 323
	econtext->domainValue_datum = (Datum) 0;
	econtext->domainValue_isNull = true;

	econtext->ecxt_estate = estate;

324
	econtext->ecxt_callbacks = NULL;
325

326
	/*
B
Bruce Momjian 已提交
327 328 329
	 * 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.
330 331 332 333 334
	 */
	estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);

	MemoryContextSwitchTo(oldcontext);

335 336
	return econtext;
}
337

338 339 340 341 342 343 344 345 346 347 348
/* ----------------
 *		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!
 *
 * Note we make no assumption about the caller's memory context.
 * ----------------
349 350 351 352
 */
void
FreeExprContext(ExprContext *econtext)
{
353 354
	EState	   *estate;

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

366 367 368 369
/*
 * ReScanExprContext
 *
 *		Reset an expression context in preparation for a rescan of its
B
Bruce Momjian 已提交
370
 *		plan node.	This requires calling any registered shutdown callbacks,
371 372 373 374 375 376 377 378 379 380 381 382 383
 *		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 */
	ShutdownExprContext(econtext);
	/* And clean up the memory used */
	MemoryContextReset(econtext->ecxt_per_tuple_memory);
}

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

	return estate->es_per_tuple_exprcontext;
}

399

400
/* ----------------------------------------------------------------
401 402 403 404
 *				 miscellaneous node-init support functions
 *
 * Note: all of these are expected to be called with CurrentMemoryContext
 * equal to the per-query memory context.
405 406 407
 * ----------------------------------------------------------------
 */

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

423
/* ----------------
424
 *		ExecAssignResultType
425 426 427
 * ----------------
 */
void
428
ExecAssignResultType(PlanState *planstate,
429
					 TupleDesc tupDesc, bool shouldFree)
430
{
431
	TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
432

433
	ExecSetSlotDescriptor(slot, tupDesc, shouldFree);
434 435 436
}

/* ----------------
437
 *		ExecAssignResultTypeFromOuterPlan
438 439 440
 * ----------------
 */
void
441
ExecAssignResultTypeFromOuterPlan(PlanState *planstate)
442
{
443
	PlanState  *outerPlan;
444
	TupleDesc	tupDesc;
445

446
	outerPlan = outerPlanState(planstate);
447
	tupDesc = ExecGetResultType(outerPlan);
448

449
	ExecAssignResultType(planstate, tupDesc, false);
450 451 452
}

/* ----------------
453
 *		ExecAssignResultTypeFromTL
454 455 456
 * ----------------
 */
void
457
ExecAssignResultTypeFromTL(PlanState *planstate)
458
{
459
	bool		hasoid;
460
	TupleDesc	tupDesc;
461

462 463 464 465
	if (ExecContextForcesOids(planstate, &hasoid))
	{
		/* context forces OID choice; hasoid is now set correctly */
	}
466
	else
467
	{
468 469
		/* given free choice, don't leave space for OIDs in result tuples */
		hasoid = false;
470
	}
B
Bruce Momjian 已提交
471

472
	/*
B
Bruce Momjian 已提交
473 474 475
	 * 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 ...
476 477 478
	 */
	tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
	ExecAssignResultType(planstate, tupDesc, true);
479 480 481
}

/* ----------------
482
 *		ExecGetResultType
483 484 485
 * ----------------
 */
TupleDesc
486
ExecGetResultType(PlanState *planstate)
487
{
488
	TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
489

490
	return slot->tts_tupleDescriptor;
491 492 493
}

/* ----------------
494 495 496 497 498 499
 *		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.
500 501
 * ----------------
 */
502 503 504 505
ProjectionInfo *
ExecBuildProjectionInfo(List *targetList,
						ExprContext *econtext,
						TupleTableSlot *slot)
506
{
507
	ProjectionInfo *projInfo = makeNode(ProjectionInfo);
508
	int			len;
509 510
	bool		isVarList;
	ListCell   *tl;
511 512 513 514

	len = ExecTargetListLength(targetList);

	projInfo->pi_targetlist = targetList;
515 516
	projInfo->pi_exprContext = econtext;
	projInfo->pi_slot = slot;
517 518 519

	/*
	 * Determine whether the target list consists entirely of simple Var
B
Bruce Momjian 已提交
520 521
	 * references (ie, references to non-system attributes).  If so, we can
	 * use the simpler ExecVariableList instead of ExecTargetList.
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546
	 */
	isVarList = true;
	foreach(tl, targetList)
	{
		GenericExprState *gstate = (GenericExprState *) lfirst(tl);
		Var		   *variable = (Var *) gstate->arg->expr;

		if (variable == NULL ||
			!IsA(variable, Var) ||
			variable->varattno <= 0)
		{
			isVarList = false;
			break;
		}
	}
	projInfo->pi_isVarList = isVarList;

	if (isVarList)
	{
		int		   *varSlotOffsets;
		int		   *varNumbers;
		AttrNumber	lastInnerVar = 0;
		AttrNumber	lastOuterVar = 0;
		AttrNumber	lastScanVar = 0;

B
Bruce Momjian 已提交
547
		projInfo->pi_itemIsDone = NULL; /* not needed */
548 549 550 551 552 553
		projInfo->pi_varSlotOffsets = varSlotOffsets = (int *)
			palloc0(len * sizeof(int));
		projInfo->pi_varNumbers = varNumbers = (int *)
			palloc0(len * sizeof(int));

		/*
B
Bruce Momjian 已提交
554 555 556 557 558
		 * Set up the data needed by ExecVariableList.	The slots in which the
		 * variables can be found at runtime are denoted by the offsets of
		 * their slot pointers within the econtext.  This rather grotty
		 * representation is needed because the caller may not have given us
		 * the real econtext yet (see hacks in nodeSubplan.c).
559 560 561 562 563 564 565
		 */
		foreach(tl, targetList)
		{
			GenericExprState *gstate = (GenericExprState *) lfirst(tl);
			Var		   *variable = (Var *) gstate->arg->expr;
			AttrNumber	attnum = variable->varattno;
			TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
566
			AttrNumber	resind = tle->resno - 1;
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596

			Assert(resind >= 0 && resind < len);
			varNumbers[resind] = attnum;

			switch (variable->varno)
			{
				case INNER:
					varSlotOffsets[resind] = offsetof(ExprContext,
													  ecxt_innertuple);
					lastInnerVar = Max(lastInnerVar, attnum);
					break;

				case OUTER:
					varSlotOffsets[resind] = offsetof(ExprContext,
													  ecxt_outertuple);
					lastOuterVar = Max(lastOuterVar, attnum);
					break;

				default:
					varSlotOffsets[resind] = offsetof(ExprContext,
													  ecxt_scantuple);
					lastScanVar = Max(lastScanVar, attnum);
					break;
			}
		}
		projInfo->pi_lastInnerVar = lastInnerVar;
		projInfo->pi_lastOuterVar = lastOuterVar;
		projInfo->pi_lastScanVar = lastScanVar;
	}
	else
597
	{
598 599 600 601
		projInfo->pi_itemIsDone = (ExprDoneCond *)
			palloc(len * sizeof(ExprDoneCond));
		projInfo->pi_varSlotOffsets = NULL;
		projInfo->pi_varNumbers = NULL;
602 603 604 605
	}

	return projInfo;
}
606

607 608 609 610 611 612 613
/* ----------------
 *		ExecAssignProjectionInfo
 *
 * forms the projection information from the node's targetlist
 * ----------------
 */
void
614
ExecAssignProjectionInfo(PlanState *planstate)
615 616 617 618 619
{
	planstate->ps_ProjInfo =
		ExecBuildProjectionInfo(planstate->targetlist,
								planstate->ps_ExprContext,
								planstate->ps_ResultTupleSlot);
620 621 622
}


623 624
/* ----------------
 *		ExecFreeExprContext
625
 *
626 627 628
 * 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
629
 * explicitly because they're just memory in the per-query memory context.)
630 631 632
 *
 * However ... there is no particular need to do it during ExecEndNode,
 * because FreeExecutorState will free any remaining ExprContexts within
B
Bruce Momjian 已提交
633
 * the EState.	Letting FreeExecutorState do it allows the ExprContexts to
634 635 636
 * 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.
637 638 639
 * ----------------
 */
void
640
ExecFreeExprContext(PlanState *planstate)
641
{
642
	/*
B
Bruce Momjian 已提交
643 644
	 * Per above discussion, don't actually delete the ExprContext. We do
	 * unlink it from the plan node, though.
645
	 */
646
	planstate->ps_ExprContext = NULL;
647 648
}

649
/* ----------------------------------------------------------------
650 651 652 653 654 655
 *		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
656 657 658 659
 * ----------------------------------------------------------------
 */

/* ----------------
660
 *		ExecGetScanType
661 662 663
 * ----------------
 */
TupleDesc
664
ExecGetScanType(ScanState *scanstate)
665
{
666
	TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
667

668
	return slot->tts_tupleDescriptor;
669 670 671
}

/* ----------------
672
 *		ExecAssignScanType
673 674 675
 * ----------------
 */
void
676
ExecAssignScanType(ScanState *scanstate,
677
				   TupleDesc tupDesc, bool shouldFree)
678
{
679
	TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
680

681
	ExecSetSlotDescriptor(slot, tupDesc, shouldFree);
682 683 684
}

/* ----------------
685
 *		ExecAssignScanTypeFromOuterPlan
686 687 688
 * ----------------
 */
void
689
ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
690
{
691
	PlanState  *outerPlan;
692
	TupleDesc	tupDesc;
693

694
	outerPlan = outerPlanState(scanstate);
695
	tupDesc = ExecGetResultType(outerPlan);
696

697
	ExecAssignScanType(scanstate, tupDesc, false);
698 699 700 701
}


/* ----------------------------------------------------------------
702
 *				  ExecInsertIndexTuples support
703 704
 * ----------------------------------------------------------------
 */
705 706 707 708

/* ----------------------------------------------------------------
 *		ExecOpenIndices
 *
709
 *		Find the indices associated with a result relation, open them,
710
 *		and save information about them in the result ResultRelInfo.
711
 *
712
 *		At entry, caller has already opened and locked
713
 *		resultRelInfo->ri_RelationDesc.
714
 *
715
 *		This used to be horribly ugly code, and slow too because it
B
Bruce Momjian 已提交
716
 *		did a sequential scan of pg_index.	Now we rely on the relcache
717 718 719
 *		to cache a list of the OIDs of the indices associated with any
 *		specific relation, and we use the pg_index syscache to get the
 *		entries we need from pg_index.
720 721 722
 * ----------------------------------------------------------------
 */
void
723
ExecOpenIndices(ResultRelInfo *resultRelInfo)
724
{
725
	Relation	resultRelation = resultRelInfo->ri_RelationDesc;
726 727
	List	   *indexoidlist;
	ListCell   *l;
728 729
	int			len,
				i;
730 731
	RelationPtr relationDescs;
	IndexInfo **indexInfoArray;
732

733
	resultRelInfo->ri_NumIndices = 0;
734

735
	/* fast path if no indexes */
B
Bruce Momjian 已提交
736
	if (!RelationGetForm(resultRelation)->relhasindex)
H
Hiroshi Inoue 已提交
737
		return;
738

739 740
	/*
	 * Get cached list of index OIDs
741
	 */
742
	indexoidlist = RelationGetIndexList(resultRelation);
743
	len = list_length(indexoidlist);
744 745
	if (len == 0)
		return;
746

747 748
	/*
	 * allocate space for result arrays
749
	 */
750 751 752
	relationDescs = (RelationPtr) palloc(len * sizeof(Relation));
	indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *));

753 754 755
	resultRelInfo->ri_NumIndices = len;
	resultRelInfo->ri_IndexRelationDescs = relationDescs;
	resultRelInfo->ri_IndexRelationInfo = indexInfoArray;
756

757 758
	/*
	 * For each index, open the index relation and save pg_index info.
759
	 */
760
	i = 0;
761
	foreach(l, indexoidlist)
762
	{
763
		Oid			indexOid = lfirst_oid(l);
764 765
		Relation	indexDesc;
		IndexInfo  *ii;
766

767
		/*
768 769 770 771 772 773
		 * Open and lock the index relation
		 *
		 * If the index AM supports concurrent updates, obtain RowExclusiveLock
		 * to signify that we are updating the index.  This locks out only
		 * operations that need exclusive access, such as relocating the index
		 * to a new tablespace.
774
		 *
775
		 * If the index AM is not safe for concurrent updates, obtain an
B
Bruce Momjian 已提交
776 777
		 * exclusive lock on the index to lock out other updaters as well as
		 * readers (index_beginscan places AccessShareLock).
778
		 *
B
Bruce Momjian 已提交
779 780 781 782
		 * If there are multiple not-concurrent-safe indexes, all backends must
		 * lock the indexes in the same order or we will get deadlocks here.
		 * This is guaranteed by RelationGetIndexList(), which promises to
		 * return the index list in OID order.
783 784
		 *
		 * The locks will be released in ExecCloseIndices.
785
		 */
786 787
		indexDesc = index_open(indexOid);

788 789 790
		if (indexDesc->rd_am->amconcurrent)
			LockRelation(indexDesc, RowExclusiveLock);
		else
791
			LockRelation(indexDesc, AccessExclusiveLock);
792

793 794
		/* extract index key information from the index's pg_index info */
		ii = BuildIndexInfo(indexDesc);
795

796 797 798
		relationDescs[i] = indexDesc;
		indexInfoArray[i] = ii;
		i++;
799
	}
800

801
	list_free(indexoidlist);
802 803 804
}

/* ----------------------------------------------------------------
805
 *		ExecCloseIndices
806
 *
807
 *		Close the index relations stored in resultRelInfo
808 809 810
 * ----------------------------------------------------------------
 */
void
811
ExecCloseIndices(ResultRelInfo *resultRelInfo)
812
{
813 814
	int			i;
	int			numIndices;
815
	RelationPtr indexDescs;
816

817
	numIndices = resultRelInfo->ri_NumIndices;
818
	indexDescs = resultRelInfo->ri_IndexRelationDescs;
819 820

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

825 826 827 828
		/* Drop lock acquired by ExecOpenIndices */
		if (indexDescs[i]->rd_am->amconcurrent)
			UnlockRelation(indexDescs[i], RowExclusiveLock);
		else
829
			UnlockRelation(indexDescs[i], AccessExclusiveLock);
830

831
		index_close(indexDescs[i]);
V
Vadim B. Mikheev 已提交
832
	}
B
Bruce Momjian 已提交
833

834
	/*
835 836
	 * XXX should free indexInfo array here too?  Currently we assume that
	 * such stuff will be cleaned up automatically in FreeExecutorState.
837
	 */
838 839 840
}

/* ----------------------------------------------------------------
841
 *		ExecInsertIndexTuples
842
 *
843 844 845 846 847 848 849
 *		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
850 851 852
 * ----------------------------------------------------------------
 */
void
853
ExecInsertIndexTuples(TupleTableSlot *slot,
854
					  ItemPointer tupleid,
855
					  EState *estate,
856
					  bool is_vacuum)
857
{
858
	ResultRelInfo *resultRelInfo;
859 860 861 862 863 864
	int			i;
	int			numIndices;
	RelationPtr relationDescs;
	Relation	heapRelation;
	IndexInfo **indexInfoArray;
	ExprContext *econtext;
865 866
	Datum		values[INDEX_MAX_KEYS];
	bool		isnull[INDEX_MAX_KEYS];
867

868 869
	/*
	 * Get information from the result relation info structure.
870
	 */
871 872 873 874 875
	resultRelInfo = estate->es_result_relation_info;
	numIndices = resultRelInfo->ri_NumIndices;
	relationDescs = resultRelInfo->ri_IndexRelationDescs;
	indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
	heapRelation = resultRelInfo->ri_RelationDesc;
876

877
	/*
B
Bruce Momjian 已提交
878 879
	 * We will use the EState's per-tuple context for evaluating predicates
	 * and index expressions (creating it if it's not already there).
880
	 */
881
	econtext = GetPerTupleExprContext(estate);
882 883 884

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

886 887
	/*
	 * for each index, form and insert the index tuple
888
	 */
889 890
	for (i = 0; i < numIndices; i++)
	{
891 892
		IndexInfo  *indexInfo;

893 894 895 896
		if (relationDescs[i] == NULL)
			continue;

		indexInfo = indexInfoArray[i];
897 898 899

		/* Check for partial index */
		if (indexInfo->ii_Predicate != NIL)
900
		{
901 902 903
			List	   *predicate;

			/*
B
Bruce Momjian 已提交
904 905
			 * If predicate state not set up yet, create it (in the estate's
			 * per-query context)
906 907 908 909 910 911 912 913 914 915
			 */
			predicate = indexInfo->ii_PredicateState;
			if (predicate == NIL)
			{
				predicate = (List *)
					ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
									estate);
				indexInfo->ii_PredicateState = predicate;
			}

916
			/* Skip this index-update if the predicate isn't satisfied */
917
			if (!ExecQual(predicate, econtext, false))
918 919 920
				continue;
		}

921
		/*
B
Bruce Momjian 已提交
922 923
		 * FormIndexDatum fills in its values and isnull parameters with the
		 * appropriate values for the column(s) of the index.
924
		 */
925
		FormIndexDatum(indexInfo,
926
					   slot,
927
					   estate,
928 929
					   values,
					   isnull);
930

931
		/*
B
Bruce Momjian 已提交
932 933 934
		 * The index AM does the rest.	Note we suppress unique-index checks
		 * if we are being called from VACUUM, since VACUUM may need to move
		 * dead tuples that have the same keys as live ones.
935
		 */
936
		index_insert(relationDescs[i],	/* index relation */
B
Bruce Momjian 已提交
937 938 939
					 values,	/* array of index Datums */
					 isnull,	/* null flags */
					 tupleid,	/* tid of heap tuple */
940 941
					 heapRelation,
					 relationDescs[i]->rd_index->indisunique && !is_vacuum);
942

943 944
		/*
		 * keep track of index inserts for debugging
945 946 947
		 */
		IncrIndexInserted();
	}
948
}
V
Vadim B. Mikheev 已提交
949

950 951 952 953
/*
 * UpdateChangedParamSet
 *		Add changed parameters to a plan node's chgParam set
 */
954
void
955
UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
V
Vadim B. Mikheev 已提交
956
{
957
	Bitmapset  *parmset;
958

959
	/*
B
Bruce Momjian 已提交
960 961
	 * The plan node only depends on params listed in its allParam set. Don't
	 * include anything else into its chgParam set.
962 963
	 */
	parmset = bms_intersect(node->plan->allParam, newchg);
B
Bruce Momjian 已提交
964

965
	/*
B
Bruce Momjian 已提交
966 967
	 * Keep node->chgParam == NULL if there's not actually any members; this
	 * allows the simplest possible tests in executor node files.
968 969 970 971 972
	 */
	if (!bms_is_empty(parmset))
		node->chgParam = bms_join(node->chgParam, parmset);
	else
		bms_free(parmset);
V
Vadim B. Mikheev 已提交
973
}
974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989

/*
 * 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 已提交
990
	ExprContext_CB *ecxt_callback;
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015

	/* 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 已提交
1016 1017
	ExprContext_CB **prev_callback;
	ExprContext_CB *ecxt_callback;
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041

	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).
 */
static void
ShutdownExprContext(ExprContext *econtext)
{
B
Bruce Momjian 已提交
1042
	ExprContext_CB *ecxt_callback;
1043 1044 1045 1046 1047 1048 1049
	MemoryContext oldcontext;

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

	/*
B
Bruce Momjian 已提交
1050 1051
	 * Call the callbacks in econtext's per-tuple context.  This ensures that
	 * any memory they might leak will get cleaned up.
1052 1053
	 */
	oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063

	/*
	 * Call each callback function in reverse registration order.
	 */
	while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
	{
		econtext->ecxt_callbacks = ecxt_callback->next;
		(*ecxt_callback->function) (ecxt_callback->arg);
		pfree(ecxt_callback);
	}
1064 1065

	MemoryContextSwitchTo(oldcontext);
1066
}