1 /*-------------------------------------------------------------------------
2  *
3  * execExpr.h
4  *	  Low level infrastructure related to expression evaluation
5  *
6  *
7  * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  * src/include/executor/execExpr.h
11  *
12  *-------------------------------------------------------------------------
13  */
14 #ifndef EXEC_EXPR_H
15 #define EXEC_EXPR_H
16 
17 #include "executor/nodeAgg.h"
18 #include "nodes/execnodes.h"
19 
20 /* forward references to avoid circularity */
21 struct ExprEvalStep;
22 struct ArrayRefState;
23 
24 /* Bits in ExprState->flags (see also execnodes.h for public flag bits): */
25 /* expression's interpreter has been initialized */
26 #define EEO_FLAG_INTERPRETER_INITIALIZED	(1 << 1)
27 /* jump-threading is in use */
28 #define EEO_FLAG_DIRECT_THREADED			(1 << 2)
29 
30 /* Typical API for out-of-line evaluation subroutines */
31 typedef void (*ExecEvalSubroutine) (ExprState *state,
32 									struct ExprEvalStep *op,
33 									ExprContext *econtext);
34 
35 /* ExprEvalSteps that cache a composite type's tupdesc need one of these */
36 /* (it fits in-line in some step types, otherwise allocate out-of-line) */
37 typedef struct ExprEvalRowtypeCache
38 {
39 	/*
40 	 * cacheptr points to composite type's TypeCacheEntry if tupdesc_id is not
41 	 * 0; or for an anonymous RECORD type, it points directly at the cached
42 	 * tupdesc for the type, and tupdesc_id is 0.  (We'd use separate fields
43 	 * if space were not at a premium.)  Initial state is cacheptr == NULL.
44 	 */
45 	void	   *cacheptr;
46 	uint64		tupdesc_id;		/* last-seen tupdesc identifier, or 0 */
47 } ExprEvalRowtypeCache;
48 
49 /*
50  * Discriminator for ExprEvalSteps.
51  *
52  * Identifies the operation to be executed and which member in the
53  * ExprEvalStep->d union is valid.
54  *
55  * The order of entries needs to be kept in sync with the dispatch_table[]
56  * array in execExprInterp.c:ExecInterpExpr().
57  */
58 typedef enum ExprEvalOp
59 {
60 	/* entire expression has been evaluated completely, return */
61 	EEOP_DONE,
62 
63 	/* apply slot_getsomeattrs on corresponding tuple slot */
64 	EEOP_INNER_FETCHSOME,
65 	EEOP_OUTER_FETCHSOME,
66 	EEOP_SCAN_FETCHSOME,
67 
68 	/* compute non-system Var value */
69 	EEOP_INNER_VAR,
70 	EEOP_OUTER_VAR,
71 	EEOP_SCAN_VAR,
72 
73 	/* compute system Var value */
74 	EEOP_INNER_SYSVAR,
75 	EEOP_OUTER_SYSVAR,
76 	EEOP_SCAN_SYSVAR,
77 
78 	/* compute wholerow Var */
79 	EEOP_WHOLEROW,
80 
81 	/*
82 	 * Compute non-system Var value, assign it into ExprState's resultslot.
83 	 * These are not used if a CheckVarSlotCompatibility() check would be
84 	 * needed.
85 	 */
86 	EEOP_ASSIGN_INNER_VAR,
87 	EEOP_ASSIGN_OUTER_VAR,
88 	EEOP_ASSIGN_SCAN_VAR,
89 
90 	/* assign ExprState's resvalue/resnull to a column of its resultslot */
91 	EEOP_ASSIGN_TMP,
92 	/* ditto, applying MakeExpandedObjectReadOnly() */
93 	EEOP_ASSIGN_TMP_MAKE_RO,
94 
95 	/* evaluate Const value */
96 	EEOP_CONST,
97 
98 	/*
99 	 * Evaluate function call (including OpExprs etc).  For speed, we
100 	 * distinguish in the opcode whether the function is strict and/or
101 	 * requires usage stats tracking.
102 	 */
103 	EEOP_FUNCEXPR,
104 	EEOP_FUNCEXPR_STRICT,
105 	EEOP_FUNCEXPR_FUSAGE,
106 	EEOP_FUNCEXPR_STRICT_FUSAGE,
107 
108 	/*
109 	 * Evaluate boolean AND expression, one step per subexpression. FIRST/LAST
110 	 * subexpressions are special-cased for performance.  Since AND always has
111 	 * at least two subexpressions, FIRST and LAST never apply to the same
112 	 * subexpression.
113 	 */
114 	EEOP_BOOL_AND_STEP_FIRST,
115 	EEOP_BOOL_AND_STEP,
116 	EEOP_BOOL_AND_STEP_LAST,
117 
118 	/* similarly for boolean OR expression */
119 	EEOP_BOOL_OR_STEP_FIRST,
120 	EEOP_BOOL_OR_STEP,
121 	EEOP_BOOL_OR_STEP_LAST,
122 
123 	/* evaluate boolean NOT expression */
124 	EEOP_BOOL_NOT_STEP,
125 
126 	/* simplified version of BOOL_AND_STEP for use by ExecQual() */
127 	EEOP_QUAL,
128 
129 	/* unconditional jump to another step */
130 	EEOP_JUMP,
131 
132 	/* conditional jumps based on current result value */
133 	EEOP_JUMP_IF_NULL,
134 	EEOP_JUMP_IF_NOT_NULL,
135 	EEOP_JUMP_IF_NOT_TRUE,
136 
137 	/* perform NULL tests for scalar values */
138 	EEOP_NULLTEST_ISNULL,
139 	EEOP_NULLTEST_ISNOTNULL,
140 
141 	/* perform NULL tests for row values */
142 	EEOP_NULLTEST_ROWISNULL,
143 	EEOP_NULLTEST_ROWISNOTNULL,
144 
145 	/* evaluate a BooleanTest expression */
146 	EEOP_BOOLTEST_IS_TRUE,
147 	EEOP_BOOLTEST_IS_NOT_TRUE,
148 	EEOP_BOOLTEST_IS_FALSE,
149 	EEOP_BOOLTEST_IS_NOT_FALSE,
150 
151 	/* evaluate PARAM_EXEC/EXTERN parameters */
152 	EEOP_PARAM_EXEC,
153 	EEOP_PARAM_EXTERN,
154 	EEOP_PARAM_CALLBACK,
155 
156 	/* return CaseTestExpr value */
157 	EEOP_CASE_TESTVAL,
158 
159 	/* apply MakeExpandedObjectReadOnly() to target value */
160 	EEOP_MAKE_READONLY,
161 
162 	/* evaluate assorted special-purpose expression types */
163 	EEOP_IOCOERCE,
164 	EEOP_DISTINCT,
165 	EEOP_NOT_DISTINCT,
166 	EEOP_NULLIF,
167 	EEOP_SQLVALUEFUNCTION,
168 	EEOP_CURRENTOFEXPR,
169 	EEOP_NEXTVALUEEXPR,
170 	EEOP_ARRAYEXPR,
171 	EEOP_ARRAYCOERCE,
172 	EEOP_ROW,
173 
174 	/*
175 	 * Compare two individual elements of each of two compared ROW()
176 	 * expressions.  Skip to ROWCOMPARE_FINAL if elements are not equal.
177 	 */
178 	EEOP_ROWCOMPARE_STEP,
179 
180 	/* evaluate boolean value based on previous ROWCOMPARE_STEP operations */
181 	EEOP_ROWCOMPARE_FINAL,
182 
183 	/* evaluate GREATEST() or LEAST() */
184 	EEOP_MINMAX,
185 
186 	/* evaluate FieldSelect expression */
187 	EEOP_FIELDSELECT,
188 
189 	/*
190 	 * Deform tuple before evaluating new values for individual fields in a
191 	 * FieldStore expression.
192 	 */
193 	EEOP_FIELDSTORE_DEFORM,
194 
195 	/*
196 	 * Form the new tuple for a FieldStore expression.  Individual fields will
197 	 * have been evaluated into columns of the tuple deformed by the preceding
198 	 * DEFORM step.
199 	 */
200 	EEOP_FIELDSTORE_FORM,
201 
202 	/* Process an array subscript; short-circuit expression to NULL if NULL */
203 	EEOP_ARRAYREF_SUBSCRIPT,
204 
205 	/*
206 	 * Compute old array element/slice when an ArrayRef assignment expression
207 	 * contains ArrayRef/FieldStore subexpressions.  Value is accessed using
208 	 * the CaseTest mechanism.
209 	 */
210 	EEOP_ARRAYREF_OLD,
211 
212 	/* compute new value for ArrayRef assignment expression */
213 	EEOP_ARRAYREF_ASSIGN,
214 
215 	/* compute element/slice for ArrayRef fetch expression */
216 	EEOP_ARRAYREF_FETCH,
217 
218 	/* evaluate value for CoerceToDomainValue */
219 	EEOP_DOMAIN_TESTVAL,
220 
221 	/* evaluate a domain's NOT NULL constraint */
222 	EEOP_DOMAIN_NOTNULL,
223 
224 	/* evaluate a single domain CHECK constraint */
225 	EEOP_DOMAIN_CHECK,
226 
227 	/* evaluate assorted special-purpose expression types */
228 	EEOP_CONVERT_ROWTYPE,
229 	EEOP_SCALARARRAYOP,
230 	EEOP_XMLEXPR,
231 	EEOP_AGGREF,
232 	EEOP_GROUPING_FUNC,
233 	EEOP_WINDOW_FUNC,
234 	EEOP_SUBPLAN,
235 	EEOP_ALTERNATIVE_SUBPLAN,
236 
237 	/* aggregation related nodes */
238 	EEOP_AGG_STRICT_DESERIALIZE,
239 	EEOP_AGG_DESERIALIZE,
240 	EEOP_AGG_STRICT_INPUT_CHECK,
241 	EEOP_AGG_INIT_TRANS,
242 	EEOP_AGG_STRICT_TRANS_CHECK,
243 	EEOP_AGG_PLAIN_TRANS_BYVAL,
244 	EEOP_AGG_PLAIN_TRANS,
245 	EEOP_AGG_ORDERED_TRANS_DATUM,
246 	EEOP_AGG_ORDERED_TRANS_TUPLE,
247 
248 	/* non-existent operation, used e.g. to check array lengths */
249 	EEOP_LAST
250 } ExprEvalOp;
251 
252 
253 typedef struct ExprEvalStep
254 {
255 	/*
256 	 * Instruction to be executed.  During instruction preparation this is an
257 	 * enum ExprEvalOp, but later it can be changed to some other type, e.g. a
258 	 * pointer for computed goto (that's why it's an intptr_t).
259 	 */
260 	intptr_t	opcode;
261 
262 	/* where to store the result of this step */
263 	Datum	   *resvalue;
264 	bool	   *resnull;
265 
266 	/*
267 	 * Inline data for the operation.  Inline data is faster to access, but
268 	 * also bloats the size of all instructions.  The union should be kept to
269 	 * no more than 40 bytes on 64-bit systems (so that the entire struct is
270 	 * no more than 64 bytes, a single cacheline on common systems).
271 	 */
272 	union
273 	{
274 		/* for EEOP_INNER/OUTER/SCAN_FETCHSOME */
275 		struct
276 		{
277 			/* attribute number up to which to fetch (inclusive) */
278 			int			last_var;
279 			TupleDesc	known_desc;
280 		}			fetch;
281 
282 		/* for EEOP_INNER/OUTER/SCAN_[SYS]VAR[_FIRST] */
283 		struct
284 		{
285 			/* attnum is attr number - 1 for regular VAR ... */
286 			/* but it's just the normal (negative) attr number for SYSVAR */
287 			int			attnum;
288 			Oid			vartype;	/* type OID of variable */
289 		}			var;
290 
291 		/* for EEOP_WHOLEROW */
292 		struct
293 		{
294 			Var		   *var;	/* original Var node in plan tree */
295 			bool		first;	/* first time through, need to initialize? */
296 			bool		slow;	/* need runtime check for nulls? */
297 			TupleDesc	tupdesc;	/* descriptor for resulting tuples */
298 			JunkFilter *junkFilter; /* JunkFilter to remove resjunk cols */
299 		}			wholerow;
300 
301 		/* for EEOP_ASSIGN_*_VAR */
302 		struct
303 		{
304 			/* target index in ExprState->resultslot->tts_values/nulls */
305 			int			resultnum;
306 			/* source attribute number - 1 */
307 			int			attnum;
308 		}			assign_var;
309 
310 		/* for EEOP_ASSIGN_TMP[_MAKE_RO] */
311 		struct
312 		{
313 			/* target index in ExprState->resultslot->tts_values/nulls */
314 			int			resultnum;
315 		}			assign_tmp;
316 
317 		/* for EEOP_CONST */
318 		struct
319 		{
320 			/* constant's value */
321 			Datum		value;
322 			bool		isnull;
323 		}			constval;
324 
325 		/* for EEOP_FUNCEXPR_* / NULLIF / DISTINCT */
326 		struct
327 		{
328 			FmgrInfo   *finfo;	/* function's lookup data */
329 			FunctionCallInfo fcinfo_data;	/* arguments etc */
330 			/* faster to access without additional indirection: */
331 			PGFunction	fn_addr;	/* actual call address */
332 			int			nargs;	/* number of arguments */
333 		}			func;
334 
335 		/* for EEOP_BOOL_*_STEP */
336 		struct
337 		{
338 			bool	   *anynull;	/* track if any input was NULL */
339 			int			jumpdone;	/* jump here if result determined */
340 		}			boolexpr;
341 
342 		/* for EEOP_QUAL */
343 		struct
344 		{
345 			int			jumpdone;	/* jump here on false or null */
346 		}			qualexpr;
347 
348 		/* for EEOP_JUMP[_CONDITION] */
349 		struct
350 		{
351 			int			jumpdone;	/* target instruction's index */
352 		}			jump;
353 
354 		/* for EEOP_NULLTEST_ROWIS[NOT]NULL */
355 		struct
356 		{
357 			/* cached descriptor for composite type - filled at runtime */
358 			ExprEvalRowtypeCache rowcache;
359 		}			nulltest_row;
360 
361 		/* for EEOP_PARAM_EXEC/EXTERN */
362 		struct
363 		{
364 			int			paramid;	/* numeric ID for parameter */
365 			Oid			paramtype;	/* OID of parameter's datatype */
366 		}			param;
367 
368 		/* for EEOP_PARAM_CALLBACK */
369 		struct
370 		{
371 			ExecEvalSubroutine paramfunc;	/* add-on evaluation subroutine */
372 			void	   *paramarg;	/* private data for same */
373 			int			paramid;	/* numeric ID for parameter */
374 			Oid			paramtype;	/* OID of parameter's datatype */
375 		}			cparam;
376 
377 		/* for EEOP_CASE_TESTVAL/DOMAIN_TESTVAL */
378 		struct
379 		{
380 			Datum	   *value;	/* value to return */
381 			bool	   *isnull;
382 		}			casetest;
383 
384 		/* for EEOP_MAKE_READONLY */
385 		struct
386 		{
387 			Datum	   *value;	/* value to coerce to read-only */
388 			bool	   *isnull;
389 		}			make_readonly;
390 
391 		/* for EEOP_IOCOERCE */
392 		struct
393 		{
394 			/* lookup and call info for source type's output function */
395 			FmgrInfo   *finfo_out;
396 			FunctionCallInfo fcinfo_data_out;
397 			/* lookup and call info for result type's input function */
398 			FmgrInfo   *finfo_in;
399 			FunctionCallInfo fcinfo_data_in;
400 		}			iocoerce;
401 
402 		/* for EEOP_SQLVALUEFUNCTION */
403 		struct
404 		{
405 			SQLValueFunction *svf;
406 		}			sqlvaluefunction;
407 
408 		/* for EEOP_NEXTVALUEEXPR */
409 		struct
410 		{
411 			Oid			seqid;
412 			Oid			seqtypid;
413 		}			nextvalueexpr;
414 
415 		/* for EEOP_ARRAYEXPR */
416 		struct
417 		{
418 			Datum	   *elemvalues; /* element values get stored here */
419 			bool	   *elemnulls;
420 			int			nelems; /* length of the above arrays */
421 			Oid			elemtype;	/* array element type */
422 			int16		elemlength; /* typlen of the array element type */
423 			bool		elembyval;	/* is the element type pass-by-value? */
424 			char		elemalign;	/* typalign of the element type */
425 			bool		multidims;	/* is array expression multi-D? */
426 		}			arrayexpr;
427 
428 		/* for EEOP_ARRAYCOERCE */
429 		struct
430 		{
431 			ExprState  *elemexprstate;	/* null if no per-element work */
432 			Oid			resultelemtype; /* element type of result array */
433 			struct ArrayMapState *amstate;	/* workspace for array_map */
434 		}			arraycoerce;
435 
436 		/* for EEOP_ROW */
437 		struct
438 		{
439 			TupleDesc	tupdesc;	/* descriptor for result tuples */
440 			/* workspace for the values constituting the row: */
441 			Datum	   *elemvalues;
442 			bool	   *elemnulls;
443 		}			row;
444 
445 		/* for EEOP_ROWCOMPARE_STEP */
446 		struct
447 		{
448 			/* lookup and call data for column comparison function */
449 			FmgrInfo   *finfo;
450 			FunctionCallInfo fcinfo_data;
451 			PGFunction	fn_addr;
452 			/* target for comparison resulting in NULL */
453 			int			jumpnull;
454 			/* target for comparison yielding inequality */
455 			int			jumpdone;
456 		}			rowcompare_step;
457 
458 		/* for EEOP_ROWCOMPARE_FINAL */
459 		struct
460 		{
461 			RowCompareType rctype;
462 		}			rowcompare_final;
463 
464 		/* for EEOP_MINMAX */
465 		struct
466 		{
467 			/* workspace for argument values */
468 			Datum	   *values;
469 			bool	   *nulls;
470 			int			nelems;
471 			/* is it GREATEST or LEAST? */
472 			MinMaxOp	op;
473 			/* lookup and call data for comparison function */
474 			FmgrInfo   *finfo;
475 			FunctionCallInfo fcinfo_data;
476 		}			minmax;
477 
478 		/* for EEOP_FIELDSELECT */
479 		struct
480 		{
481 			AttrNumber	fieldnum;	/* field number to extract */
482 			Oid			resulttype; /* field's type */
483 			/* cached descriptor for composite type - filled at runtime */
484 			ExprEvalRowtypeCache rowcache;
485 		}			fieldselect;
486 
487 		/* for EEOP_FIELDSTORE_DEFORM / FIELDSTORE_FORM */
488 		struct
489 		{
490 			/* original expression node */
491 			FieldStore *fstore;
492 
493 			/* cached descriptor for composite type - filled at runtime */
494 			/* note that a DEFORM and FORM pair share the same cache */
495 			ExprEvalRowtypeCache *rowcache;
496 
497 			/* workspace for column values */
498 			Datum	   *values;
499 			bool	   *nulls;
500 			int			ncolumns;
501 		}			fieldstore;
502 
503 		/* for EEOP_ARRAYREF_SUBSCRIPT */
504 		struct
505 		{
506 			/* too big to have inline */
507 			struct ArrayRefState *state;
508 			int			off;	/* 0-based index of this subscript */
509 			bool		isupper;	/* is it upper or lower subscript? */
510 			int			jumpdone;	/* jump here on null */
511 		}			arrayref_subscript;
512 
513 		/* for EEOP_ARRAYREF_OLD / ASSIGN / FETCH */
514 		struct
515 		{
516 			/* too big to have inline */
517 			struct ArrayRefState *state;
518 		}			arrayref;
519 
520 		/* for EEOP_DOMAIN_NOTNULL / DOMAIN_CHECK */
521 		struct
522 		{
523 			/* name of constraint */
524 			char	   *constraintname;
525 			/* where the result of a CHECK constraint will be stored */
526 			Datum	   *checkvalue;
527 			bool	   *checknull;
528 			/* OID of domain type */
529 			Oid			resulttype;
530 		}			domaincheck;
531 
532 		/* for EEOP_CONVERT_ROWTYPE */
533 		struct
534 		{
535 			Oid			inputtype;	/* input composite type */
536 			Oid			outputtype; /* output composite type */
537 			/* these three fields are filled at runtime: */
538 			ExprEvalRowtypeCache *incache;	/* cache for input type */
539 			ExprEvalRowtypeCache *outcache; /* cache for output type */
540 			TupleConversionMap *map;	/* column mapping */
541 		}			convert_rowtype;
542 
543 		/* for EEOP_SCALARARRAYOP */
544 		struct
545 		{
546 			/* element_type/typlen/typbyval/typalign are filled at runtime */
547 			Oid			element_type;	/* InvalidOid if not yet filled */
548 			bool		useOr;	/* use OR or AND semantics? */
549 			int16		typlen; /* array element type storage info */
550 			bool		typbyval;
551 			char		typalign;
552 			FmgrInfo   *finfo;	/* function's lookup data */
553 			FunctionCallInfo fcinfo_data;	/* arguments etc */
554 			/* faster to access without additional indirection: */
555 			PGFunction	fn_addr;	/* actual call address */
556 		}			scalararrayop;
557 
558 		/* for EEOP_XMLEXPR */
559 		struct
560 		{
561 			XmlExpr    *xexpr;	/* original expression node */
562 			/* workspace for evaluating named args, if any */
563 			Datum	   *named_argvalue;
564 			bool	   *named_argnull;
565 			/* workspace for evaluating unnamed args, if any */
566 			Datum	   *argvalue;
567 			bool	   *argnull;
568 		}			xmlexpr;
569 
570 		/* for EEOP_AGGREF */
571 		struct
572 		{
573 			/* out-of-line state, modified by nodeAgg.c */
574 			AggrefExprState *astate;
575 		}			aggref;
576 
577 		/* for EEOP_GROUPING_FUNC */
578 		struct
579 		{
580 			AggState   *parent; /* parent Agg */
581 			List	   *clauses;	/* integer list of column numbers */
582 		}			grouping_func;
583 
584 		/* for EEOP_WINDOW_FUNC */
585 		struct
586 		{
587 			/* out-of-line state, modified by nodeWindowFunc.c */
588 			WindowFuncExprState *wfstate;
589 		}			window_func;
590 
591 		/* for EEOP_SUBPLAN */
592 		struct
593 		{
594 			/* out-of-line state, created by nodeSubplan.c */
595 			SubPlanState *sstate;
596 		}			subplan;
597 
598 		/* for EEOP_ALTERNATIVE_SUBPLAN */
599 		struct
600 		{
601 			/* out-of-line state, created by nodeSubplan.c */
602 			AlternativeSubPlanState *asstate;
603 		}			alternative_subplan;
604 
605 		/* for EEOP_AGG_*DESERIALIZE */
606 		struct
607 		{
608 			AggState   *aggstate;
609 			FunctionCallInfo fcinfo_data;
610 			int			jumpnull;
611 		}			agg_deserialize;
612 
613 		/* for EEOP_AGG_STRICT_INPUT_CHECK */
614 		struct
615 		{
616 			bool	   *nulls;
617 			int			nargs;
618 			int			jumpnull;
619 		}			agg_strict_input_check;
620 
621 		/* for EEOP_AGG_INIT_TRANS */
622 		struct
623 		{
624 			AggState   *aggstate;
625 			AggStatePerTrans pertrans;
626 			ExprContext *aggcontext;
627 			int			setno;
628 			int			transno;
629 			int			setoff;
630 			int			jumpnull;
631 		}			agg_init_trans;
632 
633 		/* for EEOP_AGG_STRICT_TRANS_CHECK */
634 		struct
635 		{
636 			AggState   *aggstate;
637 			int			setno;
638 			int			transno;
639 			int			setoff;
640 			int			jumpnull;
641 		}			agg_strict_trans_check;
642 
643 		/* for EEOP_AGG_{PLAIN,ORDERED}_TRANS* */
644 		struct
645 		{
646 			AggState   *aggstate;
647 			AggStatePerTrans pertrans;
648 			ExprContext *aggcontext;
649 			int			setno;
650 			int			transno;
651 			int			setoff;
652 		}			agg_trans;
653 	}			d;
654 } ExprEvalStep;
655 
656 
657 /* Non-inline data for array operations */
658 typedef struct ArrayRefState
659 {
660 	bool		isassignment;	/* is it assignment, or just fetch? */
661 
662 	Oid			refelemtype;	/* OID of the array element type */
663 	int16		refattrlength;	/* typlen of array type */
664 	int16		refelemlength;	/* typlen of the array element type */
665 	bool		refelembyval;	/* is the element type pass-by-value? */
666 	char		refelemalign;	/* typalign of the element type */
667 
668 	/* numupper and upperprovided[] are filled at compile time */
669 	/* at runtime, extracted subscript datums get stored in upperindex[] */
670 	int			numupper;
671 	bool		upperprovided[MAXDIM];
672 	int			upperindex[MAXDIM];
673 
674 	/* similarly for lower indexes, if any */
675 	int			numlower;
676 	bool		lowerprovided[MAXDIM];
677 	int			lowerindex[MAXDIM];
678 
679 	/* subscript expressions get evaluated into here */
680 	Datum		subscriptvalue;
681 	bool		subscriptnull;
682 
683 	/* for assignment, new value to assign is evaluated into here */
684 	Datum		replacevalue;
685 	bool		replacenull;
686 
687 	/* if we have a nested assignment, ARRAYREF_OLD puts old value here */
688 	Datum		prevvalue;
689 	bool		prevnull;
690 } ArrayRefState;
691 
692 
693 /* functions in execExpr.c */
694 extern void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s);
695 
696 /* functions in execExprInterp.c */
697 extern void ExecReadyInterpretedExpr(ExprState *state);
698 extern ExprEvalOp ExecEvalStepOp(ExprState *state, ExprEvalStep *op);
699 
700 extern Datum ExecInterpExprStillValid(ExprState *state, ExprContext *econtext, bool *isNull);
701 extern void CheckExprStillValid(ExprState *state, ExprContext *econtext);
702 
703 /*
704  * Non fast-path execution functions. These are externs instead of statics in
705  * execExprInterp.c, because that allows them to be used by other methods of
706  * expression evaluation, reducing code duplication.
707  */
708 extern void ExecEvalFuncExprFusage(ExprState *state, ExprEvalStep *op,
709 					   ExprContext *econtext);
710 extern void ExecEvalFuncExprStrictFusage(ExprState *state, ExprEvalStep *op,
711 							 ExprContext *econtext);
712 extern void ExecEvalParamExec(ExprState *state, ExprEvalStep *op,
713 				  ExprContext *econtext);
714 extern void ExecEvalParamExtern(ExprState *state, ExprEvalStep *op,
715 					ExprContext *econtext);
716 extern void ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op);
717 extern void ExecEvalCurrentOfExpr(ExprState *state, ExprEvalStep *op);
718 extern void ExecEvalNextValueExpr(ExprState *state, ExprEvalStep *op);
719 extern void ExecEvalRowNull(ExprState *state, ExprEvalStep *op,
720 				ExprContext *econtext);
721 extern void ExecEvalRowNotNull(ExprState *state, ExprEvalStep *op,
722 				   ExprContext *econtext);
723 extern void ExecEvalArrayExpr(ExprState *state, ExprEvalStep *op);
724 extern void ExecEvalArrayCoerce(ExprState *state, ExprEvalStep *op,
725 					ExprContext *econtext);
726 extern void ExecEvalRow(ExprState *state, ExprEvalStep *op);
727 extern void ExecEvalMinMax(ExprState *state, ExprEvalStep *op);
728 extern void ExecEvalFieldSelect(ExprState *state, ExprEvalStep *op,
729 					ExprContext *econtext);
730 extern void ExecEvalFieldStoreDeForm(ExprState *state, ExprEvalStep *op,
731 						 ExprContext *econtext);
732 extern void ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op,
733 					   ExprContext *econtext);
734 extern bool ExecEvalArrayRefSubscript(ExprState *state, ExprEvalStep *op);
735 extern void ExecEvalArrayRefFetch(ExprState *state, ExprEvalStep *op);
736 extern void ExecEvalArrayRefOld(ExprState *state, ExprEvalStep *op);
737 extern void ExecEvalArrayRefAssign(ExprState *state, ExprEvalStep *op);
738 extern void ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op,
739 					   ExprContext *econtext);
740 extern void ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op);
741 extern void ExecEvalConstraintNotNull(ExprState *state, ExprEvalStep *op);
742 extern void ExecEvalConstraintCheck(ExprState *state, ExprEvalStep *op);
743 extern void ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op);
744 extern void ExecEvalGroupingFunc(ExprState *state, ExprEvalStep *op);
745 extern void ExecEvalSubPlan(ExprState *state, ExprEvalStep *op,
746 				ExprContext *econtext);
747 extern void ExecEvalAlternativeSubPlan(ExprState *state, ExprEvalStep *op,
748 						   ExprContext *econtext);
749 extern void ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op,
750 					ExprContext *econtext);
751 
752 extern void ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup);
753 extern Datum ExecAggTransReparent(AggState *aggstate, AggStatePerTrans pertrans,
754 					 Datum newValue, bool newValueIsNull,
755 					 Datum oldValue, bool oldValueIsNull);
756 extern void ExecEvalAggOrderedTransDatum(ExprState *state, ExprEvalStep *op,
757 							 ExprContext *econtext);
758 extern void ExecEvalAggOrderedTransTuple(ExprState *state, ExprEvalStep *op,
759 							 ExprContext *econtext);
760 
761 #endif							/* EXEC_EXPR_H */
762