execQual.c 51.2 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * execQual.c
4
 *	  Routines to evaluate qualification and targetlist expressions
5
 *
6
 * Portions Copyright (c) 1996-2001, 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.88 2001/09/21 00:11:30 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"
B
Bruce Momjian 已提交
38
#include "executor/execFlatten.h"
39
#include "executor/execdebug.h"
40
#include "executor/functions.h"
V
Vadim B. Mikheev 已提交
41
#include "executor/nodeSubplan.h"
42
#include "utils/array.h"
43
#include "utils/builtins.h"
44
#include "utils/fcache.h"
B
Bruce Momjian 已提交
45

46

47
/* static function decls */
48
static Datum ExecEvalAggref(Aggref *aggref, ExprContext *econtext,
B
Bruce Momjian 已提交
49
			   bool *isNull);
50
static Datum ExecEvalArrayRef(ArrayRef *arrayRef, ExprContext *econtext,
B
Bruce Momjian 已提交
51
				 bool *isNull, ExprDoneCond *isDone);
52
static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull);
53
static Datum ExecEvalOper(Expr *opClause, ExprContext *econtext,
B
Bruce Momjian 已提交
54
			 bool *isNull, ExprDoneCond *isDone);
55
static Datum ExecEvalFunc(Expr *funcClause, ExprContext *econtext,
B
Bruce Momjian 已提交
56
			 bool *isNull, ExprDoneCond *isDone);
57 58
static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo,
				 List *argList, ExprContext *econtext);
59
static Datum ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull);
60
static Datum ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull);
61
static Datum ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull);
62
static Datum ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
B
Bruce Momjian 已提交
63
			 bool *isNull, ExprDoneCond *isDone);
64 65 66 67
static Datum ExecEvalNullTest(NullTest *ntest, ExprContext *econtext,
			 bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalBooleanTest(BooleanTest *btest, ExprContext *econtext,
			 bool *isNull, ExprDoneCond *isDone);
68

69

70
/*----------
71
 *	  ExecEvalArrayRef
72
 *
73 74
 *	   This function takes an ArrayRef and returns the extracted Datum
 *	   if it's a simple reference, or the modified array value if it's
75 76 77 78 79 80 81 82
 *	   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 已提交
83
 * very desirable.	By returning the source array we make the assignment
84 85 86
 * 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.)
87 88 89 90 91 92
 *
 * 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).
93
 *----------
B
Bruce Momjian 已提交
94
 */
95
static Datum
B
Bruce Momjian 已提交
96
ExecEvalArrayRef(ArrayRef *arrayRef,
97 98
				 ExprContext *econtext,
				 bool *isNull,
99
				 ExprDoneCond *isDone)
100
{
101 102
	ArrayType  *array_source;
	ArrayType  *resultArray;
103
	bool		isAssignment = (arrayRef->refassgnexpr != NULL);
104
	List	   *elt;
105 106
	int			i = 0,
				j = 0;
107 108 109
	IntArray	upper,
				lower;
	int		   *lIndex;
110

111 112
	if (arrayRef->refexpr != NULL)
	{
113
		array_source = (ArrayType *)
114 115 116 117
			DatumGetPointer(ExecEvalExpr(arrayRef->refexpr,
										 econtext,
										 isNull,
										 isDone));
B
Bruce Momjian 已提交
118

119 120
		/*
		 * If refexpr yields NULL, result is always NULL, for now anyway.
B
Bruce Momjian 已提交
121 122
		 * (This means you cannot assign to an element or slice of an
		 * array that's NULL; it'll just stay NULL.)
123
		 */
124 125 126 127 128
		if (*isNull)
			return (Datum) NULL;
	}
	else
	{
129 130

		/*
131
		 * Empty refexpr indicates we are doing an INSERT into an array
132 133 134 135 136
		 * 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...
137
		 */
138
		array_source = NULL;
139
	}
140

141
	foreach(elt, arrayRef->refupperindexpr)
142
	{
143 144 145 146
		if (i >= MAXDIM)
			elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
				 MAXDIM);

147 148 149
		upper.indx[i++] = DatumGetInt32(ExecEvalExpr((Node *) lfirst(elt),
													 econtext,
													 isNull,
150
													 NULL));
151
		/* If any index expr yields NULL, result is NULL or source array */
152
		if (*isNull)
153
		{
B
Bruce Momjian 已提交
154
			if (!isAssignment || array_source == NULL)
155 156 157 158
				return (Datum) NULL;
			*isNull = false;
			return PointerGetDatum(array_source);
		}
159 160
	}

161
	if (arrayRef->reflowerindexpr != NIL)
162
	{
163
		foreach(elt, arrayRef->reflowerindexpr)
164
		{
165 166 167 168
			if (j >= MAXDIM)
				elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
					 MAXDIM);

169 170 171
			lower.indx[j++] = DatumGetInt32(ExecEvalExpr((Node *) lfirst(elt),
														 econtext,
														 isNull,
172
														 NULL));
B
Bruce Momjian 已提交
173 174 175 176 177

			/*
			 * If any index expr yields NULL, result is NULL or source
			 * array
			 */
178
			if (*isNull)
179
			{
B
Bruce Momjian 已提交
180
				if (!isAssignment || array_source == NULL)
181 182 183 184
					return (Datum) NULL;
				*isNull = false;
				return PointerGetDatum(array_source);
			}
185 186
		}
		if (i != j)
187
			elog(ERROR,
188 189
				 "ExecEvalArrayRef: upper and lower indices mismatch");
		lIndex = lower.indx;
190
	}
191 192
	else
		lIndex = NULL;
193

194
	if (isAssignment)
195
	{
196 197 198
		Datum		sourceData = ExecEvalExpr(arrayRef->refassgnexpr,
											  econtext,
											  isNull,
199
											  NULL);
B
Bruce Momjian 已提交
200

201
		/*
B
Bruce Momjian 已提交
202 203
		 * For now, can't cope with inserting NULL into an array, so make
		 * it a no-op per discussion above...
204
		 */
205
		if (*isNull)
206 207 208 209 210 211
		{
			if (array_source == NULL)
				return (Datum) NULL;
			*isNull = false;
			return PointerGetDatum(array_source);
		}
212

213
		if (array_source == NULL)
B
Bruce Momjian 已提交
214
			return sourceData;	/* XXX do something else? */
215

216
		if (lIndex == NULL)
217 218 219 220 221 222 223 224 225 226
			resultArray = array_set(array_source, i,
									upper.indx,
									sourceData,
									arrayRef->refelembyval,
									arrayRef->refelemlength,
									arrayRef->refattrlength,
									isNull);
		else
			resultArray = array_set_slice(array_source, i,
										  upper.indx, lower.indx,
B
Bruce Momjian 已提交
227
							   (ArrayType *) DatumGetPointer(sourceData),
228 229 230 231 232
										  arrayRef->refelembyval,
										  arrayRef->refelemlength,
										  arrayRef->refattrlength,
										  isNull);
		return PointerGetDatum(resultArray);
233
	}
234

235
	if (lIndex == NULL)
236
		return array_ref(array_source, i,
237 238 239 240 241
						 upper.indx,
						 arrayRef->refelembyval,
						 arrayRef->refelemlength,
						 arrayRef->refattrlength,
						 isNull);
242 243 244
	else
	{
		resultArray = array_get_slice(array_source, i,
245 246 247
									  upper.indx, lower.indx,
									  arrayRef->refelembyval,
									  arrayRef->refelemlength,
248 249 250 251
									  arrayRef->refattrlength,
									  isNull);
		return PointerGetDatum(resultArray);
	}
252 253 254 255
}


/* ----------------------------------------------------------------
B
Bruce Momjian 已提交
256
 *		ExecEvalAggref
257 258 259
 *
 *		Returns a Datum whose value is the value of the precomputed
 *		aggregate found in the given expression context.
260 261
 * ----------------------------------------------------------------
 */
262
static Datum
263
ExecEvalAggref(Aggref *aggref, ExprContext *econtext, bool *isNull)
264
{
265
	if (econtext->ecxt_aggvalues == NULL)		/* safety check */
266 267
		elog(ERROR, "ExecEvalAggref: no aggregates in this expression context");

268 269
	*isNull = econtext->ecxt_aggnulls[aggref->aggno];
	return econtext->ecxt_aggvalues[aggref->aggno];
270 271 272
}

/* ----------------------------------------------------------------
273 274 275 276 277 278
 *		ExecEvalVar
 *
 *		Returns a Datum whose value is the value of a range
 *		variable with respect to given expression context.
 *
 *
T
Thomas G. Lockhart 已提交
279
 *		As an entry condition, we expect that the datatype the
280 281 282 283 284 285 286 287 288 289 290
 *		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.
291
 *
292
 *		We have an Assert to make sure this entry condition is met.
293 294
 *
 * ---------------------------------------------------------------- */
295
static Datum
296
ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull)
297
{
298
	Datum		result;
299
	TupleTableSlot *slot;
300 301 302
	AttrNumber	attnum;
	HeapTuple	heapTuple;
	TupleDesc	tuple_type;
303

B
Bruce Momjian 已提交
304
	/*
B
Bruce Momjian 已提交
305
	 * get the slot we want
306 307 308
	 */
	switch (variable->varno)
	{
309 310 311
		case INNER:				/* get the tuple from the inner node */
			slot = econtext->ecxt_innertuple;
			break;
312

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

317
		default:				/* get the tuple from the relation being
318
								 * scanned */
319 320
			slot = econtext->ecxt_scantuple;
			break;
321 322
	}

B
Bruce Momjian 已提交
323
	/*
B
Bruce Momjian 已提交
324
	 * extract tuple information from the slot
325 326 327 328 329 330 331 332 333 334
	 */
	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 &&
335
		  variable->vartype == tuple_type->attrs[attnum - 1]->atttypid));
336 337 338

	/*
	 * If the attribute number is invalid, then we are supposed to return
339 340 341 342 343 344 345 346 347 348 349 350 351
	 * the entire tuple; we give back a whole slot so that callers know
	 * what the tuple looks like.
	 *
	 * 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
	 * 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.
352
	 */
353
	if (attnum == InvalidAttrNumber)
354
	{
355 356
		MemoryContext oldContext;
		TupleTableSlot *tempSlot;
357
		HeapTuple	tup;
358

359 360
		oldContext = MemoryContextSwitchTo(TransactionCommandContext);
		tempSlot = MakeTupleTableSlot();
361
		tup = heap_copytuple(heapTuple);
362
		ExecStoreTuple(tup, tempSlot, InvalidBuffer, true);
363 364
		ExecSetSlotDescriptor(tempSlot, tuple_type, false);
		MemoryContextSwitchTo(oldContext);
365
		return PointerGetDatum(tempSlot);
366
	}
367

368 369 370 371 372
	result = heap_getattr(heapTuple,	/* tuple containing attribute */
						  attnum,		/* attribute number of desired
										 * attribute */
						  tuple_type,	/* tuple descriptor of tuple */
						  isNull);		/* return: is attribute null? */
373 374

	return result;
375 376 377
}

/* ----------------------------------------------------------------
378
 *		ExecEvalParam
379
 *
380 381 382 383 384
 *		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)...
 *		so our job is to replace the param node with the datum
 *		containing the appropriate information ("sam").
385
 *
386 387 388 389 390
 *		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"
 *		   (in which case we shoud return a Const node with the
 *			isnull flag) ?	-cim 10/13/89
391
 *
392 393 394 395 396 397 398
 *		Minor modification: Param nodes now have an extra field,
 *		`paramkind' which specifies the type of parameter
 *		(see params.h). So while searching the paramList for
 *		a paramname/value pair, we have also to check for `kind'.
 *
 *		NOTE: The last entry in `paramList' is always an
 *		entry with kind == PARAM_INVALID.
399 400 401
 * ----------------------------------------------------------------
 */
Datum
402
ExecEvalParam(Param *expression, ExprContext *econtext, bool *isNull)
403
{
404
	char	   *thisParameterName;
V
Vadim B. Mikheev 已提交
405 406
	int			thisParameterKind = expression->paramkind;
	AttrNumber	thisParameterId = expression->paramid;
407 408
	int			matchFound;
	ParamListInfo paramList;
409 410

	if (thisParameterKind == PARAM_EXEC)
V
Vadim B. Mikheev 已提交
411
	{
412
		ParamExecData *prm;
413

414
		prm = &(econtext->ecxt_param_exec_vals[thisParameterId]);
415
		if (prm->execPlan != NULL)
416 417 418 419 420
		{
			ExecSetParamPlan(prm->execPlan, econtext);
			/* ExecSetParamPlan should have processed this param... */
			Assert(prm->execPlan == NULL);
		}
V
Vadim B. Mikheev 已提交
421
		*isNull = prm->isnull;
422
		return prm->value;
V
Vadim B. Mikheev 已提交
423
	}
424

425 426 427 428 429
	thisParameterName = expression->paramname;
	paramList = econtext->ecxt_param_list_info;

	*isNull = false;

430
	/*
431 432
	 * search the list with the parameter info to find a matching name. An
	 * entry with an InvalidName denotes the last element in the array.
433
	 */
434 435 436 437 438 439 440 441 442 443 444 445
	matchFound = 0;
	if (paramList != NULL)
	{

		/*
		 * search for an entry in 'paramList' that matches the
		 * `expression'.
		 */
		while (paramList->kind != PARAM_INVALID && !matchFound)
		{
			switch (thisParameterKind)
			{
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
				case PARAM_NAMED:
					if (thisParameterKind == paramList->kind &&
						strcmp(paramList->name, thisParameterName) == 0)
						matchFound = 1;
					break;
				case PARAM_NUM:
					if (thisParameterKind == paramList->kind &&
						paramList->id == thisParameterId)
						matchFound = 1;
					break;
				case PARAM_OLD:
				case PARAM_NEW:
					if (thisParameterKind == paramList->kind &&
						paramList->id == thisParameterId)
					{
						matchFound = 1;

						/*
						 * sanity check
						 */
						if (strcmp(paramList->name, thisParameterName) != 0)
						{
468
							elog(ERROR,
469 470 471 472 473
								 "ExecEvalParam: new/old params with same id & diff names");
						}
					}
					break;
				default:
474

475 476 477
					/*
					 * oops! this is not supposed to happen!
					 */
478
					elog(ERROR, "ExecEvalParam: invalid paramkind %d",
479
						 thisParameterKind);
480
			}
481 482 483 484 485 486 487 488
			if (!matchFound)
				paramList++;
		}						/* while */
	}							/* if */

	if (!matchFound)
	{

489
		/*
490 491
		 * ooops! we couldn't find this parameter in the parameter list.
		 * Signal an error
492
		 */
493
		elog(ERROR, "ExecEvalParam: Unknown value for parameter %s",
494 495 496
			 thisParameterName);
	}

497
	/*
498
	 * return the value.
499
	 */
500
	*isNull = paramList->isnull;
501
	return paramList->value;
502 503 504 505
}


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

B
Bruce Momjian 已提交
510
/*
511 512
 *		GetAttributeByName
 *		GetAttributeByNum
513
 *
514 515 516 517
 *		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().
518
 */
519
Datum
520
GetAttributeByNum(TupleTableSlot *slot,
521
				  AttrNumber attrno,
522
				  bool *isNull)
523
{
524
	Datum		retval;
525 526

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

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

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

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

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

	return retval;
549
}
550

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

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

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

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

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

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

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

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

	return retval;
596 597
}

598 599 600 601
/*
 * Evaluate arguments for a function.
 */
static ExprDoneCond
602
ExecEvalFuncArgs(FunctionCallInfo fcinfo,
603
				 List *argList,
604
				 ExprContext *econtext)
605
{
606
	ExprDoneCond argIsDone;
607 608
	int			i;
	List	   *arg;
609

B
Bruce Momjian 已提交
610
	argIsDone = ExprSingleResult;		/* default assumption */
611

612 613 614
	i = 0;
	foreach(arg, argList)
	{
B
Bruce Momjian 已提交
615
		ExprDoneCond thisArgIsDone;
B
Bruce Momjian 已提交
616

617 618 619 620
		fcinfo->arg[i] = ExecEvalExpr((Node *) lfirst(arg),
									  econtext,
									  &fcinfo->argnull[i],
									  &thisArgIsDone);
621

622
		if (thisArgIsDone != ExprSingleResult)
623
		{
624 625
			/*
			 * We allow only one argument to have a set value; we'd need
B
Bruce Momjian 已提交
626 627 628
			 * much more complexity to keep track of multiple set
			 * arguments (cf. ExecTargetList) and it doesn't seem worth
			 * it.
629 630 631 632
			 */
			if (argIsDone != ExprSingleResult)
				elog(ERROR, "Functions and operators can take only one set argument");
			argIsDone = thisArgIsDone;
633 634 635
		}
		i++;
	}
636

637 638
	fcinfo->nargs = i;

639
	return argIsDone;
640 641
}

B
Bruce Momjian 已提交
642
/*
643
 *		ExecMakeFunctionResult
644 645 646 647 648
 *
 * Evaluate the arguments to a function and then the function itself.
 *
 * NOTE: econtext is used only for evaluating the argument expressions;
 * it is not passed to the function itself.
649
 */
650 651
Datum
ExecMakeFunctionResult(FunctionCachePtr fcache,
652 653 654
					   List *arguments,
					   ExprContext *econtext,
					   bool *isNull,
655
					   ExprDoneCond *isDone)
656
{
B
Bruce Momjian 已提交
657
	Datum		result;
658 659
	FunctionCallInfoData fcinfo;
	ReturnSetInfo rsinfo;		/* for functions returning sets */
B
Bruce Momjian 已提交
660
	ExprDoneCond argDone;
661
	bool		hasSetArg;
B
Bruce Momjian 已提交
662
	int			i;
663

B
Bruce Momjian 已提交
664
	/*
B
Bruce Momjian 已提交
665
	 * arguments is a list of expressions to evaluate before passing to
666
	 * the function manager.  We skip the evaluation if it was already
B
Bruce Momjian 已提交
667 668
	 * done in the previous call (ie, we are continuing the evaluation of
	 * a set-valued function).	Otherwise, collect the current argument
669
	 * values into fcinfo.
670
	 */
671
	if (!fcache->setArgsValid)
672
	{
673 674 675 676
		/* Need to prep callinfo structure */
		MemSet(&fcinfo, 0, sizeof(fcinfo));
		fcinfo.flinfo = &(fcache->func);
		argDone = ExecEvalFuncArgs(&fcinfo, arguments, econtext);
677
		if (argDone == ExprEndResult)
678
		{
679
			/* input is an empty set, so return an empty set. */
680
			*isNull = true;
681 682 683 684
			if (isDone)
				*isDone = ExprEndResult;
			else
				elog(ERROR, "Set-valued function called in context that cannot accept a set");
685
			return (Datum) 0;
686
		}
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
		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;
706
	}
707

B
Bruce Momjian 已提交
708
	/*
B
Bruce Momjian 已提交
709 710
	 * now return the value gotten by calling the function manager,
	 * passing the function the evaluated parameter values.
711
	 */
712
	if (fcache->func.fn_retset || hasSetArg)
713
	{
714
		/*
B
Bruce Momjian 已提交
715
		 * We need to return a set result.	Complain if caller not ready
716 717 718 719 720 721
		 * to accept one.
		 */
		if (isDone == NULL)
			elog(ERROR, "Set-valued function called in context that cannot accept a set");

		/*
B
Bruce Momjian 已提交
722 723 724 725 726 727
		 * 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.
728
		 */
729
		for (;;)
730
		{
731 732 733 734
			/*
			 * If function is strict, and there are any NULL arguments,
			 * skip calling the function (at least for this set of args).
			 */
B
Bruce Momjian 已提交
735
			bool		callit = true;
736

737
			if (fcache->func.fn_strict)
738
			{
739
				for (i = 0; i < fcinfo.nargs; i++)
740
				{
741
					if (fcinfo.argnull[i])
742 743 744 745 746 747 748 749 750
					{
						callit = false;
						break;
					}
				}
			}

			if (callit)
			{
751 752 753 754 755
				fcinfo.isnull = false;
				rsinfo.isDone = ExprSingleResult;
				result = FunctionCallInvoke(&fcinfo);
				*isNull = fcinfo.isnull;
				*isDone = rsinfo.isDone;
756 757 758 759 760
			}
			else
			{
				result = (Datum) 0;
				*isNull = true;
761 762 763 764 765 766
				*isDone = ExprEndResult;
			}

			if (*isDone != ExprEndResult)
			{
				/*
B
Bruce Momjian 已提交
767
				 * Got a result from current argument.	If function itself
768 769
				 * returns set, save the current argument values to re-use
				 * on the next call.
770 771
				 */
				if (fcache->func.fn_retset)
772 773 774 775 776
				{
					memcpy(&fcache->setArgs, &fcinfo, sizeof(fcinfo));
					fcache->setHasSetArg = hasSetArg;
					fcache->setArgsValid = true;
				}
B
Bruce Momjian 已提交
777

778 779 780 781 782 783
				/*
				 * Make sure we say we are returning a set, even if the
				 * function itself doesn't return sets.
				 */
				*isDone = ExprMultipleResult;
				break;
784
			}
785

786
			/* Else, done with this argument */
787
			if (!hasSetArg)
788
				break;			/* input not a set, so done */
789

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

793
			if (argDone != ExprMultipleResult)
794
			{
795
				/* End of argument set, so we're done. */
796
				*isNull = true;
797
				*isDone = ExprEndResult;
798
				result = (Datum) 0;
799
				break;
800
			}
801

802 803
			/*
			 * If we reach here, loop around to run the function on the
804 805
			 * new argument.
			 */
806
		}
807
	}
808
	else
809
	{
810
		/*
811 812
		 * Non-set case: much easier.
		 *
B
Bruce Momjian 已提交
813 814
		 * If function is strict, and there are any NULL arguments, skip
		 * calling the function and return NULL.
815
		 */
816
		if (fcache->func.fn_strict)
817
		{
818
			for (i = 0; i < fcinfo.nargs; i++)
819
			{
820
				if (fcinfo.argnull[i])
821 822 823 824 825 826
				{
					*isNull = true;
					return (Datum) 0;
				}
			}
		}
827 828 829
		fcinfo.isnull = false;
		result = FunctionCallInvoke(&fcinfo);
		*isNull = fcinfo.isnull;
830
	}
831 832

	return result;
833 834 835 836
}


/* ----------------------------------------------------------------
837 838 839 840
 *		ExecEvalOper
 *		ExecEvalFunc
 *
 *		Evaluate the functional result of a list of arguments by calling the
841
 *		function manager.
842 843 844 845
 * ----------------------------------------------------------------
 */

/* ----------------------------------------------------------------
846
 *		ExecEvalOper
847 848
 * ----------------------------------------------------------------
 */
849
static Datum
850 851 852 853
ExecEvalOper(Expr *opClause,
			 ExprContext *econtext,
			 bool *isNull,
			 ExprDoneCond *isDone)
854
{
855 856
	Oper	   *op;
	List	   *argList;
857 858
	FunctionCachePtr fcache;

B
Bruce Momjian 已提交
859
	/*
B
Bruce Momjian 已提交
860 861 862 863
	 * we extract the oid of the function associated with the op and then
	 * pass the work onto ExecMakeFunctionResult which evaluates the
	 * arguments and returns the result of calling the function on the
	 * evaluated arguments.
864 865 866 867 868 869 870 871 872 873 874
	 */
	op = (Oper *) opClause->oper;
	argList = opClause->args;

	/*
	 * get the fcache from the Oper node. If it is NULL, then initialize
	 * it
	 */
	fcache = op->op_fcache;
	if (fcache == NULL)
	{
875 876 877
		fcache = init_fcache(op->opid, length(argList),
							 econtext->ecxt_per_query_memory);
		op->op_fcache = fcache;
878 879
	}

880 881
	return ExecMakeFunctionResult(fcache, argList, econtext,
								  isNull, isDone);
882 883 884
}

/* ----------------------------------------------------------------
885
 *		ExecEvalFunc
886 887 888
 * ----------------------------------------------------------------
 */

889
static Datum
890 891 892
ExecEvalFunc(Expr *funcClause,
			 ExprContext *econtext,
			 bool *isNull,
893
			 ExprDoneCond *isDone)
894
{
895 896
	Func	   *func;
	List	   *argList;
897 898
	FunctionCachePtr fcache;

B
Bruce Momjian 已提交
899
	/*
B
Bruce Momjian 已提交
900 901 902
	 * we extract the oid of the function associated with the func node
	 * and then pass the work onto ExecMakeFunctionResult which evaluates
	 * the arguments and returns the result of calling the function on the
B
Bruce Momjian 已提交
903
	 * evaluated arguments.
904
	 *
B
Bruce Momjian 已提交
905
	 * this is nearly identical to the ExecEvalOper code.
906 907 908 909 910 911 912 913 914 915 916
	 */
	func = (Func *) funcClause->oper;
	argList = funcClause->args;

	/*
	 * get the fcache from the Func node. If it is NULL, then initialize
	 * it
	 */
	fcache = func->func_fcache;
	if (fcache == NULL)
	{
917 918 919
		fcache = init_fcache(func->funcid, length(argList),
							 econtext->ecxt_per_query_memory);
		func->func_fcache = fcache;
920 921
	}

922
	return ExecMakeFunctionResult(fcache, argList, econtext,
923
								  isNull, isDone);
924 925 926
}

/* ----------------------------------------------------------------
927 928 929
 *		ExecEvalNot
 *		ExecEvalOr
 *		ExecEvalAnd
930
 *
931 932 933 934 935 936 937 938 939
 *		Evaluate boolean expressions.  Evaluation of 'or' is
 *		short-circuited when the first true (or null) value is found.
 *
 *		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...
940 941
 * ----------------------------------------------------------------
 */
942
static Datum
943
ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull)
944
{
945
	Node	   *clause;
946
	Datum		expr_value;
947 948

	clause = lfirst(notclause->args);
949

950
	expr_value = ExecEvalExpr(clause, econtext, isNull, NULL);
951

B
Bruce Momjian 已提交
952
	/*
B
Bruce Momjian 已提交
953 954
	 * if the expression evaluates to null, then we just cascade the null
	 * back to whoever called us.
955 956
	 */
	if (*isNull)
957 958
		return expr_value;

B
Bruce Momjian 已提交
959
	/*
B
Bruce Momjian 已提交
960 961
	 * evaluation of 'not' is simple.. expr is false, then return 'true'
	 * and vice versa.
962
	 */
B
Bruce Momjian 已提交
963
	return BoolGetDatum(!DatumGetBool(expr_value));
964 965 966
}

/* ----------------------------------------------------------------
967
 *		ExecEvalOr
968 969
 * ----------------------------------------------------------------
 */
970
static Datum
971
ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull)
972
{
973 974
	List	   *clauses;
	List	   *clause;
975 976
	bool		AnyNull;
	Datum		clause_value;
977 978

	clauses = orExpr->args;
979
	AnyNull = false;
980

B
Bruce Momjian 已提交
981
	/*
982 983
	 * 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
984 985 986 987 988 989
	 * 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
990 991 992 993
	 * 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.
994
	 */
995 996
	foreach(clause, clauses)
	{
997
		clause_value = ExecEvalExpr((Node *) lfirst(clause),
998
									econtext, isNull, NULL);
999

B
Bruce Momjian 已提交
1000
		/*
1001
		 * if we have a non-null true result, then return it.
1002 1003
		 */
		if (*isNull)
1004
			AnyNull = true;		/* remember we got a null */
1005
		else if (DatumGetBool(clause_value))
1006
			return clause_value;
1007 1008
	}

1009 1010
	/* AnyNull is true if at least one clause evaluated to NULL */
	*isNull = AnyNull;
1011
	return BoolGetDatum(false);
1012 1013 1014 1015 1016 1017
}

/* ----------------------------------------------------------------
 *		ExecEvalAnd
 * ----------------------------------------------------------------
 */
1018
static Datum
1019
ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull)
1020
{
1021 1022
	List	   *clauses;
	List	   *clause;
1023 1024
	bool		AnyNull;
	Datum		clause_value;
1025 1026

	clauses = andExpr->args;
1027
	AnyNull = false;
1028

B
Bruce Momjian 已提交
1029
	/*
1030 1031 1032
	 * 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
1033
	 * NULL, we return NULL; otherwise we return TRUE.	This makes sense
1034 1035
	 * when you interpret NULL as "don't know", using the same sort of
	 * reasoning as for OR, above.
1036
	 */
1037 1038
	foreach(clause, clauses)
	{
1039
		clause_value = ExecEvalExpr((Node *) lfirst(clause),
1040
									econtext, isNull, NULL);
1041

B
Bruce Momjian 已提交
1042
		/*
1043
		 * if we have a non-null false result, then return it.
1044 1045
		 */
		if (*isNull)
1046
			AnyNull = true;		/* remember we got a null */
B
Bruce Momjian 已提交
1047
		else if (!DatumGetBool(clause_value))
1048
			return clause_value;
1049 1050
	}

1051 1052
	/* AnyNull is true if at least one clause evaluated to NULL */
	*isNull = AnyNull;
1053
	return BoolGetDatum(!AnyNull);
1054 1055
}

T
Thomas G. Lockhart 已提交
1056 1057 1058 1059
/* ----------------------------------------------------------------
 *		ExecEvalCase
 *
 *		Evaluate a CASE clause. Will have boolean expressions
1060
 *		inside the WHEN clauses, and will have expressions
T
Thomas G. Lockhart 已提交
1061 1062 1063 1064 1065
 *		for results.
 *		- thomas 1998-11-09
 * ----------------------------------------------------------------
 */
static Datum
1066 1067
ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
			 bool *isNull, ExprDoneCond *isDone)
T
Thomas G. Lockhart 已提交
1068 1069 1070
{
	List	   *clauses;
	List	   *clause;
1071
	Datum		clause_value;
T
Thomas G. Lockhart 已提交
1072 1073 1074

	clauses = caseExpr->args;

B
Bruce Momjian 已提交
1075
	/*
B
Bruce Momjian 已提交
1076 1077
	 * 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
1078
	 * return the value of the default clause, or NULL if there is none.
T
Thomas G. Lockhart 已提交
1079 1080 1081
	 */
	foreach(clause, clauses)
	{
1082
		CaseWhen   *wclause = lfirst(clause);
T
Thomas G. Lockhart 已提交
1083

1084 1085 1086
		clause_value = ExecEvalExpr(wclause->expr,
									econtext,
									isNull,
1087
									NULL);
T
Thomas G. Lockhart 已提交
1088

B
Bruce Momjian 已提交
1089
		/*
B
Bruce Momjian 已提交
1090
		 * if we have a true test, then we return the result, since the
1091 1092
		 * case statement is satisfied.  A NULL result from the test is
		 * not considered true.
T
Thomas G. Lockhart 已提交
1093
		 */
1094
		if (DatumGetBool(clause_value) && !*isNull)
T
Thomas G. Lockhart 已提交
1095
		{
1096 1097 1098
			return ExecEvalExpr(wclause->result,
								econtext,
								isNull,
1099
								isDone);
T
Thomas G. Lockhart 已提交
1100 1101 1102 1103 1104
		}
	}

	if (caseExpr->defresult)
	{
1105 1106 1107
		return ExecEvalExpr(caseExpr->defresult,
							econtext,
							isNull,
1108
							isDone);
T
Thomas G. Lockhart 已提交
1109 1110
	}

1111 1112
	*isNull = true;
	return (Datum) 0;
T
Thomas G. Lockhart 已提交
1113 1114
}

1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234
/* ----------------------------------------------------------------
 *		ExecEvalNullTest
 *
 *		Evaluate a NullTest node.
 * ----------------------------------------------------------------
 */
static Datum
ExecEvalNullTest(NullTest *ntest,
				 ExprContext *econtext,
				 bool *isNull,
				 ExprDoneCond *isDone)
{
	Datum		result;

	result = ExecEvalExpr(ntest->arg, econtext, isNull, isDone);
	switch (ntest->nulltesttype)
    {
        case IS_NULL:
            if (*isNull)
            {
                *isNull = false;
                return BoolGetDatum(true);
            }
            else
                return BoolGetDatum(false);
        case IS_NOT_NULL:
            if (*isNull)
            {
                *isNull = false;
                return BoolGetDatum(false);
            }
            else
                return BoolGetDatum(true);
        default:
            elog(ERROR, "ExecEvalNullTest: unexpected nulltesttype %d",
                 (int) ntest->nulltesttype);
            return (Datum) 0;  /* keep compiler quiet */
    }
}

/* ----------------------------------------------------------------
 *		ExecEvalBooleanTest
 *
 *		Evaluate a BooleanTest node.
 * ----------------------------------------------------------------
 */
static Datum
ExecEvalBooleanTest(BooleanTest *btest,
					ExprContext *econtext,
					bool *isNull,
					ExprDoneCond *isDone)
{
	Datum		result;

	result = ExecEvalExpr(btest->arg, econtext, isNull, isDone);
	switch (btest->booltesttype)
    {
        case IS_TRUE:
            if (*isNull)
            {
                *isNull = false;
                return BoolGetDatum(false);
            }
            else if (DatumGetBool(result))
                return BoolGetDatum(true);
			else
                return BoolGetDatum(false);
        case IS_NOT_TRUE:
            if (*isNull)
            {
                *isNull = false;
                return BoolGetDatum(true);
            }
            else if (DatumGetBool(result))
                return BoolGetDatum(false);
			else
                return BoolGetDatum(true);
        case IS_FALSE:
            if (*isNull)
            {
                *isNull = false;
                return BoolGetDatum(false);
            }
            else if (DatumGetBool(result))
                return BoolGetDatum(false);
			else
                return BoolGetDatum(true);
        case IS_NOT_FALSE:
            if (*isNull)
            {
                *isNull = false;
                return BoolGetDatum(true);
            }
            else if (DatumGetBool(result))
                return BoolGetDatum(true);
			else
                return BoolGetDatum(false);
        case IS_UNKNOWN:
            if (*isNull)
            {
                *isNull = false;
                return BoolGetDatum(true);
            }
			else
                return BoolGetDatum(false);
        case IS_NOT_UNKNOWN:
            if (*isNull)
            {
                *isNull = false;
                return BoolGetDatum(false);
            }
			else
                return BoolGetDatum(true);
        default:
            elog(ERROR, "ExecEvalBooleanTest: unexpected booltesttype %d",
                 (int) btest->booltesttype);
            return (Datum) 0;  /* keep compiler quiet */
    }
}

1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
/* ----------------------------------------------------------------
 *		ExecEvalFieldSelect
 *
 *		Evaluate a FieldSelect node.
 * ----------------------------------------------------------------
 */
static Datum
ExecEvalFieldSelect(FieldSelect *fselect,
					ExprContext *econtext,
					bool *isNull,
1245
					ExprDoneCond *isDone)
1246
{
B
Bruce Momjian 已提交
1247
	Datum		result;
1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261
	TupleTableSlot *resSlot;

	result = ExecEvalExpr(fselect->arg, econtext, isNull, isDone);
	if (*isNull)
		return result;
	resSlot = (TupleTableSlot *) DatumGetPointer(result);
	Assert(resSlot != NULL && IsA(resSlot, TupleTableSlot));
	result = heap_getattr(resSlot->val,
						  fselect->fieldnum,
						  resSlot->ttc_tupleDescriptor,
						  isNull);
	return result;
}

1262 1263 1264 1265
/* ----------------------------------------------------------------
 *		ExecEvalExpr
 *
 *		Recursively evaluate a targetlist or qualification expression.
1266
 *
1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278
 * Inputs:
 *		expression: the expression tree to evaluate
 *		econtext: evaluation context information
 *
 * Outputs:
 *		return value: Datum value of result
 *		*isNull: set to TRUE if result is NULL (actual return value is
 *				 meaningless if so); set to FALSE if non-null result
 *		*isDone: set to indicator of set-result status
 *
 * A caller that can only accept a singleton (non-set) result should pass
 * NULL for isDone; if the expression computes a set result then an elog()
B
Bruce Momjian 已提交
1279
 * error will be reported.	If the caller does pass an isDone pointer then
1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290
 * *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.
1291
 *
1292 1293 1294
 * 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 已提交
1295
 * do the switch in an outer loop.	We do not do the switch here because
1296 1297 1298
 * 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.
1299 1300 1301
 * ----------------------------------------------------------------
 */
Datum
1302 1303 1304
ExecEvalExpr(Node *expression,
			 ExprContext *econtext,
			 bool *isNull,
1305
			 ExprDoneCond *isDone)
1306
{
1307
	Datum		retDatum;
1308

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

1314
	/* Is this still necessary?  Doubtful... */
1315 1316 1317
	if (expression == NULL)
	{
		*isNull = true;
1318
		return (Datum) 0;
1319 1320
	}

1321 1322 1323 1324
	/*
	 * here we dispatch the work to the appropriate type of function given
	 * the type of our expression.
	 */
1325 1326
	switch (nodeTag(expression))
	{
1327
		case T_Var:
1328
			retDatum = ExecEvalVar((Var *) expression, econtext, isNull);
1329 1330 1331 1332
			break;
		case T_Const:
			{
				Const	   *con = (Const *) expression;
1333

1334
				retDatum = con->constvalue;
1335
				*isNull = con->constisnull;
1336 1337 1338
				break;
			}
		case T_Param:
1339
			retDatum = ExecEvalParam((Param *) expression, econtext, isNull);
1340
			break;
1341
		case T_Iter:
1342 1343 1344 1345
			retDatum = ExecEvalIter((Iter *) expression,
									econtext,
									isNull,
									isDone);
1346
			break;
B
Bruce Momjian 已提交
1347
		case T_Aggref:
1348
			retDatum = ExecEvalAggref((Aggref *) expression, econtext, isNull);
1349 1350
			break;
		case T_ArrayRef:
1351 1352 1353 1354
			retDatum = ExecEvalArrayRef((ArrayRef *) expression,
										econtext,
										isNull,
										isDone);
1355 1356
			break;
		case T_Expr:
1357
			{
1358 1359 1360 1361 1362
				Expr	   *expr = (Expr *) expression;

				switch (expr->opType)
				{
					case OP_EXPR:
1363 1364
						retDatum = ExecEvalOper(expr, econtext,
												isNull, isDone);
1365 1366
						break;
					case FUNC_EXPR:
1367 1368
						retDatum = ExecEvalFunc(expr, econtext,
												isNull, isDone);
1369 1370
						break;
					case OR_EXPR:
1371
						retDatum = ExecEvalOr(expr, econtext, isNull);
1372 1373
						break;
					case AND_EXPR:
1374
						retDatum = ExecEvalAnd(expr, econtext, isNull);
1375 1376
						break;
					case NOT_EXPR:
1377
						retDatum = ExecEvalNot(expr, econtext, isNull);
1378
						break;
V
Vadim B. Mikheev 已提交
1379
					case SUBPLAN_EXPR:
1380 1381 1382
						retDatum = ExecSubPlan((SubPlan *) expr->oper,
											   expr->args, econtext,
											   isNull);
V
Vadim B. Mikheev 已提交
1383
						break;
1384
					default:
1385 1386
						elog(ERROR, "ExecEvalExpr: unknown expression type %d",
							 expr->opType);
1387
						retDatum = 0;	/* keep compiler quiet */
1388 1389
						break;
				}
1390 1391
				break;
			}
1392 1393 1394 1395 1396 1397
		case T_FieldSelect:
			retDatum = ExecEvalFieldSelect((FieldSelect *) expression,
										   econtext,
										   isNull,
										   isDone);
			break;
1398 1399 1400 1401 1402 1403
		case T_RelabelType:
			retDatum = ExecEvalExpr(((RelabelType *) expression)->arg,
									econtext,
									isNull,
									isDone);
			break;
T
Thomas G. Lockhart 已提交
1404
		case T_CaseExpr:
1405 1406 1407 1408
			retDatum = ExecEvalCase((CaseExpr *) expression,
									econtext,
									isNull,
									isDone);
T
Thomas G. Lockhart 已提交
1409
			break;
1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421
		case T_NullTest:
			retDatum = ExecEvalNullTest((NullTest *) expression,
									econtext,
									isNull,
									isDone);
			break;
		case T_BooleanTest:
			retDatum = ExecEvalBooleanTest((BooleanTest *) expression,
									econtext,
									isNull,
									isDone);
			break;
T
Thomas G. Lockhart 已提交
1422

1423
		default:
1424 1425 1426
			elog(ERROR, "ExecEvalExpr: unknown expression type %d",
				 nodeTag(expression));
			retDatum = 0;		/* keep compiler quiet */
1427
			break;
1428
	}
1429 1430

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

1433

1434 1435 1436 1437 1438 1439 1440
/*
 * Same as above, but get into the right allocation context explicitly.
 */
Datum
ExecEvalExprSwitchContext(Node *expression,
						  ExprContext *econtext,
						  bool *isNull,
1441
						  ExprDoneCond *isDone)
1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452
{
	Datum		retDatum;
	MemoryContext oldContext;

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


1453
/* ----------------------------------------------------------------
1454
 *					 ExecQual / ExecTargetList / ExecProject
1455 1456 1457 1458
 * ----------------------------------------------------------------
 */

/* ----------------------------------------------------------------
1459 1460
 *		ExecQual
 *
1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483
 *		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.
 *
1484 1485 1486
 * ----------------------------------------------------------------
 */
bool
1487
ExecQual(List *qual, ExprContext *econtext, bool resultForNull)
1488
{
1489 1490
	bool		result;
	MemoryContext oldContext;
1491
	List	   *qlist;
1492

B
Bruce Momjian 已提交
1493
	/*
B
Bruce Momjian 已提交
1494
	 * debugging stuff
1495 1496 1497 1498 1499 1500 1501
	 */
	EV_printf("ExecQual: qual is ");
	EV_nodeDisplay(qual);
	EV_printf("\n");

	IncrProcessed();

1502 1503 1504 1505 1506
	/*
	 * Run in short-lived per-tuple context while computing expressions.
	 */
	oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);

B
Bruce Momjian 已提交
1507
	/*
1508
	 * Evaluate the qual conditions one at a time.	If we find a FALSE
1509 1510 1511 1512
	 * 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.
1513
	 *
1514 1515 1516 1517
	 * 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.
1518
	 */
1519
	result = true;
1520

1521
	foreach(qlist, qual)
1522
	{
1523 1524 1525 1526
		Node	   *clause = (Node *) lfirst(qlist);
		Datum		expr_value;
		bool		isNull;

1527
		expr_value = ExecEvalExpr(clause, econtext, &isNull, NULL);
1528

1529
		if (isNull)
1530 1531
		{
			if (resultForNull == false)
1532
			{
B
Bruce Momjian 已提交
1533
				result = false; /* treat NULL as FALSE */
1534 1535
				break;
			}
1536 1537 1538
		}
		else
		{
B
Bruce Momjian 已提交
1539
			if (!DatumGetBool(expr_value))
1540
			{
B
Bruce Momjian 已提交
1541
				result = false; /* definitely FALSE */
1542 1543
				break;
			}
1544
		}
1545 1546
	}

1547 1548 1549
	MemoryContextSwitchTo(oldContext);

	return result;
1550 1551
}

1552 1553 1554
/*
 * Number of items in a tlist (including any resjunk items!)
 */
1555
int
1556
ExecTargetListLength(List *targetlist)
1557
{
1558
	int			len = 0;
1559
	List	   *tl;
1560 1561 1562

	foreach(tl, targetlist)
	{
B
Bruce Momjian 已提交
1563
		TargetEntry *curTle = (TargetEntry *) lfirst(tl);
1564 1565 1566 1567 1568 1569 1570

		if (curTle->resdom != NULL)
			len++;
		else
			len += curTle->fjoin->fj_nNodes;
	}
	return len;
1571 1572
}

1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583
/*
 * 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 已提交
1584
		TargetEntry *curTle = (TargetEntry *) lfirst(tl);
1585 1586 1587

		if (curTle->resdom != NULL)
		{
B
Bruce Momjian 已提交
1588
			if (!curTle->resdom->resjunk)
1589 1590 1591 1592 1593 1594 1595 1596
				len++;
		}
		else
			len += curTle->fjoin->fj_nNodes;
	}
	return len;
}

1597
/* ----------------------------------------------------------------
1598 1599 1600 1601
 *		ExecTargetList
 *
 *		Evaluates a targetlist with respect to the current
 *		expression context and return a tuple.
1602 1603 1604 1605 1606
 *
 * 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.
1607 1608
 * ----------------------------------------------------------------
 */
1609
static HeapTuple
1610
ExecTargetList(List *targetlist,
1611 1612
			   int nodomains,
			   TupleDesc targettype,
1613 1614
			   Datum *values,
			   ExprContext *econtext,
1615
			   ExprDoneCond *isDone)
1616
{
1617
	MemoryContext oldContext;
B
Bruce Momjian 已提交
1618

1619 1620 1621 1622 1623
#define NPREALLOCDOMAINS 64
	char		nullsArray[NPREALLOCDOMAINS];
	bool		fjIsNullArray[NPREALLOCDOMAINS];
	ExprDoneCond itemIsDoneArray[NPREALLOCDOMAINS];
	char	   *nulls;
1624
	bool	   *fjIsNull;
1625
	ExprDoneCond *itemIsDone;
1626 1627 1628 1629 1630
	List	   *tl;
	TargetEntry *tle;
	AttrNumber	resind;
	HeapTuple	newTuple;
	bool		isNull;
1631
	bool		haveDoneSets;
1632 1633
	static struct tupleDesc NullTupleDesc;		/* we assume this inits to
												 * zeroes */
1634

B
Bruce Momjian 已提交
1635
	/*
B
Bruce Momjian 已提交
1636
	 * debugging stuff
1637
	 */
1638 1639 1640 1641
	EV_printf("ExecTargetList: tl is ");
	EV_nodeDisplay(targetlist);
	EV_printf("\n");

1642 1643 1644 1645 1646
	/*
	 * Run in short-lived per-tuple context while computing expressions.
	 */
	oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);

B
Bruce Momjian 已提交
1647
	/*
1648 1649 1650 1651 1652 1653
	 * 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.
1654
	 */
1655 1656
	if (targettype == NULL)
		targettype = &NullTupleDesc;
1657

B
Bruce Momjian 已提交
1658
	/*
B
Bruce Momjian 已提交
1659 1660
	 * allocate an array of char's to hold the "null" information only if
	 * we have a really large targetlist.  otherwise we use the stack.
1661 1662
	 *
	 * We also allocate a bool array that is used to hold fjoin result state,
B
Bruce Momjian 已提交
1663 1664 1665
	 * and another array that holds the isDone status for each targetlist
	 * item. The isDone status is needed so that we can iterate,
	 * generating multiple tuples, when one or more tlist items return
1666 1667 1668
	 * sets.  (We expect the caller to call us again if we return:
	 *
	 *	isDone = ExprMultipleResult.)
1669
	 */
1670
	if (nodomains > NPREALLOCDOMAINS)
1671
	{
1672 1673 1674
		nulls = (char *) palloc(nodomains * sizeof(char));
		fjIsNull = (bool *) palloc(nodomains * sizeof(bool));
		itemIsDone = (ExprDoneCond *) palloc(nodomains * sizeof(ExprDoneCond));
1675 1676 1677
	}
	else
	{
1678 1679 1680
		nulls = nullsArray;
		fjIsNull = fjIsNullArray;
		itemIsDone = itemIsDoneArray;
1681 1682
	}

B
Bruce Momjian 已提交
1683
	/*
B
Bruce Momjian 已提交
1684
	 * evaluate all the expressions in the target list
1685 1686
	 */

1687
	if (isDone)
B
Bruce Momjian 已提交
1688
		*isDone = ExprSingleResult;		/* until proven otherwise */
1689 1690

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

1692 1693 1694 1695 1696 1697
	foreach(tl, targetlist)
	{
		tle = lfirst(tl);

		if (tle->resdom != NULL)
		{
1698
			resind = tle->resdom->resno - 1;
1699

1700 1701 1702 1703 1704
			values[resind] = ExecEvalExpr(tle->expr,
										  econtext,
										  &isNull,
										  &itemIsDone[resind]);
			nulls[resind] = isNull ? 'n' : ' ';
1705

1706
			if (itemIsDone[resind] != ExprSingleResult)
1707
			{
1708 1709 1710 1711 1712 1713 1714 1715
				/* 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)
				{
					/* we have undone sets in the tlist, set flag */
					*isDone = ExprMultipleResult;
				}
1716
				else
1717 1718 1719 1720
				{
					/* we have done sets in the tlist, set flag for that */
					haveDoneSets = true;
				}
1721
			}
1722 1723
		}
		else
1724
		{
1725
#ifdef SETS_FIXED
1726 1727 1728 1729 1730 1731
			int			curNode;
			Resdom	   *fjRes;
			List	   *fjTlist = (List *) tle->expr;
			Fjoin	   *fjNode = tle->fjoin;
			int			nNodes = fjNode->fj_nNodes;
			DatumPtr	results = fjNode->fj_results;
1732 1733

			ExecEvalFjoin(tle, econtext, fjIsNull, isDone);
1734

B
Bruce Momjian 已提交
1735 1736 1737 1738
			/*
			 * XXX this is wrong, but since fjoin code is completely
			 * broken anyway, I'm not going to worry about it now --- tgl
			 * 8/23/00
1739 1740
			 */
			if (isDone && *isDone == ExprEndResult)
1741
			{
1742
				MemoryContextSwitchTo(oldContext);
1743 1744 1745
				newTuple = NULL;
				goto exit;
			}
1746 1747 1748 1749 1750 1751

			/*
			 * get the result from the inner node
			 */
			fjRes = (Resdom *) fjNode->fj_innerNode;
			resind = fjRes->resno - 1;
1752 1753
			values[resind] = results[0];
			nulls[resind] = fjIsNull[0] ? 'n' : ' ';
1754 1755 1756 1757 1758 1759 1760 1761

			/*
			 * Get results from all of the outer nodes
			 */
			for (curNode = 1;
				 curNode < nNodes;
				 curNode++, fjTlist = lnext(fjTlist))
			{
1762
				Node	   *outernode = lfirst(fjTlist);
1763 1764 1765

				fjRes = (Resdom *) outernode->iterexpr;
				resind = fjRes->resno - 1;
1766 1767
				values[resind] = results[curNode];
				nulls[resind] = fjIsNull[curNode] ? 'n' : ' ';
1768
			}
1769 1770 1771
#else
			elog(ERROR, "ExecTargetList: fjoin nodes not currently supported");
#endif
1772 1773
		}
	}
1774

1775
	if (haveDoneSets)
1776
	{
B
Bruce Momjian 已提交
1777

1778 1779 1780 1781
		/*
		 * note: can't get here unless we verified isDone != NULL
		 */
		if (*isDone == ExprSingleResult)
1782
		{
1783 1784

			/*
B
Bruce Momjian 已提交
1785 1786
			 * all sets are done, so report that tlist expansion is
			 * complete.
1787
			 */
1788 1789
			*isDone = ExprEndResult;
			MemoryContextSwitchTo(oldContext);
1790 1791 1792 1793 1794
			newTuple = NULL;
			goto exit;
		}
		else
		{
1795 1796

			/*
B
Bruce Momjian 已提交
1797
			 * We have some done and some undone sets.	Restart the done
1798
			 * ones so that we can deliver a tuple (if possible).
1799 1800 1801 1802 1803 1804 1805
			 */
			foreach(tl, targetlist)
			{
				tle = lfirst(tl);

				if (tle->resdom != NULL)
				{
1806
					resind = tle->resdom->resno - 1;
1807

1808
					if (itemIsDone[resind] == ExprEndResult)
1809
					{
1810 1811 1812
						values[resind] = ExecEvalExpr(tle->expr,
													  econtext,
													  &isNull,
B
Bruce Momjian 已提交
1813
													&itemIsDone[resind]);
1814 1815 1816
						nulls[resind] = isNull ? 'n' : ' ';

						if (itemIsDone[resind] == ExprEndResult)
1817
						{
1818 1819

							/*
1820
							 * Oh dear, this item is returning an empty
1821
							 * set. Guess we can't make a tuple after all.
1822
							 */
1823 1824
							*isDone = ExprEndResult;
							break;
1825
						}
1826 1827 1828
					}
				}
			}
B
Bruce Momjian 已提交
1829

1830
			/*
B
Bruce Momjian 已提交
1831 1832 1833
			 * 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.
1834 1835 1836 1837 1838 1839
			 */
			if (*isDone == ExprEndResult)
			{
				foreach(tl, targetlist)
				{
					tle = lfirst(tl);
1840

1841 1842 1843
					if (tle->resdom != NULL)
					{
						resind = tle->resdom->resno - 1;
1844

1845 1846 1847 1848 1849 1850 1851
						while (itemIsDone[resind] == ExprMultipleResult)
						{
							(void) ExecEvalExpr(tle->expr,
												econtext,
												&isNull,
												&itemIsDone[resind]);
						}
1852 1853
					}
				}
1854 1855 1856 1857

				MemoryContextSwitchTo(oldContext);
				newTuple = NULL;
				goto exit;
1858 1859 1860 1861
			}
		}
	}

B
Bruce Momjian 已提交
1862
	/*
1863
	 * form the new result tuple (in the caller's memory context!)
1864
	 */
1865 1866
	MemoryContextSwitchTo(oldContext);

1867
	newTuple = (HeapTuple) heap_formtuple(targettype, values, nulls);
1868

1869
exit:
1870

B
Bruce Momjian 已提交
1871
	/*
1872
	 * free the status arrays if we palloc'd them
1873
	 */
1874
	if (nodomains > NPREALLOCDOMAINS)
1875
	{
1876
		pfree(nulls);
1877
		pfree(fjIsNull);
1878
		pfree(itemIsDone);
1879
	}
B
Bruce Momjian 已提交
1880

1881
	return newTuple;
1882 1883 1884
}

/* ----------------------------------------------------------------
1885 1886
 *		ExecProject
 *
1887
 *		projects a tuple based on projection info and stores
1888
 *		it in the specified tuple table slot.
1889
 *
1890 1891 1892 1893 1894
 *		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
1895 1896 1897
 * ----------------------------------------------------------------
 */
TupleTableSlot *
1898
ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
1899
{
1900
	TupleTableSlot *slot;
1901 1902 1903 1904 1905 1906
	List	   *targetlist;
	int			len;
	TupleDesc	tupType;
	Datum	   *tupValue;
	ExprContext *econtext;
	HeapTuple	newTuple;
1907

B
Bruce Momjian 已提交
1908
	/*
B
Bruce Momjian 已提交
1909
	 * sanity checks
1910 1911 1912
	 */
	if (projInfo == NULL)
		return (TupleTableSlot *) NULL;
1913

B
Bruce Momjian 已提交
1914
	/*
B
Bruce Momjian 已提交
1915
	 * get the projection info we want
1916 1917 1918 1919 1920 1921 1922 1923 1924
	 */
	slot = projInfo->pi_slot;
	targetlist = projInfo->pi_targetlist;
	len = projInfo->pi_len;
	tupType = slot->ttc_tupleDescriptor;

	tupValue = projInfo->pi_tupValue;
	econtext = projInfo->pi_exprContext;

B
Bruce Momjian 已提交
1925
	/*
1926
	 * form a new result tuple (if possible --- result can be NULL)
1927 1928 1929 1930 1931 1932 1933 1934
	 */
	newTuple = ExecTargetList(targetlist,
							  len,
							  tupType,
							  tupValue,
							  econtext,
							  isDone);

B
Bruce Momjian 已提交
1935
	/*
B
Bruce Momjian 已提交
1936
	 * store the tuple in the projection slot and return the slot.
1937
	 */
B
Bruce Momjian 已提交
1938 1939 1940
	return ExecStoreTuple(newTuple,		/* tuple to store */
						  slot, /* slot to store in */
						  InvalidBuffer,		/* tuple has no buffer */
1941
						  true);
1942
}