execQual.c 126 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * execQual.c
4
 *	  Routines to evaluate qualification and targetlist expressions
5
 *
6
 * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
Bruce Momjian's avatar
Add:  
Bruce Momjian committed
7
 * Portions Copyright (c) 1994, Regents of the University of California
8 9 10
 *
 *
 * IDENTIFICATION
11
 *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.212 2007/02/03 14:06:53 petere Exp $
12 13 14 15
 *
 *-------------------------------------------------------------------------
 */
/*
16
 *	 INTERFACE ROUTINES
17
 *		ExecEvalExpr	- (now a macro) evaluate an expression, return a datum
18
 *		ExecEvalExprSwitchContext - same, but switch into eval memory context
19
 *		ExecQual		- return true/false if qualification is satisfied
20
 *		ExecProject		- form a new tuple by projecting the given tuple
21
 *
22
 *	 NOTES
23 24
 *		The more heavily used ExecEvalExpr routines, such as ExecEvalVar(),
 *		are hotspots. Making these faster will speed up the entire system.
25
 *
26
 *		ExecProject() is used to make tuple projections.  Rather then
27 28 29
 *		trying to speed it up, the execution plan should be pre-processed
 *		to facilitate attribute sharing between nodes wherever possible,
 *		instead of doing needless copying.	-cim 5/31/91
30 31 32 33 34
 *
 *		During expression evaluation, we check_stack_depth only in
 *		ExecMakeFunctionResult rather than at every single node.  This
 *		is a compromise that trades off precision of the stack limit setting
 *		to gain speed.
35
 */
36

37
#include "postgres.h"
38

Bruce Momjian's avatar
Bruce Momjian committed
39
#include "access/heapam.h"
40
#include "access/nbtree.h"
41
#include "catalog/pg_type.h"
42
#include "commands/typecmds.h"
43
#include "executor/execdebug.h"
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
44
#include "executor/nodeSubplan.h"
45
#include "funcapi.h"
46
#include "miscadmin.h"
47
#include "nodes/makefuncs.h"
48
#include "optimizer/planmain.h"
49
#include "parser/parse_expr.h"
50
#include "utils/acl.h"
51
#include "utils/builtins.h"
52
#include "utils/lsyscache.h"
53
#include "utils/memutils.h"
54
#include "utils/typcache.h"
55
#include "utils/xml.h"
Bruce Momjian's avatar
Bruce Momjian committed
56

57

58
/* static function decls */
59
static Datum ExecEvalArrayRef(ArrayRefExprState *astate,
Bruce Momjian's avatar
Bruce Momjian committed
60 61
				 ExprContext *econtext,
				 bool *isNull, ExprDoneCond *isDone);
62
static Datum ExecEvalAggref(AggrefExprState *aggref,
Bruce Momjian's avatar
Bruce Momjian committed
63 64
			   ExprContext *econtext,
			   bool *isNull, ExprDoneCond *isDone);
65
static Datum ExecEvalVar(ExprState *exprstate, ExprContext *econtext,
Bruce Momjian's avatar
Bruce Momjian committed
66
			bool *isNull, ExprDoneCond *isDone);
67 68
static Datum ExecEvalScalarVar(ExprState *exprstate, ExprContext *econtext,
			bool *isNull, ExprDoneCond *isDone);
69
static Datum ExecEvalWholeRowVar(ExprState *exprstate, ExprContext *econtext,
70
					bool *isNull, ExprDoneCond *isDone);
71
static Datum ExecEvalConst(ExprState *exprstate, ExprContext *econtext,
Bruce Momjian's avatar
Bruce Momjian committed
72
			  bool *isNull, ExprDoneCond *isDone);
73
static Datum ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
Bruce Momjian's avatar
Bruce Momjian committed
74
			  bool *isNull, ExprDoneCond *isDone);
75 76 77 78
static void ShutdownFuncExpr(Datum arg);
static TupleDesc get_cached_rowtype(Oid type_id, int32 typmod,
				   TupleDesc *cache_field, ExprContext *econtext);
static void ShutdownTupleDescRef(Datum arg);
79 80 81
static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo,
				 List *argList, ExprContext *econtext);
static Datum ExecMakeFunctionResultNoSets(FuncExprState *fcache,
Bruce Momjian's avatar
Bruce Momjian committed
82 83
							 ExprContext *econtext,
							 bool *isNull, ExprDoneCond *isDone);
84
static Datum ExecEvalFunc(FuncExprState *fcache, ExprContext *econtext,
85
			 bool *isNull, ExprDoneCond *isDone);
86
static Datum ExecEvalOper(FuncExprState *fcache, ExprContext *econtext,
87
			 bool *isNull, ExprDoneCond *isDone);
88
static Datum ExecEvalDistinct(FuncExprState *fcache, ExprContext *econtext,
Bruce Momjian's avatar
Bruce Momjian committed
89
				 bool *isNull, ExprDoneCond *isDone);
90
static Datum ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
Bruce Momjian's avatar
Bruce Momjian committed
91 92
					  ExprContext *econtext,
					  bool *isNull, ExprDoneCond *isDone);
93
static Datum ExecEvalNot(BoolExprState *notclause, ExprContext *econtext,
Bruce Momjian's avatar
Bruce Momjian committed
94
			bool *isNull, ExprDoneCond *isDone);
95
static Datum ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,
Bruce Momjian's avatar
Bruce Momjian committed
96
		   bool *isNull, ExprDoneCond *isDone);
97
static Datum ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
Bruce Momjian's avatar
Bruce Momjian committed
98
			bool *isNull, ExprDoneCond *isDone);
99
static Datum ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
100 101
					   ExprContext *econtext,
					   bool *isNull, ExprDoneCond *isDone);
102
static Datum ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
103
			 bool *isNull, ExprDoneCond *isDone);
104
static Datum ExecEvalCaseTestExpr(ExprState *exprstate,
Bruce Momjian's avatar
Bruce Momjian committed
105 106
					 ExprContext *econtext,
					 bool *isNull, ExprDoneCond *isDone);
107
static Datum ExecEvalArray(ArrayExprState *astate,
Bruce Momjian's avatar
Bruce Momjian committed
108 109
			  ExprContext *econtext,
			  bool *isNull, ExprDoneCond *isDone);
110
static Datum ExecEvalRow(RowExprState *rstate,
Bruce Momjian's avatar
Bruce Momjian committed
111 112
			ExprContext *econtext,
			bool *isNull, ExprDoneCond *isDone);
113
static Datum ExecEvalRowCompare(RowCompareExprState *rstate,
Bruce Momjian's avatar
Bruce Momjian committed
114 115
				   ExprContext *econtext,
				   bool *isNull, ExprDoneCond *isDone);
116
static Datum ExecEvalCoalesce(CoalesceExprState *coalesceExpr,
Bruce Momjian's avatar
Bruce Momjian committed
117 118
				 ExprContext *econtext,
				 bool *isNull, ExprDoneCond *isDone);
119
static Datum ExecEvalMinMax(MinMaxExprState *minmaxExpr,
120 121
			   ExprContext *econtext,
			   bool *isNull, ExprDoneCond *isDone);
122 123
static Datum ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
						 bool *isNull, ExprDoneCond *isDone);
124
static Datum ExecEvalNullIf(FuncExprState *nullIfExpr,
Bruce Momjian's avatar
Bruce Momjian committed
125 126
			   ExprContext *econtext,
			   bool *isNull, ExprDoneCond *isDone);
127
static Datum ExecEvalNullTest(NullTestState *nstate,
Bruce Momjian's avatar
Bruce Momjian committed
128 129
				 ExprContext *econtext,
				 bool *isNull, ExprDoneCond *isDone);
130
static Datum ExecEvalBooleanTest(GenericExprState *bstate,
Bruce Momjian's avatar
Bruce Momjian committed
131 132
					ExprContext *econtext,
					bool *isNull, ExprDoneCond *isDone);
133
static Datum ExecEvalCoerceToDomain(CoerceToDomainState *cstate,
Bruce Momjian's avatar
Bruce Momjian committed
134 135
					   ExprContext *econtext,
					   bool *isNull, ExprDoneCond *isDone);
136
static Datum ExecEvalCoerceToDomainValue(ExprState *exprstate,
Bruce Momjian's avatar
Bruce Momjian committed
137 138
							ExprContext *econtext,
							bool *isNull, ExprDoneCond *isDone);
139
static Datum ExecEvalFieldSelect(FieldSelectState *fstate,
Bruce Momjian's avatar
Bruce Momjian committed
140 141
					ExprContext *econtext,
					bool *isNull, ExprDoneCond *isDone);
142
static Datum ExecEvalFieldStore(FieldStoreState *fstate,
Bruce Momjian's avatar
Bruce Momjian committed
143 144
				   ExprContext *econtext,
				   bool *isNull, ExprDoneCond *isDone);
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
static Datum ExecEvalRelabelType(GenericExprState *exprstate,
					ExprContext *econtext,
					bool *isNull, ExprDoneCond *isDone);


/* ----------------------------------------------------------------
 *		ExecEvalExpr routines
 *
 *		Recursively evaluate a targetlist or qualification expression.
 *
 * Each of the following routines having the signature
 *		Datum ExecEvalFoo(ExprState *expression,
 *						  ExprContext *econtext,
 *						  bool *isNull,
 *						  ExprDoneCond *isDone);
 * is responsible for evaluating one type or subtype of ExprState node.
 * They are normally called via the ExecEvalExpr macro, which makes use of
 * the function pointer set up when the ExprState node was built by
 * ExecInitExpr.  (In some cases, we change this pointer later to avoid
 * re-executing one-time overhead.)
 *
 * Note: for notational simplicity we declare these functions as taking the
 * specific type of ExprState that they work on.  This requires casting when
Bruce Momjian's avatar
Bruce Momjian committed
168
 * assigning the function pointer in ExecInitExpr.	Be careful that the
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
 * function signature is declared correctly, because the cast suppresses
 * automatic checking!
 *
 *
 * All these functions share this calling convention:
 *
 * Inputs:
 *		expression: the expression state tree to evaluate
 *		econtext: evaluation context information
 *
 * Outputs:
 *		return value: Datum value of result
 *		*isNull: set to TRUE if result is NULL (actual return value is
 *				 meaningless if so); set to FALSE if non-null result
 *		*isDone: set to indicator of set-result status
 *
 * A caller that can only accept a singleton (non-set) result should pass
 * NULL for isDone; if the expression computes a set result then an error
 * will be reported via ereport.  If the caller does pass an isDone pointer
 * then *isDone is set to one of these three states:
 *		ExprSingleResult		singleton result (not a set)
 *		ExprMultipleResult		return value is one element of a set
 *		ExprEndResult			there are no more elements in the set
 * When ExprMultipleResult is returned, the caller should invoke
 * ExecEvalExpr() repeatedly until ExprEndResult is returned.  ExprEndResult
 * is returned after the last real set element.  For convenience isNull will
 * always be set TRUE when ExprEndResult is returned, but this should not be
 * taken as indicating a NULL element of the set.  Note that these return
 * conventions allow us to distinguish among a singleton NULL, a NULL element
 * of a set, and an empty set.
 *
 * The caller should already have switched into the temporary memory
 * context econtext->ecxt_per_tuple_memory.  The convenience entry point
 * ExecEvalExprSwitchContext() is provided for callers who don't prefer to
 * do the switch in an outer loop.	We do not do the switch in these routines
 * because it'd be a waste of cycles during nested expression evaluation.
 * ----------------------------------------------------------------
 */
207

208

209
/*----------
210
 *	  ExecEvalArrayRef
211
 *
212 213
 *	   This function takes an ArrayRef and returns the extracted Datum
 *	   if it's a simple reference, or the modified array value if it's
214 215
 *	   an array assignment (i.e., array element or slice insertion).
 *
216 217
 * NOTE: if we get a NULL result from a subscript expression, we return NULL
 * when it's an array reference, or raise an error when it's an assignment.
218 219 220 221 222 223
 *
 * NOTE: we deliberately refrain from applying DatumGetArrayTypeP() here,
 * even though that might seem natural, because this code needs to support
 * both varlena arrays and fixed-length array types.  DatumGetArrayTypeP()
 * only works for the varlena kind.  The routines we call in arrayfuncs.c
 * have to know the difference (that's what they need refattrlength for).
224
 *----------
Bruce Momjian's avatar
Bruce Momjian committed
225
 */
226
static Datum
227
ExecEvalArrayRef(ArrayRefExprState *astate,
228 229
				 ExprContext *econtext,
				 bool *isNull,
230
				 ExprDoneCond *isDone)
231
{
232
	ArrayRef   *arrayRef = (ArrayRef *) astate->xprstate.expr;
233 234
	ArrayType  *array_source;
	ArrayType  *resultArray;
235
	bool		isAssignment = (arrayRef->refassgnexpr != NULL);
236
	bool		eisnull;
237
	ListCell   *l;
238 239
	int			i = 0,
				j = 0;
240 241 242
	IntArray	upper,
				lower;
	int		   *lIndex;
243

244 245 246 247 248
	array_source = (ArrayType *)
		DatumGetPointer(ExecEvalExpr(astate->refexpr,
									 econtext,
									 isNull,
									 isDone));
249

250
	/*
251 252
	 * If refexpr yields NULL, and it's a fetch, then result is NULL. In the
	 * assignment case, we'll cons up something below.
253 254
	 */
	if (*isNull)
255
	{
256
		if (isDone && *isDone == ExprEndResult)
Bruce Momjian's avatar
Bruce Momjian committed
257
			return (Datum) NULL;	/* end of set result */
258
		if (!isAssignment)
259 260
			return (Datum) NULL;
	}
261

262
	foreach(l, astate->refupperindexpr)
263
	{
264
		ExprState  *eltstate = (ExprState *) lfirst(l);
265

266
		if (i >= MAXDIM)
267 268
			ereport(ERROR,
					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
269 270
					 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
							i, MAXDIM)));
271

272
		upper.indx[i++] = DatumGetInt32(ExecEvalExpr(eltstate,
273
													 econtext,
274
													 &eisnull,
275
													 NULL));
276
		/* If any index expr yields NULL, result is NULL or error */
277
		if (eisnull)
278
		{
279 280 281
			if (isAssignment)
				ereport(ERROR,
						(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
282
				  errmsg("array subscript in assignment must not be null")));
283 284
			*isNull = true;
			return (Datum) NULL;
285
		}
286 287
	}

288
	if (astate->reflowerindexpr != NIL)
289
	{
290
		foreach(l, astate->reflowerindexpr)
291
		{
292
			ExprState  *eltstate = (ExprState *) lfirst(l);
293

294
			if (j >= MAXDIM)
295 296
				ereport(ERROR,
						(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
297 298
						 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
								i, MAXDIM)));
299

300
			lower.indx[j++] = DatumGetInt32(ExecEvalExpr(eltstate,
301
														 econtext,
302
														 &eisnull,
303
														 NULL));
304
			/* If any index expr yields NULL, result is NULL or error */
305
			if (eisnull)
306
			{
307 308 309
				if (isAssignment)
					ereport(ERROR,
							(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
310
							 errmsg("array subscript in assignment must not be null")));
311 312
				*isNull = true;
				return (Datum) NULL;
313
			}
314
		}
315
		/* this can't happen unless parser messed up */
316
		if (i != j)
317
			elog(ERROR, "upper and lower index lists are not same length");
318
		lIndex = lower.indx;
319
	}
320 321
	else
		lIndex = NULL;
322

323
	if (isAssignment)
324
	{
325 326 327 328 329
		Datum		sourceData;

		/*
		 * Evaluate the value to be assigned into the array.
		 *
330 331
		 * XXX At some point we'll need to look into making the old value of
		 * the array element available via CaseTestExpr, as is done by
332 333 334 335
		 * ExecEvalFieldStore.	This is not needed now but will be needed to
		 * support arrays of composite types; in an assignment to a field of
		 * an array member, the parser would generate a FieldStore that
		 * expects to fetch its input tuple via CaseTestExpr.
336 337 338 339 340
		 */
		sourceData = ExecEvalExpr(astate->refassgnexpr,
								  econtext,
								  &eisnull,
								  NULL);
341

342
		/*
343 344 345
		 * For an assignment to a fixed-length array type, both the original
		 * array and the value to be assigned into it must be non-NULL, else
		 * we punt and return the original array.
346
		 */
347
		if (astate->refattrlength > 0)	/* fixed-length array? */
348 349
			if (eisnull || *isNull)
				return PointerGetDatum(array_source);
350 351

		/*
352
		 * For assignment to varlena arrays, we handle a NULL original array
353 354 355
		 * by substituting an empty (zero-dimensional) array; insertion of the
		 * new element will result in a singleton array value.	It does not
		 * matter whether the new element is NULL.
356
		 */
357
		if (*isNull)
358
		{
359
			array_source = construct_empty_array(arrayRef->refelemtype);
360 361
			*isNull = false;
		}
362

363
		if (lIndex == NULL)
364 365 366
			resultArray = array_set(array_source, i,
									upper.indx,
									sourceData,
367
									eisnull,
368 369 370
									astate->refattrlength,
									astate->refelemlength,
									astate->refelembyval,
371
									astate->refelemalign);
372 373 374
		else
			resultArray = array_set_slice(array_source, i,
										  upper.indx, lower.indx,
375
								   (ArrayType *) DatumGetPointer(sourceData),
376
										  eisnull,
377 378 379
										  astate->refattrlength,
										  astate->refelemlength,
										  astate->refelembyval,
380
										  astate->refelemalign);
381
		return PointerGetDatum(resultArray);
382
	}
383

384
	if (lIndex == NULL)
385
		return array_ref(array_source, i, upper.indx,
386 387 388 389
						 astate->refattrlength,
						 astate->refelemlength,
						 astate->refelembyval,
						 astate->refelemalign,
390
						 isNull);
391 392 393
	else
	{
		resultArray = array_get_slice(array_source, i,
394
									  upper.indx, lower.indx,
395 396 397
									  astate->refattrlength,
									  astate->refelemlength,
									  astate->refelembyval,
398
									  astate->refelemalign);
399 400
		return PointerGetDatum(resultArray);
	}
401 402 403 404
}


/* ----------------------------------------------------------------
Bruce Momjian's avatar
Bruce Momjian committed
405
 *		ExecEvalAggref
406 407 408
 *
 *		Returns a Datum whose value is the value of the precomputed
 *		aggregate found in the given expression context.
409 410
 * ----------------------------------------------------------------
 */
411
static Datum
412 413
ExecEvalAggref(AggrefExprState *aggref, ExprContext *econtext,
			   bool *isNull, ExprDoneCond *isDone)
414
{
415 416 417
	if (isDone)
		*isDone = ExprSingleResult;

418
	if (econtext->ecxt_aggvalues == NULL)		/* safety check */
419
		elog(ERROR, "no aggregates in this expression context");
420

421 422
	*isNull = econtext->ecxt_aggnulls[aggref->aggno];
	return econtext->ecxt_aggvalues[aggref->aggno];
423 424 425
}

/* ----------------------------------------------------------------
426 427 428 429
 *		ExecEvalVar
 *
 *		Returns a Datum whose value is the value of a range
 *		variable with respect to given expression context.
430 431 432 433
 *
 * Note: ExecEvalVar is executed only the first time through in a given plan;
 * it changes the ExprState's function pointer to pass control directly to
 * ExecEvalScalarVar or ExecEvalWholeRowVar after making one-time checks.
434 435
 * ----------------------------------------------------------------
 */
436
static Datum
437 438
ExecEvalVar(ExprState *exprstate, ExprContext *econtext,
			bool *isNull, ExprDoneCond *isDone)
439
{
440
	Var		   *variable = (Var *) exprstate->expr;
441
	TupleTableSlot *slot;
442
	AttrNumber	attnum;
443

444 445 446
	if (isDone)
		*isDone = ExprSingleResult;

Bruce Momjian's avatar
Bruce Momjian committed
447
	/*
448
	 * Get the input slot and attribute number we want
449
	 *
450 451 452
	 * The asserts check that references to system attributes only appear at
	 * the level of a relation scan; at higher levels, system attributes must
	 * be treated as ordinary variables (since we no longer have access to the
453
	 * original tuple).
454
	 */
455 456
	attnum = variable->varattno;

457 458
	switch (variable->varno)
	{
459 460
		case INNER:				/* get the tuple from the inner node */
			slot = econtext->ecxt_innertuple;
461
			Assert(attnum > 0);
462
			break;
463

464 465
		case OUTER:				/* get the tuple from the outer node */
			slot = econtext->ecxt_outertuple;
466
			Assert(attnum > 0);
467
			break;
468

469
		default:				/* get the tuple from the relation being
470
								 * scanned */
471 472
			slot = econtext->ecxt_scantuple;
			break;
473 474
	}

475
	if (attnum != InvalidAttrNumber)
476 477
	{
		/*
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
		 * Scalar variable case.
		 *
		 * If it's a user attribute, check validity (bogus system attnums will
		 * be caught inside slot_getattr).  What we have to check for here
		 * is the possibility of an attribute having been changed in type
		 * since the plan tree was created.  Ideally the plan would get
		 * invalidated and not re-used, but until that day arrives, we need
		 * defenses.  Fortunately it's sufficient to check once on the first
		 * time through.
		 *
		 * Note: we allow a reference to a dropped attribute.  slot_getattr
		 * will force a NULL result in such cases.
		 *
		 * Note: we check typmod, but allow the case that the Var has
		 * unspecified typmod while the column has a specific typmod.
493
		 */
494 495 496 497 498 499 500 501 502 503
		if (attnum > 0)
		{
			TupleDesc	slot_tupdesc = slot->tts_tupleDescriptor;
			Form_pg_attribute attr;

			if (attnum > slot_tupdesc->natts)	/* should never happen */
				elog(ERROR, "attribute number %d exceeds number of columns %d",
					 attnum, slot_tupdesc->natts);

			attr = slot_tupdesc->attrs[attnum - 1];
504

505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
			/* can't check type if dropped, since atttypid is probably 0 */
			if (!attr->attisdropped)
			{
				if (variable->vartype != attr->atttypid ||
					(variable->vartypmod != attr->atttypmod &&
					 variable->vartypmod != -1))
					ereport(ERROR,
							(errmsg("attribute %d has wrong type", attnum),
							 errdetail("Table has type %s, but query expects %s.",
									   format_type_be(attr->atttypid),
									   format_type_be(variable->vartype))));
			}
		}

		/* Skip the checking on future executions of node */
		exprstate->evalfunc = ExecEvalScalarVar;

		/* Fetch the value from the slot */
		return slot_getattr(slot, attnum, isNull);
	}
	else
	{
527
		/*
528
		 * Whole-row variable.
529
		 *
530 531 532 533 534 535
		 * If it's a RECORD Var, we'll use the slot's type ID info.  It's
		 * likely that the slot's type is also RECORD; if so, make sure it's
		 * been "blessed", so that the Datum can be interpreted later.
		 *
		 * If the Var identifies a named composite type, we must check that
		 * the actual tuple type is compatible with it.
536
		 */
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
		TupleDesc	slot_tupdesc = slot->tts_tupleDescriptor;

		if (variable->vartype == RECORDOID)
		{
			if (slot_tupdesc->tdtypeid == RECORDOID &&
				slot_tupdesc->tdtypmod < 0)
				assign_record_type_typmod(slot_tupdesc);
		}
		else
		{
			TupleDesc	var_tupdesc;
			int			i;

			/*
			 * We really only care about number of attributes and data type.
			 * Also, we can ignore type mismatch on columns that are dropped
			 * in the destination type, so long as the physical storage
			 * matches.  This is helpful in some cases involving out-of-date
			 * cached plans.
			 */
			var_tupdesc = lookup_rowtype_tupdesc(variable->vartype, -1);

			if (var_tupdesc->natts != slot_tupdesc->natts)
				ereport(ERROR,
						(errcode(ERRCODE_DATATYPE_MISMATCH),
						 errmsg("table row type and query-specified row type do not match"),
						 errdetail("Table row contains %d attributes, but query expects %d.",
								   slot_tupdesc->natts, var_tupdesc->natts)));

			for (i = 0; i < var_tupdesc->natts; i++)
			{
				Form_pg_attribute vattr = var_tupdesc->attrs[i];
				Form_pg_attribute sattr = slot_tupdesc->attrs[i];

				if (vattr->atttypid == sattr->atttypid)
					continue;			/* no worries */
				if (!vattr->attisdropped)
					ereport(ERROR,
							(errcode(ERRCODE_DATATYPE_MISMATCH),
							 errmsg("table row type and query-specified row type do not match"),
							 errdetail("Table has type %s at ordinal position %d, but query expects %s.",
									   format_type_be(sattr->atttypid),
									   i + 1,
									   format_type_be(vattr->atttypid))));

				if (vattr->attlen != sattr->attlen ||
					vattr->attalign != sattr->attalign)
					ereport(ERROR,
							(errcode(ERRCODE_DATATYPE_MISMATCH),
							 errmsg("table row type and query-specified row type do not match"),
							 errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
									   i + 1)));
			}

			ReleaseTupleDesc(var_tupdesc);
		}

		/* Skip the checking on future executions of node */
		exprstate->evalfunc = ExecEvalWholeRowVar;

		/* Fetch the value */
		return ExecEvalWholeRowVar(exprstate, econtext, isNull, isDone);
599
	}
600
}
601

602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
/* ----------------------------------------------------------------
 *		ExecEvalScalarVar
 *
 *		Returns a Datum for a scalar variable.
 * ----------------------------------------------------------------
 */
static Datum
ExecEvalScalarVar(ExprState *exprstate, ExprContext *econtext,
				  bool *isNull, ExprDoneCond *isDone)
{
	Var		   *variable = (Var *) exprstate->expr;
	TupleTableSlot *slot;
	AttrNumber	attnum;

	if (isDone)
		*isDone = ExprSingleResult;

	/* Get the input slot and attribute number we want */
	switch (variable->varno)
	{
		case INNER:				/* get the tuple from the inner node */
			slot = econtext->ecxt_innertuple;
			break;

		case OUTER:				/* get the tuple from the outer node */
			slot = econtext->ecxt_outertuple;
			break;

		default:				/* get the tuple from the relation being
								 * scanned */
			slot = econtext->ecxt_scantuple;
			break;
	}

	attnum = variable->varattno;

	/* Fetch the value from the slot */
639
	return slot_getattr(slot, attnum, isNull);
640 641
}

642 643 644 645 646 647 648 649 650 651 652
/* ----------------------------------------------------------------
 *		ExecEvalWholeRowVar
 *
 *		Returns a Datum for a whole-row variable.
 * ----------------------------------------------------------------
 */
static Datum
ExecEvalWholeRowVar(ExprState *exprstate, ExprContext *econtext,
					bool *isNull, ExprDoneCond *isDone)
{
	Var		   *variable = (Var *) exprstate->expr;
653
	TupleTableSlot *slot = econtext->ecxt_scantuple;
654 655 656 657 658 659 660 661
	HeapTuple	tuple;
	TupleDesc	tupleDesc;
	HeapTupleHeader dtuple;

	if (isDone)
		*isDone = ExprSingleResult;
	*isNull = false;

662
	tuple = ExecFetchSlotTuple(slot);
663 664 665
	tupleDesc = slot->tts_tupleDescriptor;

	/*
666 667
	 * We have to make a copy of the tuple so we can safely insert the Datum
	 * overhead fields, which are not set in on-disk tuples.
668 669 670 671 672 673 674
	 */
	dtuple = (HeapTupleHeader) palloc(tuple->t_len);
	memcpy((char *) dtuple, (char *) tuple->t_data, tuple->t_len);

	HeapTupleHeaderSetDatumLength(dtuple, tuple->t_len);

	/*
675 676
	 * If the Var identifies a named composite type, label the tuple with that
	 * type; otherwise use what is in the tupleDesc.
677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
	 */
	if (variable->vartype != RECORDOID)
	{
		HeapTupleHeaderSetTypeId(dtuple, variable->vartype);
		HeapTupleHeaderSetTypMod(dtuple, variable->vartypmod);
	}
	else
	{
		HeapTupleHeaderSetTypeId(dtuple, tupleDesc->tdtypeid);
		HeapTupleHeaderSetTypMod(dtuple, tupleDesc->tdtypmod);
	}

	return PointerGetDatum(dtuple);
}

692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714
/* ----------------------------------------------------------------
 *		ExecEvalConst
 *
 *		Returns the value of a constant.
 *
 *		Note that for pass-by-ref datatypes, we return a pointer to the
 *		actual constant node.  This is one of the reasons why functions
 *		must treat their input arguments as read-only.
 * ----------------------------------------------------------------
 */
static Datum
ExecEvalConst(ExprState *exprstate, ExprContext *econtext,
			  bool *isNull, ExprDoneCond *isDone)
{
	Const	   *con = (Const *) exprstate->expr;

	if (isDone)
		*isDone = ExprSingleResult;

	*isNull = con->constisnull;
	return con->constvalue;
}

715
/* ----------------------------------------------------------------
716
 *		ExecEvalParam
717
 *
718 719 720
 *		Returns the value of a parameter.  A param node contains
 *		something like ($.name) and the expression context contains
 *		the current parameter bindings (name = "sam") (age = 34)...
721
 *		so our job is to find and return the appropriate datum ("sam").
722 723
 * ----------------------------------------------------------------
 */
724
static Datum
725 726
ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
			  bool *isNull, ExprDoneCond *isDone)
727
{
728
	Param	   *expression = (Param *) exprstate->expr;
729
	int			thisParamId = expression->paramid;
730

731 732 733
	if (isDone)
		*isDone = ExprSingleResult;

734
	if (expression->paramkind == PARAM_EXEC)
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
735
	{
736
		/*
737 738
		 * PARAM_EXEC params (internal executor parameters) are stored in the
		 * ecxt_param_exec_vals array, and can be accessed by array index.
739
		 */
740
		ParamExecData *prm;
741

742
		prm = &(econtext->ecxt_param_exec_vals[thisParamId]);
743
		if (prm->execPlan != NULL)
744
		{
745
			/* Parameter not evaluated yet, so go do it */
746 747 748 749
			ExecSetParamPlan(prm->execPlan, econtext);
			/* ExecSetParamPlan should have processed this param... */
			Assert(prm->execPlan == NULL);
		}
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
750
		*isNull = prm->isnull;
751
		return prm->value;
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
752
	}
753
	else
754 755
	{
		/*
756
		 * PARAM_EXTERN parameters must be sought in ecxt_param_list_info.
757
		 */
758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
		ParamListInfo paramInfo = econtext->ecxt_param_list_info;

		Assert(expression->paramkind == PARAM_EXTERN);
		if (paramInfo &&
			thisParamId > 0 && thisParamId <= paramInfo->numParams)
		{
			ParamExternData *prm = &paramInfo->params[thisParamId - 1];

			if (OidIsValid(prm->ptype))
			{
				Assert(prm->ptype == expression->paramtype);
				*isNull = prm->isnull;
				return prm->value;
			}
		}
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_OBJECT),
				 errmsg("no value found for parameter %d", thisParamId)));
		return (Datum) 0;		/* keep compiler quiet */
777
	}
778 779 780 781
}


/* ----------------------------------------------------------------
782
 *		ExecEvalOper / ExecEvalFunc support routines
783 784 785
 * ----------------------------------------------------------------
 */

Bruce Momjian's avatar
Bruce Momjian committed
786
/*
787 788
 *		GetAttributeByName
 *		GetAttributeByNum
789
 *
790 791
 *		These functions return the value of the requested attribute
 *		out of the given tuple Datum.
792
 *		C functions which take a tuple as an argument are expected
793 794 795
 *		to use these.  Ex: overpaid(EMP) might call GetAttributeByNum().
 *		Note: these are actually rather slow because they do a typcache
 *		lookup on each call.
796
 */
797
Datum
798
GetAttributeByNum(HeapTupleHeader tuple,
799
				  AttrNumber attrno,
800
				  bool *isNull)
801
{
802 803 804 805 806
	Datum		result;
	Oid			tupType;
	int32		tupTypmod;
	TupleDesc	tupDesc;
	HeapTupleData tmptup;
807 808

	if (!AttributeNumberIsValid(attrno))
809
		elog(ERROR, "invalid attribute number %d", attrno);
810

811
	if (isNull == NULL)
812
		elog(ERROR, "a NULL isNull pointer was passed");
813

814
	if (tuple == NULL)
815
	{
816
		/* Kinda bogus but compatible with old behavior... */
817
		*isNull = true;
818
		return (Datum) 0;
819
	}
820

821 822 823 824 825
	tupType = HeapTupleHeaderGetTypeId(tuple);
	tupTypmod = HeapTupleHeaderGetTypMod(tuple);
	tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);

	/*
826 827 828
	 * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
	 * the fields in the struct just in case user tries to inspect system
	 * columns.
829 830 831 832 833 834 835
	 */
	tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
	ItemPointerSetInvalid(&(tmptup.t_self));
	tmptup.t_tableOid = InvalidOid;
	tmptup.t_data = tuple;

	result = heap_getattr(&tmptup,
836
						  attrno,
837
						  tupDesc,
838
						  isNull);
839 840 841

	ReleaseTupleDesc(tupDesc);

842
	return result;
843
}
844

845
Datum
846
GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
847
{
848
	AttrNumber	attrno;
849 850 851 852 853
	Datum		result;
	Oid			tupType;
	int32		tupTypmod;
	TupleDesc	tupDesc;
	HeapTupleData tmptup;
854
	int			i;
855 856

	if (attname == NULL)
857
		elog(ERROR, "invalid attribute name");
858

859
	if (isNull == NULL)
860
		elog(ERROR, "a NULL isNull pointer was passed");
861

862
	if (tuple == NULL)
863
	{
864
		/* Kinda bogus but compatible with old behavior... */
865
		*isNull = true;
866
		return (Datum) 0;
867
	}
868

869 870 871
	tupType = HeapTupleHeaderGetTypeId(tuple);
	tupTypmod = HeapTupleHeaderGetTypMod(tuple);
	tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
872 873

	attrno = InvalidAttrNumber;
874
	for (i = 0; i < tupDesc->natts; i++)
875
	{
876
		if (namestrcmp(&(tupDesc->attrs[i]->attname), attname) == 0)
877
		{
878
			attrno = tupDesc->attrs[i]->attnum;
879 880
			break;
		}
881
	}
882 883

	if (attrno == InvalidAttrNumber)
884
		elog(ERROR, "attribute \"%s\" does not exist", attname);
885

886
	/*
887 888 889
	 * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
	 * the fields in the struct just in case user tries to inspect system
	 * columns.
890 891 892 893 894 895 896
	 */
	tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
	ItemPointerSetInvalid(&(tmptup.t_self));
	tmptup.t_tableOid = InvalidOid;
	tmptup.t_data = tuple;

	result = heap_getattr(&tmptup,
897
						  attrno,
898
						  tupDesc,
899
						  isNull);
900 901 902

	ReleaseTupleDesc(tupDesc);

903
	return result;
904 905
}

906 907 908 909
/*
 * init_fcache - initialize a FuncExprState node during first use
 */
void
910
init_fcache(Oid foid, FuncExprState *fcache, MemoryContext fcacheCxt)
911 912 913 914 915 916
{
	AclResult	aclresult;

	/* Check permission to call function */
	aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
	if (aclresult != ACLCHECK_OK)
917
		aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(foid));
918

919 920
	/*
	 * Safety check on nargs.  Under normal circumstances this should never
921 922 923
	 * fail, as parser should check sooner.  But possibly it might fail if
	 * server has been compiled with FUNC_MAX_ARGS smaller than some functions
	 * declared in pg_proc?
924
	 */
925
	if (list_length(fcache->args) > FUNC_MAX_ARGS)
926 927 928 929
		ereport(ERROR,
				(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
				 errmsg("cannot pass more than %d arguments to a function",
						FUNC_MAX_ARGS)));
930 931 932 933 934 935

	/* Set up the primary fmgr lookup information */
	fmgr_info_cxt(foid, &(fcache->func), fcacheCxt);

	/* Initialize additional info */
	fcache->setArgsValid = false;
936
	fcache->shutdown_reg = false;
937
	fcache->func.fn_expr = (Node *) fcache->xprstate.expr;
938 939
}

940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955
/*
 * callback function in case a FuncExpr returning a set needs to be shut down
 * before it has been run to completion
 */
static void
ShutdownFuncExpr(Datum arg)
{
	FuncExprState *fcache = (FuncExprState *) DatumGetPointer(arg);

	/* Clear any active set-argument state */
	fcache->setArgsValid = false;

	/* execUtils will deregister the callback... */
	fcache->shutdown_reg = false;
}

956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
/*
 * get_cached_rowtype: utility function to lookup a rowtype tupdesc
 *
 * type_id, typmod: identity of the rowtype
 * cache_field: where to cache the TupleDesc pointer in expression state node
 *		(field must be initialized to NULL)
 * econtext: expression context we are executing in
 *
 * NOTE: because the shutdown callback will be called during plan rescan,
 * must be prepared to re-do this during any node execution; cannot call
 * just once during expression initialization
 */
static TupleDesc
get_cached_rowtype(Oid type_id, int32 typmod,
				   TupleDesc *cache_field, ExprContext *econtext)
{
	TupleDesc	tupDesc = *cache_field;

	/* Do lookup if no cached value or if requested type changed */
	if (tupDesc == NULL ||
		type_id != tupDesc->tdtypeid ||
		typmod != tupDesc->tdtypmod)
	{
		tupDesc = lookup_rowtype_tupdesc(type_id, typmod);

		if (*cache_field)
		{
			/* Release old tupdesc; but callback is already registered */
			ReleaseTupleDesc(*cache_field);
		}
		else
		{
			/* Need to register shutdown callback to release tupdesc */
			RegisterExprContextCallback(econtext,
										ShutdownTupleDescRef,
										PointerGetDatum(cache_field));
		}
		*cache_field = tupDesc;
	}
	return tupDesc;
}

/*
 * Callback function to release a tupdesc refcount at expression tree shutdown
 */
static void
ShutdownTupleDescRef(Datum arg)
{
Bruce Momjian's avatar
Bruce Momjian committed
1004
	TupleDesc  *cache_field = (TupleDesc *) DatumGetPointer(arg);
1005 1006 1007 1008 1009 1010

	if (*cache_field)
		ReleaseTupleDesc(*cache_field);
	*cache_field = NULL;
}

1011 1012 1013 1014
/*
 * Evaluate arguments for a function.
 */
static ExprDoneCond
1015
ExecEvalFuncArgs(FunctionCallInfo fcinfo,
1016
				 List *argList,
1017
				 ExprContext *econtext)
1018
{
1019
	ExprDoneCond argIsDone;
1020
	int			i;
1021
	ListCell   *arg;
1022

1023
	argIsDone = ExprSingleResult;		/* default assumption */
1024

1025 1026 1027
	i = 0;
	foreach(arg, argList)
	{
1028
		ExprState  *argstate = (ExprState *) lfirst(arg);
1029
		ExprDoneCond thisArgIsDone;
Bruce Momjian's avatar
Bruce Momjian committed
1030

1031
		fcinfo->arg[i] = ExecEvalExpr(argstate,
1032 1033 1034
									  econtext,
									  &fcinfo->argnull[i],
									  &thisArgIsDone);
1035

1036
		if (thisArgIsDone != ExprSingleResult)
1037
		{
1038
			/*
1039 1040 1041
			 * We allow only one argument to have a set value; we'd need much
			 * more complexity to keep track of multiple set arguments (cf.
			 * ExecTargetList) and it doesn't seem worth it.
1042 1043
			 */
			if (argIsDone != ExprSingleResult)
1044 1045 1046
				ereport(ERROR,
						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
						 errmsg("functions and operators can take at most one set argument")));
1047
			argIsDone = thisArgIsDone;
1048 1049 1050
		}
		i++;
	}
1051

1052 1053
	fcinfo->nargs = i;

1054
	return argIsDone;
1055 1056
}

Bruce Momjian's avatar
Bruce Momjian committed
1057
/*
1058
 *		ExecMakeFunctionResult
1059 1060
 *
 * Evaluate the arguments to a function and then the function itself.
1061
 */
1062
Datum
1063
ExecMakeFunctionResult(FuncExprState *fcache,
1064 1065
					   ExprContext *econtext,
					   bool *isNull,
1066
					   ExprDoneCond *isDone)
1067
{
1068
	List	   *arguments = fcache->args;
1069
	Datum		result;
1070
	FunctionCallInfoData fcinfo;
1071
	ReturnSetInfo rsinfo;		/* for functions returning sets */
1072
	ExprDoneCond argDone;
1073
	bool		hasSetArg;
1074
	int			i;
1075

1076 1077 1078
	/* Guard against stack overflow due to overly complex expressions */
	check_stack_depth();

Bruce Momjian's avatar
Bruce Momjian committed
1079
	/*
1080 1081 1082 1083
	 * arguments is a list of expressions to evaluate before passing to the
	 * function manager.  We skip the evaluation if it was already done in the
	 * previous call (ie, we are continuing the evaluation of a set-valued
	 * function).  Otherwise, collect the current argument values into fcinfo.
1084
	 */
1085
	if (!fcache->setArgsValid)
1086
	{
1087
		/* Need to prep callinfo structure */
1088
		InitFunctionCallInfoData(fcinfo, &(fcache->func), 0, NULL, NULL);
1089
		argDone = ExecEvalFuncArgs(&fcinfo, arguments, econtext);
1090
		if (argDone == ExprEndResult)
1091
		{
1092
			/* input is an empty set, so return an empty set. */
1093
			*isNull = true;
1094 1095 1096
			if (isDone)
				*isDone = ExprEndResult;
			else
1097
				ereport(ERROR,
1098
						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1099
						 errmsg("set-valued function called in context that cannot accept a set")));
1100
			return (Datum) 0;
1101
		}
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
		hasSetArg = (argDone != ExprSingleResult);
	}
	else
	{
		/* Copy callinfo from previous evaluation */
		memcpy(&fcinfo, &fcache->setArgs, sizeof(fcinfo));
		hasSetArg = fcache->setHasSetArg;
		/* Reset flag (we may set it again below) */
		fcache->setArgsValid = false;
	}

	/*
1114
	 * If function returns set, prepare a resultinfo node for communication
1115 1116 1117
	 */
	if (fcache->func.fn_retset)
	{
1118 1119 1120 1121 1122 1123
		fcinfo.resultinfo = (Node *) &rsinfo;
		rsinfo.type = T_ReturnSetInfo;
		rsinfo.econtext = econtext;
		rsinfo.expectedDesc = NULL;
		rsinfo.allowedModes = (int) SFRM_ValuePerCall;
		rsinfo.returnMode = SFRM_ValuePerCall;
1124
		/* isDone is filled below */
1125 1126
		rsinfo.setResult = NULL;
		rsinfo.setDesc = NULL;
1127
	}
1128

Bruce Momjian's avatar
Bruce Momjian committed
1129
	/*
1130 1131
	 * now return the value gotten by calling the function manager, passing
	 * the function the evaluated parameter values.
1132
	 */
1133
	if (fcache->func.fn_retset || hasSetArg)
1134
	{
1135
		/*
1136 1137
		 * We need to return a set result.	Complain if caller not ready to
		 * accept one.
1138 1139
		 */
		if (isDone == NULL)
1140
			ereport(ERROR,
1141
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1142
					 errmsg("set-valued function called in context that cannot accept a set")));
1143 1144

		/*
1145 1146 1147 1148 1149 1150
		 * This loop handles the situation where we have both a set argument
		 * and a set-valued function.  Once we have exhausted the function's
		 * value(s) for a particular argument value, we have to get the next
		 * argument value and start the function over again. We might have to
		 * do it more than once, if the function produces an empty result set
		 * for a particular input value.
1151
		 */
1152
		for (;;)
1153
		{
1154
			/*
1155 1156
			 * If function is strict, and there are any NULL arguments, skip
			 * calling the function (at least for this set of args).
1157
			 */
1158
			bool		callit = true;
1159

1160
			if (fcache->func.fn_strict)
1161
			{
1162
				for (i = 0; i < fcinfo.nargs; i++)
1163
				{
1164
					if (fcinfo.argnull[i])
1165 1166 1167 1168 1169 1170 1171 1172 1173
					{
						callit = false;
						break;
					}
				}
			}

			if (callit)
			{
1174
				fcinfo.isnull = false;
1175
				rsinfo.isDone = ExprSingleResult;
1176 1177
				result = FunctionCallInvoke(&fcinfo);
				*isNull = fcinfo.isnull;
1178
				*isDone = rsinfo.isDone;
1179 1180 1181 1182 1183
			}
			else
			{
				result = (Datum) 0;
				*isNull = true;
1184 1185 1186 1187 1188 1189
				*isDone = ExprEndResult;
			}

			if (*isDone != ExprEndResult)
			{
				/*
1190
				 * Got a result from current argument.	If function itself
1191 1192
				 * returns set, save the current argument values to re-use on
				 * the next call.
1193
				 */
1194
				if (fcache->func.fn_retset && *isDone == ExprMultipleResult)
1195 1196 1197 1198
				{
					memcpy(&fcache->setArgs, &fcinfo, sizeof(fcinfo));
					fcache->setHasSetArg = hasSetArg;
					fcache->setArgsValid = true;
1199 1200 1201 1202 1203
					/* Register cleanup callback if we didn't already */
					if (!fcache->shutdown_reg)
					{
						RegisterExprContextCallback(econtext,
													ShutdownFuncExpr,
1204
													PointerGetDatum(fcache));
1205 1206
						fcache->shutdown_reg = true;
					}
1207
				}
1208

1209 1210 1211 1212
				/*
				 * Make sure we say we are returning a set, even if the
				 * function itself doesn't return sets.
				 */
1213 1214
				if (hasSetArg)
					*isDone = ExprMultipleResult;
1215
				break;
1216
			}
1217

1218
			/* Else, done with this argument */
1219
			if (!hasSetArg)
1220
				break;			/* input not a set, so done */
1221

1222
			/* Re-eval args to get the next element of the input set */
1223
			argDone = ExecEvalFuncArgs(&fcinfo, arguments, econtext);
1224

1225
			if (argDone != ExprMultipleResult)
1226
			{
1227
				/* End of argument set, so we're done. */
1228
				*isNull = true;
1229
				*isDone = ExprEndResult;
1230
				result = (Datum) 0;
1231
				break;
1232
			}
1233

1234
			/*
1235 1236
			 * If we reach here, loop around to run the function on the new
			 * argument.
1237
			 */
1238
		}
1239
	}
1240
	else
1241
	{
1242
		/*
1243 1244
		 * Non-set case: much easier.
		 *
1245
		 * We change the ExprState function pointer to use the simpler
1246 1247 1248
		 * ExecMakeFunctionResultNoSets on subsequent calls.  This amounts to
		 * assuming that no argument can return a set if it didn't do so the
		 * first time.
1249 1250 1251 1252 1253 1254 1255
		 */
		fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResultNoSets;

		if (isDone)
			*isDone = ExprSingleResult;

		/*
1256 1257
		 * If function is strict, and there are any NULL arguments, skip
		 * calling the function and return NULL.
1258
		 */
1259
		if (fcache->func.fn_strict)
1260
		{
1261
			for (i = 0; i < fcinfo.nargs; i++)
1262
			{
1263
				if (fcinfo.argnull[i])
1264 1265 1266 1267 1268 1269
				{
					*isNull = true;
					return (Datum) 0;
				}
			}
		}
1270 1271 1272
		fcinfo.isnull = false;
		result = FunctionCallInvoke(&fcinfo);
		*isNull = fcinfo.isnull;
1273
	}
1274 1275

	return result;
1276 1277
}

1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289
/*
 *		ExecMakeFunctionResultNoSets
 *
 * Simplified version of ExecMakeFunctionResult that can only handle
 * non-set cases.  Hand-tuned for speed.
 */
static Datum
ExecMakeFunctionResultNoSets(FuncExprState *fcache,
							 ExprContext *econtext,
							 bool *isNull,
							 ExprDoneCond *isDone)
{
1290
	ListCell   *arg;
1291 1292 1293 1294
	Datum		result;
	FunctionCallInfoData fcinfo;
	int			i;

1295 1296 1297
	/* Guard against stack overflow due to overly complex expressions */
	check_stack_depth();

1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309
	if (isDone)
		*isDone = ExprSingleResult;

	/* inlined, simplified version of ExecEvalFuncArgs */
	i = 0;
	foreach(arg, fcache->args)
	{
		ExprState  *argstate = (ExprState *) lfirst(arg);

		fcinfo.arg[i] = ExecEvalExpr(argstate,
									 econtext,
									 &fcinfo.argnull[i],
1310
									 NULL);
1311 1312
		i++;
	}
1313 1314

	InitFunctionCallInfoData(fcinfo, &(fcache->func), i, NULL, NULL);
1315 1316

	/*
1317 1318
	 * If function is strict, and there are any NULL arguments, skip calling
	 * the function and return NULL.
1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330
	 */
	if (fcache->func.fn_strict)
	{
		while (--i >= 0)
		{
			if (fcinfo.argnull[i])
			{
				*isNull = true;
				return (Datum) 0;
			}
		}
	}
1331
	/* fcinfo.isnull = false; */	/* handled by InitFunctionCallInfoData */
1332 1333 1334 1335 1336 1337
	result = FunctionCallInvoke(&fcinfo);
	*isNull = fcinfo.isnull;

	return result;
}

1338

1339 1340 1341 1342
/*
 *		ExecMakeTableFunctionResult
 *
 * Evaluate a table function, producing a materialized result in a Tuplestore
1343
 * object.	*returnDesc is set to the tupledesc actually returned by the
1344
 * function, or NULL if it didn't provide one.
1345 1346
 */
Tuplestorestate *
1347
ExecMakeTableFunctionResult(ExprState *funcexpr,
1348
							ExprContext *econtext,
1349
							TupleDesc expectedDesc,
1350 1351 1352 1353
							TupleDesc *returnDesc)
{
	Tuplestorestate *tupstore = NULL;
	TupleDesc	tupdesc = NULL;
1354
	Oid			funcrettype;
1355
	bool		returnsTuple;
1356
	bool		returnsSet = false;
1357
	FunctionCallInfoData fcinfo;
1358
	ReturnSetInfo rsinfo;
1359
	HeapTupleData tmptup;
1360 1361
	MemoryContext callerContext;
	MemoryContext oldcontext;
1362
	bool		direct_function_call;
1363 1364
	bool		first_time = true;

1365 1366 1367 1368
	callerContext = CurrentMemoryContext;

	funcrettype = exprType((Node *) funcexpr->expr);

1369
	returnsTuple = type_is_rowtype(funcrettype);
1370 1371

	/*
1372 1373 1374 1375 1376
	 * Prepare a resultinfo node for communication.  We always do this even if
	 * not expecting a set result, so that we can pass expectedDesc.  In the
	 * generic-expression case, the expression doesn't actually get to see the
	 * resultinfo, but set it up anyway because we use some of the fields as
	 * our own state variables.
1377
	 */
1378
	InitFunctionCallInfoData(fcinfo, NULL, 0, NULL, (Node *) &rsinfo);
1379 1380 1381 1382 1383 1384 1385 1386 1387
	rsinfo.type = T_ReturnSetInfo;
	rsinfo.econtext = econtext;
	rsinfo.expectedDesc = expectedDesc;
	rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize);
	rsinfo.returnMode = SFRM_ValuePerCall;
	/* isDone is filled below */
	rsinfo.setResult = NULL;
	rsinfo.setDesc = NULL;

1388
	/*
1389 1390 1391 1392 1393 1394 1395 1396
	 * Normally the passed expression tree will be a FuncExprState, since the
	 * grammar only allows a function call at the top level of a table
	 * function reference.	However, if the function doesn't return set then
	 * the planner might have replaced the function call via constant-folding
	 * or inlining.  So if we see any other kind of expression node, execute
	 * it via the general ExecEvalExpr() code; the only difference is that we
	 * don't get a chance to pass a special ReturnSetInfo to any functions
	 * buried in the expression.
1397
	 */
1398 1399
	if (funcexpr && IsA(funcexpr, FuncExprState) &&
		IsA(funcexpr->expr, FuncExpr))
1400
	{
1401
		FuncExprState *fcache = (FuncExprState *) funcexpr;
1402
		ExprDoneCond argDone;
1403

1404 1405 1406 1407
		/*
		 * This path is similar to ExecMakeFunctionResult.
		 */
		direct_function_call = true;
1408

1409
		/*
1410
		 * Initialize function cache if first time through
1411
		 */
1412
		if (fcache->func.fn_oid == InvalidOid)
1413
		{
Bruce Momjian's avatar
Bruce Momjian committed
1414
			FuncExpr   *func = (FuncExpr *) fcache->xprstate.expr;
1415 1416

			init_fcache(func->funcid, fcache, econtext->ecxt_per_query_memory);
1417
		}
1418
		returnsSet = fcache->func.fn_retset;
1419 1420 1421 1422 1423

		/*
		 * Evaluate the function's argument list.
		 *
		 * Note: ideally, we'd do this in the per-tuple context, but then the
1424 1425 1426
		 * argument values would disappear when we reset the context in the
		 * inner loop.	So do it in caller context.  Perhaps we should make a
		 * separate context just to hold the evaluated arguments?
1427 1428
		 */
		fcinfo.flinfo = &(fcache->func);
1429
		argDone = ExecEvalFuncArgs(&fcinfo, fcache->args, econtext);
1430 1431
		/* We don't allow sets in the arguments of the table function */
		if (argDone != ExprSingleResult)
1432
			ereport(ERROR,
1433
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1434
					 errmsg("set-valued function called in context that cannot accept a set")));
1435 1436 1437

		/*
		 * If function is strict, and there are any NULL arguments, skip
1438 1439
		 * calling the function and act like it returned NULL (or an empty
		 * set, in the returns-set case).
1440 1441 1442 1443 1444 1445
		 */
		if (fcache->func.fn_strict)
		{
			int			i;

			for (i = 0; i < fcinfo.nargs; i++)
1446
			{
1447
				if (fcinfo.argnull[i])
1448
					goto no_function_result;
1449 1450 1451
			}
		}
	}
1452 1453 1454 1455 1456
	else
	{
		/* Treat funcexpr as a generic expression */
		direct_function_call = false;
	}
1457 1458

	/*
1459
	 * Switch to short-lived context for calling the function or expression.
1460
	 */
1461
	MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
1462 1463

	/*
1464 1465
	 * Loop to handle the ValuePerCall protocol (which is also the same
	 * behavior needed in the generic ExecEvalExpr path).
1466 1467 1468 1469 1470 1471
	 */
	for (;;)
	{
		Datum		result;
		HeapTuple	tuple;

1472 1473
		CHECK_FOR_INTERRUPTS();

1474
		/*
1475 1476 1477
		 * reset per-tuple memory context before each call of the function or
		 * expression. This cleans up any local memory the function may leak
		 * when called.
1478 1479 1480
		 */
		ResetExprContext(econtext);

1481 1482 1483 1484
		/* Call the function or expression one time */
		if (direct_function_call)
		{
			fcinfo.isnull = false;
1485
			rsinfo.isDone = ExprSingleResult;
1486 1487 1488 1489 1490
			result = FunctionCallInvoke(&fcinfo);
		}
		else
		{
			result = ExecEvalExpr(funcexpr, econtext,
1491
								  &fcinfo.isnull, &rsinfo.isDone);
1492
		}
1493 1494

		/* Which protocol does function want to use? */
1495
		if (rsinfo.returnMode == SFRM_ValuePerCall)
1496 1497 1498 1499
		{
			/*
			 * Check for end of result set.
			 */
1500
			if (rsinfo.isDone == ExprEndResult)
1501
				break;
Bruce Momjian's avatar
Bruce Momjian committed
1502

1503
			/*
1504 1505 1506 1507 1508 1509
			 * Can't do anything very useful with NULL rowtype values. For a
			 * function returning set, we consider this a protocol violation
			 * (but another alternative would be to just ignore the result and
			 * "continue" to get another row).	For a function not returning
			 * set, we fall out of the loop; we'll cons up an all-nulls result
			 * row below.
1510 1511
			 */
			if (returnsTuple && fcinfo.isnull)
1512 1513 1514
			{
				if (!returnsSet)
					break;
1515 1516
				ereport(ERROR,
						(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1517 1518
						 errmsg("function returning set of rows cannot return null value")));
			}
1519

1520
			/*
1521
			 * If first time through, build tupdesc and tuplestore for result
1522 1523 1524 1525
			 */
			if (first_time)
			{
				oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
1526
				if (returnsTuple)
1527 1528
				{
					/*
1529 1530
					 * Use the type info embedded in the rowtype Datum to look
					 * up the needed tupdesc.  Make a copy for the query.
1531
					 */
Bruce Momjian's avatar
Bruce Momjian committed
1532
					HeapTupleHeader td;
1533 1534

					td = DatumGetHeapTupleHeader(result);
1535
					tupdesc = lookup_rowtype_tupdesc_copy(HeapTupleHeaderGetTypeId(td),
1536
											   HeapTupleHeaderGetTypMod(td));
1537 1538 1539 1540 1541 1542
				}
				else
				{
					/*
					 * Scalar type, so make a single-column descriptor
					 */
1543
					tupdesc = CreateTemplateTupleDesc(1, false);
1544 1545 1546 1547 1548
					TupleDescInitEntry(tupdesc,
									   (AttrNumber) 1,
									   "column",
									   funcrettype,
									   -1,
1549
									   0);
1550
				}
1551
				tupstore = tuplestore_begin_heap(true, false, work_mem);
1552
				MemoryContextSwitchTo(oldcontext);
1553 1554
				rsinfo.setResult = tupstore;
				rsinfo.setDesc = tupdesc;
1555 1556 1557 1558 1559 1560 1561
			}

			/*
			 * Store current resultset item.
			 */
			if (returnsTuple)
			{
Bruce Momjian's avatar
Bruce Momjian committed
1562
				HeapTupleHeader td;
1563 1564 1565 1566 1567 1568 1569 1570 1571 1572

				td = DatumGetHeapTupleHeader(result);

				/*
				 * tuplestore_puttuple needs a HeapTuple not a bare
				 * HeapTupleHeader, but it doesn't need all the fields.
				 */
				tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
				tmptup.t_data = td;
				tuple = &tmptup;
1573 1574 1575
			}
			else
			{
1576
				tuple = heap_form_tuple(tupdesc, &result, &fcinfo.isnull);
1577 1578 1579 1580 1581 1582 1583 1584 1585
			}

			oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
			tuplestore_puttuple(tupstore, tuple);
			MemoryContextSwitchTo(oldcontext);

			/*
			 * Are we done?
			 */
1586
			if (rsinfo.isDone != ExprMultipleResult)
1587 1588
				break;
		}
1589
		else if (rsinfo.returnMode == SFRM_Materialize)
1590 1591
		{
			/* check we're on the same page as the function author */
1592
			if (!first_time || rsinfo.isDone != ExprSingleResult)
1593 1594 1595
				ereport(ERROR,
						(errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
						 errmsg("table-function protocol for materialize mode was not followed")));
1596 1597 1598 1599
			/* Done evaluating the set result */
			break;
		}
		else
1600 1601 1602
			ereport(ERROR,
					(errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
					 errmsg("unrecognized table-function returnMode: %d",
1603
							(int) rsinfo.returnMode)));
1604 1605 1606 1607

		first_time = false;
	}

1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623
no_function_result:

	/*
	 * If we got nothing from the function (ie, an empty-set or NULL result),
	 * we have to create the tuplestore to return, and if it's a
	 * non-set-returning function then insert a single all-nulls row.
	 */
	if (rsinfo.setResult == NULL)
	{
		MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
		tupstore = tuplestore_begin_heap(true, false, work_mem);
		rsinfo.setResult = tupstore;
		if (!returnsSet)
		{
			int			natts = expectedDesc->natts;
			Datum	   *nulldatums;
1624
			bool	   *nullflags;
1625 1626 1627 1628
			HeapTuple	tuple;

			MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
			nulldatums = (Datum *) palloc0(natts * sizeof(Datum));
1629 1630 1631
			nullflags = (bool *) palloc(natts * sizeof(bool));
			memset(nullflags, true, natts * sizeof(bool));
			tuple = heap_form_tuple(expectedDesc, nulldatums, nullflags);
1632 1633 1634 1635 1636
			MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
			tuplestore_puttuple(tupstore, tuple);
		}
	}

1637 1638 1639
	MemoryContextSwitchTo(callerContext);

	/* The returned pointers are those in rsinfo */
1640 1641
	*returnDesc = rsinfo.setDesc;
	return rsinfo.setResult;
1642 1643 1644
}


1645
/* ----------------------------------------------------------------
1646
 *		ExecEvalFunc
1647
 *		ExecEvalOper
1648 1649
 *
 *		Evaluate the functional result of a list of arguments by calling the
1650
 *		function manager.
1651 1652 1653 1654
 * ----------------------------------------------------------------
 */

/* ----------------------------------------------------------------
1655
 *		ExecEvalFunc
1656 1657
 * ----------------------------------------------------------------
 */
1658
static Datum
1659
ExecEvalFunc(FuncExprState *fcache,
1660 1661 1662
			 ExprContext *econtext,
			 bool *isNull,
			 ExprDoneCond *isDone)
1663
{
1664 1665
	/* This is called only the first time through */
	FuncExpr   *func = (FuncExpr *) fcache->xprstate.expr;
1666

1667 1668 1669 1670 1671
	/* Initialize function lookup info */
	init_fcache(func->funcid, fcache, econtext->ecxt_per_query_memory);

	/* Go directly to ExecMakeFunctionResult on subsequent uses */
	fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResult;
1672

1673
	return ExecMakeFunctionResult(fcache, econtext, isNull, isDone);
1674 1675
}

1676
/* ----------------------------------------------------------------
1677
 *		ExecEvalOper
1678 1679 1680
 * ----------------------------------------------------------------
 */
static Datum
1681
ExecEvalOper(FuncExprState *fcache,
1682 1683 1684 1685
			 ExprContext *econtext,
			 bool *isNull,
			 ExprDoneCond *isDone)
{
1686 1687
	/* This is called only the first time through */
	OpExpr	   *op = (OpExpr *) fcache->xprstate.expr;
1688

1689 1690 1691 1692 1693
	/* Initialize function lookup info */
	init_fcache(op->opfuncid, fcache, econtext->ecxt_per_query_memory);

	/* Go directly to ExecMakeFunctionResult on subsequent uses */
	fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResult;
1694

1695
	return ExecMakeFunctionResult(fcache, econtext, isNull, isDone);
1696 1697
}

1698 1699 1700 1701 1702 1703 1704
/* ----------------------------------------------------------------
 *		ExecEvalDistinct
 *
 * IS DISTINCT FROM must evaluate arguments to determine whether
 * they are NULL; if either is NULL then the result is already
 * known. If neither is NULL, then proceed to evaluate the
 * function. Note that this is *always* derived from the equals
1705
 * operator, but since we need special processing of the arguments
1706 1707 1708 1709
 * we can not simply reuse ExecEvalOper() or ExecEvalFunc().
 * ----------------------------------------------------------------
 */
static Datum
1710
ExecEvalDistinct(FuncExprState *fcache,
1711
				 ExprContext *econtext,
1712 1713
				 bool *isNull,
				 ExprDoneCond *isDone)
1714
{
1715
	Datum		result;
1716 1717 1718 1719
	FunctionCallInfoData fcinfo;
	ExprDoneCond argDone;
	List	   *argList;

1720 1721 1722 1723 1724
	/* Set default values for result flags: non-null, not a set result */
	*isNull = false;
	if (isDone)
		*isDone = ExprSingleResult;

1725
	/*
1726
	 * Initialize function cache if first time through
1727
	 */
1728 1729 1730 1731 1732 1733 1734
	if (fcache->func.fn_oid == InvalidOid)
	{
		DistinctExpr *op = (DistinctExpr *) fcache->xprstate.expr;

		init_fcache(op->opfuncid, fcache, econtext->ecxt_per_query_memory);
		Assert(!fcache->func.fn_retset);
	}
1735 1736

	/*
1737
	 * extract info from fcache
1738
	 */
1739
	argList = fcache->args;
1740 1741

	/* Need to prep callinfo structure */
1742
	InitFunctionCallInfoData(fcinfo, &(fcache->func), 0, NULL, NULL);
1743
	argDone = ExecEvalFuncArgs(&fcinfo, argList, econtext);
1744
	if (argDone != ExprSingleResult)
1745 1746
		ereport(ERROR,
				(errcode(ERRCODE_DATATYPE_MISMATCH),
1747
				 errmsg("IS DISTINCT FROM does not support set arguments")));
1748
	Assert(fcinfo.nargs == 2);
1749 1750 1751 1752

	if (fcinfo.argnull[0] && fcinfo.argnull[1])
	{
		/* Both NULL? Then is not distinct... */
1753
		result = BoolGetDatum(FALSE);
1754 1755 1756
	}
	else if (fcinfo.argnull[0] || fcinfo.argnull[1])
	{
1757 1758
		/* Only one is NULL? Then is distinct... */
		result = BoolGetDatum(TRUE);
1759 1760 1761 1762 1763 1764
	}
	else
	{
		fcinfo.isnull = false;
		result = FunctionCallInvoke(&fcinfo);
		*isNull = fcinfo.isnull;
1765 1766
		/* Must invert result of "=" */
		result = BoolGetDatum(!DatumGetBool(result));
1767 1768
	}

1769
	return result;
1770 1771
}

1772 1773 1774 1775 1776
/*
 * ExecEvalScalarArrayOp
 *
 * Evaluate "scalar op ANY/ALL (array)".  The operator always yields boolean,
 * and we combine the results across all array elements using OR and AND
Bruce Momjian's avatar
Bruce Momjian committed
1777
 * (for ANY and ALL respectively).	Of course we short-circuit as soon as
1778 1779 1780
 * the result is known.
 */
static Datum
1781
ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,
1782 1783
					  ExprContext *econtext,
					  bool *isNull, ExprDoneCond *isDone)
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797
{
	ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) sstate->fxprstate.xprstate.expr;
	bool		useOr = opexpr->useOr;
	ArrayType  *arr;
	int			nitems;
	Datum		result;
	bool		resultnull;
	FunctionCallInfoData fcinfo;
	ExprDoneCond argDone;
	int			i;
	int16		typlen;
	bool		typbyval;
	char		typalign;
	char	   *s;
1798 1799
	bits8	   *bitmap;
	int			bitmask;
1800

1801 1802 1803 1804 1805
	/* Set default values for result flags: non-null, not a set result */
	*isNull = false;
	if (isDone)
		*isDone = ExprSingleResult;

1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816
	/*
	 * Initialize function cache if first time through
	 */
	if (sstate->fxprstate.func.fn_oid == InvalidOid)
	{
		init_fcache(opexpr->opfuncid, &sstate->fxprstate,
					econtext->ecxt_per_query_memory);
		Assert(!sstate->fxprstate.func.fn_retset);
	}

	/* Need to prep callinfo structure */
1817
	InitFunctionCallInfoData(fcinfo, &(sstate->fxprstate.func), 0, NULL, NULL);
1818 1819
	argDone = ExecEvalFuncArgs(&fcinfo, sstate->fxprstate.args, econtext);
	if (argDone != ExprSingleResult)
1820 1821
		ereport(ERROR,
				(errcode(ERRCODE_DATATYPE_MISMATCH),
1822
			   errmsg("op ANY/ALL (array) does not support set arguments")));
1823 1824 1825
	Assert(fcinfo.nargs == 2);

	/*
1826 1827
	 * If the array is NULL then we return NULL --- it's not very meaningful
	 * to do anything else, even if the operator isn't strict.
1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839
	 */
	if (fcinfo.argnull[1])
	{
		*isNull = true;
		return (Datum) 0;
	}
	/* Else okay to fetch and detoast the array */
	arr = DatumGetArrayTypeP(fcinfo.arg[1]);

	/*
	 * If the array is empty, we return either FALSE or TRUE per the useOr
	 * flag.  This is correct even if the scalar is NULL; since we would
1840 1841
	 * evaluate the operator zero times, it matters not whether it would want
	 * to return NULL.
1842 1843 1844 1845
	 */
	nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
	if (nitems <= 0)
		return BoolGetDatum(!useOr);
Bruce Momjian's avatar
Bruce Momjian committed
1846

1847
	/*
1848 1849
	 * If the scalar is NULL, and the function is strict, return NULL; no
	 * point in iterating the loop.
1850 1851 1852 1853 1854 1855 1856 1857
	 */
	if (fcinfo.argnull[0] && sstate->fxprstate.func.fn_strict)
	{
		*isNull = true;
		return (Datum) 0;
	}

	/*
1858 1859
	 * We arrange to look up info about the element type only once per series
	 * of calls, assuming the element type doesn't change underneath us.
1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877
	 */
	if (sstate->element_type != ARR_ELEMTYPE(arr))
	{
		get_typlenbyvalalign(ARR_ELEMTYPE(arr),
							 &sstate->typlen,
							 &sstate->typbyval,
							 &sstate->typalign);
		sstate->element_type = ARR_ELEMTYPE(arr);
	}
	typlen = sstate->typlen;
	typbyval = sstate->typbyval;
	typalign = sstate->typalign;

	result = BoolGetDatum(!useOr);
	resultnull = false;

	/* Loop over the array elements */
	s = (char *) ARR_DATA_PTR(arr);
1878 1879 1880
	bitmap = ARR_NULLBITMAP(arr);
	bitmask = 1;

1881 1882
	for (i = 0; i < nitems; i++)
	{
Bruce Momjian's avatar
Bruce Momjian committed
1883 1884
		Datum		elt;
		Datum		thisresult;
1885

1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899
		/* Get array element, checking for NULL */
		if (bitmap && (*bitmap & bitmask) == 0)
		{
			fcinfo.arg[1] = (Datum) 0;
			fcinfo.argnull[1] = true;
		}
		else
		{
			elt = fetch_att(s, typbyval, typlen);
			s = att_addlength(s, typlen, PointerGetDatum(s));
			s = (char *) att_align(s, typalign);
			fcinfo.arg[1] = elt;
			fcinfo.argnull[1] = false;
		}
1900 1901

		/* Call comparison function */
1902 1903 1904 1905 1906 1907 1908 1909 1910 1911
		if (fcinfo.argnull[1] && sstate->fxprstate.func.fn_strict)
		{
			fcinfo.isnull = true;
			thisresult = (Datum) 0;
		}
		else
		{
			fcinfo.isnull = false;
			thisresult = FunctionCallInvoke(&fcinfo);
		}
1912 1913 1914 1915 1916 1917 1918 1919 1920 1921

		/* Combine results per OR or AND semantics */
		if (fcinfo.isnull)
			resultnull = true;
		else if (useOr)
		{
			if (DatumGetBool(thisresult))
			{
				result = BoolGetDatum(true);
				resultnull = false;
Bruce Momjian's avatar
Bruce Momjian committed
1922
				break;			/* needn't look at any more elements */
1923 1924 1925 1926 1927 1928 1929 1930
			}
		}
		else
		{
			if (!DatumGetBool(thisresult))
			{
				result = BoolGetDatum(false);
				resultnull = false;
Bruce Momjian's avatar
Bruce Momjian committed
1931
				break;			/* needn't look at any more elements */
1932 1933
			}
		}
1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944

		/* advance bitmap pointer if any */
		if (bitmap)
		{
			bitmask <<= 1;
			if (bitmask == 0x100)
			{
				bitmap++;
				bitmask = 1;
			}
		}
1945 1946 1947 1948 1949 1950
	}

	*isNull = resultnull;
	return result;
}

1951
/* ----------------------------------------------------------------
1952 1953 1954
 *		ExecEvalNot
 *		ExecEvalOr
 *		ExecEvalAnd
1955
 *
1956
 *		Evaluate boolean expressions, with appropriate short-circuiting.
1957 1958 1959 1960 1961 1962 1963
 *
 *		The query planner reformulates clause expressions in the
 *		qualification to conjunctive normal form.  If we ever get
 *		an AND to evaluate, we can be sure that it's not a top-level
 *		clause in the qualification, but appears lower (as a function
 *		argument, for example), or in the target list.	Not that you
 *		need to know this, mind you...
1964 1965
 * ----------------------------------------------------------------
 */
1966
static Datum
1967 1968
ExecEvalNot(BoolExprState *notclause, ExprContext *econtext,
			bool *isNull, ExprDoneCond *isDone)
1969
{
1970
	ExprState  *clause = linitial(notclause->args);
1971
	Datum		expr_value;
1972

1973 1974
	if (isDone)
		*isDone = ExprSingleResult;
1975

1976
	expr_value = ExecEvalExpr(clause, econtext, isNull, NULL);
1977

Bruce Momjian's avatar
Bruce Momjian committed
1978
	/*
1979 1980
	 * if the expression evaluates to null, then we just cascade the null back
	 * to whoever called us.
1981 1982
	 */
	if (*isNull)
1983 1984
		return expr_value;

Bruce Momjian's avatar
Bruce Momjian committed
1985
	/*
1986 1987
	 * evaluation of 'not' is simple.. expr is false, then return 'true' and
	 * vice versa.
1988
	 */
1989
	return BoolGetDatum(!DatumGetBool(expr_value));
1990 1991 1992
}

/* ----------------------------------------------------------------
1993
 *		ExecEvalOr
1994 1995
 * ----------------------------------------------------------------
 */
1996
static Datum
1997 1998
ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,
		   bool *isNull, ExprDoneCond *isDone)
1999
{
2000
	List	   *clauses = orExpr->args;
2001
	ListCell   *clause;
2002
	bool		AnyNull;
2003

2004 2005 2006
	if (isDone)
		*isDone = ExprSingleResult;

2007
	AnyNull = false;
2008

Bruce Momjian's avatar
Bruce Momjian committed
2009
	/*
2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020
	 * If any of the clauses is TRUE, the OR result is TRUE regardless of the
	 * states of the rest of the clauses, so we can stop evaluating and return
	 * TRUE immediately.  If none are TRUE and one or more is NULL, we return
	 * NULL; otherwise we return FALSE.  This makes sense when you interpret
	 * NULL as "don't know": if we have a TRUE then the OR is TRUE even if we
	 * aren't sure about some of the other inputs. If all the known inputs are
	 * FALSE, but we have one or more "don't knows", then we have to report
	 * that we "don't know" what the OR's result should be --- perhaps one of
	 * the "don't knows" would have been TRUE if we'd known its value.  Only
	 * when all the inputs are known to be FALSE can we state confidently that
	 * the OR's result is FALSE.
2021
	 */
2022 2023
	foreach(clause, clauses)
	{
2024 2025 2026 2027
		ExprState  *clausestate = (ExprState *) lfirst(clause);
		Datum		clause_value;

		clause_value = ExecEvalExpr(clausestate, econtext, isNull, NULL);
2028

Bruce Momjian's avatar
Bruce Momjian committed
2029
		/*
2030
		 * if we have a non-null true result, then return it.
2031 2032
		 */
		if (*isNull)
2033
			AnyNull = true;		/* remember we got a null */
2034
		else if (DatumGetBool(clause_value))
2035
			return clause_value;
2036 2037
	}

2038 2039
	/* AnyNull is true if at least one clause evaluated to NULL */
	*isNull = AnyNull;
2040
	return BoolGetDatum(false);
2041 2042 2043 2044 2045 2046
}

/* ----------------------------------------------------------------
 *		ExecEvalAnd
 * ----------------------------------------------------------------
 */
2047
static Datum
2048 2049
ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
			bool *isNull, ExprDoneCond *isDone)
2050
{
2051
	List	   *clauses = andExpr->args;
2052
	ListCell   *clause;
2053
	bool		AnyNull;
2054

2055 2056 2057
	if (isDone)
		*isDone = ExprSingleResult;

2058
	AnyNull = false;
2059

Bruce Momjian's avatar
Bruce Momjian committed
2060
	/*
2061 2062 2063 2064 2065 2066
	 * If any of the clauses is FALSE, the AND result is FALSE regardless of
	 * the states of the rest of the clauses, so we can stop evaluating and
	 * return FALSE immediately.  If none are FALSE and one or more is NULL,
	 * we return NULL; otherwise we return TRUE.  This makes sense when you
	 * interpret NULL as "don't know", using the same sort of reasoning as for
	 * OR, above.
2067
	 */
2068

2069 2070
	foreach(clause, clauses)
	{
2071 2072 2073 2074
		ExprState  *clausestate = (ExprState *) lfirst(clause);
		Datum		clause_value;

		clause_value = ExecEvalExpr(clausestate, econtext, isNull, NULL);
2075

Bruce Momjian's avatar
Bruce Momjian committed
2076
		/*
2077
		 * if we have a non-null false result, then return it.
2078 2079
		 */
		if (*isNull)
2080
			AnyNull = true;		/* remember we got a null */
2081
		else if (!DatumGetBool(clause_value))
2082
			return clause_value;
2083 2084
	}

2085 2086
	/* AnyNull is true if at least one clause evaluated to NULL */
	*isNull = AnyNull;
2087
	return BoolGetDatum(!AnyNull);
2088 2089
}

2090 2091 2092
/* ----------------------------------------------------------------
 *		ExecEvalConvertRowtype
 *
2093
 *		Evaluate a rowtype coercion operation.	This may require
2094 2095 2096 2097 2098 2099 2100 2101
 *		rearranging field positions.
 * ----------------------------------------------------------------
 */
static Datum
ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
					   ExprContext *econtext,
					   bool *isNull, ExprDoneCond *isDone)
{
2102
	ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) cstate->xprstate.expr;
2103 2104 2105 2106
	HeapTuple	result;
	Datum		tupDatum;
	HeapTupleHeader tuple;
	HeapTupleData tmptup;
2107 2108 2109 2110 2111
	AttrNumber *attrMap;
	Datum	   *invalues;
	bool	   *inisnull;
	Datum	   *outvalues;
	bool	   *outisnull;
2112
	int			i;
2113
	int			outnatts;
2114 2115 2116 2117 2118 2119 2120 2121 2122

	tupDatum = ExecEvalExpr(cstate->arg, econtext, isNull, isDone);

	/* this test covers the isDone exception too: */
	if (*isNull)
		return tupDatum;

	tuple = DatumGetHeapTupleHeader(tupDatum);

2123 2124 2125 2126 2127 2128 2129 2130
	/* Lookup tupdescs if first time through or after rescan */
	if (cstate->indesc == NULL)
		get_cached_rowtype(exprType((Node *) convert->arg), -1,
						   &cstate->indesc, econtext);
	if (cstate->outdesc == NULL)
		get_cached_rowtype(convert->resulttype, -1,
						   &cstate->outdesc, econtext);

2131 2132 2133
	Assert(HeapTupleHeaderGetTypeId(tuple) == cstate->indesc->tdtypeid);
	Assert(HeapTupleHeaderGetTypMod(tuple) == cstate->indesc->tdtypmod);

2134 2135 2136
	/* if first time through, initialize */
	if (cstate->attrMap == NULL)
	{
Bruce Momjian's avatar
Bruce Momjian committed
2137 2138
		MemoryContext old_cxt;
		int			n;
2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198

		/* allocate state in long-lived memory context */
		old_cxt = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);

		/* prepare map from old to new attribute numbers */
		n = cstate->outdesc->natts;
		cstate->attrMap = (AttrNumber *) palloc0(n * sizeof(AttrNumber));
		for (i = 0; i < n; i++)
		{
			Form_pg_attribute att = cstate->outdesc->attrs[i];
			char	   *attname;
			Oid			atttypid;
			int32		atttypmod;
			int			j;

			if (att->attisdropped)
				continue;		/* attrMap[i] is already 0 */
			attname = NameStr(att->attname);
			atttypid = att->atttypid;
			atttypmod = att->atttypmod;
			for (j = 0; j < cstate->indesc->natts; j++)
			{
				att = cstate->indesc->attrs[j];
				if (att->attisdropped)
					continue;
				if (strcmp(attname, NameStr(att->attname)) == 0)
				{
					/* Found it, check type */
					if (atttypid != att->atttypid || atttypmod != att->atttypmod)
						elog(ERROR, "attribute \"%s\" of type %s does not match corresponding attribute of type %s",
							 attname,
							 format_type_be(cstate->indesc->tdtypeid),
							 format_type_be(cstate->outdesc->tdtypeid));
					cstate->attrMap[i] = (AttrNumber) (j + 1);
					break;
				}
			}
			if (cstate->attrMap[i] == 0)
				elog(ERROR, "attribute \"%s\" of type %s does not exist",
					 attname,
					 format_type_be(cstate->indesc->tdtypeid));
		}
		/* preallocate workspace for Datum arrays */
		n = cstate->indesc->natts + 1;	/* +1 for NULL */
		cstate->invalues = (Datum *) palloc(n * sizeof(Datum));
		cstate->inisnull = (bool *) palloc(n * sizeof(bool));
		n = cstate->outdesc->natts;
		cstate->outvalues = (Datum *) palloc(n * sizeof(Datum));
		cstate->outisnull = (bool *) palloc(n * sizeof(bool));

		MemoryContextSwitchTo(old_cxt);
	}

	attrMap = cstate->attrMap;
	invalues = cstate->invalues;
	inisnull = cstate->inisnull;
	outvalues = cstate->outvalues;
	outisnull = cstate->outisnull;
	outnatts = cstate->outdesc->natts;

2199
	/*
2200
	 * heap_deform_tuple needs a HeapTuple not a bare HeapTupleHeader.
2201 2202 2203 2204 2205
	 */
	tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
	tmptup.t_data = tuple;

	/*
2206 2207 2208
	 * Extract all the values of the old tuple, offsetting the arrays so that
	 * invalues[0] is NULL and invalues[1] is the first source attribute; this
	 * exactly matches the numbering convention in attrMap.
2209
	 */
2210
	heap_deform_tuple(&tmptup, cstate->indesc, invalues + 1, inisnull + 1);
2211
	invalues[0] = (Datum) 0;
2212
	inisnull[0] = true;
2213 2214 2215 2216 2217 2218 2219 2220 2221

	/*
	 * Transpose into proper fields of the new tuple.
	 */
	for (i = 0; i < outnatts; i++)
	{
		int			j = attrMap[i];

		outvalues[i] = invalues[j];
2222
		outisnull[i] = inisnull[j];
2223 2224 2225 2226 2227
	}

	/*
	 * Now form the new tuple.
	 */
2228
	result = heap_form_tuple(cstate->outdesc, outvalues, outisnull);
2229 2230 2231

	return HeapTupleGetDatum(result);
}
2232

2233 2234 2235 2236
/* ----------------------------------------------------------------
 *		ExecEvalCase
 *
 *		Evaluate a CASE clause. Will have boolean expressions
2237
 *		inside the WHEN clauses, and will have expressions
2238 2239 2240 2241 2242
 *		for results.
 *		- thomas 1998-11-09
 * ----------------------------------------------------------------
 */
static Datum
2243
ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
2244
			 bool *isNull, ExprDoneCond *isDone)
2245
{
2246
	List	   *clauses = caseExpr->args;
2247
	ListCell   *clause;
2248 2249
	Datum		save_datum;
	bool		save_isNull;
2250

2251 2252
	if (isDone)
		*isDone = ExprSingleResult;
2253

2254
	/*
2255 2256 2257 2258
	 * If there's a test expression, we have to evaluate it and save the value
	 * where the CaseTestExpr placeholders can find it. We must save and
	 * restore prior setting of econtext's caseValue fields, in case this node
	 * is itself within a larger CASE.
2259 2260 2261 2262 2263 2264 2265 2266
	 */
	save_datum = econtext->caseValue_datum;
	save_isNull = econtext->caseValue_isNull;

	if (caseExpr->arg)
	{
		econtext->caseValue_datum = ExecEvalExpr(caseExpr->arg,
												 econtext,
2267
												 &econtext->caseValue_isNull,
2268 2269 2270
												 NULL);
	}

Bruce Momjian's avatar
Bruce Momjian committed
2271
	/*
2272 2273 2274
	 * we evaluate each of the WHEN clauses in turn, as soon as one is true we
	 * return the corresponding result. If none are true then we return the
	 * value of the default clause, or NULL if there is none.
2275 2276 2277
	 */
	foreach(clause, clauses)
	{
2278
		CaseWhenState *wclause = lfirst(clause);
2279
		Datum		clause_value;
2280

2281
		clause_value = ExecEvalExpr(wclause->expr,
2282 2283
									econtext,
									isNull,
2284
									NULL);
2285

Bruce Momjian's avatar
Bruce Momjian committed
2286
		/*
2287 2288 2289
		 * if we have a true test, then we return the result, since the case
		 * statement is satisfied.	A NULL result from the test is not
		 * considered true.
2290
		 */
2291
		if (DatumGetBool(clause_value) && !*isNull)
2292
		{
2293 2294
			econtext->caseValue_datum = save_datum;
			econtext->caseValue_isNull = save_isNull;
2295
			return ExecEvalExpr(wclause->result,
2296 2297
								econtext,
								isNull,
2298
								isDone);
2299 2300 2301
		}
	}

2302 2303 2304
	econtext->caseValue_datum = save_datum;
	econtext->caseValue_isNull = save_isNull;

2305 2306
	if (caseExpr->defresult)
	{
2307
		return ExecEvalExpr(caseExpr->defresult,
2308 2309
							econtext,
							isNull,
2310
							isDone);
2311 2312
	}

2313 2314
	*isNull = true;
	return (Datum) 0;
2315 2316
}

2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332
/*
 * ExecEvalCaseTestExpr
 *
 * Return the value stored by CASE.
 */
static Datum
ExecEvalCaseTestExpr(ExprState *exprstate,
					 ExprContext *econtext,
					 bool *isNull, ExprDoneCond *isDone)
{
	if (isDone)
		*isDone = ExprSingleResult;
	*isNull = econtext->caseValue_isNull;
	return econtext->caseValue_datum;
}

2333 2334 2335 2336 2337
/* ----------------------------------------------------------------
 *		ExecEvalArray - ARRAY[] expressions
 * ----------------------------------------------------------------
 */
static Datum
2338
ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
2339
			  bool *isNull, ExprDoneCond *isDone)
2340
{
Bruce Momjian's avatar
Bruce Momjian committed
2341
	ArrayExpr  *arrayExpr = (ArrayExpr *) astate->xprstate.expr;
2342
	ArrayType  *result;
2343
	ListCell   *element;
Bruce Momjian's avatar
Bruce Momjian committed
2344
	Oid			element_type = arrayExpr->element_typeid;
2345
	int			ndims = 0;
Bruce Momjian's avatar
Bruce Momjian committed
2346 2347
	int			dims[MAXDIM];
	int			lbs[MAXDIM];
2348

2349 2350 2351 2352 2353
	/* Set default values for result flags: non-null, not a set result */
	*isNull = false;
	if (isDone)
		*isDone = ExprSingleResult;

2354
	if (!arrayExpr->multidims)
2355
	{
2356
		/* Elements are presumably of scalar type */
Bruce Momjian's avatar
Bruce Momjian committed
2357 2358
		int			nelems;
		Datum	   *dvalues;
2359
		bool	   *dnulls;
Bruce Momjian's avatar
Bruce Momjian committed
2360
		int			i = 0;
2361

2362
		ndims = 1;
2363
		nelems = list_length(astate->elements);
2364

2365
		/* Shouldn't happen here, but if length is 0, return empty array */
2366
		if (nelems == 0)
2367
			return PointerGetDatum(construct_empty_array(element_type));
2368 2369

		dvalues = (Datum *) palloc(nelems * sizeof(Datum));
2370
		dnulls = (bool *) palloc(nelems * sizeof(bool));
2371 2372 2373 2374 2375 2376

		/* loop through and build array of datums */
		foreach(element, astate->elements)
		{
			ExprState  *e = (ExprState *) lfirst(element);

2377 2378
			dvalues[i] = ExecEvalExpr(e, econtext, &dnulls[i], NULL);
			i++;
2379 2380 2381 2382 2383 2384
		}

		/* setup for 1-D array of the given length */
		dims[0] = nelems;
		lbs[0] = 1;

2385
		result = construct_md_array(dvalues, dnulls, ndims, dims, lbs,
2386 2387 2388 2389 2390 2391 2392
									element_type,
									astate->elemlength,
									astate->elembyval,
									astate->elemalign);
	}
	else
	{
2393
		/* Must be nested array expressions */
2394 2395 2396
		int			nbytes = 0;
		int			nitems = 0;
		int			outer_nelems = 0;
2397 2398 2399 2400
		int			elem_ndims = 0;
		int		   *elem_dims = NULL;
		int		   *elem_lbs = NULL;
		bool		firstone = true;
2401
		bool		havenulls = false;
2402
		bool		haveempty = false;
2403 2404 2405 2406
		char	  **subdata;
		bits8	  **subbitmaps;
		int		   *subbytes;
		int		   *subnitems;
2407
		int			i;
2408 2409 2410 2411 2412 2413 2414 2415 2416
		int32		dataoffset;
		char	   *dat;
		int			iitem;

		i = list_length(astate->elements);
		subdata = (char **) palloc(i * sizeof(char *));
		subbitmaps = (bits8 **) palloc(i * sizeof(bits8 *));
		subbytes = (int *) palloc(i * sizeof(int));
		subnitems = (int *) palloc(i * sizeof(int));
2417 2418 2419 2420

		/* loop through and get data area from each element */
		foreach(element, astate->elements)
		{
Bruce Momjian's avatar
Bruce Momjian committed
2421
			ExprState  *e = (ExprState *) lfirst(element);
2422 2423 2424
			bool		eisnull;
			Datum		arraydatum;
			ArrayType  *array;
2425
			int			this_ndims;
2426 2427

			arraydatum = ExecEvalExpr(e, econtext, &eisnull, NULL);
2428
			/* temporarily ignore null subarrays */
2429
			if (eisnull)
2430 2431
			{
				haveempty = true;
2432
				continue;
2433
			}
2434 2435 2436

			array = DatumGetArrayTypeP(arraydatum);

2437 2438 2439 2440 2441 2442
			/* run-time double-check on element type */
			if (element_type != ARR_ELEMTYPE(array))
				ereport(ERROR,
						(errcode(ERRCODE_DATATYPE_MISMATCH),
						 errmsg("cannot merge incompatible arrays"),
						 errdetail("Array with element type %s cannot be "
2443
						 "included in ARRAY construct with element type %s.",
2444 2445 2446
								   format_type_be(ARR_ELEMTYPE(array)),
								   format_type_be(element_type))));

2447 2448 2449 2450 2451 2452 2453 2454
			this_ndims = ARR_NDIM(array);
			/* temporarily ignore zero-dimensional subarrays */
			if (this_ndims <= 0)
			{
				haveempty = true;
				continue;
			}

2455 2456 2457
			if (firstone)
			{
				/* Get sub-array details from first member */
2458
				elem_ndims = this_ndims;
2459 2460 2461 2462
				ndims = elem_ndims + 1;
				if (ndims <= 0 || ndims > MAXDIM)
					ereport(ERROR,
							(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2463 2464
						  errmsg("number of array dimensions (%d) exceeds " \
								 "the maximum allowed (%d)", ndims, MAXDIM)));
2465

2466 2467 2468 2469
				elem_dims = (int *) palloc(elem_ndims * sizeof(int));
				memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int));
				elem_lbs = (int *) palloc(elem_ndims * sizeof(int));
				memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int));
2470

2471 2472 2473 2474 2475
				firstone = false;
			}
			else
			{
				/* Check other sub-arrays are compatible */
2476
				if (elem_ndims != this_ndims ||
2477 2478 2479
					memcmp(elem_dims, ARR_DIMS(array),
						   elem_ndims * sizeof(int)) != 0 ||
					memcmp(elem_lbs, ARR_LBOUND(array),
2480
						   elem_ndims * sizeof(int)) != 0)
2481 2482
					ereport(ERROR,
							(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2483 2484
							 errmsg("multidimensional arrays must have array "
									"expressions with matching dimensions")));
2485 2486
			}

2487 2488 2489 2490
			subdata[outer_nelems] = ARR_DATA_PTR(array);
			subbitmaps[outer_nelems] = ARR_NULLBITMAP(array);
			subbytes[outer_nelems] = ARR_SIZE(array) - ARR_DATA_OFFSET(array);
			nbytes += subbytes[outer_nelems];
2491
			subnitems[outer_nelems] = ArrayGetNItems(this_ndims,
2492 2493 2494 2495
													 ARR_DIMS(array));
			nitems += subnitems[outer_nelems];
			havenulls |= ARR_HASNULL(array);
			outer_nelems++;
2496 2497
		}

2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513
		/*
		 * If all items were null or empty arrays, return an empty array;
		 * otherwise, if some were and some weren't, raise error.  (Note:
		 * we must special-case this somehow to avoid trying to generate
		 * a 1-D array formed from empty arrays.  It's not ideal...)
		 */
		if (haveempty)
		{
			if (ndims == 0)		/* didn't find any nonempty array */
				return PointerGetDatum(construct_empty_array(element_type));
			ereport(ERROR,
					(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
					 errmsg("multidimensional arrays must have array "
							"expressions with matching dimensions")));
		}

2514 2515 2516 2517 2518 2519 2520 2521 2522
		/* setup for multi-D array */
		dims[0] = outer_nelems;
		lbs[0] = 1;
		for (i = 1; i < ndims; i++)
		{
			dims[i] = elem_dims[i - 1];
			lbs[i] = elem_lbs[i - 1];
		}

2523 2524 2525 2526 2527 2528 2529
		if (havenulls)
		{
			dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
			nbytes += dataoffset;
		}
		else
		{
2530
			dataoffset = 0;		/* marker for no null bitmap */
2531 2532
			nbytes += ARR_OVERHEAD_NONULLS(ndims);
		}
2533

2534
		result = (ArrayType *) palloc(nbytes);
2535 2536
		result->size = nbytes;
		result->ndim = ndims;
2537
		result->dataoffset = dataoffset;
2538 2539 2540 2541
		result->elemtype = element_type;
		memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
		memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));

2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553
		dat = ARR_DATA_PTR(result);
		iitem = 0;
		for (i = 0; i < outer_nelems; i++)
		{
			memcpy(dat, subdata[i], subbytes[i]);
			dat += subbytes[i];
			if (havenulls)
				array_bitmap_copy(ARR_NULLBITMAP(result), iitem,
								  subbitmaps[i], 0,
								  subnitems[i]);
			iitem += subnitems[i];
		}
2554 2555 2556 2557 2558
	}

	return PointerGetDatum(result);
}

2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569
/* ----------------------------------------------------------------
 *		ExecEvalRow - ROW() expressions
 * ----------------------------------------------------------------
 */
static Datum
ExecEvalRow(RowExprState *rstate,
			ExprContext *econtext,
			bool *isNull, ExprDoneCond *isDone)
{
	HeapTuple	tuple;
	Datum	   *values;
2570
	bool	   *isnull;
2571
	int			natts;
2572
	ListCell   *arg;
2573 2574 2575 2576 2577 2578 2579 2580
	int			i;

	/* Set default values for result flags: non-null, not a set result */
	*isNull = false;
	if (isDone)
		*isDone = ExprSingleResult;

	/* Allocate workspace */
2581 2582
	natts = rstate->tupdesc->natts;
	values = (Datum *) palloc0(natts * sizeof(Datum));
2583
	isnull = (bool *) palloc(natts * sizeof(bool));
2584 2585

	/* preset to nulls in case rowtype has some later-added columns */
2586
	memset(isnull, true, natts * sizeof(bool));
2587 2588 2589 2590 2591 2592 2593

	/* Evaluate field values */
	i = 0;
	foreach(arg, rstate->args)
	{
		ExprState  *e = (ExprState *) lfirst(arg);

2594
		values[i] = ExecEvalExpr(e, econtext, &isnull[i], NULL);
2595 2596 2597
		i++;
	}

2598
	tuple = heap_form_tuple(rstate->tupdesc, values, isnull);
2599 2600

	pfree(values);
2601
	pfree(isnull);
2602 2603 2604 2605

	return HeapTupleGetDatum(tuple);
}

2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652
/* ----------------------------------------------------------------
 *		ExecEvalRowCompare - ROW() comparison-op ROW()
 * ----------------------------------------------------------------
 */
static Datum
ExecEvalRowCompare(RowCompareExprState *rstate,
				   ExprContext *econtext,
				   bool *isNull, ExprDoneCond *isDone)
{
	bool		result;
	RowCompareType rctype = ((RowCompareExpr *) rstate->xprstate.expr)->rctype;
	int32		cmpresult = 0;
	ListCell   *l;
	ListCell   *r;
	int			i;

	if (isDone)
		*isDone = ExprSingleResult;
	*isNull = true;				/* until we get a result */

	i = 0;
	forboth(l, rstate->largs, r, rstate->rargs)
	{
		ExprState  *le = (ExprState *) lfirst(l);
		ExprState  *re = (ExprState *) lfirst(r);
		FunctionCallInfoData locfcinfo;

		InitFunctionCallInfoData(locfcinfo, &(rstate->funcs[i]), 2,
								 NULL, NULL);
		locfcinfo.arg[0] = ExecEvalExpr(le, econtext,
										&locfcinfo.argnull[0], NULL);
		locfcinfo.arg[1] = ExecEvalExpr(re, econtext,
										&locfcinfo.argnull[1], NULL);
		if (rstate->funcs[i].fn_strict &&
			(locfcinfo.argnull[0] || locfcinfo.argnull[1]))
			return (Datum) 0;	/* force NULL result */
		locfcinfo.isnull = false;
		cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
		if (locfcinfo.isnull)
			return (Datum) 0;	/* force NULL result */
		if (cmpresult != 0)
			break;				/* no need to compare remaining columns */
		i++;
	}

	switch (rctype)
	{
Bruce Momjian's avatar
Bruce Momjian committed
2653
			/* EQ and NE cases aren't allowed here */
2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675
		case ROWCOMPARE_LT:
			result = (cmpresult < 0);
			break;
		case ROWCOMPARE_LE:
			result = (cmpresult <= 0);
			break;
		case ROWCOMPARE_GE:
			result = (cmpresult >= 0);
			break;
		case ROWCOMPARE_GT:
			result = (cmpresult > 0);
			break;
		default:
			elog(ERROR, "unrecognized RowCompareType: %d", (int) rctype);
			result = 0;			/* keep compiler quiet */
			break;
	}

	*isNull = false;
	return BoolGetDatum(result);
}

2676 2677 2678 2679 2680
/* ----------------------------------------------------------------
 *		ExecEvalCoalesce
 * ----------------------------------------------------------------
 */
static Datum
2681
ExecEvalCoalesce(CoalesceExprState *coalesceExpr, ExprContext *econtext,
2682
				 bool *isNull, ExprDoneCond *isDone)
2683
{
2684
	ListCell   *arg;
2685

2686 2687 2688
	if (isDone)
		*isDone = ExprSingleResult;

2689 2690 2691
	/* Simply loop through until something NOT NULL is found */
	foreach(arg, coalesceExpr->args)
	{
Bruce Momjian's avatar
Bruce Momjian committed
2692 2693
		ExprState  *e = (ExprState *) lfirst(arg);
		Datum		value;
2694 2695 2696 2697 2698 2699 2700 2701 2702 2703

		value = ExecEvalExpr(e, econtext, isNull, NULL);
		if (!*isNull)
			return value;
	}

	/* Else return NULL */
	*isNull = true;
	return (Datum) 0;
}
Bruce Momjian's avatar
Bruce Momjian committed
2704

2705 2706 2707 2708 2709 2710 2711 2712
/* ----------------------------------------------------------------
 *		ExecEvalMinMax
 * ----------------------------------------------------------------
 */
static Datum
ExecEvalMinMax(MinMaxExprState *minmaxExpr, ExprContext *econtext,
			   bool *isNull, ExprDoneCond *isDone)
{
2713
	Datum		result = (Datum) 0;
2714 2715
	MinMaxOp	op = ((MinMaxExpr *) minmaxExpr->xprstate.expr)->op;
	FunctionCallInfoData locfcinfo;
2716
	ListCell   *arg;
2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749

	if (isDone)
		*isDone = ExprSingleResult;
	*isNull = true;				/* until we get a result */

	InitFunctionCallInfoData(locfcinfo, &minmaxExpr->cfunc, 2, NULL, NULL);
	locfcinfo.argnull[0] = false;
	locfcinfo.argnull[1] = false;

	foreach(arg, minmaxExpr->args)
	{
		ExprState  *e = (ExprState *) lfirst(arg);
		Datum		value;
		bool		valueIsNull;
		int32		cmpresult;

		value = ExecEvalExpr(e, econtext, &valueIsNull, NULL);
		if (valueIsNull)
			continue;			/* ignore NULL inputs */

		if (*isNull)
		{
			/* first nonnull input, adopt value */
			result = value;
			*isNull = false;
		}
		else
		{
			/* apply comparison function */
			locfcinfo.arg[0] = result;
			locfcinfo.arg[1] = value;
			locfcinfo.isnull = false;
			cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
2750
			if (locfcinfo.isnull)		/* probably should not happen */
2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761
				continue;
			if (cmpresult > 0 && op == IS_LEAST)
				result = value;
			else if (cmpresult < 0 && op == IS_GREATEST)
				result = value;
		}
	}

	return result;
}

2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786
/* ----------------------------------------------------------------
 *		ExecEvalXml
 * ----------------------------------------------------------------
 */
static Datum
ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
			bool *isNull, ExprDoneCond *isDone)
{
	XmlExpr		   *xexpr = (XmlExpr *) xmlExpr->xprstate.expr;
	text 		   *result;
	StringInfoData 	buf;
	Datum			value;
	bool 			isnull;
	ListCell 	   *arg;
	ListCell   *narg;
	int 			i;

	if (isDone)
		*isDone = ExprSingleResult;
	*isNull = true;				/* until we get a result */

	switch (xexpr->op)
	{
		case IS_XMLCONCAT:
			{
2787
				List *values = NIL;
2788

2789 2790 2791 2792 2793 2794 2795 2796 2797 2798
				foreach(arg, xmlExpr->args)
				{
					ExprState 	*e = (ExprState *) lfirst(arg);

					value = ExecEvalExpr(e, econtext, &isnull, NULL);
					if (!isnull)
						values = lappend(values, DatumGetPointer(value));
				}

				if (list_length(values) > 0)
2799 2800
				{
					*isNull = false;
2801
					return PointerGetDatum(xmlconcat(values));
2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817
				}
			}
			break;

		case IS_XMLFOREST:
			initStringInfo(&buf);
			i = 0;
			forboth(arg, xmlExpr->named_args, narg, xexpr->arg_names)
			{
				ExprState 	*e = (ExprState *) lfirst(arg);
				char	*argname = strVal(lfirst(narg));

				value = ExecEvalExpr(e, econtext, &isnull, NULL);
				if (!isnull)
				{
					appendStringInfo(&buf, "<%s>%s</%s>",
2818 2819 2820
									 argname,
									 map_sql_value_to_xml_value(value, exprType((Node *) e->expr)),
									 argname);
2821 2822 2823 2824 2825 2826 2827
					*isNull = false;
				}
				i++;
			}
			break;

			/* The remaining cases don't need to set up buf */
2828 2829 2830 2831 2832
		case IS_XMLELEMENT:
			*isNull = false;
			return PointerGetDatum(xmlelement(xmlExpr, econtext));
			break;

2833 2834 2835 2836 2837 2838
		case IS_XMLPARSE:
			{
				ExprState 	*e;
				text	    *data;
				bool		preserve_whitespace;

2839 2840
				/* arguments are known to be text, bool */
				Assert(list_length(xmlExpr->args) == 2);
2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856

				e = (ExprState *) linitial(xmlExpr->args);
				value = ExecEvalExpr(e, econtext, &isnull, NULL);
				if (isnull)
					return (Datum) 0;
				data = DatumGetTextP(value);

				e = (ExprState *) lsecond(xmlExpr->args);
				value = ExecEvalExpr(e, econtext, &isnull, NULL);
				if (isnull)		/* probably can't happen */
					return (Datum) 0;
				preserve_whitespace = DatumGetBool(value);

				*isNull = false;

				return PointerGetDatum(xmlparse(data,
2857
												xexpr->xmloption,
2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874
												preserve_whitespace));
			}
			break;

		case IS_XMLPI:
			{
				ExprState 	*e;
				text	    *arg;

				/* optional argument is known to be text */
				Assert(list_length(xmlExpr->args) <= 1);

				if (xmlExpr->args)
				{
					e = (ExprState *) linitial(xmlExpr->args);
					value = ExecEvalExpr(e, econtext, &isnull, NULL);
					if (isnull)
2875 2876 2877
						arg = NULL;
					else
						arg = DatumGetTextP(value);
2878 2879
				}
				else
2880
				{
2881
					arg = NULL;
2882 2883
					isnull = false;
				}
2884

2885
				return PointerGetDatum(xmlpi(xexpr->name, arg, isnull, isNull));
2886 2887 2888 2889 2890 2891 2892 2893 2894 2895
			}
			break;

		case IS_XMLROOT:
			{
				ExprState 	*e;
				xmltype		*data;
				text		*version;
				int			standalone;

2896
				/* arguments are known to be xml, text, int */
2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913
				Assert(list_length(xmlExpr->args) == 3);

				e = (ExprState *) linitial(xmlExpr->args);
				value = ExecEvalExpr(e, econtext, &isnull, NULL);
				if (isnull)
					return (Datum) 0;
				data = DatumGetXmlP(value);

				e = (ExprState *) lsecond(xmlExpr->args);
				value = ExecEvalExpr(e, econtext, &isnull, NULL);
				if (isnull)
					version = NULL;
				else
					version = DatumGetTextP(value);

				e = (ExprState *) lthird(xmlExpr->args);
				value = ExecEvalExpr(e, econtext, &isnull, NULL);
2914
				standalone = DatumGetInt32(value);
2915 2916 2917 2918 2919 2920 2921 2922

				*isNull = false;

				return PointerGetDatum(xmlroot(data,
											   version,
											   standalone));
			}
			break;
2923

2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941
		case IS_XMLSERIALIZE:
			{
				ExprState	*e;

				/* argument type is known to be xml */
				Assert(list_length(xmlExpr->args) == 1);

				e = (ExprState *) linitial(xmlExpr->args);
				value = ExecEvalExpr(e, econtext, &isnull, NULL);
				if (isnull)
					return (Datum) 0;

				*isNull = false;

				return PointerGetDatum(xmltotext_with_xmloption(DatumGetXmlP(value), xexpr->xmloption));
			}
			break;

2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959
		case IS_DOCUMENT:
			{
				ExprState 	*e;

				/* optional argument is known to be xml */
				Assert(list_length(xmlExpr->args) == 1);

				e = (ExprState *) linitial(xmlExpr->args);
				value = ExecEvalExpr(e, econtext, &isnull, NULL);
				if (isnull)
					return (Datum) 0;
				else
				{
					*isNull = false;
					return BoolGetDatum(xml_is_document(DatumGetXmlP(value)));
				}
			}
			break;
2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976
	}

	if (*isNull)
		result = NULL;
	else
	{
		int		len = buf.len + VARHDRSZ;

		result = palloc(len);
		VARATT_SIZEP(result) = len;
		memcpy(VARDATA(result), buf.data, buf.len);
	}

	pfree(buf.data);
	return PointerGetDatum(result);
}

2977 2978 2979 2980 2981 2982 2983 2984 2985
/* ----------------------------------------------------------------
 *		ExecEvalNullIf
 *
 * Note that this is *always* derived from the equals operator,
 * but since we need special processing of the arguments
 * we can not simply reuse ExecEvalOper() or ExecEvalFunc().
 * ----------------------------------------------------------------
 */
static Datum
2986 2987 2988
ExecEvalNullIf(FuncExprState *nullIfExpr,
			   ExprContext *econtext,
			   bool *isNull, ExprDoneCond *isDone)
2989 2990 2991 2992 2993 2994
{
	Datum		result;
	FunctionCallInfoData fcinfo;
	ExprDoneCond argDone;
	List	   *argList;

2995 2996 2997
	if (isDone)
		*isDone = ExprSingleResult;

2998 2999 3000
	/*
	 * Initialize function cache if first time through
	 */
3001
	if (nullIfExpr->func.fn_oid == InvalidOid)
3002
	{
3003
		NullIfExpr *op = (NullIfExpr *) nullIfExpr->xprstate.expr;
3004

3005 3006
		init_fcache(op->opfuncid, nullIfExpr, econtext->ecxt_per_query_memory);
		Assert(!nullIfExpr->func.fn_retset);
3007 3008 3009
	}

	/*
3010
	 * extract info from nullIfExpr
3011
	 */
3012
	argList = nullIfExpr->args;
3013 3014

	/* Need to prep callinfo structure */
3015
	InitFunctionCallInfoData(fcinfo, &(nullIfExpr->func), 0, NULL, NULL);
3016 3017
	argDone = ExecEvalFuncArgs(&fcinfo, argList, econtext);
	if (argDone != ExprSingleResult)
3018 3019 3020
		ereport(ERROR,
				(errcode(ERRCODE_DATATYPE_MISMATCH),
				 errmsg("NULLIF does not support set arguments")));
3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040
	Assert(fcinfo.nargs == 2);

	/* if either argument is NULL they can't be equal */
	if (!fcinfo.argnull[0] && !fcinfo.argnull[1])
	{
		fcinfo.isnull = false;
		result = FunctionCallInvoke(&fcinfo);
		/* if the arguments are equal return null */
		if (!fcinfo.isnull && DatumGetBool(result))
		{
			*isNull = true;
			return (Datum) 0;
		}
	}

	/* else return first argument */
	*isNull = fcinfo.argnull[0];
	return fcinfo.arg[0];
}

3041 3042 3043 3044 3045 3046 3047
/* ----------------------------------------------------------------
 *		ExecEvalNullTest
 *
 *		Evaluate a NullTest node.
 * ----------------------------------------------------------------
 */
static Datum
3048
ExecEvalNullTest(NullTestState *nstate,
3049 3050 3051 3052
				 ExprContext *econtext,
				 bool *isNull,
				 ExprDoneCond *isDone)
{
3053
	NullTest   *ntest = (NullTest *) nstate->xprstate.expr;
3054 3055
	Datum		result;

3056 3057 3058 3059 3060
	result = ExecEvalExpr(nstate->arg, econtext, isNull, isDone);

	if (isDone && *isDone == ExprEndResult)
		return result;			/* nothing to check */

3061
	if (nstate->argisrow && !(*isNull))
3062
	{
3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087
		HeapTupleHeader tuple;
		Oid			tupType;
		int32		tupTypmod;
		TupleDesc	tupDesc;
		HeapTupleData tmptup;
		int			att;

		tuple = DatumGetHeapTupleHeader(result);

		tupType = HeapTupleHeaderGetTypeId(tuple);
		tupTypmod = HeapTupleHeaderGetTypMod(tuple);

		/* Lookup tupdesc if first time through or if type changes */
		tupDesc = get_cached_rowtype(tupType, tupTypmod,
									 &nstate->argdesc, econtext);

		/*
		 * heap_attisnull needs a HeapTuple not a bare HeapTupleHeader.
		 */
		tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
		tmptup.t_data = tuple;

		for (att = 1; att <= tupDesc->natts; att++)
		{
			/* ignore dropped columns */
Bruce Momjian's avatar
Bruce Momjian committed
3088
			if (tupDesc->attrs[att - 1]->attisdropped)
3089 3090
				continue;
			if (heap_attisnull(&tmptup, att))
3091
			{
3092 3093 3094
				/* null field disproves IS NOT NULL */
				if (ntest->nulltesttype == IS_NOT_NULL)
					return BoolGetDatum(false);
3095 3096 3097
			}
			else
			{
3098 3099 3100
				/* non-null field disproves IS NULL */
				if (ntest->nulltesttype == IS_NULL)
					return BoolGetDatum(false);
3101
			}
3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129
		}

		return BoolGetDatum(true);
	}
	else
	{
		/* Simple scalar-argument case, or a null rowtype datum */
		switch (ntest->nulltesttype)
		{
			case IS_NULL:
				if (*isNull)
				{
					*isNull = false;
					return BoolGetDatum(true);
				}
				else
					return BoolGetDatum(false);
			case IS_NOT_NULL:
				if (*isNull)
				{
					*isNull = false;
					return BoolGetDatum(false);
				}
				else
					return BoolGetDatum(true);
			default:
				elog(ERROR, "unrecognized nulltesttype: %d",
					 (int) ntest->nulltesttype);
Bruce Momjian's avatar
Bruce Momjian committed
3130
				return (Datum) 0;		/* keep compiler quiet */
3131
		}
3132
	}
3133 3134 3135 3136 3137 3138 3139 3140 3141
}

/* ----------------------------------------------------------------
 *		ExecEvalBooleanTest
 *
 *		Evaluate a BooleanTest node.
 * ----------------------------------------------------------------
 */
static Datum
3142
ExecEvalBooleanTest(GenericExprState *bstate,
3143 3144 3145 3146
					ExprContext *econtext,
					bool *isNull,
					ExprDoneCond *isDone)
{
3147
	BooleanTest *btest = (BooleanTest *) bstate->xprstate.expr;
3148 3149
	Datum		result;

3150 3151 3152 3153 3154
	result = ExecEvalExpr(bstate->arg, econtext, isNull, isDone);

	if (isDone && *isDone == ExprEndResult)
		return result;			/* nothing to check */

3155
	switch (btest->booltesttype)
3156 3157 3158 3159 3160 3161 3162 3163 3164
	{
		case IS_TRUE:
			if (*isNull)
			{
				*isNull = false;
				return BoolGetDatum(false);
			}
			else if (DatumGetBool(result))
				return BoolGetDatum(true);
3165
			else
3166 3167 3168 3169 3170 3171 3172 3173 3174
				return BoolGetDatum(false);
		case IS_NOT_TRUE:
			if (*isNull)
			{
				*isNull = false;
				return BoolGetDatum(true);
			}
			else if (DatumGetBool(result))
				return BoolGetDatum(false);
3175
			else
3176 3177 3178 3179 3180 3181 3182 3183 3184
				return BoolGetDatum(true);
		case IS_FALSE:
			if (*isNull)
			{
				*isNull = false;
				return BoolGetDatum(false);
			}
			else if (DatumGetBool(result))
				return BoolGetDatum(false);
3185
			else
3186 3187 3188 3189 3190 3191 3192 3193 3194
				return BoolGetDatum(true);
		case IS_NOT_FALSE:
			if (*isNull)
			{
				*isNull = false;
				return BoolGetDatum(true);
			}
			else if (DatumGetBool(result))
				return BoolGetDatum(true);
3195
			else
3196 3197 3198 3199 3200 3201 3202
				return BoolGetDatum(false);
		case IS_UNKNOWN:
			if (*isNull)
			{
				*isNull = false;
				return BoolGetDatum(true);
			}
3203
			else
3204 3205 3206 3207 3208 3209 3210
				return BoolGetDatum(false);
		case IS_NOT_UNKNOWN:
			if (*isNull)
			{
				*isNull = false;
				return BoolGetDatum(false);
			}
3211
			else
3212 3213
				return BoolGetDatum(true);
		default:
3214
			elog(ERROR, "unrecognized booltesttype: %d",
3215 3216 3217
				 (int) btest->booltesttype);
			return (Datum) 0;	/* keep compiler quiet */
	}
3218 3219
}

3220
/*
3221
 * ExecEvalCoerceToDomain
3222
 *
3223 3224
 * Test the provided data against the domain constraint(s).  If the data
 * passes the constraint specifications, pass it through (return the
3225 3226 3227
 * datum) otherwise throw an error.
 */
static Datum
3228
ExecEvalCoerceToDomain(CoerceToDomainState *cstate, ExprContext *econtext,
3229 3230
					   bool *isNull, ExprDoneCond *isDone)
{
3231
	CoerceToDomain *ctest = (CoerceToDomain *) cstate->xprstate.expr;
3232
	Datum		result;
3233
	ListCell   *l;
3234

3235
	result = ExecEvalExpr(cstate->arg, econtext, isNull, isDone);
3236

3237 3238 3239
	if (isDone && *isDone == ExprEndResult)
		return result;			/* nothing to check */

3240
	foreach(l, cstate->constraints)
3241
	{
3242 3243 3244 3245 3246 3247
		DomainConstraintState *con = (DomainConstraintState *) lfirst(l);

		switch (con->constrainttype)
		{
			case DOM_CONSTRAINT_NOTNULL:
				if (*isNull)
3248 3249
					ereport(ERROR,
							(errcode(ERRCODE_NOT_NULL_VIOLATION),
3250 3251
							 errmsg("domain %s does not allow null values",
									format_type_be(ctest->resulttype))));
3252 3253
				break;
			case DOM_CONSTRAINT_CHECK:
Bruce Momjian's avatar
Bruce Momjian committed
3254 3255 3256 3257 3258
				{
					Datum		conResult;
					bool		conIsNull;
					Datum		save_datum;
					bool		save_isNull;
3259

Bruce Momjian's avatar
Bruce Momjian committed
3260 3261 3262 3263
					/*
					 * Set up value to be returned by CoerceToDomainValue
					 * nodes. We must save and restore prior setting of
					 * econtext's domainValue fields, in case this node is
3264
					 * itself within a check expression for another domain.
Bruce Momjian's avatar
Bruce Momjian committed
3265 3266 3267
					 */
					save_datum = econtext->domainValue_datum;
					save_isNull = econtext->domainValue_isNull;
3268

Bruce Momjian's avatar
Bruce Momjian committed
3269 3270
					econtext->domainValue_datum = result;
					econtext->domainValue_isNull = *isNull;
3271

Bruce Momjian's avatar
Bruce Momjian committed
3272 3273
					conResult = ExecEvalExpr(con->check_expr,
											 econtext, &conIsNull, NULL);
3274

Bruce Momjian's avatar
Bruce Momjian committed
3275 3276 3277 3278
					if (!conIsNull &&
						!DatumGetBool(conResult))
						ereport(ERROR,
								(errcode(ERRCODE_CHECK_VIOLATION),
3279
								 errmsg("value for domain %s violates check constraint \"%s\"",
Bruce Momjian's avatar
Bruce Momjian committed
3280 3281 3282 3283 3284 3285 3286
										format_type_be(ctest->resulttype),
										con->name)));
					econtext->domainValue_datum = save_datum;
					econtext->domainValue_isNull = save_isNull;

					break;
				}
3287
			default:
3288 3289
				elog(ERROR, "unrecognized constraint type: %d",
					 (int) con->constrainttype);
3290 3291
				break;
		}
3292 3293
	}

3294
	/* If all has gone well (constraints did not fail) return the datum */
3295 3296 3297
	return result;
}

3298
/*
3299
 * ExecEvalCoerceToDomainValue
3300
 *
3301
 * Return the value stored by CoerceToDomain.
3302 3303
 */
static Datum
3304 3305 3306
ExecEvalCoerceToDomainValue(ExprState *exprstate,
							ExprContext *econtext,
							bool *isNull, ExprDoneCond *isDone)
3307
{
3308 3309
	if (isDone)
		*isDone = ExprSingleResult;
3310 3311 3312 3313
	*isNull = econtext->domainValue_isNull;
	return econtext->domainValue_datum;
}

3314 3315 3316 3317 3318 3319 3320
/* ----------------------------------------------------------------
 *		ExecEvalFieldSelect
 *
 *		Evaluate a FieldSelect node.
 * ----------------------------------------------------------------
 */
static Datum
3321
ExecEvalFieldSelect(FieldSelectState *fstate,
3322 3323
					ExprContext *econtext,
					bool *isNull,
3324
					ExprDoneCond *isDone)
3325
{
3326
	FieldSelect *fselect = (FieldSelect *) fstate->xprstate.expr;
3327
	AttrNumber	fieldnum = fselect->fieldnum;
3328
	Datum		result;
3329 3330 3331 3332 3333
	Datum		tupDatum;
	HeapTupleHeader tuple;
	Oid			tupType;
	int32		tupTypmod;
	TupleDesc	tupDesc;
3334
	Form_pg_attribute attr;
3335
	HeapTupleData tmptup;
3336

3337
	tupDatum = ExecEvalExpr(fstate->arg, econtext, isNull, isDone);
3338 3339

	/* this test covers the isDone exception too: */
3340
	if (*isNull)
3341 3342 3343 3344 3345 3346 3347 3348
		return tupDatum;

	tuple = DatumGetHeapTupleHeader(tupDatum);

	tupType = HeapTupleHeaderGetTypeId(tuple);
	tupTypmod = HeapTupleHeaderGetTypMod(tuple);

	/* Lookup tupdesc if first time through or if type changes */
3349 3350
	tupDesc = get_cached_rowtype(tupType, tupTypmod,
								 &fstate->argdesc, econtext);
3351

3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373
	/* Check for dropped column, and force a NULL result if so */
	if (fieldnum <= 0 ||
		fieldnum > tupDesc->natts)	/* should never happen */
				elog(ERROR, "attribute number %d exceeds number of columns %d",
					 fieldnum, tupDesc->natts);
	attr = tupDesc->attrs[fieldnum - 1];
	if (attr->attisdropped)
	{
		*isNull = true;
		return (Datum) 0;
	}

	/* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
	if (fselect->resulttype != attr->atttypid ||
		(fselect->resulttypmod != attr->atttypmod &&
		 fselect->resulttypmod != -1))
		ereport(ERROR,
				(errmsg("attribute %d has wrong type", fieldnum),
				 errdetail("Table has type %s, but query expects %s.",
						   format_type_be(attr->atttypid),
						   format_type_be(fselect->resulttype))));

3374
	/*
3375 3376 3377
	 * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
	 * the fields in the struct just in case user tries to inspect system
	 * columns.
3378 3379 3380 3381 3382 3383 3384
	 */
	tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
	ItemPointerSetInvalid(&(tmptup.t_self));
	tmptup.t_tableOid = InvalidOid;
	tmptup.t_data = tuple;

	result = heap_getattr(&tmptup,
3385
						  fieldnum,
3386
						  tupDesc,
3387 3388 3389 3390
						  isNull);
	return result;
}

3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407
/* ----------------------------------------------------------------
 *		ExecEvalFieldStore
 *
 *		Evaluate a FieldStore node.
 * ----------------------------------------------------------------
 */
static Datum
ExecEvalFieldStore(FieldStoreState *fstate,
				   ExprContext *econtext,
				   bool *isNull,
				   ExprDoneCond *isDone)
{
	FieldStore *fstore = (FieldStore *) fstate->xprstate.expr;
	HeapTuple	tuple;
	Datum		tupDatum;
	TupleDesc	tupDesc;
	Datum	   *values;
3408
	bool	   *isnull;
3409 3410 3411 3412 3413 3414 3415 3416 3417 3418
	Datum		save_datum;
	bool		save_isNull;
	ListCell   *l1,
			   *l2;

	tupDatum = ExecEvalExpr(fstate->arg, econtext, isNull, isDone);

	if (isDone && *isDone == ExprEndResult)
		return tupDatum;

3419 3420 3421
	/* Lookup tupdesc if first time through or after rescan */
	tupDesc = get_cached_rowtype(fstore->resulttype, -1,
								 &fstate->argdesc, econtext);
3422 3423 3424

	/* Allocate workspace */
	values = (Datum *) palloc(tupDesc->natts * sizeof(Datum));
3425
	isnull = (bool *) palloc(tupDesc->natts * sizeof(bool));
3426 3427 3428 3429

	if (!*isNull)
	{
		/*
3430 3431
		 * heap_deform_tuple needs a HeapTuple not a bare HeapTupleHeader. We
		 * set all the fields in the struct just in case.
3432 3433 3434 3435 3436 3437 3438 3439 3440 3441
		 */
		HeapTupleHeader tuphdr;
		HeapTupleData tmptup;

		tuphdr = DatumGetHeapTupleHeader(tupDatum);
		tmptup.t_len = HeapTupleHeaderGetDatumLength(tuphdr);
		ItemPointerSetInvalid(&(tmptup.t_self));
		tmptup.t_tableOid = InvalidOid;
		tmptup.t_data = tuphdr;

3442
		heap_deform_tuple(&tmptup, tupDesc, values, isnull);
3443 3444 3445 3446
	}
	else
	{
		/* Convert null input tuple into an all-nulls row */
3447
		memset(isnull, true, tupDesc->natts * sizeof(bool));
3448 3449 3450 3451 3452 3453 3454 3455 3456 3457
	}

	/* Result is never null */
	*isNull = false;

	save_datum = econtext->caseValue_datum;
	save_isNull = econtext->caseValue_isNull;

	forboth(l1, fstate->newvals, l2, fstore->fieldnums)
	{
Bruce Momjian's avatar
Bruce Momjian committed
3458 3459
		ExprState  *newval = (ExprState *) lfirst(l1);
		AttrNumber	fieldnum = lfirst_int(l2);
3460 3461 3462 3463

		Assert(fieldnum > 0 && fieldnum <= tupDesc->natts);

		/*
3464 3465 3466 3467 3468
		 * Use the CaseTestExpr mechanism to pass down the old value of the
		 * field being replaced; this is useful in case we have a nested field
		 * update situation.  It's safe to reuse the CASE mechanism because
		 * there cannot be a CASE between here and where the value would be
		 * needed.
3469 3470
		 */
		econtext->caseValue_datum = values[fieldnum - 1];
3471
		econtext->caseValue_isNull = isnull[fieldnum - 1];
3472 3473 3474

		values[fieldnum - 1] = ExecEvalExpr(newval,
											econtext,
3475
											&isnull[fieldnum - 1],
3476 3477 3478 3479 3480 3481
											NULL);
	}

	econtext->caseValue_datum = save_datum;
	econtext->caseValue_isNull = save_isNull;

3482
	tuple = heap_form_tuple(tupDesc, values, isnull);
3483 3484

	pfree(values);
3485
	pfree(isnull);
3486 3487 3488 3489

	return HeapTupleGetDatum(tuple);
}

3490
/* ----------------------------------------------------------------
3491
 *		ExecEvalRelabelType
3492
 *
3493
 *		Evaluate a RelabelType node.
3494 3495
 * ----------------------------------------------------------------
 */
3496 3497 3498 3499
static Datum
ExecEvalRelabelType(GenericExprState *exprstate,
					ExprContext *econtext,
					bool *isNull, ExprDoneCond *isDone)
3500
{
3501 3502
	return ExecEvalExpr(exprstate->arg, econtext, isNull, isDone);
}
3503

3504

3505
/*
3506 3507 3508
 * ExecEvalExprSwitchContext
 *
 * Same as ExecEvalExpr, but get into the right allocation context explicitly.
3509 3510
 */
Datum
3511
ExecEvalExprSwitchContext(ExprState *expression,
3512 3513
						  ExprContext *econtext,
						  bool *isNull,
3514
						  ExprDoneCond *isDone)
3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525
{
	Datum		retDatum;
	MemoryContext oldContext;

	oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
	retDatum = ExecEvalExpr(expression, econtext, isNull, isDone);
	MemoryContextSwitchTo(oldContext);
	return retDatum;
}


3526 3527 3528
/*
 * ExecInitExpr: prepare an expression tree for execution
 *
3529
 * This function builds and returns an ExprState tree paralleling the given
Bruce Momjian's avatar
Bruce Momjian committed
3530
 * Expr node tree.	The ExprState tree can then be handed to ExecEvalExpr
3531 3532 3533 3534 3535 3536 3537 3538
 * for execution.  Because the Expr tree itself is read-only as far as
 * ExecInitExpr and ExecEvalExpr are concerned, several different executions
 * of the same plan tree can occur concurrently.
 *
 * This must be called in a memory context that will last as long as repeated
 * executions of the expression are needed.  Typically the context will be
 * the same as the per-query context of the associated ExprContext.
 *
3539
 * Any Aggref and SubPlan nodes found in the tree are added to the lists
Bruce Momjian's avatar
Bruce Momjian committed
3540
 * of such nodes held by the parent PlanState.	Otherwise, we do very little
3541 3542 3543 3544 3545 3546 3547 3548 3549 3550
 * initialization here other than building the state-node tree.  Any nontrivial
 * work associated with initializing runtime info for a node should happen
 * during the first actual evaluation of that node.  (This policy lets us
 * avoid work if the node is never actually evaluated.)
 *
 * Note: there is no ExecEndExpr function; we assume that any resource
 * cleanup needed will be handled by just releasing the memory context
 * in which the state tree is built.  Functions that require additional
 * cleanup work can register a shutdown callback in the ExprContext.
 *
3551
 *	'node' is the root of the expression tree to examine
3552 3553 3554 3555 3556
 *	'parent' is the PlanState node that owns the expression.
 *
 * 'parent' may be NULL if we are preparing an expression that is not
 * associated with a plan tree.  (If so, it can't have aggs or subplans.)
 * This case should usually come through ExecPrepareExpr, not directly here.
3557
 */
3558
ExprState *
3559
ExecInitExpr(Expr *node, PlanState *parent)
3560
{
3561
	ExprState  *state;
3562 3563 3564

	if (node == NULL)
		return NULL;
3565 3566 3567 3568

	/* Guard against stack overflow due to overly complex expressions */
	check_stack_depth();

3569 3570 3571
	switch (nodeTag(node))
	{
		case T_Var:
3572 3573
			state = (ExprState *) makeNode(ExprState);
			state->evalfunc = ExecEvalVar;
3574
			break;
3575
		case T_Const:
3576 3577 3578
			state = (ExprState *) makeNode(ExprState);
			state->evalfunc = ExecEvalConst;
			break;
3579
		case T_Param:
3580 3581 3582
			state = (ExprState *) makeNode(ExprState);
			state->evalfunc = ExecEvalParam;
			break;
3583
		case T_CoerceToDomainValue:
3584
			state = (ExprState *) makeNode(ExprState);
3585
			state->evalfunc = ExecEvalCoerceToDomainValue;
3586
			break;
3587 3588 3589 3590
		case T_CaseTestExpr:
			state = (ExprState *) makeNode(ExprState);
			state->evalfunc = ExecEvalCaseTestExpr;
			break;
3591 3592
		case T_Aggref:
			{
Bruce Momjian's avatar
Bruce Momjian committed
3593
				Aggref	   *aggref = (Aggref *) node;
3594
				AggrefExprState *astate = makeNode(AggrefExprState);
3595

3596
				astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalAggref;
3597 3598 3599 3600
				if (parent && IsA(parent, AggState))
				{
					AggState   *aggstate = (AggState *) parent;
					int			naggs;
3601

3602 3603
					aggstate->aggs = lcons(astate, aggstate->aggs);
					naggs = ++aggstate->numaggs;
3604

3605 3606
					astate->args = (List *) ExecInitExpr((Expr *) aggref->args,
														 parent);
3607 3608

					/*
3609
					 * Complain if the aggregate's arguments contain any
3610
					 * aggregates; nested agg functions are semantically
3611 3612
					 * nonsensical.  (This should have been caught earlier,
					 * but we defend against it here anyway.)
3613 3614
					 */
					if (naggs != aggstate->numaggs)
3615 3616
						ereport(ERROR,
								(errcode(ERRCODE_GROUPING_ERROR),
3617
								 errmsg("aggregate function calls cannot be nested")));
3618 3619
				}
				else
3620 3621 3622 3623
				{
					/* planner messed up */
					elog(ERROR, "aggref found in non-Agg plan node");
				}
3624
				state = (ExprState *) astate;
3625 3626 3627 3628 3629
			}
			break;
		case T_ArrayRef:
			{
				ArrayRef   *aref = (ArrayRef *) node;
3630 3631
				ArrayRefExprState *astate = makeNode(ArrayRefExprState);

3632
				astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalArrayRef;
3633 3634 3635 3636 3637 3638 3639
				astate->refupperindexpr = (List *)
					ExecInitExpr((Expr *) aref->refupperindexpr, parent);
				astate->reflowerindexpr = (List *)
					ExecInitExpr((Expr *) aref->reflowerindexpr, parent);
				astate->refexpr = ExecInitExpr(aref->refexpr, parent);
				astate->refassgnexpr = ExecInitExpr(aref->refassgnexpr,
													parent);
3640 3641 3642 3643 3644 3645
				/* do one-time catalog lookups for type info */
				astate->refattrlength = get_typlen(aref->refarraytype);
				get_typlenbyvalalign(aref->refelemtype,
									 &astate->refelemlength,
									 &astate->refelembyval,
									 &astate->refelemalign);
3646
				state = (ExprState *) astate;
3647 3648
			}
			break;
3649
		case T_FuncExpr:
3650
			{
3651
				FuncExpr   *funcexpr = (FuncExpr *) node;
3652
				FuncExprState *fstate = makeNode(FuncExprState);
3653

3654
				fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalFunc;
3655 3656
				fstate->args = (List *)
					ExecInitExpr((Expr *) funcexpr->args, parent);
Bruce Momjian's avatar
Bruce Momjian committed
3657
				fstate->func.fn_oid = InvalidOid;		/* not initialized */
3658
				state = (ExprState *) fstate;
3659 3660 3661 3662
			}
			break;
		case T_OpExpr:
			{
Bruce Momjian's avatar
Bruce Momjian committed
3663
				OpExpr	   *opexpr = (OpExpr *) node;
3664
				FuncExprState *fstate = makeNode(FuncExprState);
3665

3666
				fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalOper;
3667 3668
				fstate->args = (List *)
					ExecInitExpr((Expr *) opexpr->args, parent);
Bruce Momjian's avatar
Bruce Momjian committed
3669
				fstate->func.fn_oid = InvalidOid;		/* not initialized */
3670
				state = (ExprState *) fstate;
3671 3672 3673 3674
			}
			break;
		case T_DistinctExpr:
			{
Bruce Momjian's avatar
Bruce Momjian committed
3675
				DistinctExpr *distinctexpr = (DistinctExpr *) node;
3676
				FuncExprState *fstate = makeNode(FuncExprState);
3677

3678
				fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalDistinct;
3679 3680
				fstate->args = (List *)
					ExecInitExpr((Expr *) distinctexpr->args, parent);
Bruce Momjian's avatar
Bruce Momjian committed
3681
				fstate->func.fn_oid = InvalidOid;		/* not initialized */
3682
				state = (ExprState *) fstate;
3683 3684
			}
			break;
3685 3686
		case T_ScalarArrayOpExpr:
			{
Bruce Momjian's avatar
Bruce Momjian committed
3687
				ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
3688 3689
				ScalarArrayOpExprState *sstate = makeNode(ScalarArrayOpExprState);

3690
				sstate->fxprstate.xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalScalarArrayOp;
3691 3692
				sstate->fxprstate.args = (List *)
					ExecInitExpr((Expr *) opexpr->args, parent);
Bruce Momjian's avatar
Bruce Momjian committed
3693 3694
				sstate->fxprstate.func.fn_oid = InvalidOid;		/* not initialized */
				sstate->element_type = InvalidOid;		/* ditto */
3695 3696 3697
				state = (ExprState *) sstate;
			}
			break;
3698 3699 3700
		case T_BoolExpr:
			{
				BoolExpr   *boolexpr = (BoolExpr *) node;
3701
				BoolExprState *bstate = makeNode(BoolExprState);
3702

3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718
				switch (boolexpr->boolop)
				{
					case AND_EXPR:
						bstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalAnd;
						break;
					case OR_EXPR:
						bstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalOr;
						break;
					case NOT_EXPR:
						bstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalNot;
						break;
					default:
						elog(ERROR, "unrecognized boolop: %d",
							 (int) boolexpr->boolop);
						break;
				}
3719 3720 3721
				bstate->args = (List *)
					ExecInitExpr((Expr *) boolexpr->args, parent);
				state = (ExprState *) bstate;
3722 3723
			}
			break;
3724
		case T_SubPlan:
3725
			{
3726
				/* Keep this in sync with ExecInitExprInitPlan, below */
Bruce Momjian's avatar
Bruce Momjian committed
3727
				SubPlan    *subplan = (SubPlan *) node;
3728
				SubPlanState *sstate = makeNode(SubPlanState);
3729

3730 3731
				sstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecSubPlan;

3732
				if (!parent)
3733
					elog(ERROR, "SubPlan found with no parent plan");
3734 3735

				/*
3736 3737
				 * Here we just add the SubPlanState nodes to parent->subPlan.
				 * The subplans will be initialized later.
3738
				 */
3739
				parent->subPlan = lcons(sstate, parent->subPlan);
3740
				sstate->sub_estate = NULL;
3741 3742
				sstate->planstate = NULL;

3743 3744
				sstate->testexpr =
					ExecInitExpr((Expr *) subplan->testexpr, parent);
3745 3746
				sstate->args = (List *)
					ExecInitExpr((Expr *) subplan->args, parent);
3747

3748
				state = (ExprState *) sstate;
3749 3750 3751
			}
			break;
		case T_FieldSelect:
3752
			{
Bruce Momjian's avatar
Bruce Momjian committed
3753
				FieldSelect *fselect = (FieldSelect *) node;
3754
				FieldSelectState *fstate = makeNode(FieldSelectState);
3755

3756 3757 3758 3759
				fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalFieldSelect;
				fstate->arg = ExecInitExpr(fselect->arg, parent);
				fstate->argdesc = NULL;
				state = (ExprState *) fstate;
3760
			}
3761
			break;
3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773
		case T_FieldStore:
			{
				FieldStore *fstore = (FieldStore *) node;
				FieldStoreState *fstate = makeNode(FieldStoreState);

				fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalFieldStore;
				fstate->arg = ExecInitExpr(fstore->arg, parent);
				fstate->newvals = (List *) ExecInitExpr((Expr *) fstore->newvals, parent);
				fstate->argdesc = NULL;
				state = (ExprState *) fstate;
			}
			break;
3774
		case T_RelabelType:
3775
			{
Bruce Momjian's avatar
Bruce Momjian committed
3776
				RelabelType *relabel = (RelabelType *) node;
3777 3778
				GenericExprState *gstate = makeNode(GenericExprState);

3779
				gstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalRelabelType;
3780 3781 3782
				gstate->arg = ExecInitExpr(relabel->arg, parent);
				state = (ExprState *) gstate;
			}
3783 3784 3785 3786 3787 3788 3789 3790 3791 3792
			break;
		case T_ConvertRowtypeExpr:
			{
				ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
				ConvertRowtypeExprState *cstate = makeNode(ConvertRowtypeExprState);

				cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalConvertRowtype;
				cstate->arg = ExecInitExpr(convert->arg, parent);
				state = (ExprState *) cstate;
			}
3793 3794 3795 3796
			break;
		case T_CaseExpr:
			{
				CaseExpr   *caseexpr = (CaseExpr *) node;
3797
				CaseExprState *cstate = makeNode(CaseExprState);
Tom Lane's avatar
Tom Lane committed
3798
				List	   *outlist = NIL;
3799
				ListCell   *l;
3800

3801
				cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCase;
3802
				cstate->arg = ExecInitExpr(caseexpr->arg, parent);
3803
				foreach(l, caseexpr->args)
3804
				{
3805
					CaseWhen   *when = (CaseWhen *) lfirst(l);
3806
					CaseWhenState *wstate = makeNode(CaseWhenState);
3807 3808

					Assert(IsA(when, CaseWhen));
3809
					wstate->xprstate.evalfunc = NULL;	/* not used */
3810 3811 3812
					wstate->xprstate.expr = (Expr *) when;
					wstate->expr = ExecInitExpr(when->expr, parent);
					wstate->result = ExecInitExpr(when->result, parent);
Tom Lane's avatar
Tom Lane committed
3813
					outlist = lappend(outlist, wstate);
3814
				}
Tom Lane's avatar
Tom Lane committed
3815
				cstate->args = outlist;
3816 3817
				cstate->defresult = ExecInitExpr(caseexpr->defresult, parent);
				state = (ExprState *) cstate;
3818 3819
			}
			break;
3820 3821
		case T_ArrayExpr:
			{
Bruce Momjian's avatar
Bruce Momjian committed
3822
				ArrayExpr  *arrayexpr = (ArrayExpr *) node;
3823
				ArrayExprState *astate = makeNode(ArrayExprState);
Tom Lane's avatar
Tom Lane committed
3824
				List	   *outlist = NIL;
3825
				ListCell   *l;
3826

3827
				astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalArray;
3828
				foreach(l, arrayexpr->elements)
3829
				{
3830
					Expr	   *e = (Expr *) lfirst(l);
3831 3832 3833
					ExprState  *estate;

					estate = ExecInitExpr(e, parent);
Tom Lane's avatar
Tom Lane committed
3834
					outlist = lappend(outlist, estate);
3835
				}
Tom Lane's avatar
Tom Lane committed
3836
				astate->elements = outlist;
3837 3838 3839 3840 3841 3842 3843 3844
				/* do one-time catalog lookup for type info */
				get_typlenbyvalalign(arrayexpr->element_typeid,
									 &astate->elemlength,
									 &astate->elembyval,
									 &astate->elemalign);
				state = (ExprState *) astate;
			}
			break;
3845 3846
		case T_RowExpr:
			{
Bruce Momjian's avatar
Bruce Momjian committed
3847
				RowExpr    *rowexpr = (RowExpr *) node;
3848
				RowExprState *rstate = makeNode(RowExprState);
3849
				Form_pg_attribute *attrs;
Tom Lane's avatar
Tom Lane committed
3850
				List	   *outlist = NIL;
3851
				ListCell   *l;
3852
				int			i;
3853 3854 3855 3856 3857 3858 3859

				rstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalRow;
				/* Build tupdesc to describe result tuples */
				if (rowexpr->row_typeid == RECORDOID)
				{
					/* generic record, use runtime type assignment */
					rstate->tupdesc = ExecTypeFromExprList(rowexpr->args);
3860
					BlessTupleDesc(rstate->tupdesc);
3861
					/* we won't need to redo this at runtime */
3862 3863 3864 3865
				}
				else
				{
					/* it's been cast to a named type, use that */
3866
					rstate->tupdesc = lookup_rowtype_tupdesc_copy(rowexpr->row_typeid, -1);
3867
				}
3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879
				/* Set up evaluation, skipping any deleted columns */
				Assert(list_length(rowexpr->args) <= rstate->tupdesc->natts);
				attrs = rstate->tupdesc->attrs;
				i = 0;
				foreach(l, rowexpr->args)
				{
					Expr	   *e = (Expr *) lfirst(l);
					ExprState  *estate;

					if (!attrs[i]->attisdropped)
					{
						/*
3880 3881 3882 3883
						 * Guard against ALTER COLUMN TYPE on rowtype since
						 * the RowExpr was created.  XXX should we check
						 * typmod too?	Not sure we can be sure it'll be the
						 * same.
3884 3885 3886 3887 3888
						 */
						if (exprType((Node *) e) != attrs[i]->atttypid)
							ereport(ERROR,
									(errcode(ERRCODE_DATATYPE_MISMATCH),
									 errmsg("ROW() column has type %s instead of type %s",
3889 3890
										format_type_be(exprType((Node *) e)),
									   format_type_be(attrs[i]->atttypid))));
3891 3892 3893 3894
					}
					else
					{
						/*
3895 3896 3897
						 * Ignore original expression and insert a NULL. We
						 * don't really care what type of NULL it is, so
						 * always make an int4 NULL.
3898 3899 3900 3901 3902 3903 3904 3905
						 */
						e = (Expr *) makeNullConst(INT4OID);
					}
					estate = ExecInitExpr(e, parent);
					outlist = lappend(outlist, estate);
					i++;
				}
				rstate->args = outlist;
3906 3907 3908
				state = (ExprState *) rstate;
			}
			break;
3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941
		case T_RowCompareExpr:
			{
				RowCompareExpr *rcexpr = (RowCompareExpr *) node;
				RowCompareExprState *rstate = makeNode(RowCompareExprState);
				int			nopers = list_length(rcexpr->opnos);
				List	   *outlist;
				ListCell   *l;
				ListCell   *l2;
				int			i;

				rstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalRowCompare;
				Assert(list_length(rcexpr->largs) == nopers);
				outlist = NIL;
				foreach(l, rcexpr->largs)
				{
					Expr	   *e = (Expr *) lfirst(l);
					ExprState  *estate;

					estate = ExecInitExpr(e, parent);
					outlist = lappend(outlist, estate);
				}
				rstate->largs = outlist;
				Assert(list_length(rcexpr->rargs) == nopers);
				outlist = NIL;
				foreach(l, rcexpr->rargs)
				{
					Expr	   *e = (Expr *) lfirst(l);
					ExprState  *estate;

					estate = ExecInitExpr(e, parent);
					outlist = lappend(outlist, estate);
				}
				rstate->rargs = outlist;
3942
				Assert(list_length(rcexpr->opfamilies) == nopers);
3943 3944
				rstate->funcs = (FmgrInfo *) palloc(nopers * sizeof(FmgrInfo));
				i = 0;
3945
				forboth(l, rcexpr->opnos, l2, rcexpr->opfamilies)
3946
				{
Bruce Momjian's avatar
Bruce Momjian committed
3947
					Oid			opno = lfirst_oid(l);
3948
					Oid			opfamily = lfirst_oid(l2);
Bruce Momjian's avatar
Bruce Momjian committed
3949
					int			strategy;
3950 3951
					Oid			lefttype;
					Oid			righttype;
Bruce Momjian's avatar
Bruce Momjian committed
3952 3953
					bool		recheck;
					Oid			proc;
3954

3955 3956 3957 3958 3959 3960 3961 3962 3963
					get_op_opfamily_properties(opno, opfamily,
											   &strategy,
											   &lefttype,
											   &righttype,
											   &recheck);
					proc = get_opfamily_proc(opfamily,
											 lefttype,
											 righttype,
											 BTORDER_PROC);
Bruce Momjian's avatar
Bruce Momjian committed
3964

3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976
					/*
					 * If we enforced permissions checks on index support
					 * functions, we'd need to make a check here.  But the
					 * index support machinery doesn't do that, and neither
					 * does this code.
					 */
					fmgr_info(proc, &(rstate->funcs[i]));
					i++;
				}
				state = (ExprState *) rstate;
			}
			break;
3977 3978 3979 3980
		case T_CoalesceExpr:
			{
				CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
				CoalesceExprState *cstate = makeNode(CoalesceExprState);
Tom Lane's avatar
Tom Lane committed
3981
				List	   *outlist = NIL;
3982
				ListCell   *l;
3983

3984
				cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCoalesce;
3985
				foreach(l, coalesceexpr->args)
3986
				{
3987
					Expr	   *e = (Expr *) lfirst(l);
Bruce Momjian's avatar
Bruce Momjian committed
3988
					ExprState  *estate;
3989 3990

					estate = ExecInitExpr(e, parent);
Tom Lane's avatar
Tom Lane committed
3991
					outlist = lappend(outlist, estate);
3992
				}
Tom Lane's avatar
Tom Lane committed
3993
				cstate->args = outlist;
3994 3995 3996
				state = (ExprState *) cstate;
			}
			break;
3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022
		case T_MinMaxExpr:
			{
				MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
				MinMaxExprState *mstate = makeNode(MinMaxExprState);
				List	   *outlist = NIL;
				ListCell   *l;
				TypeCacheEntry *typentry;

				mstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalMinMax;
				foreach(l, minmaxexpr->args)
				{
					Expr	   *e = (Expr *) lfirst(l);
					ExprState  *estate;

					estate = ExecInitExpr(e, parent);
					outlist = lappend(outlist, estate);
				}
				mstate->args = outlist;
				/* Look up the btree comparison function for the datatype */
				typentry = lookup_type_cache(minmaxexpr->minmaxtype,
											 TYPECACHE_CMP_PROC);
				if (!OidIsValid(typentry->cmp_proc))
					ereport(ERROR,
							(errcode(ERRCODE_UNDEFINED_FUNCTION),
							 errmsg("could not identify a comparison function for type %s",
									format_type_be(minmaxexpr->minmaxtype))));
Bruce Momjian's avatar
Bruce Momjian committed
4023

4024 4025
				/*
				 * If we enforced permissions checks on index support
Bruce Momjian's avatar
Bruce Momjian committed
4026 4027 4028
				 * functions, we'd need to make a check here.  But the index
				 * support machinery doesn't do that, and neither does this
				 * code.
4029
				 */
4030 4031 4032 4033
				fmgr_info(typentry->cmp_proc, &(mstate->cfunc));
				state = (ExprState *) mstate;
			}
			break;
4034 4035 4036 4037
		case T_XmlExpr:
			{
				XmlExpr			*xexpr = (XmlExpr *) node;
				XmlExprState	*xstate = makeNode(XmlExprState);
4038 4039 4040 4041
				List			*outlist;
				ListCell		*arg;
				int				i;

4042
				xstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalXml;
4043 4044
				xstate->named_outfuncs = (FmgrInfo *)
					palloc0(list_length(xexpr->named_args) * sizeof(FmgrInfo));
4045
				outlist = NIL;
4046 4047
				i = 0;
				foreach(arg, xexpr->named_args)
4048
				{
4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060
					Expr		*e = (Expr *) lfirst(arg);
					ExprState	*estate;
					Oid			typOutFunc;
					bool		typIsVarlena;

					estate = ExecInitExpr(e, parent);
					outlist = lappend(outlist, estate);

					getTypeOutputInfo(exprType((Node *) e),
									  &typOutFunc, &typIsVarlena);
					fmgr_info(typOutFunc, &xstate->named_outfuncs[i]);
					i++;
4061 4062 4063
				}
				xstate->named_args = outlist;

4064
				outlist = NIL;
4065 4066
				foreach(arg, xexpr->args)
				{
4067 4068 4069
					Expr		*e = (Expr *) lfirst(arg);
					ExprState	*estate;

4070 4071 4072 4073
					estate = ExecInitExpr(e, parent);
					outlist = lappend(outlist, estate);
				}
				xstate->args = outlist;
4074

4075 4076 4077
				state = (ExprState *) xstate;
			}
			break;
4078 4079 4080 4081 4082
		case T_NullIfExpr:
			{
				NullIfExpr *nullifexpr = (NullIfExpr *) node;
				FuncExprState *fstate = makeNode(FuncExprState);

4083
				fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalNullIf;
4084 4085
				fstate->args = (List *)
					ExecInitExpr((Expr *) nullifexpr->args, parent);
Bruce Momjian's avatar
Bruce Momjian committed
4086
				fstate->func.fn_oid = InvalidOid;		/* not initialized */
4087 4088 4089
				state = (ExprState *) fstate;
			}
			break;
4090
		case T_NullTest:
4091 4092
			{
				NullTest   *ntest = (NullTest *) node;
4093
				NullTestState *nstate = makeNode(NullTestState);
4094

4095 4096 4097 4098 4099
				nstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalNullTest;
				nstate->arg = ExecInitExpr(ntest->arg, parent);
				nstate->argisrow = type_is_rowtype(exprType((Node *) ntest->arg));
				nstate->argdesc = NULL;
				state = (ExprState *) nstate;
4100
			}
4101 4102
			break;
		case T_BooleanTest:
4103
			{
Bruce Momjian's avatar
Bruce Momjian committed
4104
				BooleanTest *btest = (BooleanTest *) node;
4105 4106
				GenericExprState *gstate = makeNode(GenericExprState);

4107
				gstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalBooleanTest;
4108 4109 4110
				gstate->arg = ExecInitExpr(btest->arg, parent);
				state = (ExprState *) gstate;
			}
4111
			break;
4112
		case T_CoerceToDomain:
4113
			{
Bruce Momjian's avatar
Bruce Momjian committed
4114
				CoerceToDomain *ctest = (CoerceToDomain *) node;
4115
				CoerceToDomainState *cstate = makeNode(CoerceToDomainState);
4116

4117
				cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCoerceToDomain;
4118
				cstate->arg = ExecInitExpr(ctest->arg, parent);
4119
				cstate->constraints = GetDomainConstraints(ctest->resulttype);
4120 4121
				state = (ExprState *) cstate;
			}
4122
			break;
4123
		case T_TargetEntry:
4124
			{
Bruce Momjian's avatar
Bruce Momjian committed
4125
				TargetEntry *tle = (TargetEntry *) node;
4126 4127
				GenericExprState *gstate = makeNode(GenericExprState);

Bruce Momjian's avatar
Bruce Momjian committed
4128
				gstate->xprstate.evalfunc = NULL;		/* not used */
4129 4130 4131
				gstate->arg = ExecInitExpr(tle->expr, parent);
				state = (ExprState *) gstate;
			}
4132
			break;
4133 4134
		case T_List:
			{
Tom Lane's avatar
Tom Lane committed
4135
				List	   *outlist = NIL;
4136
				ListCell   *l;
4137

4138
				foreach(l, (List *) node)
4139
				{
Tom Lane's avatar
Tom Lane committed
4140 4141 4142
					outlist = lappend(outlist,
									  ExecInitExpr((Expr *) lfirst(l),
												   parent));
4143 4144
				}
				/* Don't fall through to the "common" code below */
Tom Lane's avatar
Tom Lane committed
4145
				return (ExprState *) outlist;
4146 4147
			}
		default:
4148 4149
			elog(ERROR, "unrecognized node type: %d",
				 (int) nodeTag(node));
4150
			state = NULL;		/* keep compiler quiet */
4151 4152 4153
			break;
	}

4154 4155 4156 4157 4158 4159 4160 4161
	/* Common code for all state-node types */
	state->expr = node;

	return state;
}

/*
 * ExecInitExprInitPlan --- initialize a subplan expr that's being handled
Bruce Momjian's avatar
Bruce Momjian committed
4162
 * as an InitPlan.	This is identical to ExecInitExpr's handling of a regular
4163 4164 4165
 * subplan expr, except we do NOT want to add the node to the parent's
 * subplan list.
 */
4166
SubPlanState *
4167
ExecInitExprInitPlan(SubPlan *node, PlanState *parent)
4168
{
4169
	SubPlanState *sstate = makeNode(SubPlanState);
4170 4171

	if (!parent)
4172
		elog(ERROR, "SubPlan found with no parent plan");
4173 4174

	/* The subplan's state will be initialized later */
4175
	sstate->sub_estate = NULL;
4176 4177
	sstate->planstate = NULL;

4178
	sstate->testexpr = ExecInitExpr((Expr *) node->testexpr, parent);
4179 4180 4181 4182 4183
	sstate->args = (List *) ExecInitExpr((Expr *) node->args, parent);

	sstate->xprstate.expr = (Expr *) node;

	return sstate;
4184 4185
}

4186 4187 4188 4189 4190 4191 4192
/*
 * ExecPrepareExpr --- initialize for expression execution outside a normal
 * Plan tree context.
 *
 * This differs from ExecInitExpr in that we don't assume the caller is
 * already running in the EState's per-query context.  Also, we apply
 * fix_opfuncids() to the passed expression tree to be sure it is ready
Bruce Momjian's avatar
Bruce Momjian committed
4193
 * to run.	(In ordinary Plan trees the planner will have fixed opfuncids,
4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212
 * but callers outside the executor will not have done this.)
 */
ExprState *
ExecPrepareExpr(Expr *node, EState *estate)
{
	ExprState  *result;
	MemoryContext oldcontext;

	fix_opfuncids((Node *) node);

	oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);

	result = ExecInitExpr(node, NULL);

	MemoryContextSwitchTo(oldcontext);

	return result;
}

4213

4214
/* ----------------------------------------------------------------
4215
 *					 ExecQual / ExecTargetList / ExecProject
4216 4217 4218 4219
 * ----------------------------------------------------------------
 */

/* ----------------------------------------------------------------
4220 4221
 *		ExecQual
 *
4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244
 *		Evaluates a conjunctive boolean expression (qual list) and
 *		returns true iff none of the subexpressions are false.
 *		(We also return true if the list is empty.)
 *
 *	If some of the subexpressions yield NULL but none yield FALSE,
 *	then the result of the conjunction is NULL (ie, unknown)
 *	according to three-valued boolean logic.  In this case,
 *	we return the value specified by the "resultForNull" parameter.
 *
 *	Callers evaluating WHERE clauses should pass resultForNull=FALSE,
 *	since SQL specifies that tuples with null WHERE results do not
 *	get selected.  On the other hand, callers evaluating constraint
 *	conditions should pass resultForNull=TRUE, since SQL also specifies
 *	that NULL constraint conditions are not failures.
 *
 *	NOTE: it would not be correct to use this routine to evaluate an
 *	AND subclause of a boolean expression; for that purpose, a NULL
 *	result must be returned as NULL so that it can be properly treated
 *	in the next higher operator (cf. ExecEvalAnd and ExecEvalOr).
 *	This routine is only used in contexts where a complete expression
 *	is being evaluated and we know that NULL can be treated the same
 *	as one boolean result or the other.
 *
4245 4246 4247
 * ----------------------------------------------------------------
 */
bool
4248
ExecQual(List *qual, ExprContext *econtext, bool resultForNull)
4249
{
4250 4251
	bool		result;
	MemoryContext oldContext;
4252
	ListCell   *l;
4253

Bruce Momjian's avatar
Bruce Momjian committed
4254
	/*
Bruce Momjian's avatar
Bruce Momjian committed
4255
	 * debugging stuff
4256 4257 4258 4259 4260 4261 4262
	 */
	EV_printf("ExecQual: qual is ");
	EV_nodeDisplay(qual);
	EV_printf("\n");

	IncrProcessed();

4263 4264 4265 4266 4267
	/*
	 * Run in short-lived per-tuple context while computing expressions.
	 */
	oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);

Bruce Momjian's avatar
Bruce Momjian committed
4268
	/*
4269 4270 4271 4272 4273
	 * Evaluate the qual conditions one at a time.	If we find a FALSE result,
	 * we can stop evaluating and return FALSE --- the AND result must be
	 * FALSE.  Also, if we find a NULL result when resultForNull is FALSE, we
	 * can stop and return FALSE --- the AND result must be FALSE or NULL in
	 * that case, and the caller doesn't care which.
4274
	 *
4275 4276 4277 4278
	 * If we get to the end of the list, we can return TRUE.  This will happen
	 * when the AND result is indeed TRUE, or when the AND result is NULL (one
	 * or more NULL subresult, with all the rest TRUE) and the caller has
	 * specified resultForNull = TRUE.
4279
	 */
4280
	result = true;
4281

4282
	foreach(l, qual)
4283
	{
4284
		ExprState  *clause = (ExprState *) lfirst(l);
4285 4286 4287
		Datum		expr_value;
		bool		isNull;

4288
		expr_value = ExecEvalExpr(clause, econtext, &isNull, NULL);
4289

4290
		if (isNull)
4291 4292
		{
			if (resultForNull == false)
4293
			{
4294
				result = false; /* treat NULL as FALSE */
4295 4296
				break;
			}
4297 4298 4299
		}
		else
		{
4300
			if (!DatumGetBool(expr_value))
4301
			{
4302
				result = false; /* definitely FALSE */
4303 4304
				break;
			}
4305
		}
4306 4307
	}

4308 4309 4310
	MemoryContextSwitchTo(oldContext);

	return result;
4311 4312
}

4313 4314 4315
/*
 * Number of items in a tlist (including any resjunk items!)
 */
4316
int
4317
ExecTargetListLength(List *targetlist)
4318
{
4319
	/* This used to be more complex, but fjoins are dead */
4320
	return list_length(targetlist);
4321 4322
}

4323 4324 4325 4326 4327 4328 4329
/*
 * Number of items in a tlist, not including any resjunk items
 */
int
ExecCleanTargetListLength(List *targetlist)
{
	int			len = 0;
4330
	ListCell   *tl;
4331 4332 4333

	foreach(tl, targetlist)
	{
4334
		TargetEntry *curTle = (TargetEntry *) lfirst(tl);
4335

4336
		Assert(IsA(curTle, TargetEntry));
4337
		if (!curTle->resjunk)
4338
			len++;
4339 4340 4341 4342
	}
	return len;
}

4343 4344
/*
 * ExecTargetList
4345
 *		Evaluates a targetlist with respect to the given
4346 4347
 *		expression context.  Returns TRUE if we were able to create
 *		a result, FALSE if we have exhausted a set-valued expression.
4348
 *
4349 4350
 * Results are stored into the passed values and isnull arrays.
 * The caller must provide an itemIsDone array that persists across calls.
4351 4352 4353 4354 4355
 *
 * As with ExecEvalExpr, the caller should pass isDone = NULL if not
 * prepared to deal with sets of result tuples.  Otherwise, a return
 * of *isDone = ExprMultipleResult signifies a set element, and a return
 * of *isDone = ExprEndResult signifies end of the set of tuple.
4356
 */
4357
static bool
4358 4359
ExecTargetList(List *targetlist,
			   ExprContext *econtext,
4360
			   Datum *values,
4361
			   bool *isnull,
4362
			   ExprDoneCond *itemIsDone,
4363
			   ExprDoneCond *isDone)
4364
{
4365
	MemoryContext oldContext;
4366
	ListCell   *tl;
4367
	bool		haveDoneSets;
4368

4369 4370 4371 4372 4373
	/*
	 * Run in short-lived per-tuple context while computing expressions.
	 */
	oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);

Bruce Momjian's avatar
Bruce Momjian committed
4374
	/*
Bruce Momjian's avatar
Bruce Momjian committed
4375
	 * evaluate all the expressions in the target list
4376
	 */
4377
	if (isDone)
4378
		*isDone = ExprSingleResult;		/* until proven otherwise */
4379 4380

	haveDoneSets = false;		/* any exhausted set exprs in tlist? */
4381

4382 4383
	foreach(tl, targetlist)
	{
4384 4385
		GenericExprState *gstate = (GenericExprState *) lfirst(tl);
		TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
4386
		AttrNumber	resind = tle->resno - 1;
4387

4388
		values[resind] = ExecEvalExpr(gstate->arg,
4389
									  econtext,
4390
									  &isnull[resind],
4391
									  &itemIsDone[resind]);
4392

4393
		if (itemIsDone[resind] != ExprSingleResult)
4394
		{
4395 4396
			/* We have a set-valued expression in the tlist */
			if (isDone == NULL)
4397
				ereport(ERROR,
4398
						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4399
						 errmsg("set-valued function called in context that cannot accept a set")));
4400
			if (itemIsDone[resind] == ExprMultipleResult)
4401
			{
4402 4403
				/* we have undone sets in the tlist, set flag */
				*isDone = ExprMultipleResult;
4404
			}
4405
			else
4406
			{
4407 4408
				/* we have done sets in the tlist, set flag for that */
				haveDoneSets = true;
4409
			}
4410 4411
		}
	}
4412

4413
	if (haveDoneSets)
4414
	{
4415 4416 4417 4418
		/*
		 * note: can't get here unless we verified isDone != NULL
		 */
		if (*isDone == ExprSingleResult)
4419
		{
4420
			/*
4421
			 * all sets are done, so report that tlist expansion is complete.
4422
			 */
4423 4424
			*isDone = ExprEndResult;
			MemoryContextSwitchTo(oldContext);
4425
			return false;
4426 4427 4428
		}
		else
		{
4429
			/*
4430 4431
			 * We have some done and some undone sets.	Restart the done ones
			 * so that we can deliver a tuple (if possible).
4432 4433 4434
			 */
			foreach(tl, targetlist)
			{
4435 4436
				GenericExprState *gstate = (GenericExprState *) lfirst(tl);
				TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
4437
				AttrNumber	resind = tle->resno - 1;
4438

4439
				if (itemIsDone[resind] == ExprEndResult)
4440
				{
4441 4442
					values[resind] = ExecEvalExpr(gstate->arg,
												  econtext,
4443
												  &isnull[resind],
4444
												  &itemIsDone[resind]);
4445

4446
					if (itemIsDone[resind] == ExprEndResult)
4447
					{
4448
						/*
4449 4450
						 * Oh dear, this item is returning an empty set. Guess
						 * we can't make a tuple after all.
4451 4452 4453
						 */
						*isDone = ExprEndResult;
						break;
4454 4455 4456
					}
				}
			}
4457

4458
			/*
4459 4460 4461
			 * If we cannot make a tuple because some sets are empty, we still
			 * have to cycle the nonempty sets to completion, else resources
			 * will not be released from subplans etc.
4462 4463
			 *
			 * XXX is that still necessary?
4464 4465 4466 4467 4468
			 */
			if (*isDone == ExprEndResult)
			{
				foreach(tl, targetlist)
				{
4469 4470
					GenericExprState *gstate = (GenericExprState *) lfirst(tl);
					TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
4471
					AttrNumber	resind = tle->resno - 1;
4472

4473
					while (itemIsDone[resind] == ExprMultipleResult)
4474
					{
4475 4476 4477 4478
						values[resind] = ExecEvalExpr(gstate->arg,
													  econtext,
													  &isnull[resind],
													  &itemIsDone[resind]);
4479 4480
					}
				}
4481 4482

				MemoryContextSwitchTo(oldContext);
4483
				return false;
4484 4485 4486 4487
			}
		}
	}

4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509
	/* Report success */
	MemoryContextSwitchTo(oldContext);

	return true;
}

/*
 * ExecVariableList
 *		Evaluates a simple-Variable-list projection.
 *
 * Results are stored into the passed values and isnull arrays.
 */
static void
ExecVariableList(ProjectionInfo *projInfo,
				 Datum *values,
				 bool *isnull)
{
	ExprContext *econtext = projInfo->pi_exprContext;
	int		   *varSlotOffsets = projInfo->pi_varSlotOffsets;
	int		   *varNumbers = projInfo->pi_varNumbers;
	int			i;

Bruce Momjian's avatar
Bruce Momjian committed
4510
	/*
4511
	 * Force extraction of all input values that we need.
4512
	 */
4513 4514 4515 4516 4517 4518 4519 4520 4521
	if (projInfo->pi_lastInnerVar > 0)
		slot_getsomeattrs(econtext->ecxt_innertuple,
						  projInfo->pi_lastInnerVar);
	if (projInfo->pi_lastOuterVar > 0)
		slot_getsomeattrs(econtext->ecxt_outertuple,
						  projInfo->pi_lastOuterVar);
	if (projInfo->pi_lastScanVar > 0)
		slot_getsomeattrs(econtext->ecxt_scantuple,
						  projInfo->pi_lastScanVar);
4522

4523
	/*
4524 4525
	 * Assign to result by direct extraction of fields from source slots ... a
	 * mite ugly, but fast ...
4526 4527 4528 4529 4530 4531 4532 4533 4534 4535
	 */
	for (i = list_length(projInfo->pi_targetlist) - 1; i >= 0; i--)
	{
		char	   *slotptr = ((char *) econtext) + varSlotOffsets[i];
		TupleTableSlot *varSlot = *((TupleTableSlot **) slotptr);
		int			varNumber = varNumbers[i] - 1;

		values[i] = varSlot->tts_values[varNumber];
		isnull[i] = varSlot->tts_isnull[varNumber];
	}
4536 4537
}

4538 4539
/*
 * ExecProject
4540
 *
4541
 *		projects a tuple based on projection info and stores
4542 4543 4544 4545 4546 4547 4548 4549
 *		it in the previously specified tuple table slot.
 *
 *		Note: the result is always a virtual tuple; therefore it
 *		may reference the contents of the exprContext's scan tuples
 *		and/or temporary results constructed in the exprContext.
 *		If the caller wishes the result to be valid longer than that
 *		data will be valid, he must call ExecMaterializeSlot on the
 *		result slot.
4550 4551
 */
TupleTableSlot *
4552
ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
4553
{
4554 4555
	TupleTableSlot *slot;

Bruce Momjian's avatar
Bruce Momjian committed
4556
	/*
Bruce Momjian's avatar
Bruce Momjian committed
4557
	 * sanity checks
4558
	 */
4559
	Assert(projInfo != NULL);
4560

Bruce Momjian's avatar
Bruce Momjian committed
4561
	/*
Bruce Momjian's avatar
Bruce Momjian committed
4562
	 * get the projection info we want
4563 4564 4565
	 */
	slot = projInfo->pi_slot;

Bruce Momjian's avatar
Bruce Momjian committed
4566
	/*
4567 4568 4569
	 * Clear any former contents of the result slot.  This makes it safe for
	 * us to use the slot's Datum/isnull arrays as workspace. (Also, we can
	 * return the slot as-is if we decide no rows can be projected.)
4570
	 */
4571
	ExecClearTuple(slot);
4572

Bruce Momjian's avatar
Bruce Momjian committed
4573
	/*
4574 4575
	 * form a new result tuple (if possible); if successful, mark the result
	 * slot as containing a valid virtual tuple
4576
	 */
4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598
	if (projInfo->pi_isVarList)
	{
		/* simple Var list: this always succeeds with one result row */
		if (isDone)
			*isDone = ExprSingleResult;
		ExecVariableList(projInfo,
						 slot->tts_values,
						 slot->tts_isnull);
		ExecStoreVirtualTuple(slot);
	}
	else
	{
		if (ExecTargetList(projInfo->pi_targetlist,
						   projInfo->pi_exprContext,
						   slot->tts_values,
						   slot->tts_isnull,
						   projInfo->pi_itemIsDone,
						   isDone))
			ExecStoreVirtualTuple(slot);
	}

	return slot;
4599
}