execQual.c 78.3 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * execQual.c
4
 *	  Routines to evaluate qualification and targetlist expressions
5
 *
B
Bruce Momjian 已提交
6
 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
B
Add:  
Bruce Momjian 已提交
7
 * Portions Copyright (c) 1994, Regents of the University of California
8 9 10
 *
 *
 * IDENTIFICATION
11
 *	  $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.128 2003/04/08 23:20:00 tgl Exp $
12 13 14 15
 *
 *-------------------------------------------------------------------------
 */
/*
16 17
 *	 INTERFACE ROUTINES
 *		ExecEvalExpr	- evaluate an expression and 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 23 24
 *	 NOTES
 *		ExecEvalExpr() and ExecEvalVar() are hotspots.	making these faster
 *		will speed up the entire system.  Unfortunately they are currently
T
Thomas G. Lockhart 已提交
25
 *		implemented recursively.  Eliminating the recursion is bound to
26
 *		improve the speed of the executor.
27
 *
28
 *		ExecProject() is used to make tuple projections.  Rather then
29 30 31
 *		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
32 33
 *
 */
34

35
#include "postgres.h"
36

B
Bruce Momjian 已提交
37
#include "access/heapam.h"
38
#include "catalog/pg_type.h"
39
#include "commands/typecmds.h"
40
#include "executor/execdebug.h"
41
#include "executor/functions.h"
V
Vadim B. Mikheev 已提交
42
#include "executor/nodeSubplan.h"
43
#include "miscadmin.h"
44
#include "optimizer/planmain.h"
45
#include "parser/parse_expr.h"
46
#include "utils/acl.h"
47
#include "utils/array.h"
48
#include "utils/builtins.h"
49
#include "utils/lsyscache.h"
B
Bruce Momjian 已提交
50

51

52
/* static function decls */
53 54 55 56 57 58
static Datum ExecEvalAggref(AggrefExprState *aggref,
							ExprContext *econtext,
							bool *isNull);
static Datum ExecEvalArrayRef(ArrayRefExprState *astate,
							  ExprContext *econtext,
							  bool *isNull, ExprDoneCond *isDone);
59
static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull);
60 61 62
static Datum ExecEvalParam(Param *expression, ExprContext *econtext,
						   bool *isNull);
static Datum ExecEvalFunc(FuncExprState *fcache, ExprContext *econtext,
B
Bruce Momjian 已提交
63
			 bool *isNull, ExprDoneCond *isDone);
64
static Datum ExecEvalOper(FuncExprState *fcache, ExprContext *econtext,
B
Bruce Momjian 已提交
65
			 bool *isNull, ExprDoneCond *isDone);
66
static Datum ExecEvalDistinct(FuncExprState *fcache, ExprContext *econtext,
67
				 bool *isNull);
68 69
static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo,
				 List *argList, ExprContext *econtext);
70
static Datum ExecEvalNot(BoolExprState *notclause, ExprContext *econtext,
71
						 bool *isNull);
72
static Datum ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,
73
						bool *isNull);
74
static Datum ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
75
						 bool *isNull);
76
static Datum ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
B
Bruce Momjian 已提交
77
			 bool *isNull, ExprDoneCond *isDone);
78 79 80
static Datum ExecEvalArray(ArrayExprState *astate,
						   ExprContext *econtext,
						   bool *isNull);
81 82 83 84 85
static Datum ExecEvalCoalesce(CoalesceExprState *coalesceExpr,
							  ExprContext *econtext,
							  bool *isNull);
static Datum ExecEvalNullIf(FuncExprState *nullIfExpr, ExprContext *econtext,
							bool *isNull);
86 87 88 89 90 91
static Datum ExecEvalNullTest(GenericExprState *nstate,
							  ExprContext *econtext,
							  bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalBooleanTest(GenericExprState *bstate,
								 ExprContext *econtext,
								 bool *isNull, ExprDoneCond *isDone);
92
static Datum ExecEvalCoerceToDomain(CoerceToDomainState *cstate,
B
Bruce Momjian 已提交
93 94
					   ExprContext *econtext,
					   bool *isNull, ExprDoneCond *isDone);
95
static Datum ExecEvalCoerceToDomainValue(CoerceToDomainValue *conVal,
96
					   ExprContext *econtext, bool *isNull);
97 98 99
static Datum ExecEvalFieldSelect(GenericExprState *fstate,
								 ExprContext *econtext,
								 bool *isNull, ExprDoneCond *isDone);
100

101

102
/*----------
103
 *	  ExecEvalArrayRef
104
 *
105 106
 *	   This function takes an ArrayRef and returns the extracted Datum
 *	   if it's a simple reference, or the modified array value if it's
107 108 109 110 111 112 113 114
 *	   an array assignment (i.e., array element or slice insertion).
 *
 * NOTE: if we get a NULL result from a subexpression, we return NULL when
 * it's an array reference, or the unmodified source array when it's an
 * array assignment.  This may seem peculiar, but if we return NULL (as was
 * done in versions up through 7.0) then an assignment like
 *			UPDATE table SET arrayfield[4] = NULL
 * will result in setting the whole array to NULL, which is certainly not
B
Bruce Momjian 已提交
115
 * very desirable.	By returning the source array we make the assignment
116 117 118
 * into a no-op, instead.  (Eventually we need to redesign arrays so that
 * individual elements can be NULL, but for now, let's try to protect users
 * from shooting themselves in the foot.)
119 120 121 122 123 124
 *
 * 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).
125
 *----------
B
Bruce Momjian 已提交
126
 */
127
static Datum
128
ExecEvalArrayRef(ArrayRefExprState *astate,
129 130
				 ExprContext *econtext,
				 bool *isNull,
131
				 ExprDoneCond *isDone)
132
{
133
	ArrayRef   *arrayRef = (ArrayRef *) astate->xprstate.expr;
134 135
	ArrayType  *array_source;
	ArrayType  *resultArray;
136
	bool		isAssignment = (arrayRef->refassgnexpr != NULL);
137
	List	   *elt;
138 139
	int			i = 0,
				j = 0;
140 141 142
	IntArray	upper,
				lower;
	int		   *lIndex;
143

144 145
	if (arrayRef->refexpr != NULL)
	{
146
		array_source = (ArrayType *)
147
			DatumGetPointer(ExecEvalExpr(astate->refexpr,
148 149 150
										 econtext,
										 isNull,
										 isDone));
B
Bruce Momjian 已提交
151

152 153
		/*
		 * If refexpr yields NULL, result is always NULL, for now anyway.
B
Bruce Momjian 已提交
154 155
		 * (This means you cannot assign to an element or slice of an
		 * array that's NULL; it'll just stay NULL.)
156
		 */
157 158 159 160 161
		if (*isNull)
			return (Datum) NULL;
	}
	else
	{
162
		/*
163
		 * Empty refexpr indicates we are doing an INSERT into an array
164 165 166 167 168
		 * column. For now, we just take the refassgnexpr (which the
		 * parser will have ensured is an array value) and return it
		 * as-is, ignoring any subscripts that may have been supplied in
		 * the INSERT column list. This is a kluge, but it's not real
		 * clear what the semantics ought to be...
169
		 */
170
		array_source = NULL;
171
	}
172

173
	foreach(elt, astate->refupperindexpr)
174
	{
175 176 177 178
		if (i >= MAXDIM)
			elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
				 MAXDIM);

179
		upper.indx[i++] = DatumGetInt32(ExecEvalExpr((ExprState *) lfirst(elt),
180 181
													 econtext,
													 isNull,
182
													 NULL));
183
		/* If any index expr yields NULL, result is NULL or source array */
184
		if (*isNull)
185
		{
B
Bruce Momjian 已提交
186
			if (!isAssignment || array_source == NULL)
187 188 189 190
				return (Datum) NULL;
			*isNull = false;
			return PointerGetDatum(array_source);
		}
191 192
	}

193
	if (astate->reflowerindexpr != NIL)
194
	{
195
		foreach(elt, astate->reflowerindexpr)
196
		{
197 198 199 200
			if (j >= MAXDIM)
				elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
					 MAXDIM);

201
			lower.indx[j++] = DatumGetInt32(ExecEvalExpr((ExprState *) lfirst(elt),
202 203
														 econtext,
														 isNull,
204
														 NULL));
B
Bruce Momjian 已提交
205 206 207 208 209

			/*
			 * If any index expr yields NULL, result is NULL or source
			 * array
			 */
210
			if (*isNull)
211
			{
B
Bruce Momjian 已提交
212
				if (!isAssignment || array_source == NULL)
213 214 215 216
					return (Datum) NULL;
				*isNull = false;
				return PointerGetDatum(array_source);
			}
217 218
		}
		if (i != j)
219
			elog(ERROR,
220 221
				 "ExecEvalArrayRef: upper and lower indices mismatch");
		lIndex = lower.indx;
222
	}
223 224
	else
		lIndex = NULL;
225

226
	if (isAssignment)
227
	{
228
		Datum		sourceData = ExecEvalExpr(astate->refassgnexpr,
229 230
											  econtext,
											  isNull,
231
											  NULL);
B
Bruce Momjian 已提交
232

233
		/*
B
Bruce Momjian 已提交
234 235
		 * For now, can't cope with inserting NULL into an array, so make
		 * it a no-op per discussion above...
236
		 */
237
		if (*isNull)
238 239 240 241 242 243
		{
			if (array_source == NULL)
				return (Datum) NULL;
			*isNull = false;
			return PointerGetDatum(array_source);
		}
244

245
		if (array_source == NULL)
B
Bruce Momjian 已提交
246
			return sourceData;	/* XXX do something else? */
247

248
		if (lIndex == NULL)
249 250 251
			resultArray = array_set(array_source, i,
									upper.indx,
									sourceData,
252 253 254 255
									astate->refattrlength,
									astate->refelemlength,
									astate->refelembyval,
									astate->refelemalign,
256 257 258 259
									isNull);
		else
			resultArray = array_set_slice(array_source, i,
										  upper.indx, lower.indx,
B
Bruce Momjian 已提交
260
							   (ArrayType *) DatumGetPointer(sourceData),
261 262 263 264
										  astate->refattrlength,
										  astate->refelemlength,
										  astate->refelembyval,
										  astate->refelemalign,
265 266
										  isNull);
		return PointerGetDatum(resultArray);
267
	}
268

269
	if (lIndex == NULL)
270
		return array_ref(array_source, i, upper.indx,
271 272 273 274
						 astate->refattrlength,
						 astate->refelemlength,
						 astate->refelembyval,
						 astate->refelemalign,
275
						 isNull);
276 277 278
	else
	{
		resultArray = array_get_slice(array_source, i,
279
									  upper.indx, lower.indx,
280 281 282 283
									  astate->refattrlength,
									  astate->refelemlength,
									  astate->refelembyval,
									  astate->refelemalign,
284 285 286
									  isNull);
		return PointerGetDatum(resultArray);
	}
287 288 289 290
}


/* ----------------------------------------------------------------
B
Bruce Momjian 已提交
291
 *		ExecEvalAggref
292 293 294
 *
 *		Returns a Datum whose value is the value of the precomputed
 *		aggregate found in the given expression context.
295 296
 * ----------------------------------------------------------------
 */
297
static Datum
298
ExecEvalAggref(AggrefExprState *aggref, ExprContext *econtext, bool *isNull)
299
{
300
	if (econtext->ecxt_aggvalues == NULL)		/* safety check */
301 302
		elog(ERROR, "ExecEvalAggref: no aggregates in this expression context");

303 304
	*isNull = econtext->ecxt_aggnulls[aggref->aggno];
	return econtext->ecxt_aggvalues[aggref->aggno];
305 306 307
}

/* ----------------------------------------------------------------
308 309 310 311 312 313
 *		ExecEvalVar
 *
 *		Returns a Datum whose value is the value of a range
 *		variable with respect to given expression context.
 *
 *
T
Thomas G. Lockhart 已提交
314
 *		As an entry condition, we expect that the datatype the
315 316 317 318 319 320 321 322 323 324 325
 *		plan expects to get (as told by our "variable" argument) is in
 *		fact the datatype of the attribute the plan says to fetch (as
 *		seen in the current context, identified by our "econtext"
 *		argument).
 *
 *		If we fetch a Type A attribute and Caller treats it as if it
 *		were Type B, there will be undefined results (e.g. crash).
 *		One way these might mismatch now is that we're accessing a
 *		catalog class and the type information in the pg_attribute
 *		class does not match the hardcoded pg_attribute information
 *		(in pg_attribute.h) for the class in question.
326
 *
327
 *		We have an Assert to make sure this entry condition is met.
328 329
 *
 * ---------------------------------------------------------------- */
330
static Datum
331
ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull)
332
{
333
	Datum		result;
334
	TupleTableSlot *slot;
335 336 337
	AttrNumber	attnum;
	HeapTuple	heapTuple;
	TupleDesc	tuple_type;
338

B
Bruce Momjian 已提交
339
	/*
B
Bruce Momjian 已提交
340
	 * get the slot we want
341 342 343
	 */
	switch (variable->varno)
	{
344 345 346
		case INNER:				/* get the tuple from the inner node */
			slot = econtext->ecxt_innertuple;
			break;
347

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

352
		default:				/* get the tuple from the relation being
353
								 * scanned */
354 355
			slot = econtext->ecxt_scantuple;
			break;
356 357
	}

B
Bruce Momjian 已提交
358
	/*
B
Bruce Momjian 已提交
359
	 * extract tuple information from the slot
360 361 362 363 364 365 366 367 368 369
	 */
	heapTuple = slot->val;
	tuple_type = slot->ttc_tupleDescriptor;

	attnum = variable->varattno;

	/* (See prolog for explanation of this Assert) */
	Assert(attnum <= 0 ||
		   (attnum - 1 <= tuple_type->natts - 1 &&
			tuple_type->attrs[attnum - 1] != NULL &&
370
		  variable->vartype == tuple_type->attrs[attnum - 1]->atttypid));
371 372 373

	/*
	 * If the attribute number is invalid, then we are supposed to return
374 375 376
	 * the entire tuple; we give back a whole slot so that callers know
	 * what the tuple looks like.
	 *
377 378 379
	 * XXX this is a horrid crock: since the pointer to the slot might live
	 * longer than the current evaluation context, we are forced to copy
	 * the tuple and slot into a long-lived context --- we use
380 381 382 383 384 385 386
	 * TransactionCommandContext which should be safe enough.  This
	 * represents a serious memory leak if many such tuples are processed
	 * in one command, however.  We ought to redesign the representation
	 * of whole-tuple datums so that this is not necessary.
	 *
	 * We assume it's OK to point to the existing tupleDescriptor, rather
	 * than copy that too.
387
	 */
388
	if (attnum == InvalidAttrNumber)
389
	{
390 391
		MemoryContext oldContext;
		TupleTableSlot *tempSlot;
392
		HeapTuple	tup;
393

394 395
		oldContext = MemoryContextSwitchTo(TransactionCommandContext);
		tempSlot = MakeTupleTableSlot();
396
		tup = heap_copytuple(heapTuple);
397
		ExecStoreTuple(tup, tempSlot, InvalidBuffer, true);
398 399
		ExecSetSlotDescriptor(tempSlot, tuple_type, false);
		MemoryContextSwitchTo(oldContext);
400
		return PointerGetDatum(tempSlot);
401
	}
402

403 404 405 406 407
	result = heap_getattr(heapTuple,	/* tuple containing attribute */
						  attnum,		/* attribute number of desired
										 * attribute */
						  tuple_type,	/* tuple descriptor of tuple */
						  isNull);		/* return: is attribute null? */
408 409

	return result;
410 411 412
}

/* ----------------------------------------------------------------
413
 *		ExecEvalParam
414
 *
415 416 417
 *		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)...
418
 *		so our job is to find and return the appropriate datum ("sam").
419
 *
420 421 422
 *		Q: if we have a parameter ($.foo) without a binding, i.e.
 *		   there is no (foo = xxx) in the parameter list info,
 *		   is this a fatal error or should this be a "not available"
423
 *		   (in which case we could return NULL)?	-cim 10/13/89
424 425
 * ----------------------------------------------------------------
 */
426
static Datum
427
ExecEvalParam(Param *expression, ExprContext *econtext, bool *isNull)
428
{
429 430
	int			thisParamKind = expression->paramkind;
	AttrNumber	thisParamId = expression->paramid;
431

432
	if (thisParamKind == PARAM_EXEC)
V
Vadim B. Mikheev 已提交
433
	{
434 435 436 437
		/*
		 * PARAM_EXEC params (internal executor parameters) are stored in
		 * the ecxt_param_exec_vals array, and can be accessed by array index.
		 */
438
		ParamExecData *prm;
439

440
		prm = &(econtext->ecxt_param_exec_vals[thisParamId]);
441
		if (prm->execPlan != NULL)
442
		{
443
			/* Parameter not evaluated yet, so go do it */
444 445 446 447
			ExecSetParamPlan(prm->execPlan, econtext);
			/* ExecSetParamPlan should have processed this param... */
			Assert(prm->execPlan == NULL);
		}
V
Vadim B. Mikheev 已提交
448
		*isNull = prm->isnull;
449
		return prm->value;
V
Vadim B. Mikheev 已提交
450
	}
451
	else
452 453
	{
		/*
454 455 456
		 * All other parameter types must be sought in ecxt_param_list_info.
		 * NOTE: The last entry in the param array is always an
		 * entry with kind == PARAM_INVALID.
457
		 */
458 459 460 461 462
		ParamListInfo paramList = econtext->ecxt_param_list_info;
		char	   *thisParamName = expression->paramname;
		bool		matchFound = false;

		if (paramList != NULL)
463
		{
464
			while (paramList->kind != PARAM_INVALID && !matchFound)
465
			{
466 467 468
				if (thisParamKind == paramList->kind)
				{
					switch (thisParamKind)
469
					{
470 471 472 473 474 475 476 477 478 479 480
						case PARAM_NAMED:
							if (strcmp(paramList->name, thisParamName) == 0)
								matchFound = true;
							break;
						case PARAM_NUM:
							if (paramList->id == thisParamId)
								matchFound = true;
							break;
						default:
							elog(ERROR, "ExecEvalParam: invalid paramkind %d",
								 thisParamKind);
481
					}
482 483 484 485 486
				}
				if (!matchFound)
					paramList++;
			} /* while */
		} /* if */
487

488 489 490 491 492 493 494 495 496
		if (!matchFound)
		{
			if (thisParamKind == PARAM_NAMED)
				elog(ERROR, "ExecEvalParam: Unknown value for parameter %s",
					 thisParamName);
			else
				elog(ERROR, "ExecEvalParam: Unknown value for parameter %d",
					 thisParamId);
		}
497

498 499 500
		*isNull = paramList->isnull;
		return paramList->value;
	}
501 502 503 504
}


/* ----------------------------------------------------------------
505
 *		ExecEvalOper / ExecEvalFunc support routines
506 507 508
 * ----------------------------------------------------------------
 */

B
Bruce Momjian 已提交
509
/*
510 511
 *		GetAttributeByName
 *		GetAttributeByNum
512
 *
513 514 515 516
 *		These are functions which return the value of the
 *		named attribute out of the tuple from the arg slot.  User defined
 *		C functions which take a tuple as an argument are expected
 *		to use this.  Ex: overpaid(EMP) might call GetAttributeByNum().
517
 */
518
Datum
519
GetAttributeByNum(TupleTableSlot *slot,
520
				  AttrNumber attrno,
521
				  bool *isNull)
522
{
523
	Datum		retval;
524 525

	if (!AttributeNumberIsValid(attrno))
526
		elog(ERROR, "GetAttributeByNum: Invalid attribute number");
527 528

	if (!AttrNumberIsForUserDefinedAttr(attrno))
529
		elog(ERROR, "GetAttributeByNum: cannot access system attributes here");
530 531

	if (isNull == (bool *) NULL)
532
		elog(ERROR, "GetAttributeByNum: a NULL isNull flag was passed");
533 534

	if (TupIsNull(slot))
535
	{
536
		*isNull = true;
537
		return (Datum) 0;
538
	}
539

540 541 542 543
	retval = heap_getattr(slot->val,
						  attrno,
						  slot->ttc_tupleDescriptor,
						  isNull);
544
	if (*isNull)
545 546 547
		return (Datum) 0;

	return retval;
548
}
549

550
Datum
551
GetAttributeByName(TupleTableSlot *slot, char *attname, bool *isNull)
552
{
553 554 555 556 557
	AttrNumber	attrno;
	TupleDesc	tupdesc;
	Datum		retval;
	int			natts;
	int			i;
558 559

	if (attname == NULL)
560
		elog(ERROR, "GetAttributeByName: Invalid attribute name");
561 562

	if (isNull == (bool *) NULL)
563
		elog(ERROR, "GetAttributeByName: a NULL isNull flag was passed");
564 565

	if (TupIsNull(slot))
566
	{
567
		*isNull = true;
568
		return (Datum) 0;
569
	}
570 571

	tupdesc = slot->ttc_tupleDescriptor;
572
	natts = slot->val->t_data->t_natts;
573 574 575 576 577 578 579 580 581

	attrno = InvalidAttrNumber;
	for (i = 0; i < tupdesc->natts; i++)
	{
		if (namestrcmp(&(tupdesc->attrs[i]->attname), attname) == 0)
		{
			attrno = tupdesc->attrs[i]->attnum;
			break;
		}
582
	}
583 584

	if (attrno == InvalidAttrNumber)
585
		elog(ERROR, "GetAttributeByName: attribute %s not found", attname);
586

587 588 589 590
	retval = heap_getattr(slot->val,
						  attrno,
						  tupdesc,
						  isNull);
591
	if (*isNull)
592 593 594
		return (Datum) 0;

	return retval;
595 596
}

597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
/*
 * init_fcache - initialize a FuncExprState node during first use
 */
void
init_fcache(Oid foid, FuncExprState *fcache, MemoryContext fcacheCxt)
{
	AclResult	aclresult;

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

	/* Safety check (should never fail, as parser should check sooner) */
	if (length(fcache->args) > FUNC_MAX_ARGS)
		elog(ERROR, "init_fcache: too many arguments");

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

	/* Initialize additional info */
	fcache->setArgsValid = false;
619
	fcache->func.fn_expr = (Node *) fcache->xprstate.expr;
620 621
}

622 623 624 625
/*
 * Evaluate arguments for a function.
 */
static ExprDoneCond
626
ExecEvalFuncArgs(FunctionCallInfo fcinfo,
627
				 List *argList,
628
				 ExprContext *econtext)
629
{
630
	ExprDoneCond argIsDone;
631 632
	int			i;
	List	   *arg;
633

B
Bruce Momjian 已提交
634
	argIsDone = ExprSingleResult;		/* default assumption */
635

636 637 638
	i = 0;
	foreach(arg, argList)
	{
B
Bruce Momjian 已提交
639
		ExprDoneCond thisArgIsDone;
B
Bruce Momjian 已提交
640

641
		fcinfo->arg[i] = ExecEvalExpr((ExprState *) lfirst(arg),
642 643 644
									  econtext,
									  &fcinfo->argnull[i],
									  &thisArgIsDone);
645

646
		if (thisArgIsDone != ExprSingleResult)
647
		{
648 649
			/*
			 * We allow only one argument to have a set value; we'd need
B
Bruce Momjian 已提交
650 651 652
			 * much more complexity to keep track of multiple set
			 * arguments (cf. ExecTargetList) and it doesn't seem worth
			 * it.
653 654 655 656
			 */
			if (argIsDone != ExprSingleResult)
				elog(ERROR, "Functions and operators can take only one set argument");
			argIsDone = thisArgIsDone;
657 658 659
		}
		i++;
	}
660

661 662
	fcinfo->nargs = i;

663
	return argIsDone;
664 665
}

B
Bruce Momjian 已提交
666
/*
667
 *		ExecMakeFunctionResult
668 669
 *
 * Evaluate the arguments to a function and then the function itself.
670
 */
671
Datum
672
ExecMakeFunctionResult(FuncExprState *fcache,
673 674
					   ExprContext *econtext,
					   bool *isNull,
675
					   ExprDoneCond *isDone)
676
{
677
	List	   *arguments = fcache->args;
B
Bruce Momjian 已提交
678
	Datum		result;
679 680
	FunctionCallInfoData fcinfo;
	ReturnSetInfo rsinfo;		/* for functions returning sets */
B
Bruce Momjian 已提交
681
	ExprDoneCond argDone;
682
	bool		hasSetArg;
B
Bruce Momjian 已提交
683
	int			i;
684

B
Bruce Momjian 已提交
685
	/*
B
Bruce Momjian 已提交
686
	 * arguments is a list of expressions to evaluate before passing to
687
	 * the function manager.  We skip the evaluation if it was already
B
Bruce Momjian 已提交
688 689
	 * done in the previous call (ie, we are continuing the evaluation of
	 * a set-valued function).	Otherwise, collect the current argument
690
	 * values into fcinfo.
691
	 */
692
	if (!fcache->setArgsValid)
693
	{
694 695 696 697
		/* Need to prep callinfo structure */
		MemSet(&fcinfo, 0, sizeof(fcinfo));
		fcinfo.flinfo = &(fcache->func);
		argDone = ExecEvalFuncArgs(&fcinfo, arguments, econtext);
698
		if (argDone == ExprEndResult)
699
		{
700
			/* input is an empty set, so return an empty set. */
701
			*isNull = true;
702 703 704 705
			if (isDone)
				*isDone = ExprEndResult;
			else
				elog(ERROR, "Set-valued function called in context that cannot accept a set");
706
			return (Datum) 0;
707
		}
708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726
		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;
	}

	/*
	 * If function returns set, prepare a resultinfo node for
	 * communication
	 */
	if (fcache->func.fn_retset)
	{
		fcinfo.resultinfo = (Node *) &rsinfo;
		rsinfo.type = T_ReturnSetInfo;
727
		rsinfo.econtext = econtext;
728
		rsinfo.expectedDesc = NULL;
729 730 731 732 733
		rsinfo.allowedModes = (int) SFRM_ValuePerCall;
		rsinfo.returnMode = SFRM_ValuePerCall;
		/* isDone is filled below */
		rsinfo.setResult = NULL;
		rsinfo.setDesc = NULL;
734
	}
735

B
Bruce Momjian 已提交
736
	/*
B
Bruce Momjian 已提交
737 738
	 * now return the value gotten by calling the function manager,
	 * passing the function the evaluated parameter values.
739
	 */
740
	if (fcache->func.fn_retset || hasSetArg)
741
	{
742
		/*
B
Bruce Momjian 已提交
743
		 * We need to return a set result.	Complain if caller not ready
744 745 746 747 748 749
		 * to accept one.
		 */
		if (isDone == NULL)
			elog(ERROR, "Set-valued function called in context that cannot accept a set");

		/*
B
Bruce Momjian 已提交
750 751 752 753 754 755
		 * 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.
756
		 */
757
		for (;;)
758
		{
759 760 761 762
			/*
			 * If function is strict, and there are any NULL arguments,
			 * skip calling the function (at least for this set of args).
			 */
B
Bruce Momjian 已提交
763
			bool		callit = true;
764

765
			if (fcache->func.fn_strict)
766
			{
767
				for (i = 0; i < fcinfo.nargs; i++)
768
				{
769
					if (fcinfo.argnull[i])
770 771 772 773 774 775 776 777 778
					{
						callit = false;
						break;
					}
				}
			}

			if (callit)
			{
779 780 781 782 783
				fcinfo.isnull = false;
				rsinfo.isDone = ExprSingleResult;
				result = FunctionCallInvoke(&fcinfo);
				*isNull = fcinfo.isnull;
				*isDone = rsinfo.isDone;
784 785 786 787 788
			}
			else
			{
				result = (Datum) 0;
				*isNull = true;
789 790 791 792 793 794
				*isDone = ExprEndResult;
			}

			if (*isDone != ExprEndResult)
			{
				/*
B
Bruce Momjian 已提交
795
				 * Got a result from current argument.	If function itself
796 797
				 * returns set, save the current argument values to re-use
				 * on the next call.
798 799
				 */
				if (fcache->func.fn_retset)
800 801 802 803 804
				{
					memcpy(&fcache->setArgs, &fcinfo, sizeof(fcinfo));
					fcache->setHasSetArg = hasSetArg;
					fcache->setArgsValid = true;
				}
B
Bruce Momjian 已提交
805

806 807 808 809 810 811
				/*
				 * Make sure we say we are returning a set, even if the
				 * function itself doesn't return sets.
				 */
				*isDone = ExprMultipleResult;
				break;
812
			}
813

814
			/* Else, done with this argument */
815
			if (!hasSetArg)
816
				break;			/* input not a set, so done */
817

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

821
			if (argDone != ExprMultipleResult)
822
			{
823
				/* End of argument set, so we're done. */
824
				*isNull = true;
825
				*isDone = ExprEndResult;
826
				result = (Datum) 0;
827
				break;
828
			}
829

830 831
			/*
			 * If we reach here, loop around to run the function on the
832 833
			 * new argument.
			 */
834
		}
835
	}
836
	else
837
	{
838
		/*
839 840
		 * Non-set case: much easier.
		 *
B
Bruce Momjian 已提交
841 842
		 * If function is strict, and there are any NULL arguments, skip
		 * calling the function and return NULL.
843
		 */
844
		if (fcache->func.fn_strict)
845
		{
846
			for (i = 0; i < fcinfo.nargs; i++)
847
			{
848
				if (fcinfo.argnull[i])
849 850 851 852 853 854
				{
					*isNull = true;
					return (Datum) 0;
				}
			}
		}
855 856 857
		fcinfo.isnull = false;
		result = FunctionCallInvoke(&fcinfo);
		*isNull = fcinfo.isnull;
858
	}
859 860

	return result;
861 862 863
}


864 865 866 867
/*
 *		ExecMakeTableFunctionResult
 *
 * Evaluate a table function, producing a materialized result in a Tuplestore
B
Bruce Momjian 已提交
868
 * object.	(If function returns an empty set, we just return NULL instead.)
869 870
 */
Tuplestorestate *
871
ExecMakeTableFunctionResult(ExprState *funcexpr,
872
							ExprContext *econtext,
873
							TupleDesc expectedDesc,
874 875 876 877
							TupleDesc *returnDesc)
{
	Tuplestorestate *tupstore = NULL;
	TupleDesc	tupdesc = NULL;
878
	Oid			funcrettype;
879
	FunctionCallInfoData fcinfo;
880
	ReturnSetInfo rsinfo;
881 882 883
	MemoryContext callerContext;
	MemoryContext oldcontext;
	TupleTableSlot *slot;
884
	bool		direct_function_call;
885 886 887 888
	bool		first_time = true;
	bool		returnsTuple = false;

	/*
889
	 * Normally the passed expression tree will be a FuncExprState, since the
890 891 892 893 894 895 896
	 * 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.
897
	 */
898 899
	if (funcexpr && IsA(funcexpr, FuncExprState) &&
		IsA(funcexpr->expr, FuncExpr))
900
	{
901
		FuncExprState *fcache = (FuncExprState *) funcexpr;
902
		ExprDoneCond argDone;
903

904 905 906 907
		/*
		 * This path is similar to ExecMakeFunctionResult.
		 */
		direct_function_call = true;
908

909
		/*
910
		 * Initialize function cache if first time through
911
		 */
912
		if (fcache->func.fn_oid == InvalidOid)
913
		{
914 915 916
			FuncExpr *func = (FuncExpr *) fcache->xprstate.expr;

			init_fcache(func->funcid, fcache, econtext->ecxt_per_query_memory);
917 918 919 920 921 922 923 924 925 926 927 928
		}

		/*
		 * Evaluate the function's argument list.
		 *
		 * Note: ideally, we'd do this in the per-tuple context, but then the
		 * 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?
		 */
		MemSet(&fcinfo, 0, sizeof(fcinfo));
		fcinfo.flinfo = &(fcache->func);
929
		argDone = ExecEvalFuncArgs(&fcinfo, fcache->args, econtext);
930 931 932 933 934 935 936 937 938 939 940 941 942
		/* We don't allow sets in the arguments of the table function */
		if (argDone != ExprSingleResult)
			elog(ERROR, "Set-valued function called in context that cannot accept a set");

		/*
		 * If function is strict, and there are any NULL arguments, skip
		 * calling the function and return NULL (actually an empty set).
		 */
		if (fcache->func.fn_strict)
		{
			int			i;

			for (i = 0; i < fcinfo.nargs; i++)
943
			{
944 945 946 947 948
				if (fcinfo.argnull[i])
				{
					*returnDesc = NULL;
					return NULL;
				}
949 950 951
			}
		}
	}
952 953 954 955 956
	else
	{
		/* Treat funcexpr as a generic expression */
		direct_function_call = false;
	}
957

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

960
	/*
B
Bruce Momjian 已提交
961 962
	 * Prepare a resultinfo node for communication.  We always do this
	 * even if not expecting a set result, so that we can pass
963 964 965
	 * 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.
966
	 */
967 968 969 970 971
	fcinfo.resultinfo = (Node *) &rsinfo;
	rsinfo.type = T_ReturnSetInfo;
	rsinfo.econtext = econtext;
	rsinfo.expectedDesc = expectedDesc;
	rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize);
972 973 974 975 976 977
	rsinfo.returnMode = SFRM_ValuePerCall;
	/* isDone is filled below */
	rsinfo.setResult = NULL;
	rsinfo.setDesc = NULL;

	/*
978
	 * Switch to short-lived context for calling the function or expression.
979 980 981 982
	 */
	callerContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);

	/*
983 984
	 * Loop to handle the ValuePerCall protocol (which is also the same
	 * behavior needed in the generic ExecEvalExpr path).
985 986 987 988 989 990 991
	 */
	for (;;)
	{
		Datum		result;
		HeapTuple	tuple;

		/*
B
Bruce Momjian 已提交
992
		 * reset per-tuple memory context before each call of the
993 994
		 * function or expression. This cleans up any local memory the
		 * function may leak when called.
995 996 997
		 */
		ResetExprContext(econtext);

998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
		/* Call the function or expression one time */
		if (direct_function_call)
		{
			fcinfo.isnull = false;
			rsinfo.isDone = ExprSingleResult;
			result = FunctionCallInvoke(&fcinfo);
		}
		else
		{
			result = ExecEvalExpr(funcexpr, econtext,
								  &fcinfo.isnull, &rsinfo.isDone);
		}
1010 1011 1012 1013 1014 1015 1016

		/* Which protocol does function want to use? */
		if (rsinfo.returnMode == SFRM_ValuePerCall)
		{
			/*
			 * Check for end of result set.
			 *
B
Bruce Momjian 已提交
1017
			 * Note: if function returns an empty set, we don't build a
1018 1019 1020 1021 1022
			 * tupdesc or tuplestore (since we can't get a tupdesc in the
			 * function-returning-tuple case)
			 */
			if (rsinfo.isDone == ExprEndResult)
				break;
B
Bruce Momjian 已提交
1023

1024
			/*
B
Bruce Momjian 已提交
1025 1026
			 * If first time through, build tupdesc and tuplestore for
			 * result
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
			 */
			if (first_time)
			{
				oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
				if (funcrettype == RECORDOID ||
					get_typtype(funcrettype) == 'c')
				{
					/*
					 * Composite type, so function should have returned a
					 * TupleTableSlot; use its descriptor
					 */
					slot = (TupleTableSlot *) DatumGetPointer(result);
1039 1040 1041
					if (fcinfo.isnull ||
						!slot ||
						!IsA(slot, TupleTableSlot) ||
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051
						!slot->ttc_tupleDescriptor)
						elog(ERROR, "ExecMakeTableFunctionResult: Invalid result from function returning tuple");
					tupdesc = CreateTupleDescCopy(slot->ttc_tupleDescriptor);
					returnsTuple = true;
				}
				else
				{
					/*
					 * Scalar type, so make a single-column descriptor
					 */
1052
					tupdesc = CreateTemplateTupleDesc(1, false);
1053 1054 1055 1056 1057 1058 1059 1060
					TupleDescInitEntry(tupdesc,
									   (AttrNumber) 1,
									   "column",
									   funcrettype,
									   -1,
									   0,
									   false);
				}
1061
				tupstore = tuplestore_begin_heap(true, false, SortMem);
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072
				MemoryContextSwitchTo(oldcontext);
				rsinfo.setResult = tupstore;
				rsinfo.setDesc = tupdesc;
			}

			/*
			 * Store current resultset item.
			 */
			if (returnsTuple)
			{
				slot = (TupleTableSlot *) DatumGetPointer(result);
1073 1074 1075
				if (fcinfo.isnull ||
					!slot ||
					!IsA(slot, TupleTableSlot) ||
1076 1077 1078 1079 1080 1081
					TupIsNull(slot))
					elog(ERROR, "ExecMakeTableFunctionResult: Invalid result from function returning tuple");
				tuple = slot->val;
			}
			else
			{
B
Bruce Momjian 已提交
1082
				char		nullflag;
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120

				nullflag = fcinfo.isnull ? 'n' : ' ';
				tuple = heap_formtuple(tupdesc, &result, &nullflag);
			}

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

			/*
			 * Are we done?
			 */
			if (rsinfo.isDone != ExprMultipleResult)
				break;
		}
		else if (rsinfo.returnMode == SFRM_Materialize)
		{
			/* check we're on the same page as the function author */
			if (!first_time || rsinfo.isDone != ExprSingleResult)
				elog(ERROR, "ExecMakeTableFunctionResult: Materialize-mode protocol not followed");
			/* Done evaluating the set result */
			break;
		}
		else
			elog(ERROR, "ExecMakeTableFunctionResult: unknown returnMode %d",
				 (int) rsinfo.returnMode);

		first_time = false;
	}

	MemoryContextSwitchTo(callerContext);

	/* The returned pointers are those in rsinfo */
	*returnDesc = rsinfo.setDesc;
	return rsinfo.setResult;
}


1121
/* ----------------------------------------------------------------
1122
 *		ExecEvalFunc
1123
 *		ExecEvalOper
1124
 *		ExecEvalDistinct
1125 1126
 *
 *		Evaluate the functional result of a list of arguments by calling the
1127
 *		function manager.
1128 1129 1130 1131
 * ----------------------------------------------------------------
 */

/* ----------------------------------------------------------------
1132
 *		ExecEvalFunc
1133 1134
 * ----------------------------------------------------------------
 */
1135
static Datum
1136
ExecEvalFunc(FuncExprState *fcache,
1137 1138 1139
			 ExprContext *econtext,
			 bool *isNull,
			 ExprDoneCond *isDone)
1140
{
B
Bruce Momjian 已提交
1141
	/*
1142
	 * Initialize function cache if first time through
1143
	 */
1144
	if (fcache->func.fn_oid == InvalidOid)
1145
	{
1146 1147 1148
		FuncExpr *func = (FuncExpr *) fcache->xprstate.expr;

		init_fcache(func->funcid, fcache, econtext->ecxt_per_query_memory);
1149 1150
	}

1151
	return ExecMakeFunctionResult(fcache, econtext, isNull, isDone);
1152 1153
}

1154
/* ----------------------------------------------------------------
1155
 *		ExecEvalOper
1156 1157 1158
 * ----------------------------------------------------------------
 */
static Datum
1159
ExecEvalOper(FuncExprState *fcache,
1160 1161 1162 1163 1164
			 ExprContext *econtext,
			 bool *isNull,
			 ExprDoneCond *isDone)
{
	/*
1165
	 * Initialize function cache if first time through
1166
	 */
1167
	if (fcache->func.fn_oid == InvalidOid)
1168
	{
1169 1170 1171
		OpExpr *op = (OpExpr *) fcache->xprstate.expr;

		init_fcache(op->opfuncid, fcache, econtext->ecxt_per_query_memory);
1172 1173
	}

1174
	return ExecMakeFunctionResult(fcache, econtext, isNull, isDone);
1175 1176
}

1177 1178 1179 1180 1181 1182 1183
/* ----------------------------------------------------------------
 *		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
1184
 * operator, but since we need special processing of the arguments
1185 1186 1187 1188
 * we can not simply reuse ExecEvalOper() or ExecEvalFunc().
 * ----------------------------------------------------------------
 */
static Datum
1189
ExecEvalDistinct(FuncExprState *fcache,
1190
				 ExprContext *econtext,
1191
				 bool *isNull)
1192
{
1193
	Datum		result;
1194 1195 1196 1197 1198
	FunctionCallInfoData fcinfo;
	ExprDoneCond argDone;
	List	   *argList;

	/*
1199
	 * Initialize function cache if first time through
1200
	 */
1201 1202 1203 1204 1205 1206 1207
	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);
	}
1208 1209

	/*
1210
	 * extract info from fcache
1211
	 */
1212
	argList = fcache->args;
1213 1214 1215 1216 1217

	/* Need to prep callinfo structure */
	MemSet(&fcinfo, 0, sizeof(fcinfo));
	fcinfo.flinfo = &(fcache->func);
	argDone = ExecEvalFuncArgs(&fcinfo, argList, econtext);
1218 1219
	if (argDone != ExprSingleResult)
		elog(ERROR, "IS DISTINCT FROM does not support set arguments");
1220
	Assert(fcinfo.nargs == 2);
1221 1222 1223 1224

	if (fcinfo.argnull[0] && fcinfo.argnull[1])
	{
		/* Both NULL? Then is not distinct... */
1225
		result = BoolGetDatum(FALSE);
1226 1227 1228
	}
	else if (fcinfo.argnull[0] || fcinfo.argnull[1])
	{
1229 1230
		/* Only one is NULL? Then is distinct... */
		result = BoolGetDatum(TRUE);
1231 1232 1233 1234 1235 1236
	}
	else
	{
		fcinfo.isnull = false;
		result = FunctionCallInvoke(&fcinfo);
		*isNull = fcinfo.isnull;
1237 1238
		/* Must invert result of "=" */
		result = BoolGetDatum(!DatumGetBool(result));
1239 1240
	}

1241
	return result;
1242 1243
}

1244
/* ----------------------------------------------------------------
1245 1246 1247
 *		ExecEvalNot
 *		ExecEvalOr
 *		ExecEvalAnd
1248
 *
1249
 *		Evaluate boolean expressions, with appropriate short-circuiting.
1250 1251 1252 1253 1254 1255 1256
 *
 *		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...
1257 1258
 * ----------------------------------------------------------------
 */
1259
static Datum
1260
ExecEvalNot(BoolExprState *notclause, ExprContext *econtext, bool *isNull)
1261
{
1262
	ExprState  *clause;
1263
	Datum		expr_value;
1264 1265

	clause = lfirst(notclause->args);
1266

1267
	expr_value = ExecEvalExpr(clause, econtext, isNull, NULL);
1268

B
Bruce Momjian 已提交
1269
	/*
B
Bruce Momjian 已提交
1270 1271
	 * if the expression evaluates to null, then we just cascade the null
	 * back to whoever called us.
1272 1273
	 */
	if (*isNull)
1274 1275
		return expr_value;

B
Bruce Momjian 已提交
1276
	/*
B
Bruce Momjian 已提交
1277 1278
	 * evaluation of 'not' is simple.. expr is false, then return 'true'
	 * and vice versa.
1279
	 */
B
Bruce Momjian 已提交
1280
	return BoolGetDatum(!DatumGetBool(expr_value));
1281 1282 1283
}

/* ----------------------------------------------------------------
1284
 *		ExecEvalOr
1285 1286
 * ----------------------------------------------------------------
 */
1287
static Datum
1288
ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext, bool *isNull)
1289
{
1290 1291
	List	   *clauses;
	List	   *clause;
1292 1293
	bool		AnyNull;
	Datum		clause_value;
1294 1295

	clauses = orExpr->args;
1296
	AnyNull = false;
1297

B
Bruce Momjian 已提交
1298
	/*
1299 1300
	 * 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
1301 1302 1303 1304 1305 1306
	 * 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
1307 1308 1309 1310
	 * 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.
1311
	 */
1312 1313
	foreach(clause, clauses)
	{
1314
		clause_value = ExecEvalExpr((ExprState *) lfirst(clause),
1315
									econtext, isNull, NULL);
1316

B
Bruce Momjian 已提交
1317
		/*
1318
		 * if we have a non-null true result, then return it.
1319 1320
		 */
		if (*isNull)
1321
			AnyNull = true;		/* remember we got a null */
1322
		else if (DatumGetBool(clause_value))
1323
			return clause_value;
1324 1325
	}

1326 1327
	/* AnyNull is true if at least one clause evaluated to NULL */
	*isNull = AnyNull;
1328
	return BoolGetDatum(false);
1329 1330 1331 1332 1333 1334
}

/* ----------------------------------------------------------------
 *		ExecEvalAnd
 * ----------------------------------------------------------------
 */
1335
static Datum
1336
ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext, bool *isNull)
1337
{
1338 1339
	List	   *clauses;
	List	   *clause;
1340 1341
	bool		AnyNull;
	Datum		clause_value;
1342 1343

	clauses = andExpr->args;
1344
	AnyNull = false;
1345

B
Bruce Momjian 已提交
1346
	/*
1347 1348 1349
	 * 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
1350
	 * NULL, we return NULL; otherwise we return TRUE.	This makes sense
1351 1352
	 * when you interpret NULL as "don't know", using the same sort of
	 * reasoning as for OR, above.
1353
	 */
1354 1355
	foreach(clause, clauses)
	{
1356
		clause_value = ExecEvalExpr((ExprState *) lfirst(clause),
1357
									econtext, isNull, NULL);
1358

B
Bruce Momjian 已提交
1359
		/*
1360
		 * if we have a non-null false result, then return it.
1361 1362
		 */
		if (*isNull)
1363
			AnyNull = true;		/* remember we got a null */
B
Bruce Momjian 已提交
1364
		else if (!DatumGetBool(clause_value))
1365
			return clause_value;
1366 1367
	}

1368 1369
	/* AnyNull is true if at least one clause evaluated to NULL */
	*isNull = AnyNull;
1370
	return BoolGetDatum(!AnyNull);
1371 1372
}

1373

T
Thomas G. Lockhart 已提交
1374 1375 1376 1377
/* ----------------------------------------------------------------
 *		ExecEvalCase
 *
 *		Evaluate a CASE clause. Will have boolean expressions
1378
 *		inside the WHEN clauses, and will have expressions
T
Thomas G. Lockhart 已提交
1379 1380 1381 1382 1383
 *		for results.
 *		- thomas 1998-11-09
 * ----------------------------------------------------------------
 */
static Datum
1384
ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
1385
			 bool *isNull, ExprDoneCond *isDone)
T
Thomas G. Lockhart 已提交
1386 1387 1388
{
	List	   *clauses;
	List	   *clause;
1389
	Datum		clause_value;
T
Thomas G. Lockhart 已提交
1390 1391 1392

	clauses = caseExpr->args;

B
Bruce Momjian 已提交
1393
	/*
B
Bruce Momjian 已提交
1394 1395
	 * 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
1396
	 * return the value of the default clause, or NULL if there is none.
T
Thomas G. Lockhart 已提交
1397 1398 1399
	 */
	foreach(clause, clauses)
	{
1400
		CaseWhenState *wclause = lfirst(clause);
T
Thomas G. Lockhart 已提交
1401

1402
		clause_value = ExecEvalExpr(wclause->expr,
1403 1404
									econtext,
									isNull,
1405
									NULL);
T
Thomas G. Lockhart 已提交
1406

B
Bruce Momjian 已提交
1407
		/*
B
Bruce Momjian 已提交
1408
		 * if we have a true test, then we return the result, since the
1409 1410
		 * case statement is satisfied.  A NULL result from the test is
		 * not considered true.
T
Thomas G. Lockhart 已提交
1411
		 */
1412
		if (DatumGetBool(clause_value) && !*isNull)
T
Thomas G. Lockhart 已提交
1413
		{
1414
			return ExecEvalExpr(wclause->result,
1415 1416
								econtext,
								isNull,
1417
								isDone);
T
Thomas G. Lockhart 已提交
1418 1419 1420 1421 1422
		}
	}

	if (caseExpr->defresult)
	{
1423
		return ExecEvalExpr(caseExpr->defresult,
1424 1425
							econtext,
							isNull,
1426
							isDone);
T
Thomas G. Lockhart 已提交
1427 1428
	}

1429 1430
	*isNull = true;
	return (Datum) 0;
T
Thomas G. Lockhart 已提交
1431 1432
}

1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584
/* ----------------------------------------------------------------
 *		ExecEvalArray - ARRAY[] expressions
 * ----------------------------------------------------------------
 */
static Datum
ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
			  bool *isNull)
{
	ArrayExpr   *arrayExpr = (ArrayExpr *) astate->xprstate.expr;
	ArrayType  *result;
	List   *element;
	Oid		element_type = arrayExpr->element_typeid;
	int		ndims = arrayExpr->ndims;
	int		dims[MAXDIM];
	int		lbs[MAXDIM];

	if (ndims == 1)
	{
		int		nelems;
		Datum  *dvalues;
		int		i = 0;

		nelems = length(astate->elements);

		/* Shouldn't happen here, but if length is 0, return NULL */
		if (nelems == 0)
		{
			*isNull = true;
			return (Datum) 0;
		}

		dvalues = (Datum *) palloc(nelems * sizeof(Datum));

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

			dvalues[i++] = ExecEvalExpr(e, econtext, &eisnull, NULL);
			if (eisnull)
				elog(ERROR, "Arrays cannot have NULL elements");
		}

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

		result = construct_md_array(dvalues, ndims, dims, lbs,
									element_type,
									astate->elemlength,
									astate->elembyval,
									astate->elemalign);
	}
	else
	{
		char	   *dat = NULL;
		Size		ndatabytes = 0;
		int			nbytes;
		int			outer_nelems = length(astate->elements);
		int			elem_ndims = 0;
		int		   *elem_dims = NULL;
		int		   *elem_lbs = NULL;
		bool		firstone = true;
		int			i;

		if (ndims <= 0 || ndims > MAXDIM)
			elog(ERROR, "Arrays cannot have more than %d dimensions", MAXDIM);

		/* loop through and get data area from each element */
		foreach(element, astate->elements)
		{
			ExprState   *e = (ExprState *) lfirst(element);
			bool		eisnull;
			Datum		arraydatum;
			ArrayType  *array;
			int			elem_ndatabytes;

			arraydatum = ExecEvalExpr(e, econtext, &eisnull, NULL);
			if (eisnull)
				elog(ERROR, "Arrays cannot have NULL elements");

			array = DatumGetArrayTypeP(arraydatum);

			if (firstone)
			{
				/* Get sub-array details from first member */
				elem_ndims = ARR_NDIM(array);
				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));
				firstone = false;
			}
			else
			{
				/* Check other sub-arrays are compatible */
				if (elem_ndims != ARR_NDIM(array))
					elog(ERROR, "Multiple dimension arrays must have array "
						 "expressions with matching number of dimensions");

				if (memcmp(elem_dims, ARR_DIMS(array),
						   elem_ndims * sizeof(int)) != 0)
					elog(ERROR, "Multiple dimension arrays must have array "
						 "expressions with matching dimensions");

				if (memcmp(elem_lbs, ARR_LBOUND(array),
						   elem_ndims * sizeof(int)) != 0)
					elog(ERROR, "Multiple dimension arrays must have array "
						 "expressions with matching dimensions");
			}

			elem_ndatabytes = ARR_SIZE(array) - ARR_OVERHEAD(elem_ndims);
			ndatabytes += elem_ndatabytes;
			if (dat == NULL)
				dat = (char *) palloc(ndatabytes);
			else
				dat = (char *) repalloc(dat, ndatabytes);

			memcpy(dat + (ndatabytes - elem_ndatabytes),
				   ARR_DATA_PTR(array),
				   elem_ndatabytes);
		}

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

		nbytes = ndatabytes + ARR_OVERHEAD(ndims);
		result = (ArrayType *) palloc(nbytes);

		result->size = nbytes;
		result->ndim = ndims;
		result->flags = 0;
		result->elemtype = element_type;
		memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
		memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
		if (ndatabytes > 0)
			memcpy(ARR_DATA_PTR(result), dat, ndatabytes);

		if (dat != NULL)
			pfree(dat);
	}

	return PointerGetDatum(result);
}

1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669
/* ----------------------------------------------------------------
 *		ExecEvalCoalesce
 * ----------------------------------------------------------------
 */
static Datum
ExecEvalCoalesce(CoalesceExprState *coalesceExpr, ExprContext *econtext,
				 bool *isNull)
{
	List *arg;

	/* Simply loop through until something NOT NULL is found */
	foreach(arg, coalesceExpr->args)
	{
		ExprState *e = (ExprState *) lfirst(arg);
		Datum value;

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

	/* Else return NULL */
	*isNull = true;
	return (Datum) 0;
}
	
/* ----------------------------------------------------------------
 *		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
ExecEvalNullIf(FuncExprState *fcache, ExprContext *econtext,
			   bool *isNull)
{
	Datum		result;
	FunctionCallInfoData fcinfo;
	ExprDoneCond argDone;
	List	   *argList;

	/*
	 * Initialize function cache if first time through
	 */
	if (fcache->func.fn_oid == InvalidOid)
	{
		NullIfExpr *op = (NullIfExpr *) fcache->xprstate.expr;

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

	/*
	 * extract info from fcache
	 */
	argList = fcache->args;

	/* Need to prep callinfo structure */
	MemSet(&fcinfo, 0, sizeof(fcinfo));
	fcinfo.flinfo = &(fcache->func);
	argDone = ExecEvalFuncArgs(&fcinfo, argList, econtext);
	if (argDone != ExprSingleResult)
		elog(ERROR, "NULLIF does not support set arguments");
	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];
}

1670 1671 1672 1673 1674 1675 1676
/* ----------------------------------------------------------------
 *		ExecEvalNullTest
 *
 *		Evaluate a NullTest node.
 * ----------------------------------------------------------------
 */
static Datum
1677
ExecEvalNullTest(GenericExprState *nstate,
1678 1679 1680 1681
				 ExprContext *econtext,
				 bool *isNull,
				 ExprDoneCond *isDone)
{
1682
	NullTest   *ntest = (NullTest *) nstate->xprstate.expr;
1683 1684
	Datum		result;

1685 1686 1687 1688 1689
	result = ExecEvalExpr(nstate->arg, econtext, isNull, isDone);

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

1690
	switch (ntest->nulltesttype)
1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712
	{
		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, "ExecEvalNullTest: unexpected nulltesttype %d",
				 (int) ntest->nulltesttype);
			return (Datum) 0;	/* keep compiler quiet */
	}
1713 1714 1715 1716 1717 1718 1719 1720 1721
}

/* ----------------------------------------------------------------
 *		ExecEvalBooleanTest
 *
 *		Evaluate a BooleanTest node.
 * ----------------------------------------------------------------
 */
static Datum
1722
ExecEvalBooleanTest(GenericExprState *bstate,
1723 1724 1725 1726
					ExprContext *econtext,
					bool *isNull,
					ExprDoneCond *isDone)
{
1727
	BooleanTest *btest = (BooleanTest *) bstate->xprstate.expr;
1728 1729
	Datum		result;

1730 1731 1732 1733 1734
	result = ExecEvalExpr(bstate->arg, econtext, isNull, isDone);

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

1735
	switch (btest->booltesttype)
1736 1737 1738 1739 1740 1741 1742 1743 1744
	{
		case IS_TRUE:
			if (*isNull)
			{
				*isNull = false;
				return BoolGetDatum(false);
			}
			else if (DatumGetBool(result))
				return BoolGetDatum(true);
1745
			else
1746 1747 1748 1749 1750 1751 1752 1753 1754
				return BoolGetDatum(false);
		case IS_NOT_TRUE:
			if (*isNull)
			{
				*isNull = false;
				return BoolGetDatum(true);
			}
			else if (DatumGetBool(result))
				return BoolGetDatum(false);
1755
			else
1756 1757 1758 1759 1760 1761 1762 1763 1764
				return BoolGetDatum(true);
		case IS_FALSE:
			if (*isNull)
			{
				*isNull = false;
				return BoolGetDatum(false);
			}
			else if (DatumGetBool(result))
				return BoolGetDatum(false);
1765
			else
1766 1767 1768 1769 1770 1771 1772 1773 1774
				return BoolGetDatum(true);
		case IS_NOT_FALSE:
			if (*isNull)
			{
				*isNull = false;
				return BoolGetDatum(true);
			}
			else if (DatumGetBool(result))
				return BoolGetDatum(true);
1775
			else
1776 1777 1778 1779 1780 1781 1782
				return BoolGetDatum(false);
		case IS_UNKNOWN:
			if (*isNull)
			{
				*isNull = false;
				return BoolGetDatum(true);
			}
1783
			else
1784 1785 1786 1787 1788 1789 1790
				return BoolGetDatum(false);
		case IS_NOT_UNKNOWN:
			if (*isNull)
			{
				*isNull = false;
				return BoolGetDatum(false);
			}
1791
			else
1792 1793 1794 1795 1796 1797
				return BoolGetDatum(true);
		default:
			elog(ERROR, "ExecEvalBooleanTest: unexpected booltesttype %d",
				 (int) btest->booltesttype);
			return (Datum) 0;	/* keep compiler quiet */
	}
1798 1799
}

1800
/*
1801
 * ExecEvalCoerceToDomain
1802
 *
1803 1804
 * Test the provided data against the domain constraint(s).  If the data
 * passes the constraint specifications, pass it through (return the
1805 1806 1807
 * datum) otherwise throw an error.
 */
static Datum
1808
ExecEvalCoerceToDomain(CoerceToDomainState *cstate, ExprContext *econtext,
1809 1810
					   bool *isNull, ExprDoneCond *isDone)
{
1811
	CoerceToDomain *ctest = (CoerceToDomain *) cstate->xprstate.expr;
1812
	Datum		result;
1813
	List	   *l;
1814

1815
	result = ExecEvalExpr(cstate->arg, econtext, isNull, isDone);
1816

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

1820
	foreach(l, cstate->constraints)
1821
	{
1822 1823 1824 1825 1826 1827 1828 1829 1830 1831
		DomainConstraintState *con = (DomainConstraintState *) lfirst(l);

		switch (con->constrainttype)
		{
			case DOM_CONSTRAINT_NOTNULL:
				if (*isNull)
					elog(ERROR, "Domain %s does not allow NULL values",
						 format_type_be(ctest->resulttype));
				break;
			case DOM_CONSTRAINT_CHECK:
B
Bruce Momjian 已提交
1832 1833
			{
				Datum	conResult;
1834 1835 1836 1837 1838
				bool	conIsNull;
				Datum	save_datum;
				bool	save_isNull;

				/*
1839
				 * Set up value to be returned by CoerceToDomainValue nodes.
1840 1841 1842 1843 1844 1845
				 * We must save and restore prior setting of econtext's
				 * domainValue fields, in case this node is itself within
				 * a check expression for another domain.
				 */
				save_datum = econtext->domainValue_datum;
				save_isNull = econtext->domainValue_isNull;
B
Bruce Momjian 已提交
1846 1847 1848 1849

				econtext->domainValue_datum = result;
				econtext->domainValue_isNull = *isNull;

1850
				conResult = ExecEvalExpr(con->check_expr,
1851
										 econtext, &conIsNull, NULL);
B
Bruce Momjian 已提交
1852

1853 1854
				if (!conIsNull &&
					!DatumGetBool(conResult))
1855 1856
					elog(ERROR, "ExecEvalCoerceToDomain: Domain %s constraint %s failed",
						 format_type_be(ctest->resulttype), con->name);
1857 1858 1859

				econtext->domainValue_datum = save_datum;
				econtext->domainValue_isNull = save_isNull;
1860 1861

				break;
B
Bruce Momjian 已提交
1862
			}
1863 1864 1865 1866
			default:
				elog(ERROR, "ExecEvalCoerceToDomain: Constraint type unknown");
				break;
		}
1867 1868
	}

1869
	/* If all has gone well (constraints did not fail) return the datum */
1870 1871 1872
	return result;
}

1873
/*
1874
 * ExecEvalCoerceToDomainValue
1875
 *
1876
 * Return the value stored by CoerceToDomain.
1877 1878
 */
static Datum
1879 1880
ExecEvalCoerceToDomainValue(CoerceToDomainValue *conVal,
							ExprContext *econtext, bool *isNull)
1881 1882 1883 1884 1885
{
	*isNull = econtext->domainValue_isNull;
	return econtext->domainValue_datum;
}

1886 1887 1888 1889 1890 1891 1892
/* ----------------------------------------------------------------
 *		ExecEvalFieldSelect
 *
 *		Evaluate a FieldSelect node.
 * ----------------------------------------------------------------
 */
static Datum
1893
ExecEvalFieldSelect(GenericExprState *fstate,
1894 1895
					ExprContext *econtext,
					bool *isNull,
1896
					ExprDoneCond *isDone)
1897
{
1898
	FieldSelect *fselect = (FieldSelect *) fstate->xprstate.expr;
B
Bruce Momjian 已提交
1899
	Datum		result;
1900 1901
	TupleTableSlot *resSlot;

1902 1903 1904
	result = ExecEvalExpr(fstate->arg, econtext, isNull, isDone);

	/* this test covers the isDone exception too: */
1905 1906
	if (*isNull)
		return result;
1907

1908 1909 1910 1911 1912 1913 1914 1915 1916
	resSlot = (TupleTableSlot *) DatumGetPointer(result);
	Assert(resSlot != NULL && IsA(resSlot, TupleTableSlot));
	result = heap_getattr(resSlot->val,
						  fselect->fieldnum,
						  resSlot->ttc_tupleDescriptor,
						  isNull);
	return result;
}

1917 1918 1919 1920
/* ----------------------------------------------------------------
 *		ExecEvalExpr
 *
 *		Recursively evaluate a targetlist or qualification expression.
1921
 *
1922
 * Inputs:
1923
 *		expression: the expression state tree to evaluate
1924 1925 1926 1927 1928 1929 1930 1931 1932 1933
 *		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 elog()
B
Bruce Momjian 已提交
1934
 * error will be reported.	If the caller does pass an isDone pointer then
1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945
 * *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.
1946
 *
1947 1948 1949
 * 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
B
Bruce Momjian 已提交
1950
 * do the switch in an outer loop.	We do not do the switch here because
1951 1952 1953
 * it'd be a waste of cycles during recursive entries to ExecEvalExpr().
 *
 * This routine is an inner loop routine and must be as fast as possible.
1954 1955 1956
 * ----------------------------------------------------------------
 */
Datum
1957
ExecEvalExpr(ExprState *expression,
1958 1959
			 ExprContext *econtext,
			 bool *isNull,
1960
			 ExprDoneCond *isDone)
1961
{
1962
	Datum		retDatum;
1963
	Expr	   *expr;
1964

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

1970
	/* Is this still necessary?  Doubtful... */
1971 1972 1973
	if (expression == NULL)
	{
		*isNull = true;
1974
		return (Datum) 0;
1975 1976
	}

1977 1978 1979 1980
	/*
	 * here we dispatch the work to the appropriate type of function given
	 * the type of our expression.
	 */
1981 1982
	expr = expression->expr;
	switch (nodeTag(expr))
1983
	{
1984
		case T_Var:
1985
			retDatum = ExecEvalVar((Var *) expr, econtext, isNull);
1986 1987 1988
			break;
		case T_Const:
			{
1989
				Const	   *con = (Const *) expr;
1990

1991
				retDatum = con->constvalue;
1992
				*isNull = con->constisnull;
1993 1994 1995
				break;
			}
		case T_Param:
1996
			retDatum = ExecEvalParam((Param *) expr, econtext, isNull);
1997
			break;
B
Bruce Momjian 已提交
1998
		case T_Aggref:
1999 2000 2001
			retDatum = ExecEvalAggref((AggrefExprState *) expression,
									  econtext,
									  isNull);
2002 2003
			break;
		case T_ArrayRef:
2004
			retDatum = ExecEvalArrayRef((ArrayRefExprState *) expression,
2005 2006 2007
										econtext,
										isNull,
										isDone);
2008
			break;
2009
		case T_FuncExpr:
2010
			retDatum = ExecEvalFunc((FuncExprState *) expression, econtext,
2011 2012 2013
									isNull, isDone);
			break;
		case T_OpExpr:
2014
			retDatum = ExecEvalOper((FuncExprState *) expression, econtext,
2015 2016 2017
									isNull, isDone);
			break;
		case T_DistinctExpr:
2018
			retDatum = ExecEvalDistinct((FuncExprState *) expression, econtext,
2019
										isNull);
2020 2021
			break;
		case T_BoolExpr:
2022
			{
2023
				BoolExprState *state = (BoolExprState *) expression;
2024

2025
				switch (((BoolExpr *) expr)->boolop)
2026
				{
2027
					case AND_EXPR:
2028
						retDatum = ExecEvalAnd(state, econtext, isNull);
2029 2030
						break;
					case OR_EXPR:
2031
						retDatum = ExecEvalOr(state, econtext, isNull);
2032 2033
						break;
					case NOT_EXPR:
2034
						retDatum = ExecEvalNot(state, econtext, isNull);
2035 2036
						break;
					default:
2037
						elog(ERROR, "ExecEvalExpr: unknown boolop %d",
2038
							 ((BoolExpr *) expr)->boolop);
2039
						retDatum = 0;	/* keep compiler quiet */
2040 2041
						break;
				}
2042 2043
				break;
			}
2044 2045
		case T_SubPlan:
			retDatum = ExecSubPlan((SubPlanState *) expression,
2046 2047 2048
								   econtext,
								   isNull);
			break;
2049
		case T_FieldSelect:
2050
			retDatum = ExecEvalFieldSelect((GenericExprState *) expression,
2051 2052 2053 2054
										   econtext,
										   isNull,
										   isDone);
			break;
2055
		case T_RelabelType:
2056
			retDatum = ExecEvalExpr(((GenericExprState *) expression)->arg,
2057 2058 2059 2060
									econtext,
									isNull,
									isDone);
			break;
T
Thomas G. Lockhart 已提交
2061
		case T_CaseExpr:
2062
			retDatum = ExecEvalCase((CaseExprState *) expression,
2063 2064 2065
									econtext,
									isNull,
									isDone);
T
Thomas G. Lockhart 已提交
2066
			break;
2067 2068 2069 2070 2071
		case T_ArrayExpr:
			retDatum = ExecEvalArray((ArrayExprState *) expression,
									 econtext,
									 isNull);
			break;
2072 2073 2074 2075 2076 2077 2078 2079 2080 2081
		case T_CoalesceExpr:
			retDatum = ExecEvalCoalesce((CoalesceExprState *) expression,
										econtext,
										isNull);
			break;
		case T_NullIfExpr:
			retDatum = ExecEvalNullIf((FuncExprState *) expression,
									  econtext,
									  isNull);
			break;
2082
		case T_NullTest:
2083
			retDatum = ExecEvalNullTest((GenericExprState *) expression,
2084 2085 2086
										econtext,
										isNull,
										isDone);
2087 2088
			break;
		case T_BooleanTest:
2089
			retDatum = ExecEvalBooleanTest((GenericExprState *) expression,
2090 2091 2092
										   econtext,
										   isNull,
										   isDone);
2093
			break;
2094 2095
		case T_CoerceToDomain:
			retDatum = ExecEvalCoerceToDomain((CoerceToDomainState *) expression,
2096 2097 2098 2099
											  econtext,
											  isNull,
											  isDone);
			break;
2100 2101
		case T_CoerceToDomainValue:
			retDatum = ExecEvalCoerceToDomainValue((CoerceToDomainValue *) expr,
2102 2103
												   econtext,
												   isNull);
B
Bruce Momjian 已提交
2104
			break;
2105
		default:
2106 2107 2108
			elog(ERROR, "ExecEvalExpr: unknown expression type %d",
				 nodeTag(expression));
			retDatum = 0;		/* keep compiler quiet */
2109
			break;
2110
	}
2111 2112

	return retDatum;
B
Bruce Momjian 已提交
2113
}	/* ExecEvalExpr() */
T
Thomas G. Lockhart 已提交
2114

2115

2116 2117 2118 2119
/*
 * Same as above, but get into the right allocation context explicitly.
 */
Datum
2120
ExecEvalExprSwitchContext(ExprState *expression,
2121 2122
						  ExprContext *econtext,
						  bool *isNull,
2123
						  ExprDoneCond *isDone)
2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134
{
	Datum		retDatum;
	MemoryContext oldContext;

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


2135 2136 2137
/*
 * ExecInitExpr: prepare an expression tree for execution
 *
2138 2139 2140 2141 2142 2143 2144 2145 2146 2147
 * This function builds and returns an ExprState tree paralleling the given
 * Expr node tree.  The ExprState tree can then be handed to ExecEvalExpr
 * 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.
 *
2148
 * Any Aggref and SubPlan nodes found in the tree are added to the lists
2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159
 * of such nodes held by the parent PlanState.  Otherwise, we do very little
 * 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.
 *
2160
 *	'node' is the root of the expression tree to examine
2161 2162 2163 2164 2165
 *	'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.
2166
 */
2167 2168
ExprState *
ExecInitExpr(Expr *node, PlanState *parent)
2169
{
2170
	ExprState  *state;
2171 2172 2173 2174 2175 2176 2177 2178

	if (node == NULL)
		return NULL;
	switch (nodeTag(node))
	{
		case T_Var:
		case T_Const:
		case T_Param:
2179
		case T_CoerceToDomainValue:
2180 2181
			/* No special setup needed for these node types */
			state = (ExprState *) makeNode(ExprState);
2182 2183 2184
			break;
		case T_Aggref:
			{
2185 2186
				Aggref   *aggref = (Aggref *) node;
				AggrefExprState *astate = makeNode(AggrefExprState);
2187

2188 2189 2190 2191
				if (parent && IsA(parent, AggState))
				{
					AggState   *aggstate = (AggState *) parent;
					int			naggs;
2192

2193 2194
					aggstate->aggs = lcons(astate, aggstate->aggs);
					naggs = ++aggstate->numaggs;
2195

2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209
					astate->target = ExecInitExpr(aggref->target, parent);

					/*
					 * Complain if the aggregate's argument contains any
					 * aggregates; nested agg functions are semantically
					 * nonsensical.  (This probably was caught earlier,
					 * but we defend against it here anyway.)
					 */
					if (naggs != aggstate->numaggs)
						elog(ERROR, "Aggregate function calls may not be nested");
				}
				else
					elog(ERROR, "ExecInitExpr: Aggref not expected here");
				state = (ExprState *) astate;
2210 2211 2212 2213 2214
			}
			break;
		case T_ArrayRef:
			{
				ArrayRef   *aref = (ArrayRef *) node;
2215 2216 2217 2218 2219 2220 2221 2222 2223
				ArrayRefExprState *astate = makeNode(ArrayRefExprState);

				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);
2224 2225 2226 2227 2228 2229
				/* do one-time catalog lookups for type info */
				astate->refattrlength = get_typlen(aref->refarraytype);
				get_typlenbyvalalign(aref->refelemtype,
									 &astate->refelemlength,
									 &astate->refelembyval,
									 &astate->refelemalign);
2230
				state = (ExprState *) astate;
2231 2232
			}
			break;
2233
		case T_FuncExpr:
2234
			{
2235
				FuncExpr   *funcexpr = (FuncExpr *) node;
2236
				FuncExprState *fstate = makeNode(FuncExprState);
2237

2238 2239 2240 2241
				fstate->args = (List *)
					ExecInitExpr((Expr *) funcexpr->args, parent);
				fstate->func.fn_oid = InvalidOid; /* not initialized */
				state = (ExprState *) fstate;
2242 2243 2244 2245 2246
			}
			break;
		case T_OpExpr:
			{
				OpExpr   *opexpr = (OpExpr *) node;
2247
				FuncExprState *fstate = makeNode(FuncExprState);
2248

2249 2250 2251 2252
				fstate->args = (List *)
					ExecInitExpr((Expr *) opexpr->args, parent);
				fstate->func.fn_oid = InvalidOid; /* not initialized */
				state = (ExprState *) fstate;
2253 2254 2255 2256 2257
			}
			break;
		case T_DistinctExpr:
			{
				DistinctExpr   *distinctexpr = (DistinctExpr *) node;
2258
				FuncExprState *fstate = makeNode(FuncExprState);
2259

2260 2261 2262 2263
				fstate->args = (List *)
					ExecInitExpr((Expr *) distinctexpr->args, parent);
				fstate->func.fn_oid = InvalidOid; /* not initialized */
				state = (ExprState *) fstate;
2264 2265 2266 2267 2268
			}
			break;
		case T_BoolExpr:
			{
				BoolExpr   *boolexpr = (BoolExpr *) node;
2269
				BoolExprState *bstate = makeNode(BoolExprState);
2270

2271 2272 2273
				bstate->args = (List *)
					ExecInitExpr((Expr *) boolexpr->args, parent);
				state = (ExprState *) bstate;
2274 2275
			}
			break;
2276
		case T_SubPlan:
2277
			{
2278
				/* Keep this in sync with ExecInitExprInitPlan, below */
2279 2280
				SubPlan *subplan = (SubPlan *) node;
				SubPlanState *sstate = makeNode(SubPlanState);
2281 2282

				if (!parent)
2283
					elog(ERROR, "ExecInitExpr: SubPlan not expected here");
2284 2285

				/*
2286
				 * Here we just add the SubPlanState nodes to
2287
				 * parent->subPlan.  The subplans will be initialized later.
2288
				 */
2289
				parent->subPlan = lcons(sstate, parent->subPlan);
2290
				sstate->sub_estate = NULL;
2291 2292
				sstate->planstate = NULL;

2293 2294
				sstate->exprs = (List *)
					ExecInitExpr((Expr *) subplan->exprs, parent);
2295 2296
				sstate->args = (List *)
					ExecInitExpr((Expr *) subplan->args, parent);
2297

2298
				state = (ExprState *) sstate;
2299 2300 2301
			}
			break;
		case T_FieldSelect:
2302 2303 2304 2305 2306 2307 2308
			{
				FieldSelect   *fselect = (FieldSelect *) node;
				GenericExprState *gstate = makeNode(GenericExprState);

				gstate->arg = ExecInitExpr(fselect->arg, parent);
				state = (ExprState *) gstate;
			}
2309 2310
			break;
		case T_RelabelType:
2311 2312 2313 2314 2315 2316 2317
			{
				RelabelType   *relabel = (RelabelType *) node;
				GenericExprState *gstate = makeNode(GenericExprState);

				gstate->arg = ExecInitExpr(relabel->arg, parent);
				state = (ExprState *) gstate;
			}
2318 2319 2320 2321
			break;
		case T_CaseExpr:
			{
				CaseExpr   *caseexpr = (CaseExpr *) node;
2322 2323 2324
				CaseExprState *cstate = makeNode(CaseExprState);
				List	   *outlist = NIL;
				List	   *inlist;
2325

2326
				foreach(inlist, caseexpr->args)
2327
				{
2328 2329
					CaseWhen   *when = (CaseWhen *) lfirst(inlist);
					CaseWhenState *wstate = makeNode(CaseWhenState);
2330 2331

					Assert(IsA(when, CaseWhen));
2332 2333 2334 2335
					wstate->xprstate.expr = (Expr *) when;
					wstate->expr = ExecInitExpr(when->expr, parent);
					wstate->result = ExecInitExpr(when->result, parent);
					outlist = lappend(outlist, wstate);
2336
				}
2337 2338 2339 2340 2341
				cstate->args = outlist;
				/* caseexpr->arg should be null by now */
				Assert(caseexpr->arg == NULL);
				cstate->defresult = ExecInitExpr(caseexpr->defresult, parent);
				state = (ExprState *) cstate;
2342 2343
			}
			break;
2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367
		case T_ArrayExpr:
			{
				ArrayExpr	   *arrayexpr = (ArrayExpr *) node;
				ArrayExprState *astate = makeNode(ArrayExprState);
				List		   *outlist = NIL;
				List		   *inlist;

				foreach(inlist, arrayexpr->elements)
				{
					Expr	   *e = (Expr *) lfirst(inlist);
					ExprState  *estate;

					estate = ExecInitExpr(e, parent);
					outlist = lappend(outlist, estate);
				}
				astate->elements = outlist;
				/* do one-time catalog lookup for type info */
				get_typlenbyvalalign(arrayexpr->element_typeid,
									 &astate->elemlength,
									 &astate->elembyval,
									 &astate->elemalign);
				state = (ExprState *) astate;
			}
			break;
2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397
		case T_CoalesceExpr:
			{
				CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
				CoalesceExprState *cstate = makeNode(CoalesceExprState);
				List	   *outlist = NIL;
				List	   *inlist;

				foreach(inlist, coalesceexpr->args)
				{
					Expr *e = (Expr *) lfirst(inlist);
					ExprState *estate;

					estate = ExecInitExpr(e, parent);
					outlist = lappend(outlist, estate);
				}
				cstate->args = outlist;
				state = (ExprState *) cstate;
			}
			break;
		case T_NullIfExpr:
			{
				NullIfExpr *nullifexpr = (NullIfExpr *) node;
				FuncExprState *fstate = makeNode(FuncExprState);

				fstate->args = (List *)
					ExecInitExpr((Expr *) nullifexpr->args, parent);
				fstate->func.fn_oid = InvalidOid; /* not initialized */
				state = (ExprState *) fstate;
			}
			break;
2398
		case T_NullTest:
2399 2400 2401 2402 2403 2404 2405
			{
				NullTest   *ntest = (NullTest *) node;
				GenericExprState *gstate = makeNode(GenericExprState);

				gstate->arg = ExecInitExpr(ntest->arg, parent);
				state = (ExprState *) gstate;
			}
2406 2407
			break;
		case T_BooleanTest:
2408 2409 2410 2411 2412 2413 2414
			{
				BooleanTest   *btest = (BooleanTest *) node;
				GenericExprState *gstate = makeNode(GenericExprState);

				gstate->arg = ExecInitExpr(btest->arg, parent);
				state = (ExprState *) gstate;
			}
2415
			break;
2416
		case T_CoerceToDomain:
2417
			{
2418 2419
				CoerceToDomain   *ctest = (CoerceToDomain *) node;
				CoerceToDomainState *cstate = makeNode(CoerceToDomainState);
2420 2421

				cstate->arg = ExecInitExpr(ctest->arg, parent);
2422
				cstate->constraints = GetDomainConstraints(ctest->resulttype);
2423 2424
				state = (ExprState *) cstate;
			}
2425
			break;
2426
		case T_TargetEntry:
2427 2428 2429 2430 2431 2432 2433
			{
				TargetEntry   *tle = (TargetEntry *) node;
				GenericExprState *gstate = makeNode(GenericExprState);

				gstate->arg = ExecInitExpr(tle->expr, parent);
				state = (ExprState *) gstate;
			}
2434
			break;
2435 2436
		case T_List:
			{
2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447
				List	   *outlist = NIL;
				List	   *inlist;

				foreach(inlist, (List *) node)
				{
					outlist = lappend(outlist,
									  ExecInitExpr((Expr *) lfirst(inlist),
												   parent));
				}
				/* Don't fall through to the "common" code below */
				return (ExprState *) outlist;
2448 2449 2450 2451
			}
		default:
			elog(ERROR, "ExecInitExpr: unknown expression type %d",
				 nodeTag(node));
2452
			state = NULL;		/* keep compiler quiet */
2453 2454 2455
			break;
	}

2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467
	/* Common code for all state-node types */
	state->expr = node;

	return state;
}

/*
 * ExecInitExprInitPlan --- initialize a subplan expr that's being handled
 * as an InitPlan.  This is identical to ExecInitExpr's handling of a regular
 * subplan expr, except we do NOT want to add the node to the parent's
 * subplan list.
 */
2468 2469
SubPlanState *
ExecInitExprInitPlan(SubPlan *node, PlanState *parent)
2470
{
2471
	SubPlanState *sstate = makeNode(SubPlanState);
2472 2473

	if (!parent)
2474
		elog(ERROR, "ExecInitExpr: SubPlan not expected here");
2475 2476

	/* The subplan's state will be initialized later */
2477
	sstate->sub_estate = NULL;
2478 2479
	sstate->planstate = NULL;

2480
	sstate->exprs = (List *) ExecInitExpr((Expr *) node->exprs, parent);
2481 2482 2483 2484 2485
	sstate->args = (List *) ExecInitExpr((Expr *) node->args, parent);

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

	return sstate;
2486 2487
}

2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514
/*
 * 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
 * to run.  (In ordinary Plan trees the planner will have fixed opfuncids,
 * 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;
}

2515

2516
/* ----------------------------------------------------------------
2517
 *					 ExecQual / ExecTargetList / ExecProject
2518 2519 2520 2521
 * ----------------------------------------------------------------
 */

/* ----------------------------------------------------------------
2522 2523
 *		ExecQual
 *
2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546
 *		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.
 *
2547 2548 2549
 * ----------------------------------------------------------------
 */
bool
2550
ExecQual(List *qual, ExprContext *econtext, bool resultForNull)
2551
{
2552 2553
	bool		result;
	MemoryContext oldContext;
2554
	List	   *qlist;
2555

B
Bruce Momjian 已提交
2556
	/*
B
Bruce Momjian 已提交
2557
	 * debugging stuff
2558 2559 2560 2561 2562 2563 2564
	 */
	EV_printf("ExecQual: qual is ");
	EV_nodeDisplay(qual);
	EV_printf("\n");

	IncrProcessed();

2565 2566 2567 2568 2569
	/*
	 * Run in short-lived per-tuple context while computing expressions.
	 */
	oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);

B
Bruce Momjian 已提交
2570
	/*
2571
	 * Evaluate the qual conditions one at a time.	If we find a FALSE
2572 2573 2574 2575
	 * 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.
2576
	 *
2577 2578 2579 2580
	 * 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.
2581
	 */
2582
	result = true;
2583

2584
	foreach(qlist, qual)
2585
	{
2586
		ExprState  *clause = (ExprState *) lfirst(qlist);
2587 2588 2589
		Datum		expr_value;
		bool		isNull;

2590
		expr_value = ExecEvalExpr(clause, econtext, &isNull, NULL);
2591

2592
		if (isNull)
2593 2594
		{
			if (resultForNull == false)
2595
			{
B
Bruce Momjian 已提交
2596
				result = false; /* treat NULL as FALSE */
2597 2598
				break;
			}
2599 2600 2601
		}
		else
		{
B
Bruce Momjian 已提交
2602
			if (!DatumGetBool(expr_value))
2603
			{
B
Bruce Momjian 已提交
2604
				result = false; /* definitely FALSE */
2605 2606
				break;
			}
2607
		}
2608 2609
	}

2610 2611 2612
	MemoryContextSwitchTo(oldContext);

	return result;
2613 2614
}

2615 2616 2617
/*
 * Number of items in a tlist (including any resjunk items!)
 */
2618
int
2619
ExecTargetListLength(List *targetlist)
2620
{
2621 2622
	/* This used to be more complex, but fjoins are dead */
	return length(targetlist);
2623 2624
}

2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635
/*
 * Number of items in a tlist, not including any resjunk items
 */
int
ExecCleanTargetListLength(List *targetlist)
{
	int			len = 0;
	List	   *tl;

	foreach(tl, targetlist)
	{
B
Bruce Momjian 已提交
2636
		TargetEntry *curTle = (TargetEntry *) lfirst(tl);
2637

2638
		Assert(IsA(curTle, TargetEntry));
2639 2640
		if (!curTle->resdom->resjunk)
			len++;
2641 2642 2643 2644
	}
	return len;
}

2645
/* ----------------------------------------------------------------
2646 2647
 *		ExecTargetList
 *
2648 2649 2650 2651 2652 2653 2654
 *		Evaluates a targetlist with respect to the given
 *		expression context and returns a tuple.
 *
 * The caller must pass workspace for the values and nulls arrays
 * as well as the itemIsDone array.  This convention saves palloc'ing
 * workspace on each call, and some callers may find it useful to examine
 * the values array directly.
2655 2656 2657 2658 2659
 *
 * 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.
2660 2661
 * ----------------------------------------------------------------
 */
2662
static HeapTuple
2663
ExecTargetList(List *targetlist,
2664
			   TupleDesc targettype,
2665
			   ExprContext *econtext,
2666 2667 2668
			   Datum *values,
			   char *nulls,
			   ExprDoneCond *itemIsDone,
2669
			   ExprDoneCond *isDone)
2670
{
2671
	MemoryContext oldContext;
2672 2673
	List	   *tl;
	bool		isNull;
2674
	bool		haveDoneSets;
2675 2676
	static struct tupleDesc NullTupleDesc;		/* we assume this inits to
												 * zeroes */
2677

B
Bruce Momjian 已提交
2678
	/*
B
Bruce Momjian 已提交
2679
	 * debugging stuff
2680
	 */
2681 2682 2683 2684
	EV_printf("ExecTargetList: tl is ");
	EV_nodeDisplay(targetlist);
	EV_printf("\n");

2685 2686 2687 2688 2689
	/*
	 * Run in short-lived per-tuple context while computing expressions.
	 */
	oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);

B
Bruce Momjian 已提交
2690
	/*
2691 2692 2693 2694 2695 2696
	 * There used to be some klugy and demonstrably broken code here that
	 * special-cased the situation where targetlist == NIL.  Now we just
	 * fall through and return an empty-but-valid tuple.  We do, however,
	 * have to cope with the possibility that targettype is NULL ---
	 * heap_formtuple won't like that, so pass a dummy descriptor with
	 * natts = 0 to deal with it.
2697
	 */
2698 2699
	if (targettype == NULL)
		targettype = &NullTupleDesc;
2700

B
Bruce Momjian 已提交
2701
	/*
B
Bruce Momjian 已提交
2702
	 * evaluate all the expressions in the target list
2703
	 */
2704
	if (isDone)
B
Bruce Momjian 已提交
2705
		*isDone = ExprSingleResult;		/* until proven otherwise */
2706 2707

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

2709 2710
	foreach(tl, targetlist)
	{
2711 2712 2713
		GenericExprState *gstate = (GenericExprState *) lfirst(tl);
		TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
		AttrNumber	resind = tle->resdom->resno - 1;
2714

2715
		values[resind] = ExecEvalExpr(gstate->arg,
2716 2717 2718 2719
									  econtext,
									  &isNull,
									  &itemIsDone[resind]);
		nulls[resind] = isNull ? 'n' : ' ';
2720

2721
		if (itemIsDone[resind] != ExprSingleResult)
2722
		{
2723 2724 2725 2726
			/* We have a set-valued expression in the tlist */
			if (isDone == NULL)
				elog(ERROR, "Set-valued function called in context that cannot accept a set");
			if (itemIsDone[resind] == ExprMultipleResult)
2727
			{
2728 2729
				/* we have undone sets in the tlist, set flag */
				*isDone = ExprMultipleResult;
2730
			}
2731
			else
2732
			{
2733 2734
				/* we have done sets in the tlist, set flag for that */
				haveDoneSets = true;
2735
			}
2736 2737
		}
	}
2738

2739
	if (haveDoneSets)
2740
	{
2741 2742 2743 2744
		/*
		 * note: can't get here unless we verified isDone != NULL
		 */
		if (*isDone == ExprSingleResult)
2745
		{
2746
			/*
B
Bruce Momjian 已提交
2747 2748
			 * all sets are done, so report that tlist expansion is
			 * complete.
2749
			 */
2750 2751
			*isDone = ExprEndResult;
			MemoryContextSwitchTo(oldContext);
2752
			return NULL;
2753 2754 2755
		}
		else
		{
2756
			/*
B
Bruce Momjian 已提交
2757
			 * We have some done and some undone sets.	Restart the done
2758
			 * ones so that we can deliver a tuple (if possible).
2759 2760 2761
			 */
			foreach(tl, targetlist)
			{
2762 2763 2764
				GenericExprState *gstate = (GenericExprState *) lfirst(tl);
				TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
				AttrNumber	resind = tle->resdom->resno - 1;
2765

2766
				if (itemIsDone[resind] == ExprEndResult)
2767
				{
2768 2769 2770 2771 2772
					values[resind] = ExecEvalExpr(gstate->arg,
												  econtext,
												  &isNull,
												  &itemIsDone[resind]);
					nulls[resind] = isNull ? 'n' : ' ';
2773

2774
					if (itemIsDone[resind] == ExprEndResult)
2775
					{
2776 2777 2778 2779 2780 2781
						/*
						 * Oh dear, this item is returning an empty
						 * set. Guess we can't make a tuple after all.
						 */
						*isDone = ExprEndResult;
						break;
2782 2783 2784
					}
				}
			}
B
Bruce Momjian 已提交
2785

2786
			/*
B
Bruce Momjian 已提交
2787 2788 2789
			 * 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.
2790 2791
			 *
			 * XXX is that still necessary?
2792 2793 2794 2795 2796
			 */
			if (*isDone == ExprEndResult)
			{
				foreach(tl, targetlist)
				{
2797 2798 2799
					GenericExprState *gstate = (GenericExprState *) lfirst(tl);
					TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
					AttrNumber	resind = tle->resdom->resno - 1;
2800

2801
					while (itemIsDone[resind] == ExprMultipleResult)
2802
					{
2803 2804 2805 2806
						(void) ExecEvalExpr(gstate->arg,
											econtext,
											&isNull,
											&itemIsDone[resind]);
2807 2808
					}
				}
2809 2810

				MemoryContextSwitchTo(oldContext);
2811
				return NULL;
2812 2813 2814 2815
			}
		}
	}

B
Bruce Momjian 已提交
2816
	/*
2817
	 * form the new result tuple (in the caller's memory context!)
2818
	 */
2819 2820
	MemoryContextSwitchTo(oldContext);

2821
	return heap_formtuple(targettype, values, nulls);
2822 2823 2824
}

/* ----------------------------------------------------------------
2825 2826
 *		ExecProject
 *
2827
 *		projects a tuple based on projection info and stores
2828
 *		it in the specified tuple table slot.
2829
 *
2830 2831 2832 2833 2834
 *		Note: someday soon the executor can be extended to eliminate
 *			  redundant projections by storing pointers to datums
 *			  in the tuple table and then passing these around when
 *			  possible.  this should make things much quicker.
 *			  -cim 6/3/91
2835 2836 2837
 * ----------------------------------------------------------------
 */
TupleTableSlot *
2838
ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
2839
{
2840
	TupleTableSlot *slot;
2841 2842
	TupleDesc	tupType;
	HeapTuple	newTuple;
2843

B
Bruce Momjian 已提交
2844
	/*
B
Bruce Momjian 已提交
2845
	 * sanity checks
2846 2847 2848
	 */
	if (projInfo == NULL)
		return (TupleTableSlot *) NULL;
2849

B
Bruce Momjian 已提交
2850
	/*
B
Bruce Momjian 已提交
2851
	 * get the projection info we want
2852 2853 2854 2855
	 */
	slot = projInfo->pi_slot;
	tupType = slot->ttc_tupleDescriptor;

B
Bruce Momjian 已提交
2856
	/*
2857
	 * form a new result tuple (if possible --- result can be NULL)
2858
	 */
2859
	newTuple = ExecTargetList(projInfo->pi_targetlist,
2860
							  tupType,
2861 2862 2863 2864
							  projInfo->pi_exprContext,
							  projInfo->pi_tupValues,
							  projInfo->pi_tupNulls,
							  projInfo->pi_itemIsDone,
2865 2866
							  isDone);

B
Bruce Momjian 已提交
2867
	/*
B
Bruce Momjian 已提交
2868
	 * store the tuple in the projection slot and return the slot.
2869
	 */
B
Bruce Momjian 已提交
2870 2871 2872
	return ExecStoreTuple(newTuple,		/* tuple to store */
						  slot, /* slot to store in */
						  InvalidBuffer,		/* tuple has no buffer */
2873
						  true);
2874
}