1 /*-------------------------------------------------------------------------
4 * Interpreted evaluation of an expression step list.
6 * This file provides either a "direct threaded" (for gcc, clang and
7 * compatible) or a "switch threaded" (for all compilers) implementation of
8 * expression evaluation. The former is amongst the fastest known methods
9 * of interpreting programs without resorting to assembly level work, or
10 * just-in-time compilation, but it requires support for computed gotos.
11 * The latter is amongst the fastest approaches doable in standard C.
13 * In either case we use ExprEvalStep->opcode to dispatch to the code block
14 * within ExecInterpExpr() that implements the specific opcode type.
16 * Switch-threading uses a plain switch() statement to perform the
17 * dispatch. This has the advantages of being plain C and allowing the
18 * compiler to warn if implementation of a specific opcode has been forgotten.
19 * The disadvantage is that dispatches will, as commonly implemented by
20 * compilers, happen from a single location, requiring more jumps and causing
21 * bad branch prediction.
23 * In direct threading, we use gcc's label-as-values extension - also adopted
24 * by some other compilers - to replace ExprEvalStep->opcode with the address
25 * of the block implementing the instruction. Dispatch to the next instruction
26 * is done by a "computed goto". This allows for better branch prediction
27 * (as the jumps are happening from different locations) and fewer jumps
28 * (as no preparatory jump to a common dispatch location is needed).
30 * When using direct threading, ExecReadyInterpretedExpr will replace
31 * each step's opcode field with the address of the relevant code block and
32 * ExprState->flags will contain EEO_FLAG_DIRECT_THREADED to remember that
35 * For very simple instructions the overhead of the full interpreter
36 * "startup", as minimal as it is, is noticeable. Therefore
37 * ExecReadyInterpretedExpr will choose to implement certain simple
38 * opcode patterns using special fast-path routines (ExecJust*).
40 * Complex or uncommon instructions are not implemented in-line in
41 * ExecInterpExpr(), rather we call out to a helper function appearing later
42 * in this file. For one reason, there'd not be a noticeable performance
43 * benefit, but more importantly those complex routines are intended to be
44 * shared between different expression evaluation approaches. For instance
45 * a JIT compiler would generate calls to them. (This is why they are
46 * exported rather than being "static" in this file.)
49 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
50 * Portions Copyright (c) 1994, Regents of the University of California
53 * src/backend/executor/execExprInterp.c
55 *-------------------------------------------------------------------------
59 #include "access/heaptoast.h"
60 #include "access/xact.h"
61 #include "catalog/pg_proc.h"
62 #include "catalog/pg_type.h"
63 #include "commands/sequence.h"
64 #include "executor/execExpr.h"
65 #include "executor/nodeSubplan.h"
67 #include "miscadmin.h"
68 #include "nodes/makefuncs.h"
69 #include "nodes/nodeFuncs.h"
70 #include "parser/parsetree.h"
71 #include "parser/parse_expr.h"
73 #include "utils/array.h"
74 #include "utils/builtins.h"
75 #include "utils/date.h"
76 #include "utils/datum.h"
77 #include "utils/expandedrecord.h"
78 #include "utils/json.h"
79 #include "utils/jsonb.h"
80 #include "utils/jsonfuncs.h"
81 #include "utils/jsonpath.h"
82 #include "utils/lsyscache.h"
83 #include "utils/memutils.h"
84 #include "utils/resowner.h"
85 #include "utils/timestamp.h"
86 #include "utils/typcache.h"
87 #include "utils/xml.h"
90 * Use computed-goto-based opcode dispatch when computed gotos are available.
91 * But use a separate symbol so that it's easy to adjust locally in this file
92 * for development and testing.
94 #ifdef HAVE_COMPUTED_GOTO
95 #define EEO_USE_COMPUTED_GOTO
96 #endif /* HAVE_COMPUTED_GOTO */
99 * Macros for opcode dispatch.
101 * EEO_SWITCH - just hides the switch if not in use.
102 * EEO_CASE - labels the implementation of named expression step type.
103 * EEO_DISPATCH - jump to the implementation of the step type for 'op'.
104 * EEO_OPCODE - compute opcode required by used expression evaluation method.
105 * EEO_NEXT - increment 'op' and jump to correct next step type.
106 * EEO_JUMP - jump to the specified step number within the current expression.
108 #if defined(EEO_USE_COMPUTED_GOTO)
110 /* struct for jump target -> opcode lookup table */
111 typedef struct ExprEvalOpLookup
117 /* to make dispatch_table accessible outside ExecInterpExpr() */
118 static const void **dispatch_table
= NULL
;
120 /* jump target -> opcode lookup table */
121 static ExprEvalOpLookup reverse_dispatch_table
[EEOP_LAST
];
124 #define EEO_CASE(name) CASE_##name:
125 #define EEO_DISPATCH() goto *((void *) op->opcode)
126 #define EEO_OPCODE(opcode) ((intptr_t) dispatch_table[opcode])
128 #else /* !EEO_USE_COMPUTED_GOTO */
130 #define EEO_SWITCH() starteval: switch ((ExprEvalOp) op->opcode)
131 #define EEO_CASE(name) case name:
132 #define EEO_DISPATCH() goto starteval
133 #define EEO_OPCODE(opcode) (opcode)
135 #endif /* EEO_USE_COMPUTED_GOTO */
143 #define EEO_JUMP(stepno) \
145 op = &state->steps[stepno]; \
150 static Datum
ExecInterpExpr(ExprState
*state
, ExprContext
*econtext
, bool *isnull
);
151 static void ExecInitInterpreter(void);
153 /* support functions */
154 static void CheckVarSlotCompatibility(TupleTableSlot
*slot
, int attnum
, Oid vartype
);
155 static void CheckOpSlotCompatibility(ExprEvalStep
*op
, TupleTableSlot
*slot
);
156 static TupleDesc
get_cached_rowtype(Oid type_id
, int32 typmod
,
157 ExprEvalRowtypeCache
*rowcache
,
159 static void ExecEvalRowNullInt(ExprState
*state
, ExprEvalStep
*op
,
160 ExprContext
*econtext
, bool checkisnull
);
162 /* fast-path evaluation functions */
163 static Datum
ExecJustInnerVar(ExprState
*state
, ExprContext
*econtext
, bool *isnull
);
164 static Datum
ExecJustOuterVar(ExprState
*state
, ExprContext
*econtext
, bool *isnull
);
165 static Datum
ExecJustScanVar(ExprState
*state
, ExprContext
*econtext
, bool *isnull
);
166 static Datum
ExecJustAssignInnerVar(ExprState
*state
, ExprContext
*econtext
, bool *isnull
);
167 static Datum
ExecJustAssignOuterVar(ExprState
*state
, ExprContext
*econtext
, bool *isnull
);
168 static Datum
ExecJustAssignScanVar(ExprState
*state
, ExprContext
*econtext
, bool *isnull
);
169 static Datum
ExecJustApplyFuncToCase(ExprState
*state
, ExprContext
*econtext
, bool *isnull
);
170 static Datum
ExecJustConst(ExprState
*state
, ExprContext
*econtext
, bool *isnull
);
171 static Datum
ExecJustInnerVarVirt(ExprState
*state
, ExprContext
*econtext
, bool *isnull
);
172 static Datum
ExecJustOuterVarVirt(ExprState
*state
, ExprContext
*econtext
, bool *isnull
);
173 static Datum
ExecJustScanVarVirt(ExprState
*state
, ExprContext
*econtext
, bool *isnull
);
174 static Datum
ExecJustAssignInnerVarVirt(ExprState
*state
, ExprContext
*econtext
, bool *isnull
);
175 static Datum
ExecJustAssignOuterVarVirt(ExprState
*state
, ExprContext
*econtext
, bool *isnull
);
176 static Datum
ExecJustAssignScanVarVirt(ExprState
*state
, ExprContext
*econtext
, bool *isnull
);
178 /* execution helper functions */
179 static pg_attribute_always_inline
void ExecAggPlainTransByVal(AggState
*aggstate
,
180 AggStatePerTrans pertrans
,
181 AggStatePerGroup pergroup
,
182 ExprContext
*aggcontext
,
184 static pg_attribute_always_inline
void ExecAggPlainTransByRef(AggState
*aggstate
,
185 AggStatePerTrans pertrans
,
186 AggStatePerGroup pergroup
,
187 ExprContext
*aggcontext
,
191 * ScalarArrayOpExprHashEntry
192 * Hash table entry type used during EEOP_HASHED_SCALARARRAYOP
194 typedef struct ScalarArrayOpExprHashEntry
197 uint32 status
; /* hash status */
198 uint32 hash
; /* hash value (cached) */
199 } ScalarArrayOpExprHashEntry
;
201 #define SH_PREFIX saophash
202 #define SH_ELEMENT_TYPE ScalarArrayOpExprHashEntry
203 #define SH_KEY_TYPE Datum
204 #define SH_SCOPE static inline
206 #include "lib/simplehash.h"
208 static bool saop_hash_element_match(struct saophash_hash
*tb
, Datum key1
,
210 static uint32
saop_element_hash(struct saophash_hash
*tb
, Datum key
);
213 * ScalarArrayOpExprHashTable
214 * Hash table for EEOP_HASHED_SCALARARRAYOP
216 typedef struct ScalarArrayOpExprHashTable
218 saophash_hash
*hashtab
; /* underlying hash table */
219 struct ExprEvalStep
*op
;
220 FmgrInfo hash_finfo
; /* function's lookup data */
221 FunctionCallInfoBaseData hash_fcinfo_data
; /* arguments etc */
222 } ScalarArrayOpExprHashTable
;
224 /* Define parameters for ScalarArrayOpExpr hash table code generation. */
225 #define SH_PREFIX saophash
226 #define SH_ELEMENT_TYPE ScalarArrayOpExprHashEntry
227 #define SH_KEY_TYPE Datum
229 #define SH_HASH_KEY(tb, key) saop_element_hash(tb, key)
230 #define SH_EQUAL(tb, a, b) saop_hash_element_match(tb, a, b)
231 #define SH_SCOPE static inline
232 #define SH_STORE_HASH
233 #define SH_GET_HASH(tb, a) a->hash
235 #include "lib/simplehash.h"
238 * Prepare ExprState for interpreted execution.
241 ExecReadyInterpretedExpr(ExprState
*state
)
243 /* Ensure one-time interpreter setup has been done */
244 ExecInitInterpreter();
246 /* Simple validity checks on expression */
247 Assert(state
->steps_len
>= 1);
248 Assert(state
->steps
[state
->steps_len
- 1].opcode
== EEOP_DONE
);
251 * Don't perform redundant initialization. This is unreachable in current
252 * cases, but might be hit if there's additional expression evaluation
253 * methods that rely on interpreted execution to work.
255 if (state
->flags
& EEO_FLAG_INTERPRETER_INITIALIZED
)
259 * First time through, check whether attribute matches Var. Might not be
260 * ok anymore, due to schema changes. We do that by setting up a callback
261 * that does checking on the first call, which then sets the evalfunc
262 * callback to the actual method of execution.
264 state
->evalfunc
= ExecInterpExprStillValid
;
266 /* DIRECT_THREADED should not already be set */
267 Assert((state
->flags
& EEO_FLAG_DIRECT_THREADED
) == 0);
270 * There shouldn't be any errors before the expression is fully
271 * initialized, and even if so, it'd lead to the expression being
272 * abandoned. So we can set the flag now and save some code.
274 state
->flags
|= EEO_FLAG_INTERPRETER_INITIALIZED
;
277 * Select fast-path evalfuncs for very simple expressions. "Starting up"
278 * the full interpreter is a measurable overhead for these, and these
279 * patterns occur often enough to be worth optimizing.
281 if (state
->steps_len
== 3)
283 ExprEvalOp step0
= state
->steps
[0].opcode
;
284 ExprEvalOp step1
= state
->steps
[1].opcode
;
286 if (step0
== EEOP_INNER_FETCHSOME
&&
287 step1
== EEOP_INNER_VAR
)
289 state
->evalfunc_private
= (void *) ExecJustInnerVar
;
292 else if (step0
== EEOP_OUTER_FETCHSOME
&&
293 step1
== EEOP_OUTER_VAR
)
295 state
->evalfunc_private
= (void *) ExecJustOuterVar
;
298 else if (step0
== EEOP_SCAN_FETCHSOME
&&
299 step1
== EEOP_SCAN_VAR
)
301 state
->evalfunc_private
= (void *) ExecJustScanVar
;
304 else if (step0
== EEOP_INNER_FETCHSOME
&&
305 step1
== EEOP_ASSIGN_INNER_VAR
)
307 state
->evalfunc_private
= (void *) ExecJustAssignInnerVar
;
310 else if (step0
== EEOP_OUTER_FETCHSOME
&&
311 step1
== EEOP_ASSIGN_OUTER_VAR
)
313 state
->evalfunc_private
= (void *) ExecJustAssignOuterVar
;
316 else if (step0
== EEOP_SCAN_FETCHSOME
&&
317 step1
== EEOP_ASSIGN_SCAN_VAR
)
319 state
->evalfunc_private
= (void *) ExecJustAssignScanVar
;
322 else if (step0
== EEOP_CASE_TESTVAL
&&
323 step1
== EEOP_FUNCEXPR_STRICT
&&
324 state
->steps
[0].d
.casetest
.value
)
326 state
->evalfunc_private
= (void *) ExecJustApplyFuncToCase
;
330 else if (state
->steps_len
== 2)
332 ExprEvalOp step0
= state
->steps
[0].opcode
;
334 if (step0
== EEOP_CONST
)
336 state
->evalfunc_private
= (void *) ExecJustConst
;
339 else if (step0
== EEOP_INNER_VAR
)
341 state
->evalfunc_private
= (void *) ExecJustInnerVarVirt
;
344 else if (step0
== EEOP_OUTER_VAR
)
346 state
->evalfunc_private
= (void *) ExecJustOuterVarVirt
;
349 else if (step0
== EEOP_SCAN_VAR
)
351 state
->evalfunc_private
= (void *) ExecJustScanVarVirt
;
354 else if (step0
== EEOP_ASSIGN_INNER_VAR
)
356 state
->evalfunc_private
= (void *) ExecJustAssignInnerVarVirt
;
359 else if (step0
== EEOP_ASSIGN_OUTER_VAR
)
361 state
->evalfunc_private
= (void *) ExecJustAssignOuterVarVirt
;
364 else if (step0
== EEOP_ASSIGN_SCAN_VAR
)
366 state
->evalfunc_private
= (void *) ExecJustAssignScanVarVirt
;
371 #if defined(EEO_USE_COMPUTED_GOTO)
374 * In the direct-threaded implementation, replace each opcode with the
375 * address to jump to. (Use ExecEvalStepOp() to get back the opcode.)
377 for (int off
= 0; off
< state
->steps_len
; off
++)
379 ExprEvalStep
*op
= &state
->steps
[off
];
381 op
->opcode
= EEO_OPCODE(op
->opcode
);
384 state
->flags
|= EEO_FLAG_DIRECT_THREADED
;
385 #endif /* EEO_USE_COMPUTED_GOTO */
387 state
->evalfunc_private
= (void *) ExecInterpExpr
;
392 * Evaluate expression identified by "state" in the execution context
393 * given by "econtext". *isnull is set to the is-null flag for the result,
394 * and the Datum value is the function result.
396 * As a special case, return the dispatch table's address if state is NULL.
397 * This is used by ExecInitInterpreter to set up the dispatch_table global.
398 * (Only applies when EEO_USE_COMPUTED_GOTO is defined.)
401 ExecInterpExpr(ExprState
*state
, ExprContext
*econtext
, bool *isnull
)
404 TupleTableSlot
*resultslot
;
405 TupleTableSlot
*innerslot
;
406 TupleTableSlot
*outerslot
;
407 TupleTableSlot
*scanslot
;
410 * This array has to be in the same order as enum ExprEvalOp.
412 #if defined(EEO_USE_COMPUTED_GOTO)
413 static const void *const dispatch_table
[] = {
415 &&CASE_EEOP_INNER_FETCHSOME
,
416 &&CASE_EEOP_OUTER_FETCHSOME
,
417 &&CASE_EEOP_SCAN_FETCHSOME
,
418 &&CASE_EEOP_INNER_VAR
,
419 &&CASE_EEOP_OUTER_VAR
,
420 &&CASE_EEOP_SCAN_VAR
,
421 &&CASE_EEOP_INNER_SYSVAR
,
422 &&CASE_EEOP_OUTER_SYSVAR
,
423 &&CASE_EEOP_SCAN_SYSVAR
,
424 &&CASE_EEOP_WHOLEROW
,
425 &&CASE_EEOP_ASSIGN_INNER_VAR
,
426 &&CASE_EEOP_ASSIGN_OUTER_VAR
,
427 &&CASE_EEOP_ASSIGN_SCAN_VAR
,
428 &&CASE_EEOP_ASSIGN_TMP
,
429 &&CASE_EEOP_ASSIGN_TMP_MAKE_RO
,
431 &&CASE_EEOP_FUNCEXPR
,
432 &&CASE_EEOP_FUNCEXPR_STRICT
,
433 &&CASE_EEOP_FUNCEXPR_FUSAGE
,
434 &&CASE_EEOP_FUNCEXPR_STRICT_FUSAGE
,
435 &&CASE_EEOP_BOOL_AND_STEP_FIRST
,
436 &&CASE_EEOP_BOOL_AND_STEP
,
437 &&CASE_EEOP_BOOL_AND_STEP_LAST
,
438 &&CASE_EEOP_BOOL_OR_STEP_FIRST
,
439 &&CASE_EEOP_BOOL_OR_STEP
,
440 &&CASE_EEOP_BOOL_OR_STEP_LAST
,
441 &&CASE_EEOP_BOOL_NOT_STEP
,
444 &&CASE_EEOP_JUMP_IF_NULL
,
445 &&CASE_EEOP_JUMP_IF_NOT_NULL
,
446 &&CASE_EEOP_JUMP_IF_NOT_TRUE
,
447 &&CASE_EEOP_NULLTEST_ISNULL
,
448 &&CASE_EEOP_NULLTEST_ISNOTNULL
,
449 &&CASE_EEOP_NULLTEST_ROWISNULL
,
450 &&CASE_EEOP_NULLTEST_ROWISNOTNULL
,
451 &&CASE_EEOP_BOOLTEST_IS_TRUE
,
452 &&CASE_EEOP_BOOLTEST_IS_NOT_TRUE
,
453 &&CASE_EEOP_BOOLTEST_IS_FALSE
,
454 &&CASE_EEOP_BOOLTEST_IS_NOT_FALSE
,
455 &&CASE_EEOP_PARAM_EXEC
,
456 &&CASE_EEOP_PARAM_EXTERN
,
457 &&CASE_EEOP_PARAM_CALLBACK
,
458 &&CASE_EEOP_CASE_TESTVAL
,
459 &&CASE_EEOP_MAKE_READONLY
,
460 &&CASE_EEOP_IOCOERCE
,
461 &&CASE_EEOP_DISTINCT
,
462 &&CASE_EEOP_NOT_DISTINCT
,
464 &&CASE_EEOP_SQLVALUEFUNCTION
,
465 &&CASE_EEOP_CURRENTOFEXPR
,
466 &&CASE_EEOP_NEXTVALUEEXPR
,
467 &&CASE_EEOP_ARRAYEXPR
,
468 &&CASE_EEOP_ARRAYCOERCE
,
470 &&CASE_EEOP_ROWCOMPARE_STEP
,
471 &&CASE_EEOP_ROWCOMPARE_FINAL
,
473 &&CASE_EEOP_FIELDSELECT
,
474 &&CASE_EEOP_FIELDSTORE_DEFORM
,
475 &&CASE_EEOP_FIELDSTORE_FORM
,
476 &&CASE_EEOP_SBSREF_SUBSCRIPTS
,
477 &&CASE_EEOP_SBSREF_OLD
,
478 &&CASE_EEOP_SBSREF_ASSIGN
,
479 &&CASE_EEOP_SBSREF_FETCH
,
480 &&CASE_EEOP_DOMAIN_TESTVAL
,
481 &&CASE_EEOP_DOMAIN_NOTNULL
,
482 &&CASE_EEOP_DOMAIN_CHECK
,
483 &&CASE_EEOP_CONVERT_ROWTYPE
,
484 &&CASE_EEOP_SCALARARRAYOP
,
485 &&CASE_EEOP_HASHED_SCALARARRAYOP
,
488 &&CASE_EEOP_GROUPING_FUNC
,
489 &&CASE_EEOP_WINDOW_FUNC
,
491 &&CASE_EEOP_JSON_CONSTRUCTOR
,
493 &&CASE_EEOP_JSONEXPR
,
494 &&CASE_EEOP_AGG_STRICT_DESERIALIZE
,
495 &&CASE_EEOP_AGG_DESERIALIZE
,
496 &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS
,
497 &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_NULLS
,
498 &&CASE_EEOP_AGG_PLAIN_PERGROUP_NULLCHECK
,
499 &&CASE_EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL
,
500 &&CASE_EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL
,
501 &&CASE_EEOP_AGG_PLAIN_TRANS_BYVAL
,
502 &&CASE_EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF
,
503 &&CASE_EEOP_AGG_PLAIN_TRANS_STRICT_BYREF
,
504 &&CASE_EEOP_AGG_PLAIN_TRANS_BYREF
,
505 &&CASE_EEOP_AGG_ORDERED_TRANS_DATUM
,
506 &&CASE_EEOP_AGG_ORDERED_TRANS_TUPLE
,
510 StaticAssertStmt(EEOP_LAST
+ 1 == lengthof(dispatch_table
),
511 "dispatch_table out of whack with ExprEvalOp");
513 if (unlikely(state
== NULL
))
514 return PointerGetDatum(dispatch_table
);
516 Assert(state
!= NULL
);
517 #endif /* EEO_USE_COMPUTED_GOTO */
521 resultslot
= state
->resultslot
;
522 innerslot
= econtext
->ecxt_innertuple
;
523 outerslot
= econtext
->ecxt_outertuple
;
524 scanslot
= econtext
->ecxt_scantuple
;
526 #if defined(EEO_USE_COMPUTED_GOTO)
537 EEO_CASE(EEOP_INNER_FETCHSOME
)
539 CheckOpSlotCompatibility(op
, innerslot
);
541 slot_getsomeattrs(innerslot
, op
->d
.fetch
.last_var
);
546 EEO_CASE(EEOP_OUTER_FETCHSOME
)
548 CheckOpSlotCompatibility(op
, outerslot
);
550 slot_getsomeattrs(outerslot
, op
->d
.fetch
.last_var
);
555 EEO_CASE(EEOP_SCAN_FETCHSOME
)
557 CheckOpSlotCompatibility(op
, scanslot
);
559 slot_getsomeattrs(scanslot
, op
->d
.fetch
.last_var
);
564 EEO_CASE(EEOP_INNER_VAR
)
566 int attnum
= op
->d
.var
.attnum
;
569 * Since we already extracted all referenced columns from the
570 * tuple with a FETCHSOME step, we can just grab the value
571 * directly out of the slot's decomposed-data arrays. But let's
572 * have an Assert to check that that did happen.
574 Assert(attnum
>= 0 && attnum
< innerslot
->tts_nvalid
);
575 *op
->resvalue
= innerslot
->tts_values
[attnum
];
576 *op
->resnull
= innerslot
->tts_isnull
[attnum
];
581 EEO_CASE(EEOP_OUTER_VAR
)
583 int attnum
= op
->d
.var
.attnum
;
585 /* See EEOP_INNER_VAR comments */
587 Assert(attnum
>= 0 && attnum
< outerslot
->tts_nvalid
);
588 *op
->resvalue
= outerslot
->tts_values
[attnum
];
589 *op
->resnull
= outerslot
->tts_isnull
[attnum
];
594 EEO_CASE(EEOP_SCAN_VAR
)
596 int attnum
= op
->d
.var
.attnum
;
598 /* See EEOP_INNER_VAR comments */
600 Assert(attnum
>= 0 && attnum
< scanslot
->tts_nvalid
);
601 *op
->resvalue
= scanslot
->tts_values
[attnum
];
602 *op
->resnull
= scanslot
->tts_isnull
[attnum
];
607 EEO_CASE(EEOP_INNER_SYSVAR
)
609 ExecEvalSysVar(state
, op
, econtext
, innerslot
);
613 EEO_CASE(EEOP_OUTER_SYSVAR
)
615 ExecEvalSysVar(state
, op
, econtext
, outerslot
);
619 EEO_CASE(EEOP_SCAN_SYSVAR
)
621 ExecEvalSysVar(state
, op
, econtext
, scanslot
);
625 EEO_CASE(EEOP_WHOLEROW
)
627 /* too complex for an inline implementation */
628 ExecEvalWholeRowVar(state
, op
, econtext
);
633 EEO_CASE(EEOP_ASSIGN_INNER_VAR
)
635 int resultnum
= op
->d
.assign_var
.resultnum
;
636 int attnum
= op
->d
.assign_var
.attnum
;
639 * We do not need CheckVarSlotCompatibility here; that was taken
640 * care of at compilation time. But see EEOP_INNER_VAR comments.
642 Assert(attnum
>= 0 && attnum
< innerslot
->tts_nvalid
);
643 Assert(resultnum
>= 0 && resultnum
< resultslot
->tts_tupleDescriptor
->natts
);
644 resultslot
->tts_values
[resultnum
] = innerslot
->tts_values
[attnum
];
645 resultslot
->tts_isnull
[resultnum
] = innerslot
->tts_isnull
[attnum
];
650 EEO_CASE(EEOP_ASSIGN_OUTER_VAR
)
652 int resultnum
= op
->d
.assign_var
.resultnum
;
653 int attnum
= op
->d
.assign_var
.attnum
;
656 * We do not need CheckVarSlotCompatibility here; that was taken
657 * care of at compilation time. But see EEOP_INNER_VAR comments.
659 Assert(attnum
>= 0 && attnum
< outerslot
->tts_nvalid
);
660 Assert(resultnum
>= 0 && resultnum
< resultslot
->tts_tupleDescriptor
->natts
);
661 resultslot
->tts_values
[resultnum
] = outerslot
->tts_values
[attnum
];
662 resultslot
->tts_isnull
[resultnum
] = outerslot
->tts_isnull
[attnum
];
667 EEO_CASE(EEOP_ASSIGN_SCAN_VAR
)
669 int resultnum
= op
->d
.assign_var
.resultnum
;
670 int attnum
= op
->d
.assign_var
.attnum
;
673 * We do not need CheckVarSlotCompatibility here; that was taken
674 * care of at compilation time. But see EEOP_INNER_VAR comments.
676 Assert(attnum
>= 0 && attnum
< scanslot
->tts_nvalid
);
677 Assert(resultnum
>= 0 && resultnum
< resultslot
->tts_tupleDescriptor
->natts
);
678 resultslot
->tts_values
[resultnum
] = scanslot
->tts_values
[attnum
];
679 resultslot
->tts_isnull
[resultnum
] = scanslot
->tts_isnull
[attnum
];
684 EEO_CASE(EEOP_ASSIGN_TMP
)
686 int resultnum
= op
->d
.assign_tmp
.resultnum
;
688 Assert(resultnum
>= 0 && resultnum
< resultslot
->tts_tupleDescriptor
->natts
);
689 resultslot
->tts_values
[resultnum
] = state
->resvalue
;
690 resultslot
->tts_isnull
[resultnum
] = state
->resnull
;
695 EEO_CASE(EEOP_ASSIGN_TMP_MAKE_RO
)
697 int resultnum
= op
->d
.assign_tmp
.resultnum
;
699 Assert(resultnum
>= 0 && resultnum
< resultslot
->tts_tupleDescriptor
->natts
);
700 resultslot
->tts_isnull
[resultnum
] = state
->resnull
;
701 if (!resultslot
->tts_isnull
[resultnum
])
702 resultslot
->tts_values
[resultnum
] =
703 MakeExpandedObjectReadOnlyInternal(state
->resvalue
);
705 resultslot
->tts_values
[resultnum
] = state
->resvalue
;
712 *op
->resnull
= op
->d
.constval
.isnull
;
713 *op
->resvalue
= op
->d
.constval
.value
;
719 * Function-call implementations. Arguments have previously been
720 * evaluated directly into fcinfo->args.
722 * As both STRICT checks and function-usage are noticeable performance
723 * wise, and function calls are a very hot-path (they also back
724 * operators!), it's worth having so many separate opcodes.
726 * Note: the reason for using a temporary variable "d", here and in
727 * other places, is that some compilers think "*op->resvalue = f();"
728 * requires them to evaluate op->resvalue into a register before
729 * calling f(), just in case f() is able to modify op->resvalue
730 * somehow. The extra line of code can save a useless register spill
731 * and reload across the function call.
733 EEO_CASE(EEOP_FUNCEXPR
)
735 FunctionCallInfo fcinfo
= op
->d
.func
.fcinfo_data
;
738 fcinfo
->isnull
= false;
739 d
= op
->d
.func
.fn_addr(fcinfo
);
741 *op
->resnull
= fcinfo
->isnull
;
746 EEO_CASE(EEOP_FUNCEXPR_STRICT
)
748 FunctionCallInfo fcinfo
= op
->d
.func
.fcinfo_data
;
749 NullableDatum
*args
= fcinfo
->args
;
750 int nargs
= op
->d
.func
.nargs
;
753 /* strict function, so check for NULL args */
754 for (int argno
= 0; argno
< nargs
; argno
++)
756 if (args
[argno
].isnull
)
762 fcinfo
->isnull
= false;
763 d
= op
->d
.func
.fn_addr(fcinfo
);
765 *op
->resnull
= fcinfo
->isnull
;
771 EEO_CASE(EEOP_FUNCEXPR_FUSAGE
)
773 /* not common enough to inline */
774 ExecEvalFuncExprFusage(state
, op
, econtext
);
779 EEO_CASE(EEOP_FUNCEXPR_STRICT_FUSAGE
)
781 /* not common enough to inline */
782 ExecEvalFuncExprStrictFusage(state
, op
, econtext
);
788 * If any of its clauses is FALSE, an AND's result is FALSE regardless
789 * of the states of the rest of the clauses, so we can stop evaluating
790 * and return FALSE immediately. If none are FALSE and one or more is
791 * NULL, we return NULL; otherwise we return TRUE. This makes sense
792 * when you interpret NULL as "don't know": perhaps one of the "don't
793 * knows" would have been FALSE if we'd known its value. Only when
794 * all the inputs are known to be TRUE can we state confidently that
795 * the AND's result is TRUE.
797 EEO_CASE(EEOP_BOOL_AND_STEP_FIRST
)
799 *op
->d
.boolexpr
.anynull
= false;
802 * EEOP_BOOL_AND_STEP_FIRST resets anynull, otherwise it's the
803 * same as EEOP_BOOL_AND_STEP - so fall through to that.
809 EEO_CASE(EEOP_BOOL_AND_STEP
)
813 *op
->d
.boolexpr
.anynull
= true;
815 else if (!DatumGetBool(*op
->resvalue
))
817 /* result is already set to FALSE, need not change it */
819 EEO_JUMP(op
->d
.boolexpr
.jumpdone
);
825 EEO_CASE(EEOP_BOOL_AND_STEP_LAST
)
829 /* result is already set to NULL, need not change it */
831 else if (!DatumGetBool(*op
->resvalue
))
833 /* result is already set to FALSE, need not change it */
836 * No point jumping early to jumpdone - would be same target
837 * (as this is the last argument to the AND expression),
838 * except more expensive.
841 else if (*op
->d
.boolexpr
.anynull
)
843 *op
->resvalue
= (Datum
) 0;
848 /* result is already set to TRUE, need not change it */
855 * If any of its clauses is TRUE, an OR's result is TRUE regardless of
856 * the states of the rest of the clauses, so we can stop evaluating
857 * and return TRUE immediately. If none are TRUE and one or more is
858 * NULL, we return NULL; otherwise we return FALSE. This makes sense
859 * when you interpret NULL as "don't know": perhaps one of the "don't
860 * knows" would have been TRUE if we'd known its value. Only when all
861 * the inputs are known to be FALSE can we state confidently that the
862 * OR's result is FALSE.
864 EEO_CASE(EEOP_BOOL_OR_STEP_FIRST
)
866 *op
->d
.boolexpr
.anynull
= false;
869 * EEOP_BOOL_OR_STEP_FIRST resets anynull, otherwise it's the same
870 * as EEOP_BOOL_OR_STEP - so fall through to that.
876 EEO_CASE(EEOP_BOOL_OR_STEP
)
880 *op
->d
.boolexpr
.anynull
= true;
882 else if (DatumGetBool(*op
->resvalue
))
884 /* result is already set to TRUE, need not change it */
886 EEO_JUMP(op
->d
.boolexpr
.jumpdone
);
892 EEO_CASE(EEOP_BOOL_OR_STEP_LAST
)
896 /* result is already set to NULL, need not change it */
898 else if (DatumGetBool(*op
->resvalue
))
900 /* result is already set to TRUE, need not change it */
903 * No point jumping to jumpdone - would be same target (as
904 * this is the last argument to the AND expression), except
908 else if (*op
->d
.boolexpr
.anynull
)
910 *op
->resvalue
= (Datum
) 0;
915 /* result is already set to FALSE, need not change it */
921 EEO_CASE(EEOP_BOOL_NOT_STEP
)
924 * Evaluation of 'not' is simple... if expr is false, then return
925 * 'true' and vice versa. It's safe to do this even on a
926 * nominally null value, so we ignore resnull; that means that
927 * NULL in produces NULL out, which is what we want.
929 *op
->resvalue
= BoolGetDatum(!DatumGetBool(*op
->resvalue
));
936 /* simplified version of BOOL_AND_STEP for use by ExecQual() */
938 /* If argument (also result) is false or null ... */
940 !DatumGetBool(*op
->resvalue
))
942 /* ... bail out early, returning FALSE */
943 *op
->resnull
= false;
944 *op
->resvalue
= BoolGetDatum(false);
945 EEO_JUMP(op
->d
.qualexpr
.jumpdone
);
949 * Otherwise, leave the TRUE value in place, in case this is the
950 * last qual. Then, TRUE is the correct answer.
958 /* Unconditionally jump to target step */
959 EEO_JUMP(op
->d
.jump
.jumpdone
);
962 EEO_CASE(EEOP_JUMP_IF_NULL
)
964 /* Transfer control if current result is null */
966 EEO_JUMP(op
->d
.jump
.jumpdone
);
971 EEO_CASE(EEOP_JUMP_IF_NOT_NULL
)
973 /* Transfer control if current result is non-null */
975 EEO_JUMP(op
->d
.jump
.jumpdone
);
980 EEO_CASE(EEOP_JUMP_IF_NOT_TRUE
)
982 /* Transfer control if current result is null or false */
983 if (*op
->resnull
|| !DatumGetBool(*op
->resvalue
))
984 EEO_JUMP(op
->d
.jump
.jumpdone
);
989 EEO_CASE(EEOP_NULLTEST_ISNULL
)
991 *op
->resvalue
= BoolGetDatum(*op
->resnull
);
992 *op
->resnull
= false;
997 EEO_CASE(EEOP_NULLTEST_ISNOTNULL
)
999 *op
->resvalue
= BoolGetDatum(!*op
->resnull
);
1000 *op
->resnull
= false;
1005 EEO_CASE(EEOP_NULLTEST_ROWISNULL
)
1007 /* out of line implementation: too large */
1008 ExecEvalRowNull(state
, op
, econtext
);
1013 EEO_CASE(EEOP_NULLTEST_ROWISNOTNULL
)
1015 /* out of line implementation: too large */
1016 ExecEvalRowNotNull(state
, op
, econtext
);
1021 /* BooleanTest implementations for all booltesttypes */
1023 EEO_CASE(EEOP_BOOLTEST_IS_TRUE
)
1027 *op
->resvalue
= BoolGetDatum(false);
1028 *op
->resnull
= false;
1030 /* else, input value is the correct output as well */
1035 EEO_CASE(EEOP_BOOLTEST_IS_NOT_TRUE
)
1039 *op
->resvalue
= BoolGetDatum(true);
1040 *op
->resnull
= false;
1043 *op
->resvalue
= BoolGetDatum(!DatumGetBool(*op
->resvalue
));
1048 EEO_CASE(EEOP_BOOLTEST_IS_FALSE
)
1052 *op
->resvalue
= BoolGetDatum(false);
1053 *op
->resnull
= false;
1056 *op
->resvalue
= BoolGetDatum(!DatumGetBool(*op
->resvalue
));
1061 EEO_CASE(EEOP_BOOLTEST_IS_NOT_FALSE
)
1065 *op
->resvalue
= BoolGetDatum(true);
1066 *op
->resnull
= false;
1068 /* else, input value is the correct output as well */
1073 EEO_CASE(EEOP_PARAM_EXEC
)
1075 /* out of line implementation: too large */
1076 ExecEvalParamExec(state
, op
, econtext
);
1081 EEO_CASE(EEOP_PARAM_EXTERN
)
1083 /* out of line implementation: too large */
1084 ExecEvalParamExtern(state
, op
, econtext
);
1088 EEO_CASE(EEOP_PARAM_CALLBACK
)
1090 /* allow an extension module to supply a PARAM_EXTERN value */
1091 op
->d
.cparam
.paramfunc(state
, op
, econtext
);
1095 EEO_CASE(EEOP_CASE_TESTVAL
)
1098 * Normally upper parts of the expression tree have setup the
1099 * values to be returned here, but some parts of the system
1100 * currently misuse {caseValue,domainValue}_{datum,isNull} to set
1101 * run-time data. So if no values have been set-up, use
1102 * ExprContext's. This isn't pretty, but also not *that* ugly,
1103 * and this is unlikely to be performance sensitive enough to
1104 * worry about an extra branch.
1106 if (op
->d
.casetest
.value
)
1108 *op
->resvalue
= *op
->d
.casetest
.value
;
1109 *op
->resnull
= *op
->d
.casetest
.isnull
;
1113 *op
->resvalue
= econtext
->caseValue_datum
;
1114 *op
->resnull
= econtext
->caseValue_isNull
;
1120 EEO_CASE(EEOP_DOMAIN_TESTVAL
)
1123 * See EEOP_CASE_TESTVAL comment.
1125 if (op
->d
.casetest
.value
)
1127 *op
->resvalue
= *op
->d
.casetest
.value
;
1128 *op
->resnull
= *op
->d
.casetest
.isnull
;
1132 *op
->resvalue
= econtext
->domainValue_datum
;
1133 *op
->resnull
= econtext
->domainValue_isNull
;
1139 EEO_CASE(EEOP_MAKE_READONLY
)
1142 * Force a varlena value that might be read multiple times to R/O
1144 if (!*op
->d
.make_readonly
.isnull
)
1146 MakeExpandedObjectReadOnlyInternal(*op
->d
.make_readonly
.value
);
1147 *op
->resnull
= *op
->d
.make_readonly
.isnull
;
1152 EEO_CASE(EEOP_IOCOERCE
)
1155 * Evaluate a CoerceViaIO node. This can be quite a hot path, so
1156 * inline as much work as possible. The source value is in our
1161 /* call output function (similar to OutputFunctionCall) */
1164 /* output functions are not called on nulls */
1169 FunctionCallInfo fcinfo_out
;
1171 fcinfo_out
= op
->d
.iocoerce
.fcinfo_data_out
;
1172 fcinfo_out
->args
[0].value
= *op
->resvalue
;
1173 fcinfo_out
->args
[0].isnull
= false;
1175 fcinfo_out
->isnull
= false;
1176 str
= DatumGetCString(FunctionCallInvoke(fcinfo_out
));
1178 /* OutputFunctionCall assumes result isn't null */
1179 Assert(!fcinfo_out
->isnull
);
1182 /* call input function (similar to InputFunctionCall) */
1183 if (!op
->d
.iocoerce
.finfo_in
->fn_strict
|| str
!= NULL
)
1185 FunctionCallInfo fcinfo_in
;
1188 fcinfo_in
= op
->d
.iocoerce
.fcinfo_data_in
;
1189 fcinfo_in
->args
[0].value
= PointerGetDatum(str
);
1190 fcinfo_in
->args
[0].isnull
= *op
->resnull
;
1191 /* second and third arguments are already set up */
1193 fcinfo_in
->isnull
= false;
1194 d
= FunctionCallInvoke(fcinfo_in
);
1197 /* Should get null result if and only if str is NULL */
1200 Assert(*op
->resnull
);
1201 Assert(fcinfo_in
->isnull
);
1205 Assert(!*op
->resnull
);
1206 Assert(!fcinfo_in
->isnull
);
1213 EEO_CASE(EEOP_DISTINCT
)
1216 * IS DISTINCT FROM must evaluate arguments (already done into
1217 * fcinfo->args) to determine whether they are NULL; if either is
1218 * NULL then the result is determined. If neither is NULL, then
1219 * proceed to evaluate the comparison function, which is just the
1220 * type's standard equality operator. We need not care whether
1221 * that function is strict. Because the handling of nulls is
1222 * different, we can't just reuse EEOP_FUNCEXPR.
1224 FunctionCallInfo fcinfo
= op
->d
.func
.fcinfo_data
;
1226 /* check function arguments for NULLness */
1227 if (fcinfo
->args
[0].isnull
&& fcinfo
->args
[1].isnull
)
1229 /* Both NULL? Then is not distinct... */
1230 *op
->resvalue
= BoolGetDatum(false);
1231 *op
->resnull
= false;
1233 else if (fcinfo
->args
[0].isnull
|| fcinfo
->args
[1].isnull
)
1235 /* Only one is NULL? Then is distinct... */
1236 *op
->resvalue
= BoolGetDatum(true);
1237 *op
->resnull
= false;
1241 /* Neither null, so apply the equality function */
1244 fcinfo
->isnull
= false;
1245 eqresult
= op
->d
.func
.fn_addr(fcinfo
);
1246 /* Must invert result of "="; safe to do even if null */
1247 *op
->resvalue
= BoolGetDatum(!DatumGetBool(eqresult
));
1248 *op
->resnull
= fcinfo
->isnull
;
1254 /* see EEOP_DISTINCT for comments, this is just inverted */
1255 EEO_CASE(EEOP_NOT_DISTINCT
)
1257 FunctionCallInfo fcinfo
= op
->d
.func
.fcinfo_data
;
1259 if (fcinfo
->args
[0].isnull
&& fcinfo
->args
[1].isnull
)
1261 *op
->resvalue
= BoolGetDatum(true);
1262 *op
->resnull
= false;
1264 else if (fcinfo
->args
[0].isnull
|| fcinfo
->args
[1].isnull
)
1266 *op
->resvalue
= BoolGetDatum(false);
1267 *op
->resnull
= false;
1273 fcinfo
->isnull
= false;
1274 eqresult
= op
->d
.func
.fn_addr(fcinfo
);
1275 *op
->resvalue
= eqresult
;
1276 *op
->resnull
= fcinfo
->isnull
;
1282 EEO_CASE(EEOP_NULLIF
)
1285 * The arguments are already evaluated into fcinfo->args.
1287 FunctionCallInfo fcinfo
= op
->d
.func
.fcinfo_data
;
1289 /* if either argument is NULL they can't be equal */
1290 if (!fcinfo
->args
[0].isnull
&& !fcinfo
->args
[1].isnull
)
1294 fcinfo
->isnull
= false;
1295 result
= op
->d
.func
.fn_addr(fcinfo
);
1297 /* if the arguments are equal return null */
1298 if (!fcinfo
->isnull
&& DatumGetBool(result
))
1300 *op
->resvalue
= (Datum
) 0;
1301 *op
->resnull
= true;
1307 /* Arguments aren't equal, so return the first one */
1308 *op
->resvalue
= fcinfo
->args
[0].value
;
1309 *op
->resnull
= fcinfo
->args
[0].isnull
;
1314 EEO_CASE(EEOP_SQLVALUEFUNCTION
)
1317 * Doesn't seem worthwhile to have an inline implementation
1320 ExecEvalSQLValueFunction(state
, op
);
1325 EEO_CASE(EEOP_CURRENTOFEXPR
)
1327 /* error invocation uses space, and shouldn't ever occur */
1328 ExecEvalCurrentOfExpr(state
, op
);
1333 EEO_CASE(EEOP_NEXTVALUEEXPR
)
1336 * Doesn't seem worthwhile to have an inline implementation
1339 ExecEvalNextValueExpr(state
, op
);
1344 EEO_CASE(EEOP_ARRAYEXPR
)
1346 /* too complex for an inline implementation */
1347 ExecEvalArrayExpr(state
, op
);
1352 EEO_CASE(EEOP_ARRAYCOERCE
)
1354 /* too complex for an inline implementation */
1355 ExecEvalArrayCoerce(state
, op
, econtext
);
1362 /* too complex for an inline implementation */
1363 ExecEvalRow(state
, op
);
1368 EEO_CASE(EEOP_ROWCOMPARE_STEP
)
1370 FunctionCallInfo fcinfo
= op
->d
.rowcompare_step
.fcinfo_data
;
1373 /* force NULL result if strict fn and NULL input */
1374 if (op
->d
.rowcompare_step
.finfo
->fn_strict
&&
1375 (fcinfo
->args
[0].isnull
|| fcinfo
->args
[1].isnull
))
1377 *op
->resnull
= true;
1378 EEO_JUMP(op
->d
.rowcompare_step
.jumpnull
);
1381 /* Apply comparison function */
1382 fcinfo
->isnull
= false;
1383 d
= op
->d
.rowcompare_step
.fn_addr(fcinfo
);
1386 /* force NULL result if NULL function result */
1389 *op
->resnull
= true;
1390 EEO_JUMP(op
->d
.rowcompare_step
.jumpnull
);
1392 *op
->resnull
= false;
1394 /* If unequal, no need to compare remaining columns */
1395 if (DatumGetInt32(*op
->resvalue
) != 0)
1397 EEO_JUMP(op
->d
.rowcompare_step
.jumpdone
);
1403 EEO_CASE(EEOP_ROWCOMPARE_FINAL
)
1405 int32 cmpresult
= DatumGetInt32(*op
->resvalue
);
1406 RowCompareType rctype
= op
->d
.rowcompare_final
.rctype
;
1408 *op
->resnull
= false;
1411 /* EQ and NE cases aren't allowed here */
1413 *op
->resvalue
= BoolGetDatum(cmpresult
< 0);
1416 *op
->resvalue
= BoolGetDatum(cmpresult
<= 0);
1419 *op
->resvalue
= BoolGetDatum(cmpresult
>= 0);
1422 *op
->resvalue
= BoolGetDatum(cmpresult
> 0);
1432 EEO_CASE(EEOP_MINMAX
)
1434 /* too complex for an inline implementation */
1435 ExecEvalMinMax(state
, op
);
1440 EEO_CASE(EEOP_FIELDSELECT
)
1442 /* too complex for an inline implementation */
1443 ExecEvalFieldSelect(state
, op
, econtext
);
1448 EEO_CASE(EEOP_FIELDSTORE_DEFORM
)
1450 /* too complex for an inline implementation */
1451 ExecEvalFieldStoreDeForm(state
, op
, econtext
);
1456 EEO_CASE(EEOP_FIELDSTORE_FORM
)
1458 /* too complex for an inline implementation */
1459 ExecEvalFieldStoreForm(state
, op
, econtext
);
1464 EEO_CASE(EEOP_SBSREF_SUBSCRIPTS
)
1466 /* Precheck SubscriptingRef subscript(s) */
1467 if (op
->d
.sbsref_subscript
.subscriptfunc(state
, op
, econtext
))
1473 /* Subscript is null, short-circuit SubscriptingRef to NULL */
1474 EEO_JUMP(op
->d
.sbsref_subscript
.jumpdone
);
1478 EEO_CASE(EEOP_SBSREF_OLD
)
1479 EEO_CASE(EEOP_SBSREF_ASSIGN
)
1480 EEO_CASE(EEOP_SBSREF_FETCH
)
1482 /* Perform a SubscriptingRef fetch or assignment */
1483 op
->d
.sbsref
.subscriptfunc(state
, op
, econtext
);
1488 EEO_CASE(EEOP_CONVERT_ROWTYPE
)
1490 /* too complex for an inline implementation */
1491 ExecEvalConvertRowtype(state
, op
, econtext
);
1496 EEO_CASE(EEOP_SCALARARRAYOP
)
1498 /* too complex for an inline implementation */
1499 ExecEvalScalarArrayOp(state
, op
);
1504 EEO_CASE(EEOP_HASHED_SCALARARRAYOP
)
1506 /* too complex for an inline implementation */
1507 ExecEvalHashedScalarArrayOp(state
, op
, econtext
);
1512 EEO_CASE(EEOP_DOMAIN_NOTNULL
)
1514 /* too complex for an inline implementation */
1515 ExecEvalConstraintNotNull(state
, op
);
1520 EEO_CASE(EEOP_DOMAIN_CHECK
)
1522 /* too complex for an inline implementation */
1523 ExecEvalConstraintCheck(state
, op
);
1528 EEO_CASE(EEOP_XMLEXPR
)
1530 /* too complex for an inline implementation */
1531 ExecEvalXmlExpr(state
, op
);
1536 EEO_CASE(EEOP_AGGREF
)
1539 * Returns a Datum whose value is the precomputed aggregate value
1540 * found in the given expression context.
1542 int aggno
= op
->d
.aggref
.aggno
;
1544 Assert(econtext
->ecxt_aggvalues
!= NULL
);
1546 *op
->resvalue
= econtext
->ecxt_aggvalues
[aggno
];
1547 *op
->resnull
= econtext
->ecxt_aggnulls
[aggno
];
1552 EEO_CASE(EEOP_GROUPING_FUNC
)
1554 /* too complex/uncommon for an inline implementation */
1555 ExecEvalGroupingFunc(state
, op
);
1560 EEO_CASE(EEOP_WINDOW_FUNC
)
1563 * Like Aggref, just return a precomputed value from the econtext.
1565 WindowFuncExprState
*wfunc
= op
->d
.window_func
.wfstate
;
1567 Assert(econtext
->ecxt_aggvalues
!= NULL
);
1569 *op
->resvalue
= econtext
->ecxt_aggvalues
[wfunc
->wfuncno
];
1570 *op
->resnull
= econtext
->ecxt_aggnulls
[wfunc
->wfuncno
];
1575 EEO_CASE(EEOP_SUBPLAN
)
1577 /* too complex for an inline implementation */
1578 ExecEvalSubPlan(state
, op
, econtext
);
1583 /* evaluate a strict aggregate deserialization function */
1584 EEO_CASE(EEOP_AGG_STRICT_DESERIALIZE
)
1586 /* Don't call a strict deserialization function with NULL input */
1587 if (op
->d
.agg_deserialize
.fcinfo_data
->args
[0].isnull
)
1588 EEO_JUMP(op
->d
.agg_deserialize
.jumpnull
);
1593 /* evaluate aggregate deserialization function (non-strict portion) */
1594 EEO_CASE(EEOP_AGG_DESERIALIZE
)
1596 FunctionCallInfo fcinfo
= op
->d
.agg_deserialize
.fcinfo_data
;
1597 AggState
*aggstate
= castNode(AggState
, state
->parent
);
1598 MemoryContext oldContext
;
1601 * We run the deserialization functions in per-input-tuple memory
1604 oldContext
= MemoryContextSwitchTo(aggstate
->tmpcontext
->ecxt_per_tuple_memory
);
1605 fcinfo
->isnull
= false;
1606 *op
->resvalue
= FunctionCallInvoke(fcinfo
);
1607 *op
->resnull
= fcinfo
->isnull
;
1608 MemoryContextSwitchTo(oldContext
);
1614 * Check that a strict aggregate transition / combination function's
1615 * input is not NULL.
1618 EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_ARGS
)
1620 NullableDatum
*args
= op
->d
.agg_strict_input_check
.args
;
1621 int nargs
= op
->d
.agg_strict_input_check
.nargs
;
1623 for (int argno
= 0; argno
< nargs
; argno
++)
1625 if (args
[argno
].isnull
)
1626 EEO_JUMP(op
->d
.agg_strict_input_check
.jumpnull
);
1631 EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_NULLS
)
1633 bool *nulls
= op
->d
.agg_strict_input_check
.nulls
;
1634 int nargs
= op
->d
.agg_strict_input_check
.nargs
;
1636 for (int argno
= 0; argno
< nargs
; argno
++)
1639 EEO_JUMP(op
->d
.agg_strict_input_check
.jumpnull
);
1645 * Check for a NULL pointer to the per-group states.
1648 EEO_CASE(EEOP_AGG_PLAIN_PERGROUP_NULLCHECK
)
1650 AggState
*aggstate
= castNode(AggState
, state
->parent
);
1651 AggStatePerGroup pergroup_allaggs
=
1652 aggstate
->all_pergroups
[op
->d
.agg_plain_pergroup_nullcheck
.setoff
];
1654 if (pergroup_allaggs
== NULL
)
1655 EEO_JUMP(op
->d
.agg_plain_pergroup_nullcheck
.jumpnull
);
1661 * Different types of aggregate transition functions are implemented
1662 * as different types of steps, to avoid incurring unnecessary
1663 * overhead. There's a step type for each valid combination of having
1664 * a by value / by reference transition type, [not] needing to the
1665 * initialize the transition value for the first row in a group from
1666 * input, and [not] strict transition function.
1668 * Could optimize further by splitting off by-reference for
1669 * fixed-length types, but currently that doesn't seem worth it.
1672 EEO_CASE(EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL
)
1674 AggState
*aggstate
= castNode(AggState
, state
->parent
);
1675 AggStatePerTrans pertrans
= op
->d
.agg_trans
.pertrans
;
1676 AggStatePerGroup pergroup
=
1677 &aggstate
->all_pergroups
[op
->d
.agg_trans
.setoff
][op
->d
.agg_trans
.transno
];
1679 Assert(pertrans
->transtypeByVal
);
1681 if (pergroup
->noTransValue
)
1683 /* If transValue has not yet been initialized, do so now. */
1684 ExecAggInitGroup(aggstate
, pertrans
, pergroup
,
1685 op
->d
.agg_trans
.aggcontext
);
1686 /* copied trans value from input, done this round */
1688 else if (likely(!pergroup
->transValueIsNull
))
1690 /* invoke transition function, unless prevented by strictness */
1691 ExecAggPlainTransByVal(aggstate
, pertrans
, pergroup
,
1692 op
->d
.agg_trans
.aggcontext
,
1693 op
->d
.agg_trans
.setno
);
1699 /* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1700 EEO_CASE(EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL
)
1702 AggState
*aggstate
= castNode(AggState
, state
->parent
);
1703 AggStatePerTrans pertrans
= op
->d
.agg_trans
.pertrans
;
1704 AggStatePerGroup pergroup
=
1705 &aggstate
->all_pergroups
[op
->d
.agg_trans
.setoff
][op
->d
.agg_trans
.transno
];
1707 Assert(pertrans
->transtypeByVal
);
1709 if (likely(!pergroup
->transValueIsNull
))
1710 ExecAggPlainTransByVal(aggstate
, pertrans
, pergroup
,
1711 op
->d
.agg_trans
.aggcontext
,
1712 op
->d
.agg_trans
.setno
);
1717 /* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1718 EEO_CASE(EEOP_AGG_PLAIN_TRANS_BYVAL
)
1720 AggState
*aggstate
= castNode(AggState
, state
->parent
);
1721 AggStatePerTrans pertrans
= op
->d
.agg_trans
.pertrans
;
1722 AggStatePerGroup pergroup
=
1723 &aggstate
->all_pergroups
[op
->d
.agg_trans
.setoff
][op
->d
.agg_trans
.transno
];
1725 Assert(pertrans
->transtypeByVal
);
1727 ExecAggPlainTransByVal(aggstate
, pertrans
, pergroup
,
1728 op
->d
.agg_trans
.aggcontext
,
1729 op
->d
.agg_trans
.setno
);
1734 /* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1735 EEO_CASE(EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF
)
1737 AggState
*aggstate
= castNode(AggState
, state
->parent
);
1738 AggStatePerTrans pertrans
= op
->d
.agg_trans
.pertrans
;
1739 AggStatePerGroup pergroup
=
1740 &aggstate
->all_pergroups
[op
->d
.agg_trans
.setoff
][op
->d
.agg_trans
.transno
];
1742 Assert(!pertrans
->transtypeByVal
);
1744 if (pergroup
->noTransValue
)
1745 ExecAggInitGroup(aggstate
, pertrans
, pergroup
,
1746 op
->d
.agg_trans
.aggcontext
);
1747 else if (likely(!pergroup
->transValueIsNull
))
1748 ExecAggPlainTransByRef(aggstate
, pertrans
, pergroup
,
1749 op
->d
.agg_trans
.aggcontext
,
1750 op
->d
.agg_trans
.setno
);
1755 /* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1756 EEO_CASE(EEOP_AGG_PLAIN_TRANS_STRICT_BYREF
)
1758 AggState
*aggstate
= castNode(AggState
, state
->parent
);
1759 AggStatePerTrans pertrans
= op
->d
.agg_trans
.pertrans
;
1760 AggStatePerGroup pergroup
=
1761 &aggstate
->all_pergroups
[op
->d
.agg_trans
.setoff
][op
->d
.agg_trans
.transno
];
1763 Assert(!pertrans
->transtypeByVal
);
1765 if (likely(!pergroup
->transValueIsNull
))
1766 ExecAggPlainTransByRef(aggstate
, pertrans
, pergroup
,
1767 op
->d
.agg_trans
.aggcontext
,
1768 op
->d
.agg_trans
.setno
);
1772 /* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1773 EEO_CASE(EEOP_AGG_PLAIN_TRANS_BYREF
)
1775 AggState
*aggstate
= castNode(AggState
, state
->parent
);
1776 AggStatePerTrans pertrans
= op
->d
.agg_trans
.pertrans
;
1777 AggStatePerGroup pergroup
=
1778 &aggstate
->all_pergroups
[op
->d
.agg_trans
.setoff
][op
->d
.agg_trans
.transno
];
1780 Assert(!pertrans
->transtypeByVal
);
1782 ExecAggPlainTransByRef(aggstate
, pertrans
, pergroup
,
1783 op
->d
.agg_trans
.aggcontext
,
1784 op
->d
.agg_trans
.setno
);
1789 /* process single-column ordered aggregate datum */
1790 EEO_CASE(EEOP_AGG_ORDERED_TRANS_DATUM
)
1792 /* too complex for an inline implementation */
1793 ExecEvalAggOrderedTransDatum(state
, op
, econtext
);
1798 /* process multi-column ordered aggregate tuple */
1799 EEO_CASE(EEOP_AGG_ORDERED_TRANS_TUPLE
)
1801 /* too complex for an inline implementation */
1802 ExecEvalAggOrderedTransTuple(state
, op
, econtext
);
1806 EEO_CASE(EEOP_JSON_CONSTRUCTOR
)
1808 /* too complex for an inline implementation */
1809 ExecEvalJsonConstructor(state
, op
, econtext
);
1813 EEO_CASE(EEOP_IS_JSON
)
1815 /* too complex for an inline implementation */
1816 ExecEvalJsonIsPredicate(state
, op
);
1820 EEO_CASE(EEOP_JSONEXPR
)
1822 /* too complex for an inline implementation */
1823 ExecEvalJson(state
, op
, econtext
);
1836 *isnull
= state
->resnull
;
1837 return state
->resvalue
;
1841 * Expression evaluation callback that performs extra checks before executing
1842 * the expression. Declared extern so other methods of execution can use it
1846 ExecInterpExprStillValid(ExprState
*state
, ExprContext
*econtext
, bool *isNull
)
1849 * First time through, check whether attribute matches Var. Might not be
1850 * ok anymore, due to schema changes.
1852 CheckExprStillValid(state
, econtext
);
1854 /* skip the check during further executions */
1855 state
->evalfunc
= (ExprStateEvalFunc
) state
->evalfunc_private
;
1857 /* and actually execute */
1858 return state
->evalfunc(state
, econtext
, isNull
);
1862 * Check that an expression is still valid in the face of potential schema
1863 * changes since the plan has been created.
1866 CheckExprStillValid(ExprState
*state
, ExprContext
*econtext
)
1868 TupleTableSlot
*innerslot
;
1869 TupleTableSlot
*outerslot
;
1870 TupleTableSlot
*scanslot
;
1872 innerslot
= econtext
->ecxt_innertuple
;
1873 outerslot
= econtext
->ecxt_outertuple
;
1874 scanslot
= econtext
->ecxt_scantuple
;
1876 for (int i
= 0; i
< state
->steps_len
; i
++)
1878 ExprEvalStep
*op
= &state
->steps
[i
];
1880 switch (ExecEvalStepOp(state
, op
))
1882 case EEOP_INNER_VAR
:
1884 int attnum
= op
->d
.var
.attnum
;
1886 CheckVarSlotCompatibility(innerslot
, attnum
+ 1, op
->d
.var
.vartype
);
1890 case EEOP_OUTER_VAR
:
1892 int attnum
= op
->d
.var
.attnum
;
1894 CheckVarSlotCompatibility(outerslot
, attnum
+ 1, op
->d
.var
.vartype
);
1900 int attnum
= op
->d
.var
.attnum
;
1902 CheckVarSlotCompatibility(scanslot
, attnum
+ 1, op
->d
.var
.vartype
);
1912 * Check whether a user attribute in a slot can be referenced by a Var
1913 * expression. This should succeed unless there have been schema changes
1914 * since the expression tree has been created.
1917 CheckVarSlotCompatibility(TupleTableSlot
*slot
, int attnum
, Oid vartype
)
1920 * What we have to check for here is the possibility of an attribute
1921 * having been dropped or changed in type since the plan tree was created.
1922 * Ideally the plan will get invalidated and not re-used, but just in
1923 * case, we keep these defenses. Fortunately it's sufficient to check
1924 * once on the first time through.
1926 * Note: ideally we'd check typmod as well as typid, but that seems
1927 * impractical at the moment: in many cases the tupdesc will have been
1928 * generated by ExecTypeFromTL(), and that can't guarantee to generate an
1929 * accurate typmod in all cases, because some expression node types don't
1930 * carry typmod. Fortunately, for precisely that reason, there should be
1931 * no places with a critical dependency on the typmod of a value.
1933 * System attributes don't require checking since their types never
1938 TupleDesc slot_tupdesc
= slot
->tts_tupleDescriptor
;
1939 Form_pg_attribute attr
;
1941 if (attnum
> slot_tupdesc
->natts
) /* should never happen */
1942 elog(ERROR
, "attribute number %d exceeds number of columns %d",
1943 attnum
, slot_tupdesc
->natts
);
1945 attr
= TupleDescAttr(slot_tupdesc
, attnum
- 1);
1947 if (attr
->attisdropped
)
1949 (errcode(ERRCODE_UNDEFINED_COLUMN
),
1950 errmsg("attribute %d of type %s has been dropped",
1951 attnum
, format_type_be(slot_tupdesc
->tdtypeid
))));
1953 if (vartype
!= attr
->atttypid
)
1955 (errcode(ERRCODE_DATATYPE_MISMATCH
),
1956 errmsg("attribute %d of type %s has wrong type",
1957 attnum
, format_type_be(slot_tupdesc
->tdtypeid
)),
1958 errdetail("Table has type %s, but query expects %s.",
1959 format_type_be(attr
->atttypid
),
1960 format_type_be(vartype
))));
1965 * Verify that the slot is compatible with a EEOP_*_FETCHSOME operation.
1968 CheckOpSlotCompatibility(ExprEvalStep
*op
, TupleTableSlot
*slot
)
1970 #ifdef USE_ASSERT_CHECKING
1971 /* there's nothing to check */
1972 if (!op
->d
.fetch
.fixed
)
1976 * Should probably fixed at some point, but for now it's easier to allow
1977 * buffer and heap tuples to be used interchangeably.
1979 if (slot
->tts_ops
== &TTSOpsBufferHeapTuple
&&
1980 op
->d
.fetch
.kind
== &TTSOpsHeapTuple
)
1982 if (slot
->tts_ops
== &TTSOpsHeapTuple
&&
1983 op
->d
.fetch
.kind
== &TTSOpsBufferHeapTuple
)
1987 * At the moment we consider it OK if a virtual slot is used instead of a
1988 * specific type of slot, as a virtual slot never needs to be deformed.
1990 if (slot
->tts_ops
== &TTSOpsVirtual
)
1993 Assert(op
->d
.fetch
.kind
== slot
->tts_ops
);
1998 * get_cached_rowtype: utility function to lookup a rowtype tupdesc
2000 * type_id, typmod: identity of the rowtype
2001 * rowcache: space for caching identity info
2002 * (rowcache->cacheptr must be initialized to NULL)
2003 * changed: if not NULL, *changed is set to true on any update
2005 * The returned TupleDesc is not guaranteed pinned; caller must pin it
2006 * to use it across any operation that might incur cache invalidation.
2007 * (The TupleDesc is always refcounted, so just use IncrTupleDescRefCount.)
2009 * NOTE: because composite types can change contents, we must be prepared
2010 * to re-do this during any node execution; cannot call just once during
2011 * expression initialization.
2014 get_cached_rowtype(Oid type_id
, int32 typmod
,
2015 ExprEvalRowtypeCache
*rowcache
,
2018 if (type_id
!= RECORDOID
)
2021 * It's a named composite type, so use the regular typcache. Do a
2022 * lookup first time through, or if the composite type changed. Note:
2023 * "tupdesc_id == 0" may look redundant, but it protects against the
2024 * admittedly-theoretical possibility that type_id was RECORDOID the
2025 * last time through, so that the cacheptr isn't TypeCacheEntry *.
2027 TypeCacheEntry
*typentry
= (TypeCacheEntry
*) rowcache
->cacheptr
;
2029 if (unlikely(typentry
== NULL
||
2030 rowcache
->tupdesc_id
== 0 ||
2031 typentry
->tupDesc_identifier
!= rowcache
->tupdesc_id
))
2033 typentry
= lookup_type_cache(type_id
, TYPECACHE_TUPDESC
);
2034 if (typentry
->tupDesc
== NULL
)
2036 (errcode(ERRCODE_WRONG_OBJECT_TYPE
),
2037 errmsg("type %s is not composite",
2038 format_type_be(type_id
))));
2039 rowcache
->cacheptr
= (void *) typentry
;
2040 rowcache
->tupdesc_id
= typentry
->tupDesc_identifier
;
2044 return typentry
->tupDesc
;
2049 * A RECORD type, once registered, doesn't change for the life of the
2050 * backend. So we don't need a typcache entry as such, which is good
2051 * because there isn't one. It's possible that the caller is asking
2052 * about a different type than before, though.
2054 TupleDesc tupDesc
= (TupleDesc
) rowcache
->cacheptr
;
2056 if (unlikely(tupDesc
== NULL
||
2057 rowcache
->tupdesc_id
!= 0 ||
2058 type_id
!= tupDesc
->tdtypeid
||
2059 typmod
!= tupDesc
->tdtypmod
))
2061 tupDesc
= lookup_rowtype_tupdesc(type_id
, typmod
);
2062 /* Drop pin acquired by lookup_rowtype_tupdesc */
2063 ReleaseTupleDesc(tupDesc
);
2064 rowcache
->cacheptr
= (void *) tupDesc
;
2065 rowcache
->tupdesc_id
= 0; /* not a valid value for non-RECORD */
2075 * Fast-path functions, for very simple expressions
2078 /* implementation of ExecJust(Inner|Outer|Scan)Var */
2079 static pg_attribute_always_inline Datum
2080 ExecJustVarImpl(ExprState
*state
, TupleTableSlot
*slot
, bool *isnull
)
2082 ExprEvalStep
*op
= &state
->steps
[1];
2083 int attnum
= op
->d
.var
.attnum
+ 1;
2085 CheckOpSlotCompatibility(&state
->steps
[0], slot
);
2088 * Since we use slot_getattr(), we don't need to implement the FETCHSOME
2089 * step explicitly, and we also needn't Assert that the attnum is in range
2090 * --- slot_getattr() will take care of any problems.
2092 return slot_getattr(slot
, attnum
, isnull
);
2095 /* Simple reference to inner Var */
2097 ExecJustInnerVar(ExprState
*state
, ExprContext
*econtext
, bool *isnull
)
2099 return ExecJustVarImpl(state
, econtext
->ecxt_innertuple
, isnull
);
2102 /* Simple reference to outer Var */
2104 ExecJustOuterVar(ExprState
*state
, ExprContext
*econtext
, bool *isnull
)
2106 return ExecJustVarImpl(state
, econtext
->ecxt_outertuple
, isnull
);
2109 /* Simple reference to scan Var */
2111 ExecJustScanVar(ExprState
*state
, ExprContext
*econtext
, bool *isnull
)
2113 return ExecJustVarImpl(state
, econtext
->ecxt_scantuple
, isnull
);
2116 /* implementation of ExecJustAssign(Inner|Outer|Scan)Var */
2117 static pg_attribute_always_inline Datum
2118 ExecJustAssignVarImpl(ExprState
*state
, TupleTableSlot
*inslot
, bool *isnull
)
2120 ExprEvalStep
*op
= &state
->steps
[1];
2121 int attnum
= op
->d
.assign_var
.attnum
+ 1;
2122 int resultnum
= op
->d
.assign_var
.resultnum
;
2123 TupleTableSlot
*outslot
= state
->resultslot
;
2125 CheckOpSlotCompatibility(&state
->steps
[0], inslot
);
2128 * We do not need CheckVarSlotCompatibility here; that was taken care of
2129 * at compilation time.
2131 * Since we use slot_getattr(), we don't need to implement the FETCHSOME
2132 * step explicitly, and we also needn't Assert that the attnum is in range
2133 * --- slot_getattr() will take care of any problems. Nonetheless, check
2134 * that resultnum is in range.
2136 Assert(resultnum
>= 0 && resultnum
< outslot
->tts_tupleDescriptor
->natts
);
2137 outslot
->tts_values
[resultnum
] =
2138 slot_getattr(inslot
, attnum
, &outslot
->tts_isnull
[resultnum
]);
2142 /* Evaluate inner Var and assign to appropriate column of result tuple */
2144 ExecJustAssignInnerVar(ExprState
*state
, ExprContext
*econtext
, bool *isnull
)
2146 return ExecJustAssignVarImpl(state
, econtext
->ecxt_innertuple
, isnull
);
2149 /* Evaluate outer Var and assign to appropriate column of result tuple */
2151 ExecJustAssignOuterVar(ExprState
*state
, ExprContext
*econtext
, bool *isnull
)
2153 return ExecJustAssignVarImpl(state
, econtext
->ecxt_outertuple
, isnull
);
2156 /* Evaluate scan Var and assign to appropriate column of result tuple */
2158 ExecJustAssignScanVar(ExprState
*state
, ExprContext
*econtext
, bool *isnull
)
2160 return ExecJustAssignVarImpl(state
, econtext
->ecxt_scantuple
, isnull
);
2163 /* Evaluate CASE_TESTVAL and apply a strict function to it */
2165 ExecJustApplyFuncToCase(ExprState
*state
, ExprContext
*econtext
, bool *isnull
)
2167 ExprEvalStep
*op
= &state
->steps
[0];
2168 FunctionCallInfo fcinfo
;
2169 NullableDatum
*args
;
2174 * XXX with some redesign of the CaseTestExpr mechanism, maybe we could
2175 * get rid of this data shuffling?
2177 *op
->resvalue
= *op
->d
.casetest
.value
;
2178 *op
->resnull
= *op
->d
.casetest
.isnull
;
2182 nargs
= op
->d
.func
.nargs
;
2183 fcinfo
= op
->d
.func
.fcinfo_data
;
2184 args
= fcinfo
->args
;
2186 /* strict function, so check for NULL args */
2187 for (int argno
= 0; argno
< nargs
; argno
++)
2189 if (args
[argno
].isnull
)
2195 fcinfo
->isnull
= false;
2196 d
= op
->d
.func
.fn_addr(fcinfo
);
2197 *isnull
= fcinfo
->isnull
;
2201 /* Simple Const expression */
2203 ExecJustConst(ExprState
*state
, ExprContext
*econtext
, bool *isnull
)
2205 ExprEvalStep
*op
= &state
->steps
[0];
2207 *isnull
= op
->d
.constval
.isnull
;
2208 return op
->d
.constval
.value
;
2211 /* implementation of ExecJust(Inner|Outer|Scan)VarVirt */
2212 static pg_attribute_always_inline Datum
2213 ExecJustVarVirtImpl(ExprState
*state
, TupleTableSlot
*slot
, bool *isnull
)
2215 ExprEvalStep
*op
= &state
->steps
[0];
2216 int attnum
= op
->d
.var
.attnum
;
2219 * As it is guaranteed that a virtual slot is used, there never is a need
2220 * to perform tuple deforming (nor would it be possible). Therefore
2221 * execExpr.c has not emitted an EEOP_*_FETCHSOME step. Verify, as much as
2222 * possible, that that determination was accurate.
2224 Assert(TTS_IS_VIRTUAL(slot
));
2225 Assert(TTS_FIXED(slot
));
2226 Assert(attnum
>= 0 && attnum
< slot
->tts_nvalid
);
2228 *isnull
= slot
->tts_isnull
[attnum
];
2230 return slot
->tts_values
[attnum
];
2233 /* Like ExecJustInnerVar, optimized for virtual slots */
2235 ExecJustInnerVarVirt(ExprState
*state
, ExprContext
*econtext
, bool *isnull
)
2237 return ExecJustVarVirtImpl(state
, econtext
->ecxt_innertuple
, isnull
);
2240 /* Like ExecJustOuterVar, optimized for virtual slots */
2242 ExecJustOuterVarVirt(ExprState
*state
, ExprContext
*econtext
, bool *isnull
)
2244 return ExecJustVarVirtImpl(state
, econtext
->ecxt_outertuple
, isnull
);
2247 /* Like ExecJustScanVar, optimized for virtual slots */
2249 ExecJustScanVarVirt(ExprState
*state
, ExprContext
*econtext
, bool *isnull
)
2251 return ExecJustVarVirtImpl(state
, econtext
->ecxt_scantuple
, isnull
);
2254 /* implementation of ExecJustAssign(Inner|Outer|Scan)VarVirt */
2255 static pg_attribute_always_inline Datum
2256 ExecJustAssignVarVirtImpl(ExprState
*state
, TupleTableSlot
*inslot
, bool *isnull
)
2258 ExprEvalStep
*op
= &state
->steps
[0];
2259 int attnum
= op
->d
.assign_var
.attnum
;
2260 int resultnum
= op
->d
.assign_var
.resultnum
;
2261 TupleTableSlot
*outslot
= state
->resultslot
;
2263 /* see ExecJustVarVirtImpl for comments */
2265 Assert(TTS_IS_VIRTUAL(inslot
));
2266 Assert(TTS_FIXED(inslot
));
2267 Assert(attnum
>= 0 && attnum
< inslot
->tts_nvalid
);
2268 Assert(resultnum
>= 0 && resultnum
< outslot
->tts_tupleDescriptor
->natts
);
2270 outslot
->tts_values
[resultnum
] = inslot
->tts_values
[attnum
];
2271 outslot
->tts_isnull
[resultnum
] = inslot
->tts_isnull
[attnum
];
2276 /* Like ExecJustAssignInnerVar, optimized for virtual slots */
2278 ExecJustAssignInnerVarVirt(ExprState
*state
, ExprContext
*econtext
, bool *isnull
)
2280 return ExecJustAssignVarVirtImpl(state
, econtext
->ecxt_innertuple
, isnull
);
2283 /* Like ExecJustAssignOuterVar, optimized for virtual slots */
2285 ExecJustAssignOuterVarVirt(ExprState
*state
, ExprContext
*econtext
, bool *isnull
)
2287 return ExecJustAssignVarVirtImpl(state
, econtext
->ecxt_outertuple
, isnull
);
2290 /* Like ExecJustAssignScanVar, optimized for virtual slots */
2292 ExecJustAssignScanVarVirt(ExprState
*state
, ExprContext
*econtext
, bool *isnull
)
2294 return ExecJustAssignVarVirtImpl(state
, econtext
->ecxt_scantuple
, isnull
);
2297 #if defined(EEO_USE_COMPUTED_GOTO)
2299 * Comparator used when building address->opcode lookup table for
2300 * ExecEvalStepOp() in the threaded dispatch case.
2303 dispatch_compare_ptr(const void *a
, const void *b
)
2305 const ExprEvalOpLookup
*la
= (const ExprEvalOpLookup
*) a
;
2306 const ExprEvalOpLookup
*lb
= (const ExprEvalOpLookup
*) b
;
2308 if (la
->opcode
< lb
->opcode
)
2310 else if (la
->opcode
> lb
->opcode
)
2317 * Do one-time initialization of interpretation machinery.
2320 ExecInitInterpreter(void)
2322 #if defined(EEO_USE_COMPUTED_GOTO)
2323 /* Set up externally-visible pointer to dispatch table */
2324 if (dispatch_table
== NULL
)
2326 dispatch_table
= (const void **)
2327 DatumGetPointer(ExecInterpExpr(NULL
, NULL
, NULL
));
2329 /* build reverse lookup table */
2330 for (int i
= 0; i
< EEOP_LAST
; i
++)
2332 reverse_dispatch_table
[i
].opcode
= dispatch_table
[i
];
2333 reverse_dispatch_table
[i
].op
= (ExprEvalOp
) i
;
2336 /* make it bsearch()able */
2337 qsort(reverse_dispatch_table
,
2338 EEOP_LAST
/* nmembers */ ,
2339 sizeof(ExprEvalOpLookup
),
2340 dispatch_compare_ptr
);
2346 * Function to return the opcode of an expression step.
2348 * When direct-threading is in use, ExprState->opcode isn't easily
2349 * decipherable. This function returns the appropriate enum member.
2352 ExecEvalStepOp(ExprState
*state
, ExprEvalStep
*op
)
2354 #if defined(EEO_USE_COMPUTED_GOTO)
2355 if (state
->flags
& EEO_FLAG_DIRECT_THREADED
)
2357 ExprEvalOpLookup key
;
2358 ExprEvalOpLookup
*res
;
2360 key
.opcode
= (void *) op
->opcode
;
2362 reverse_dispatch_table
,
2363 EEOP_LAST
/* nmembers */ ,
2364 sizeof(ExprEvalOpLookup
),
2365 dispatch_compare_ptr
);
2366 Assert(res
); /* unknown ops shouldn't get looked up */
2370 return (ExprEvalOp
) op
->opcode
;
2375 * Out-of-line helper functions for complex instructions.
2379 * Evaluate EEOP_FUNCEXPR_FUSAGE
2382 ExecEvalFuncExprFusage(ExprState
*state
, ExprEvalStep
*op
,
2383 ExprContext
*econtext
)
2385 FunctionCallInfo fcinfo
= op
->d
.func
.fcinfo_data
;
2386 PgStat_FunctionCallUsage fcusage
;
2389 pgstat_init_function_usage(fcinfo
, &fcusage
);
2391 fcinfo
->isnull
= false;
2392 d
= op
->d
.func
.fn_addr(fcinfo
);
2394 *op
->resnull
= fcinfo
->isnull
;
2396 pgstat_end_function_usage(&fcusage
, true);
2400 * Evaluate EEOP_FUNCEXPR_STRICT_FUSAGE
2403 ExecEvalFuncExprStrictFusage(ExprState
*state
, ExprEvalStep
*op
,
2404 ExprContext
*econtext
)
2407 FunctionCallInfo fcinfo
= op
->d
.func
.fcinfo_data
;
2408 PgStat_FunctionCallUsage fcusage
;
2409 NullableDatum
*args
= fcinfo
->args
;
2410 int nargs
= op
->d
.func
.nargs
;
2413 /* strict function, so check for NULL args */
2414 for (int argno
= 0; argno
< nargs
; argno
++)
2416 if (args
[argno
].isnull
)
2418 *op
->resnull
= true;
2423 pgstat_init_function_usage(fcinfo
, &fcusage
);
2425 fcinfo
->isnull
= false;
2426 d
= op
->d
.func
.fn_addr(fcinfo
);
2428 *op
->resnull
= fcinfo
->isnull
;
2430 pgstat_end_function_usage(&fcusage
, true);
2434 * Evaluate a PARAM_EXEC parameter.
2436 * PARAM_EXEC params (internal executor parameters) are stored in the
2437 * ecxt_param_exec_vals array, and can be accessed by array index.
2440 ExecEvalParamExec(ExprState
*state
, ExprEvalStep
*op
, ExprContext
*econtext
)
2444 prm
= &(econtext
->ecxt_param_exec_vals
[op
->d
.param
.paramid
]);
2445 if (unlikely(prm
->execPlan
!= NULL
))
2447 /* Parameter not evaluated yet, so go do it */
2448 ExecSetParamPlan(prm
->execPlan
, econtext
);
2449 /* ExecSetParamPlan should have processed this param... */
2450 Assert(prm
->execPlan
== NULL
);
2452 *op
->resvalue
= prm
->value
;
2453 *op
->resnull
= prm
->isnull
;
2457 * Evaluate a PARAM_EXTERN parameter.
2459 * PARAM_EXTERN parameters must be sought in ecxt_param_list_info.
2462 ExecEvalParamExtern(ExprState
*state
, ExprEvalStep
*op
, ExprContext
*econtext
)
2464 ParamListInfo paramInfo
= econtext
->ecxt_param_list_info
;
2465 int paramId
= op
->d
.param
.paramid
;
2467 if (likely(paramInfo
&&
2468 paramId
> 0 && paramId
<= paramInfo
->numParams
))
2470 ParamExternData
*prm
;
2471 ParamExternData prmdata
;
2473 /* give hook a chance in case parameter is dynamic */
2474 if (paramInfo
->paramFetch
!= NULL
)
2475 prm
= paramInfo
->paramFetch(paramInfo
, paramId
, false, &prmdata
);
2477 prm
= ¶mInfo
->params
[paramId
- 1];
2479 if (likely(OidIsValid(prm
->ptype
)))
2481 /* safety check in case hook did something unexpected */
2482 if (unlikely(prm
->ptype
!= op
->d
.param
.paramtype
))
2484 (errcode(ERRCODE_DATATYPE_MISMATCH
),
2485 errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
2487 format_type_be(prm
->ptype
),
2488 format_type_be(op
->d
.param
.paramtype
))));
2489 *op
->resvalue
= prm
->value
;
2490 *op
->resnull
= prm
->isnull
;
2496 (errcode(ERRCODE_UNDEFINED_OBJECT
),
2497 errmsg("no value found for parameter %d", paramId
)));
2501 * Evaluate a SQLValueFunction expression.
2504 ExecEvalSQLValueFunction(ExprState
*state
, ExprEvalStep
*op
)
2506 LOCAL_FCINFO(fcinfo
, 0);
2507 SQLValueFunction
*svf
= op
->d
.sqlvaluefunction
.svf
;
2509 *op
->resnull
= false;
2512 * Note: current_schema() can return NULL. current_user() etc currently
2513 * cannot, but might as well code those cases the same way for safety.
2517 case SVFOP_CURRENT_DATE
:
2518 *op
->resvalue
= DateADTGetDatum(GetSQLCurrentDate());
2520 case SVFOP_CURRENT_TIME
:
2521 case SVFOP_CURRENT_TIME_N
:
2522 *op
->resvalue
= TimeTzADTPGetDatum(GetSQLCurrentTime(svf
->typmod
));
2524 case SVFOP_CURRENT_TIMESTAMP
:
2525 case SVFOP_CURRENT_TIMESTAMP_N
:
2526 *op
->resvalue
= TimestampTzGetDatum(GetSQLCurrentTimestamp(svf
->typmod
));
2528 case SVFOP_LOCALTIME
:
2529 case SVFOP_LOCALTIME_N
:
2530 *op
->resvalue
= TimeADTGetDatum(GetSQLLocalTime(svf
->typmod
));
2532 case SVFOP_LOCALTIMESTAMP
:
2533 case SVFOP_LOCALTIMESTAMP_N
:
2534 *op
->resvalue
= TimestampGetDatum(GetSQLLocalTimestamp(svf
->typmod
));
2536 case SVFOP_CURRENT_ROLE
:
2537 case SVFOP_CURRENT_USER
:
2539 InitFunctionCallInfoData(*fcinfo
, NULL
, 0, InvalidOid
, NULL
, NULL
);
2540 *op
->resvalue
= current_user(fcinfo
);
2541 *op
->resnull
= fcinfo
->isnull
;
2543 case SVFOP_SESSION_USER
:
2544 InitFunctionCallInfoData(*fcinfo
, NULL
, 0, InvalidOid
, NULL
, NULL
);
2545 *op
->resvalue
= session_user(fcinfo
);
2546 *op
->resnull
= fcinfo
->isnull
;
2548 case SVFOP_CURRENT_CATALOG
:
2549 InitFunctionCallInfoData(*fcinfo
, NULL
, 0, InvalidOid
, NULL
, NULL
);
2550 *op
->resvalue
= current_database(fcinfo
);
2551 *op
->resnull
= fcinfo
->isnull
;
2553 case SVFOP_CURRENT_SCHEMA
:
2554 InitFunctionCallInfoData(*fcinfo
, NULL
, 0, InvalidOid
, NULL
, NULL
);
2555 *op
->resvalue
= current_schema(fcinfo
);
2556 *op
->resnull
= fcinfo
->isnull
;
2562 * Raise error if a CURRENT OF expression is evaluated.
2564 * The planner should convert CURRENT OF into a TidScan qualification, or some
2565 * other special handling in a ForeignScan node. So we have to be able to do
2566 * ExecInitExpr on a CurrentOfExpr, but we shouldn't ever actually execute it.
2567 * If we get here, we suppose we must be dealing with CURRENT OF on a foreign
2568 * table whose FDW doesn't handle it, and complain accordingly.
2571 ExecEvalCurrentOfExpr(ExprState
*state
, ExprEvalStep
*op
)
2574 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
2575 errmsg("WHERE CURRENT OF is not supported for this table type")));
2579 * Evaluate NextValueExpr.
2582 ExecEvalNextValueExpr(ExprState
*state
, ExprEvalStep
*op
)
2584 int64 newval
= nextval_internal(op
->d
.nextvalueexpr
.seqid
, false);
2586 switch (op
->d
.nextvalueexpr
.seqtypid
)
2589 *op
->resvalue
= Int16GetDatum((int16
) newval
);
2592 *op
->resvalue
= Int32GetDatum((int32
) newval
);
2595 *op
->resvalue
= Int64GetDatum((int64
) newval
);
2598 elog(ERROR
, "unsupported sequence type %u",
2599 op
->d
.nextvalueexpr
.seqtypid
);
2601 *op
->resnull
= false;
2605 * Evaluate NullTest / IS NULL for rows.
2608 ExecEvalRowNull(ExprState
*state
, ExprEvalStep
*op
, ExprContext
*econtext
)
2610 ExecEvalRowNullInt(state
, op
, econtext
, true);
2614 * Evaluate NullTest / IS NOT NULL for rows.
2617 ExecEvalRowNotNull(ExprState
*state
, ExprEvalStep
*op
, ExprContext
*econtext
)
2619 ExecEvalRowNullInt(state
, op
, econtext
, false);
2622 /* Common code for IS [NOT] NULL on a row value */
2624 ExecEvalRowNullInt(ExprState
*state
, ExprEvalStep
*op
,
2625 ExprContext
*econtext
, bool checkisnull
)
2627 Datum value
= *op
->resvalue
;
2628 bool isnull
= *op
->resnull
;
2629 HeapTupleHeader tuple
;
2633 HeapTupleData tmptup
;
2635 *op
->resnull
= false;
2637 /* NULL row variables are treated just as NULL scalar columns */
2640 *op
->resvalue
= BoolGetDatum(checkisnull
);
2645 * The SQL standard defines IS [NOT] NULL for a non-null rowtype argument
2648 * "R IS NULL" is true if every field is the null value.
2650 * "R IS NOT NULL" is true if no field is the null value.
2652 * This definition is (apparently intentionally) not recursive; so our
2653 * tests on the fields are primitive attisnull tests, not recursive checks
2654 * to see if they are all-nulls or no-nulls rowtypes.
2656 * The standard does not consider the possibility of zero-field rows, but
2657 * here we consider them to vacuously satisfy both predicates.
2660 tuple
= DatumGetHeapTupleHeader(value
);
2662 tupType
= HeapTupleHeaderGetTypeId(tuple
);
2663 tupTypmod
= HeapTupleHeaderGetTypMod(tuple
);
2665 /* Lookup tupdesc if first time through or if type changes */
2666 tupDesc
= get_cached_rowtype(tupType
, tupTypmod
,
2667 &op
->d
.nulltest_row
.rowcache
, NULL
);
2670 * heap_attisnull needs a HeapTuple not a bare HeapTupleHeader.
2672 tmptup
.t_len
= HeapTupleHeaderGetDatumLength(tuple
);
2673 tmptup
.t_data
= tuple
;
2675 for (int att
= 1; att
<= tupDesc
->natts
; att
++)
2677 /* ignore dropped columns */
2678 if (TupleDescAttr(tupDesc
, att
- 1)->attisdropped
)
2680 if (heap_attisnull(&tmptup
, att
, tupDesc
))
2682 /* null field disproves IS NOT NULL */
2685 *op
->resvalue
= BoolGetDatum(false);
2691 /* non-null field disproves IS NULL */
2694 *op
->resvalue
= BoolGetDatum(false);
2700 *op
->resvalue
= BoolGetDatum(true);
2704 * Evaluate an ARRAY[] expression.
2706 * The individual array elements (or subarrays) have already been evaluated
2707 * into op->d.arrayexpr.elemvalues[]/elemnulls[].
2710 ExecEvalArrayExpr(ExprState
*state
, ExprEvalStep
*op
)
2713 Oid element_type
= op
->d
.arrayexpr
.elemtype
;
2714 int nelems
= op
->d
.arrayexpr
.nelems
;
2719 /* Set non-null as default */
2720 *op
->resnull
= false;
2722 if (!op
->d
.arrayexpr
.multidims
)
2724 /* Elements are presumably of scalar type */
2725 Datum
*dvalues
= op
->d
.arrayexpr
.elemvalues
;
2726 bool *dnulls
= op
->d
.arrayexpr
.elemnulls
;
2728 /* setup for 1-D array of the given length */
2733 result
= construct_md_array(dvalues
, dnulls
, ndims
, dims
, lbs
,
2735 op
->d
.arrayexpr
.elemlength
,
2736 op
->d
.arrayexpr
.elembyval
,
2737 op
->d
.arrayexpr
.elemalign
);
2741 /* Must be nested array expressions */
2744 int outer_nelems
= 0;
2746 int *elem_dims
= NULL
;
2747 int *elem_lbs
= NULL
;
2748 bool firstone
= true;
2749 bool havenulls
= false;
2750 bool haveempty
= false;
2759 subdata
= (char **) palloc(nelems
* sizeof(char *));
2760 subbitmaps
= (bits8
**) palloc(nelems
* sizeof(bits8
*));
2761 subbytes
= (int *) palloc(nelems
* sizeof(int));
2762 subnitems
= (int *) palloc(nelems
* sizeof(int));
2764 /* loop through and get data area from each element */
2765 for (int elemoff
= 0; elemoff
< nelems
; elemoff
++)
2772 arraydatum
= op
->d
.arrayexpr
.elemvalues
[elemoff
];
2773 eisnull
= op
->d
.arrayexpr
.elemnulls
[elemoff
];
2775 /* temporarily ignore null subarrays */
2782 array
= DatumGetArrayTypeP(arraydatum
);
2784 /* run-time double-check on element type */
2785 if (element_type
!= ARR_ELEMTYPE(array
))
2787 (errcode(ERRCODE_DATATYPE_MISMATCH
),
2788 errmsg("cannot merge incompatible arrays"),
2789 errdetail("Array with element type %s cannot be "
2790 "included in ARRAY construct with element type %s.",
2791 format_type_be(ARR_ELEMTYPE(array
)),
2792 format_type_be(element_type
))));
2794 this_ndims
= ARR_NDIM(array
);
2795 /* temporarily ignore zero-dimensional subarrays */
2796 if (this_ndims
<= 0)
2804 /* Get sub-array details from first member */
2805 elem_ndims
= this_ndims
;
2806 ndims
= elem_ndims
+ 1;
2807 if (ndims
<= 0 || ndims
> MAXDIM
)
2809 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED
),
2810 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
2813 elem_dims
= (int *) palloc(elem_ndims
* sizeof(int));
2814 memcpy(elem_dims
, ARR_DIMS(array
), elem_ndims
* sizeof(int));
2815 elem_lbs
= (int *) palloc(elem_ndims
* sizeof(int));
2816 memcpy(elem_lbs
, ARR_LBOUND(array
), elem_ndims
* sizeof(int));
2822 /* Check other sub-arrays are compatible */
2823 if (elem_ndims
!= this_ndims
||
2824 memcmp(elem_dims
, ARR_DIMS(array
),
2825 elem_ndims
* sizeof(int)) != 0 ||
2826 memcmp(elem_lbs
, ARR_LBOUND(array
),
2827 elem_ndims
* sizeof(int)) != 0)
2829 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR
),
2830 errmsg("multidimensional arrays must have array "
2831 "expressions with matching dimensions")));
2834 subdata
[outer_nelems
] = ARR_DATA_PTR(array
);
2835 subbitmaps
[outer_nelems
] = ARR_NULLBITMAP(array
);
2836 subbytes
[outer_nelems
] = ARR_SIZE(array
) - ARR_DATA_OFFSET(array
);
2837 nbytes
+= subbytes
[outer_nelems
];
2838 subnitems
[outer_nelems
] = ArrayGetNItems(this_ndims
,
2840 nitems
+= subnitems
[outer_nelems
];
2841 havenulls
|= ARR_HASNULL(array
);
2846 * If all items were null or empty arrays, return an empty array;
2847 * otherwise, if some were and some weren't, raise error. (Note: we
2848 * must special-case this somehow to avoid trying to generate a 1-D
2849 * array formed from empty arrays. It's not ideal...)
2853 if (ndims
== 0) /* didn't find any nonempty array */
2855 *op
->resvalue
= PointerGetDatum(construct_empty_array(element_type
));
2859 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR
),
2860 errmsg("multidimensional arrays must have array "
2861 "expressions with matching dimensions")));
2864 /* setup for multi-D array */
2865 dims
[0] = outer_nelems
;
2867 for (int i
= 1; i
< ndims
; i
++)
2869 dims
[i
] = elem_dims
[i
- 1];
2870 lbs
[i
] = elem_lbs
[i
- 1];
2873 /* check for subscript overflow */
2874 (void) ArrayGetNItems(ndims
, dims
);
2875 ArrayCheckBounds(ndims
, dims
, lbs
);
2879 dataoffset
= ARR_OVERHEAD_WITHNULLS(ndims
, nitems
);
2880 nbytes
+= dataoffset
;
2884 dataoffset
= 0; /* marker for no null bitmap */
2885 nbytes
+= ARR_OVERHEAD_NONULLS(ndims
);
2888 result
= (ArrayType
*) palloc(nbytes
);
2889 SET_VARSIZE(result
, nbytes
);
2890 result
->ndim
= ndims
;
2891 result
->dataoffset
= dataoffset
;
2892 result
->elemtype
= element_type
;
2893 memcpy(ARR_DIMS(result
), dims
, ndims
* sizeof(int));
2894 memcpy(ARR_LBOUND(result
), lbs
, ndims
* sizeof(int));
2896 dat
= ARR_DATA_PTR(result
);
2898 for (int i
= 0; i
< outer_nelems
; i
++)
2900 memcpy(dat
, subdata
[i
], subbytes
[i
]);
2903 array_bitmap_copy(ARR_NULLBITMAP(result
), iitem
,
2906 iitem
+= subnitems
[i
];
2910 *op
->resvalue
= PointerGetDatum(result
);
2914 * Evaluate an ArrayCoerceExpr expression.
2916 * Source array is in step's result variable.
2919 ExecEvalArrayCoerce(ExprState
*state
, ExprEvalStep
*op
, ExprContext
*econtext
)
2923 /* NULL array -> NULL result */
2927 arraydatum
= *op
->resvalue
;
2930 * If it's binary-compatible, modify the element type in the array header,
2931 * but otherwise leave the array as we received it.
2933 if (op
->d
.arraycoerce
.elemexprstate
== NULL
)
2935 /* Detoast input array if necessary, and copy in any case */
2936 ArrayType
*array
= DatumGetArrayTypePCopy(arraydatum
);
2938 ARR_ELEMTYPE(array
) = op
->d
.arraycoerce
.resultelemtype
;
2939 *op
->resvalue
= PointerGetDatum(array
);
2944 * Use array_map to apply the sub-expression to each array element.
2946 *op
->resvalue
= array_map(arraydatum
,
2947 op
->d
.arraycoerce
.elemexprstate
,
2949 op
->d
.arraycoerce
.resultelemtype
,
2950 op
->d
.arraycoerce
.amstate
);
2954 * Evaluate a ROW() expression.
2956 * The individual columns have already been evaluated into
2957 * op->d.row.elemvalues[]/elemnulls[].
2960 ExecEvalRow(ExprState
*state
, ExprEvalStep
*op
)
2964 /* build tuple from evaluated field values */
2965 tuple
= heap_form_tuple(op
->d
.row
.tupdesc
,
2966 op
->d
.row
.elemvalues
,
2967 op
->d
.row
.elemnulls
);
2969 *op
->resvalue
= HeapTupleGetDatum(tuple
);
2970 *op
->resnull
= false;
2974 * Evaluate GREATEST() or LEAST() expression (note this is *not* MIN()/MAX()).
2976 * All of the to-be-compared expressions have already been evaluated into
2977 * op->d.minmax.values[]/nulls[].
2980 ExecEvalMinMax(ExprState
*state
, ExprEvalStep
*op
)
2982 Datum
*values
= op
->d
.minmax
.values
;
2983 bool *nulls
= op
->d
.minmax
.nulls
;
2984 FunctionCallInfo fcinfo
= op
->d
.minmax
.fcinfo_data
;
2985 MinMaxOp
operator = op
->d
.minmax
.op
;
2987 /* set at initialization */
2988 Assert(fcinfo
->args
[0].isnull
== false);
2989 Assert(fcinfo
->args
[1].isnull
== false);
2991 /* default to null result */
2992 *op
->resnull
= true;
2994 for (int off
= 0; off
< op
->d
.minmax
.nelems
; off
++)
2996 /* ignore NULL inputs */
3002 /* first nonnull input, adopt value */
3003 *op
->resvalue
= values
[off
];
3004 *op
->resnull
= false;
3010 /* apply comparison function */
3011 fcinfo
->args
[0].value
= *op
->resvalue
;
3012 fcinfo
->args
[1].value
= values
[off
];
3014 fcinfo
->isnull
= false;
3015 cmpresult
= DatumGetInt32(FunctionCallInvoke(fcinfo
));
3016 if (fcinfo
->isnull
) /* probably should not happen */
3019 if (cmpresult
> 0 && operator == IS_LEAST
)
3020 *op
->resvalue
= values
[off
];
3021 else if (cmpresult
< 0 && operator == IS_GREATEST
)
3022 *op
->resvalue
= values
[off
];
3028 * Evaluate a FieldSelect node.
3030 * Source record is in step's result variable.
3033 ExecEvalFieldSelect(ExprState
*state
, ExprEvalStep
*op
, ExprContext
*econtext
)
3035 AttrNumber fieldnum
= op
->d
.fieldselect
.fieldnum
;
3037 HeapTupleHeader tuple
;
3041 Form_pg_attribute attr
;
3042 HeapTupleData tmptup
;
3044 /* NULL record -> NULL result */
3048 tupDatum
= *op
->resvalue
;
3050 /* We can special-case expanded records for speed */
3051 if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(tupDatum
)))
3053 ExpandedRecordHeader
*erh
= (ExpandedRecordHeader
*) DatumGetEOHP(tupDatum
);
3055 Assert(erh
->er_magic
== ER_MAGIC
);
3057 /* Extract record's TupleDesc */
3058 tupDesc
= expanded_record_get_tupdesc(erh
);
3061 * Find field's attr record. Note we don't support system columns
3062 * here: a datum tuple doesn't have valid values for most of the
3063 * interesting system columns anyway.
3065 if (fieldnum
<= 0) /* should never happen */
3066 elog(ERROR
, "unsupported reference to system column %d in FieldSelect",
3068 if (fieldnum
> tupDesc
->natts
) /* should never happen */
3069 elog(ERROR
, "attribute number %d exceeds number of columns %d",
3070 fieldnum
, tupDesc
->natts
);
3071 attr
= TupleDescAttr(tupDesc
, fieldnum
- 1);
3073 /* Check for dropped column, and force a NULL result if so */
3074 if (attr
->attisdropped
)
3076 *op
->resnull
= true;
3080 /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
3081 /* As in CheckVarSlotCompatibility, we should but can't check typmod */
3082 if (op
->d
.fieldselect
.resulttype
!= attr
->atttypid
)
3084 (errcode(ERRCODE_DATATYPE_MISMATCH
),
3085 errmsg("attribute %d has wrong type", fieldnum
),
3086 errdetail("Table has type %s, but query expects %s.",
3087 format_type_be(attr
->atttypid
),
3088 format_type_be(op
->d
.fieldselect
.resulttype
))));
3090 /* extract the field */
3091 *op
->resvalue
= expanded_record_get_field(erh
, fieldnum
,
3096 /* Get the composite datum and extract its type fields */
3097 tuple
= DatumGetHeapTupleHeader(tupDatum
);
3099 tupType
= HeapTupleHeaderGetTypeId(tuple
);
3100 tupTypmod
= HeapTupleHeaderGetTypMod(tuple
);
3102 /* Lookup tupdesc if first time through or if type changes */
3103 tupDesc
= get_cached_rowtype(tupType
, tupTypmod
,
3104 &op
->d
.fieldselect
.rowcache
, NULL
);
3107 * Find field's attr record. Note we don't support system columns
3108 * here: a datum tuple doesn't have valid values for most of the
3109 * interesting system columns anyway.
3111 if (fieldnum
<= 0) /* should never happen */
3112 elog(ERROR
, "unsupported reference to system column %d in FieldSelect",
3114 if (fieldnum
> tupDesc
->natts
) /* should never happen */
3115 elog(ERROR
, "attribute number %d exceeds number of columns %d",
3116 fieldnum
, tupDesc
->natts
);
3117 attr
= TupleDescAttr(tupDesc
, fieldnum
- 1);
3119 /* Check for dropped column, and force a NULL result if so */
3120 if (attr
->attisdropped
)
3122 *op
->resnull
= true;
3126 /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
3127 /* As in CheckVarSlotCompatibility, we should but can't check typmod */
3128 if (op
->d
.fieldselect
.resulttype
!= attr
->atttypid
)
3130 (errcode(ERRCODE_DATATYPE_MISMATCH
),
3131 errmsg("attribute %d has wrong type", fieldnum
),
3132 errdetail("Table has type %s, but query expects %s.",
3133 format_type_be(attr
->atttypid
),
3134 format_type_be(op
->d
.fieldselect
.resulttype
))));
3136 /* heap_getattr needs a HeapTuple not a bare HeapTupleHeader */
3137 tmptup
.t_len
= HeapTupleHeaderGetDatumLength(tuple
);
3138 tmptup
.t_data
= tuple
;
3140 /* extract the field */
3141 *op
->resvalue
= heap_getattr(&tmptup
,
3149 * Deform source tuple, filling in the step's values/nulls arrays, before
3150 * evaluating individual new values as part of a FieldStore expression.
3151 * Subsequent steps will overwrite individual elements of the values/nulls
3152 * arrays with the new field values, and then FIELDSTORE_FORM will build the
3155 * Source record is in step's result variable.
3158 ExecEvalFieldStoreDeForm(ExprState
*state
, ExprEvalStep
*op
, ExprContext
*econtext
)
3162 /* Lookup tupdesc if first time through or if type changes */
3163 tupDesc
= get_cached_rowtype(op
->d
.fieldstore
.fstore
->resulttype
, -1,
3164 op
->d
.fieldstore
.rowcache
, NULL
);
3166 /* Check that current tupdesc doesn't have more fields than we allocated */
3167 if (unlikely(tupDesc
->natts
> op
->d
.fieldstore
.ncolumns
))
3168 elog(ERROR
, "too many columns in composite type %u",
3169 op
->d
.fieldstore
.fstore
->resulttype
);
3173 /* Convert null input tuple into an all-nulls row */
3174 memset(op
->d
.fieldstore
.nulls
, true,
3175 op
->d
.fieldstore
.ncolumns
* sizeof(bool));
3180 * heap_deform_tuple needs a HeapTuple not a bare HeapTupleHeader. We
3181 * set all the fields in the struct just in case.
3183 Datum tupDatum
= *op
->resvalue
;
3184 HeapTupleHeader tuphdr
;
3185 HeapTupleData tmptup
;
3187 tuphdr
= DatumGetHeapTupleHeader(tupDatum
);
3188 tmptup
.t_len
= HeapTupleHeaderGetDatumLength(tuphdr
);
3189 ItemPointerSetInvalid(&(tmptup
.t_self
));
3190 tmptup
.t_tableOid
= InvalidOid
;
3191 tmptup
.t_data
= tuphdr
;
3193 heap_deform_tuple(&tmptup
, tupDesc
,
3194 op
->d
.fieldstore
.values
,
3195 op
->d
.fieldstore
.nulls
);
3200 * Compute the new composite datum after each individual field value of a
3201 * FieldStore expression has been evaluated.
3204 ExecEvalFieldStoreForm(ExprState
*state
, ExprEvalStep
*op
, ExprContext
*econtext
)
3209 /* Lookup tupdesc (should be valid already) */
3210 tupDesc
= get_cached_rowtype(op
->d
.fieldstore
.fstore
->resulttype
, -1,
3211 op
->d
.fieldstore
.rowcache
, NULL
);
3213 tuple
= heap_form_tuple(tupDesc
,
3214 op
->d
.fieldstore
.values
,
3215 op
->d
.fieldstore
.nulls
);
3217 *op
->resvalue
= HeapTupleGetDatum(tuple
);
3218 *op
->resnull
= false;
3222 * Evaluate a rowtype coercion operation.
3223 * This may require rearranging field positions.
3225 * Source record is in step's result variable.
3228 ExecEvalConvertRowtype(ExprState
*state
, ExprEvalStep
*op
, ExprContext
*econtext
)
3232 HeapTupleHeader tuple
;
3233 HeapTupleData tmptup
;
3236 bool changed
= false;
3238 /* NULL in -> NULL out */
3242 tupDatum
= *op
->resvalue
;
3243 tuple
= DatumGetHeapTupleHeader(tupDatum
);
3246 * Lookup tupdescs if first time through or if type changes. We'd better
3247 * pin them since type conversion functions could do catalog lookups and
3248 * hence cause cache invalidation.
3250 indesc
= get_cached_rowtype(op
->d
.convert_rowtype
.inputtype
, -1,
3251 op
->d
.convert_rowtype
.incache
,
3253 IncrTupleDescRefCount(indesc
);
3254 outdesc
= get_cached_rowtype(op
->d
.convert_rowtype
.outputtype
, -1,
3255 op
->d
.convert_rowtype
.outcache
,
3257 IncrTupleDescRefCount(outdesc
);
3260 * We used to be able to assert that incoming tuples are marked with
3261 * exactly the rowtype of indesc. However, now that ExecEvalWholeRowVar
3262 * might change the tuples' marking to plain RECORD due to inserting
3263 * aliases, we can only make this weak test:
3265 Assert(HeapTupleHeaderGetTypeId(tuple
) == indesc
->tdtypeid
||
3266 HeapTupleHeaderGetTypeId(tuple
) == RECORDOID
);
3268 /* if first time through, or after change, initialize conversion map */
3271 MemoryContext old_cxt
;
3273 /* allocate map in long-lived memory context */
3274 old_cxt
= MemoryContextSwitchTo(econtext
->ecxt_per_query_memory
);
3276 /* prepare map from old to new attribute numbers */
3277 op
->d
.convert_rowtype
.map
= convert_tuples_by_name(indesc
, outdesc
);
3279 MemoryContextSwitchTo(old_cxt
);
3282 /* Following steps need a HeapTuple not a bare HeapTupleHeader */
3283 tmptup
.t_len
= HeapTupleHeaderGetDatumLength(tuple
);
3284 tmptup
.t_data
= tuple
;
3286 if (op
->d
.convert_rowtype
.map
!= NULL
)
3288 /* Full conversion with attribute rearrangement needed */
3289 result
= execute_attr_map_tuple(&tmptup
, op
->d
.convert_rowtype
.map
);
3290 /* Result already has appropriate composite-datum header fields */
3291 *op
->resvalue
= HeapTupleGetDatum(result
);
3296 * The tuple is physically compatible as-is, but we need to insert the
3297 * destination rowtype OID in its composite-datum header field, so we
3298 * have to copy it anyway. heap_copy_tuple_as_datum() is convenient
3299 * for this since it will both make the physical copy and insert the
3300 * correct composite header fields. Note that we aren't expecting to
3301 * have to flatten any toasted fields: the input was a composite
3302 * datum, so it shouldn't contain any. So heap_copy_tuple_as_datum()
3303 * is overkill here, but its check for external fields is cheap.
3305 *op
->resvalue
= heap_copy_tuple_as_datum(&tmptup
, outdesc
);
3308 DecrTupleDescRefCount(indesc
);
3309 DecrTupleDescRefCount(outdesc
);
3313 * Evaluate "scalar op ANY/ALL (array)".
3315 * Source array is in our result area, scalar arg is already evaluated into
3318 * The operator always yields boolean, and we combine the results across all
3319 * array elements using OR and AND (for ANY and ALL respectively). Of course
3320 * we short-circuit as soon as the result is known.
3323 ExecEvalScalarArrayOp(ExprState
*state
, ExprEvalStep
*op
)
3325 FunctionCallInfo fcinfo
= op
->d
.scalararrayop
.fcinfo_data
;
3326 bool useOr
= op
->d
.scalararrayop
.useOr
;
3327 bool strictfunc
= op
->d
.scalararrayop
.finfo
->fn_strict
;
3340 * If the array is NULL then we return NULL --- it's not very meaningful
3341 * to do anything else, even if the operator isn't strict.
3346 /* Else okay to fetch and detoast the array */
3347 arr
= DatumGetArrayTypeP(*op
->resvalue
);
3350 * If the array is empty, we return either FALSE or TRUE per the useOr
3351 * flag. This is correct even if the scalar is NULL; since we would
3352 * evaluate the operator zero times, it matters not whether it would want
3355 nitems
= ArrayGetNItems(ARR_NDIM(arr
), ARR_DIMS(arr
));
3358 *op
->resvalue
= BoolGetDatum(!useOr
);
3359 *op
->resnull
= false;
3364 * If the scalar is NULL, and the function is strict, return NULL; no
3365 * point in iterating the loop.
3367 if (fcinfo
->args
[0].isnull
&& strictfunc
)
3369 *op
->resnull
= true;
3374 * We arrange to look up info about the element type only once per series
3375 * of calls, assuming the element type doesn't change underneath us.
3377 if (op
->d
.scalararrayop
.element_type
!= ARR_ELEMTYPE(arr
))
3379 get_typlenbyvalalign(ARR_ELEMTYPE(arr
),
3380 &op
->d
.scalararrayop
.typlen
,
3381 &op
->d
.scalararrayop
.typbyval
,
3382 &op
->d
.scalararrayop
.typalign
);
3383 op
->d
.scalararrayop
.element_type
= ARR_ELEMTYPE(arr
);
3386 typlen
= op
->d
.scalararrayop
.typlen
;
3387 typbyval
= op
->d
.scalararrayop
.typbyval
;
3388 typalign
= op
->d
.scalararrayop
.typalign
;
3390 /* Initialize result appropriately depending on useOr */
3391 result
= BoolGetDatum(!useOr
);
3394 /* Loop over the array elements */
3395 s
= (char *) ARR_DATA_PTR(arr
);
3396 bitmap
= ARR_NULLBITMAP(arr
);
3399 for (int i
= 0; i
< nitems
; i
++)
3404 /* Get array element, checking for NULL */
3405 if (bitmap
&& (*bitmap
& bitmask
) == 0)
3407 fcinfo
->args
[1].value
= (Datum
) 0;
3408 fcinfo
->args
[1].isnull
= true;
3412 elt
= fetch_att(s
, typbyval
, typlen
);
3413 s
= att_addlength_pointer(s
, typlen
, s
);
3414 s
= (char *) att_align_nominal(s
, typalign
);
3415 fcinfo
->args
[1].value
= elt
;
3416 fcinfo
->args
[1].isnull
= false;
3419 /* Call comparison function */
3420 if (fcinfo
->args
[1].isnull
&& strictfunc
)
3422 fcinfo
->isnull
= true;
3423 thisresult
= (Datum
) 0;
3427 fcinfo
->isnull
= false;
3428 thisresult
= op
->d
.scalararrayop
.fn_addr(fcinfo
);
3431 /* Combine results per OR or AND semantics */
3436 if (DatumGetBool(thisresult
))
3438 result
= BoolGetDatum(true);
3440 break; /* needn't look at any more elements */
3445 if (!DatumGetBool(thisresult
))
3447 result
= BoolGetDatum(false);
3449 break; /* needn't look at any more elements */
3453 /* advance bitmap pointer if any */
3457 if (bitmask
== 0x100)
3465 *op
->resvalue
= result
;
3466 *op
->resnull
= resultnull
;
3470 * Hash function for scalar array hash op elements.
3472 * We use the element type's default hash opclass, and the column collation
3473 * if the type is collation-sensitive.
3476 saop_element_hash(struct saophash_hash
*tb
, Datum key
)
3478 ScalarArrayOpExprHashTable
*elements_tab
= (ScalarArrayOpExprHashTable
*) tb
->private_data
;
3479 FunctionCallInfo fcinfo
= &elements_tab
->hash_fcinfo_data
;
3482 fcinfo
->args
[0].value
= key
;
3483 fcinfo
->args
[0].isnull
= false;
3485 hash
= elements_tab
->hash_finfo
.fn_addr(fcinfo
);
3487 return DatumGetUInt32(hash
);
3491 * Matching function for scalar array hash op elements, to be used in hashtable
3495 saop_hash_element_match(struct saophash_hash
*tb
, Datum key1
, Datum key2
)
3499 ScalarArrayOpExprHashTable
*elements_tab
= (ScalarArrayOpExprHashTable
*) tb
->private_data
;
3500 FunctionCallInfo fcinfo
= elements_tab
->op
->d
.hashedscalararrayop
.fcinfo_data
;
3502 fcinfo
->args
[0].value
= key1
;
3503 fcinfo
->args
[0].isnull
= false;
3504 fcinfo
->args
[1].value
= key2
;
3505 fcinfo
->args
[1].isnull
= false;
3507 result
= elements_tab
->op
->d
.hashedscalararrayop
.finfo
->fn_addr(fcinfo
);
3509 return DatumGetBool(result
);
3513 * Evaluate "scalar op ANY (const array)".
3515 * Similar to ExecEvalScalarArrayOp, but optimized for faster repeat lookups
3516 * by building a hashtable on the first lookup. This hashtable will be reused
3517 * by subsequent lookups. Unlike ExecEvalScalarArrayOp, this version only
3518 * supports OR semantics.
3520 * Source array is in our result area, scalar arg is already evaluated into
3523 * The operator always yields boolean.
3526 ExecEvalHashedScalarArrayOp(ExprState
*state
, ExprEvalStep
*op
, ExprContext
*econtext
)
3528 ScalarArrayOpExprHashTable
*elements_tab
= op
->d
.hashedscalararrayop
.elements_tab
;
3529 FunctionCallInfo fcinfo
= op
->d
.hashedscalararrayop
.fcinfo_data
;
3530 bool inclause
= op
->d
.hashedscalararrayop
.inclause
;
3531 bool strictfunc
= op
->d
.hashedscalararrayop
.finfo
->fn_strict
;
3532 Datum scalar
= fcinfo
->args
[0].value
;
3533 bool scalar_isnull
= fcinfo
->args
[0].isnull
;
3538 /* We don't setup a hashed scalar array op if the array const is null. */
3539 Assert(!*op
->resnull
);
3542 * If the scalar is NULL, and the function is strict, return NULL; no
3543 * point in executing the search.
3545 if (fcinfo
->args
[0].isnull
&& strictfunc
)
3547 *op
->resnull
= true;
3551 /* Build the hash table on first evaluation */
3552 if (elements_tab
== NULL
)
3554 ScalarArrayOpExpr
*saop
;
3559 bool has_nulls
= false;
3563 MemoryContext oldcontext
;
3566 saop
= op
->d
.hashedscalararrayop
.saop
;
3568 arr
= DatumGetArrayTypeP(*op
->resvalue
);
3569 nitems
= ArrayGetNItems(ARR_NDIM(arr
), ARR_DIMS(arr
));
3571 get_typlenbyvalalign(ARR_ELEMTYPE(arr
),
3576 oldcontext
= MemoryContextSwitchTo(econtext
->ecxt_per_query_memory
);
3578 elements_tab
= (ScalarArrayOpExprHashTable
*)
3579 palloc0(offsetof(ScalarArrayOpExprHashTable
, hash_fcinfo_data
) +
3580 SizeForFunctionCallInfo(1));
3581 op
->d
.hashedscalararrayop
.elements_tab
= elements_tab
;
3582 elements_tab
->op
= op
;
3584 fmgr_info(saop
->hashfuncid
, &elements_tab
->hash_finfo
);
3585 fmgr_info_set_expr((Node
*) saop
, &elements_tab
->hash_finfo
);
3587 InitFunctionCallInfoData(elements_tab
->hash_fcinfo_data
,
3588 &elements_tab
->hash_finfo
,
3595 * Create the hash table sizing it according to the number of elements
3596 * in the array. This does assume that the array has no duplicates.
3597 * If the array happens to contain many duplicate values then it'll
3598 * just mean that we sized the table a bit on the large side.
3600 elements_tab
->hashtab
= saophash_create(CurrentMemoryContext
, nitems
,
3603 MemoryContextSwitchTo(oldcontext
);
3605 s
= (char *) ARR_DATA_PTR(arr
);
3606 bitmap
= ARR_NULLBITMAP(arr
);
3608 for (int i
= 0; i
< nitems
; i
++)
3610 /* Get array element, checking for NULL. */
3611 if (bitmap
&& (*bitmap
& bitmask
) == 0)
3619 element
= fetch_att(s
, typbyval
, typlen
);
3620 s
= att_addlength_pointer(s
, typlen
, s
);
3621 s
= (char *) att_align_nominal(s
, typalign
);
3623 saophash_insert(elements_tab
->hashtab
, element
, &hashfound
);
3626 /* Advance bitmap pointer if any. */
3630 if (bitmask
== 0x100)
3639 * Remember if we had any nulls so that we know if we need to execute
3640 * non-strict functions with a null lhs value if no match is found.
3642 op
->d
.hashedscalararrayop
.has_nulls
= has_nulls
;
3645 /* Check the hash to see if we have a match. */
3646 hashfound
= NULL
!= saophash_lookup(elements_tab
->hashtab
, scalar
);
3648 /* the result depends on if the clause is an IN or NOT IN clause */
3650 result
= BoolGetDatum(hashfound
); /* IN */
3652 result
= BoolGetDatum(!hashfound
); /* NOT IN */
3657 * If we didn't find a match in the array, we still might need to handle
3658 * the possibility of null values. We didn't put any NULLs into the
3659 * hashtable, but instead marked if we found any when building the table
3662 if (!hashfound
&& op
->d
.hashedscalararrayop
.has_nulls
)
3668 * We have nulls in the array so a non-null lhs and no match must
3677 * Execute function will null rhs just once.
3679 * The hash lookup path will have scribbled on the lhs argument so
3680 * we need to set it up also (even though we entered this function
3681 * with it already set).
3683 fcinfo
->args
[0].value
= scalar
;
3684 fcinfo
->args
[0].isnull
= scalar_isnull
;
3685 fcinfo
->args
[1].value
= (Datum
) 0;
3686 fcinfo
->args
[1].isnull
= true;
3688 result
= op
->d
.hashedscalararrayop
.finfo
->fn_addr(fcinfo
);
3689 resultnull
= fcinfo
->isnull
;
3692 * Reverse the result for NOT IN clauses since the above function
3693 * is the equality function and we need not-equals.
3700 *op
->resvalue
= result
;
3701 *op
->resnull
= resultnull
;
3705 * Evaluate a NOT NULL domain constraint.
3708 ExecEvalConstraintNotNull(ExprState
*state
, ExprEvalStep
*op
)
3712 (errcode(ERRCODE_NOT_NULL_VIOLATION
),
3713 errmsg("domain %s does not allow null values",
3714 format_type_be(op
->d
.domaincheck
.resulttype
)),
3715 errdatatype(op
->d
.domaincheck
.resulttype
)));
3719 * Evaluate a CHECK domain constraint.
3722 ExecEvalConstraintCheck(ExprState
*state
, ExprEvalStep
*op
)
3724 if (!*op
->d
.domaincheck
.checknull
&&
3725 !DatumGetBool(*op
->d
.domaincheck
.checkvalue
))
3727 (errcode(ERRCODE_CHECK_VIOLATION
),
3728 errmsg("value for domain %s violates check constraint \"%s\"",
3729 format_type_be(op
->d
.domaincheck
.resulttype
),
3730 op
->d
.domaincheck
.constraintname
),
3731 errdomainconstraint(op
->d
.domaincheck
.resulttype
,
3732 op
->d
.domaincheck
.constraintname
)));
3736 * Evaluate the various forms of XmlExpr.
3738 * Arguments have been evaluated into named_argvalue/named_argnull
3739 * and/or argvalue/argnull arrays.
3742 ExecEvalXmlExpr(ExprState
*state
, ExprEvalStep
*op
)
3744 XmlExpr
*xexpr
= op
->d
.xmlexpr
.xexpr
;
3747 *op
->resnull
= true; /* until we get a result */
3748 *op
->resvalue
= (Datum
) 0;
3754 Datum
*argvalue
= op
->d
.xmlexpr
.argvalue
;
3755 bool *argnull
= op
->d
.xmlexpr
.argnull
;
3758 for (int i
= 0; i
< list_length(xexpr
->args
); i
++)
3761 values
= lappend(values
, DatumGetPointer(argvalue
[i
]));
3766 *op
->resvalue
= PointerGetDatum(xmlconcat(values
));
3767 *op
->resnull
= false;
3774 Datum
*argvalue
= op
->d
.xmlexpr
.named_argvalue
;
3775 bool *argnull
= op
->d
.xmlexpr
.named_argnull
;
3781 initStringInfo(&buf
);
3784 forboth(lc
, xexpr
->named_args
, lc2
, xexpr
->arg_names
)
3786 Expr
*e
= (Expr
*) lfirst(lc
);
3787 char *argname
= strVal(lfirst(lc2
));
3791 value
= argvalue
[i
];
3792 appendStringInfo(&buf
, "<%s>%s</%s>",
3794 map_sql_value_to_xml_value(value
,
3795 exprType((Node
*) e
), true),
3797 *op
->resnull
= false;
3806 result
= cstring_to_text_with_len(buf
.data
, buf
.len
);
3807 *op
->resvalue
= PointerGetDatum(result
);
3815 *op
->resvalue
= PointerGetDatum(xmlelement(xexpr
,
3816 op
->d
.xmlexpr
.named_argvalue
,
3817 op
->d
.xmlexpr
.named_argnull
,
3818 op
->d
.xmlexpr
.argvalue
,
3819 op
->d
.xmlexpr
.argnull
));
3820 *op
->resnull
= false;
3825 Datum
*argvalue
= op
->d
.xmlexpr
.argvalue
;
3826 bool *argnull
= op
->d
.xmlexpr
.argnull
;
3828 bool preserve_whitespace
;
3830 /* arguments are known to be text, bool */
3831 Assert(list_length(xexpr
->args
) == 2);
3835 value
= argvalue
[0];
3836 data
= DatumGetTextPP(value
);
3838 if (argnull
[1]) /* probably can't happen */
3840 value
= argvalue
[1];
3841 preserve_whitespace
= DatumGetBool(value
);
3843 *op
->resvalue
= PointerGetDatum(xmlparse(data
,
3845 preserve_whitespace
));
3846 *op
->resnull
= false;
3855 /* optional argument is known to be text */
3856 Assert(list_length(xexpr
->args
) <= 1);
3860 isnull
= op
->d
.xmlexpr
.argnull
[0];
3864 arg
= DatumGetTextPP(op
->d
.xmlexpr
.argvalue
[0]);
3872 *op
->resvalue
= PointerGetDatum(xmlpi(xexpr
->name
,
3881 Datum
*argvalue
= op
->d
.xmlexpr
.argvalue
;
3882 bool *argnull
= op
->d
.xmlexpr
.argnull
;
3887 /* arguments are known to be xml, text, int */
3888 Assert(list_length(xexpr
->args
) == 3);
3892 data
= DatumGetXmlP(argvalue
[0]);
3897 version
= DatumGetTextPP(argvalue
[1]);
3899 Assert(!argnull
[2]); /* always present */
3900 standalone
= DatumGetInt32(argvalue
[2]);
3902 *op
->resvalue
= PointerGetDatum(xmlroot(data
,
3905 *op
->resnull
= false;
3909 case IS_XMLSERIALIZE
:
3911 Datum
*argvalue
= op
->d
.xmlexpr
.argvalue
;
3912 bool *argnull
= op
->d
.xmlexpr
.argnull
;
3914 /* argument type is known to be xml */
3915 Assert(list_length(xexpr
->args
) == 1);
3919 value
= argvalue
[0];
3921 *op
->resvalue
= PointerGetDatum(xmltotext_with_xmloption(DatumGetXmlP(value
),
3923 *op
->resnull
= false;
3929 Datum
*argvalue
= op
->d
.xmlexpr
.argvalue
;
3930 bool *argnull
= op
->d
.xmlexpr
.argnull
;
3932 /* optional argument is known to be xml */
3933 Assert(list_length(xexpr
->args
) == 1);
3937 value
= argvalue
[0];
3940 BoolGetDatum(xml_is_document(DatumGetXmlP(value
)));
3941 *op
->resnull
= false;
3946 elog(ERROR
, "unrecognized XML operation");
3952 ExecEvalJsonIsPredicate(ExprState
*state
, ExprEvalStep
*op
)
3954 JsonIsPredicate
*pred
= op
->d
.is_json
.pred
;
3955 Datum js
= *op
->resvalue
;
3961 *op
->resvalue
= BoolGetDatum(false);
3965 exprtype
= exprType(pred
->expr
);
3967 if (exprtype
== TEXTOID
|| exprtype
== JSONOID
)
3969 text
*json
= DatumGetTextP(js
);
3971 if (pred
->item_type
== JS_TYPE_ANY
)
3975 switch (json_get_first_token(json
, false))
3977 case JSON_TOKEN_OBJECT_START
:
3978 res
= pred
->item_type
== JS_TYPE_OBJECT
;
3980 case JSON_TOKEN_ARRAY_START
:
3981 res
= pred
->item_type
== JS_TYPE_ARRAY
;
3983 case JSON_TOKEN_STRING
:
3984 case JSON_TOKEN_NUMBER
:
3985 case JSON_TOKEN_TRUE
:
3986 case JSON_TOKEN_FALSE
:
3987 case JSON_TOKEN_NULL
:
3988 res
= pred
->item_type
== JS_TYPE_SCALAR
;
3997 * Do full parsing pass only for uniqueness check or for JSON text
4000 if (res
&& (pred
->unique_keys
|| exprtype
== TEXTOID
))
4001 res
= json_validate(json
, pred
->unique_keys
, false);
4003 else if (exprtype
== JSONBOID
)
4005 if (pred
->item_type
== JS_TYPE_ANY
)
4009 Jsonb
*jb
= DatumGetJsonbP(js
);
4011 switch (pred
->item_type
)
4013 case JS_TYPE_OBJECT
:
4014 res
= JB_ROOT_IS_OBJECT(jb
);
4017 res
= JB_ROOT_IS_ARRAY(jb
) && !JB_ROOT_IS_SCALAR(jb
);
4019 case JS_TYPE_SCALAR
:
4020 res
= JB_ROOT_IS_ARRAY(jb
) && JB_ROOT_IS_SCALAR(jb
);
4028 /* Key uniqueness check is redundant for jsonb */
4033 *op
->resvalue
= BoolGetDatum(res
);
4037 * ExecEvalGroupingFunc
4039 * Computes a bitmask with a bit for each (unevaluated) argument expression
4040 * (rightmost arg is least significant bit).
4042 * A bit is set if the corresponding expression is NOT part of the set of
4043 * grouping expressions in the current grouping set.
4046 ExecEvalGroupingFunc(ExprState
*state
, ExprEvalStep
*op
)
4048 AggState
*aggstate
= castNode(AggState
, state
->parent
);
4050 Bitmapset
*grouped_cols
= aggstate
->grouped_cols
;
4053 foreach(lc
, op
->d
.grouping_func
.clauses
)
4055 int attnum
= lfirst_int(lc
);
4059 if (!bms_is_member(attnum
, grouped_cols
))
4063 *op
->resvalue
= Int32GetDatum(result
);
4064 *op
->resnull
= false;
4068 * Hand off evaluation of a subplan to nodeSubplan.c
4071 ExecEvalSubPlan(ExprState
*state
, ExprEvalStep
*op
, ExprContext
*econtext
)
4073 SubPlanState
*sstate
= op
->d
.subplan
.sstate
;
4075 /* could potentially be nested, so make sure there's enough stack */
4076 check_stack_depth();
4078 *op
->resvalue
= ExecSubPlan(sstate
, econtext
, op
->resnull
);
4082 * Evaluate a wholerow Var expression.
4084 * Returns a Datum whose value is the value of a whole-row range variable
4085 * with respect to given expression context.
4088 ExecEvalWholeRowVar(ExprState
*state
, ExprEvalStep
*op
, ExprContext
*econtext
)
4090 Var
*variable
= op
->d
.wholerow
.var
;
4091 TupleTableSlot
*slot
;
4092 TupleDesc output_tupdesc
;
4093 MemoryContext oldcontext
;
4094 HeapTupleHeader dtuple
;
4097 /* This was checked by ExecInitExpr */
4098 Assert(variable
->varattno
== InvalidAttrNumber
);
4100 /* Get the input slot we want */
4101 switch (variable
->varno
)
4104 /* get the tuple from the inner node */
4105 slot
= econtext
->ecxt_innertuple
;
4109 /* get the tuple from the outer node */
4110 slot
= econtext
->ecxt_outertuple
;
4113 /* INDEX_VAR is handled by default case */
4116 /* get the tuple from the relation being scanned */
4117 slot
= econtext
->ecxt_scantuple
;
4121 /* Apply the junkfilter if any */
4122 if (op
->d
.wholerow
.junkFilter
!= NULL
)
4123 slot
= ExecFilterJunk(op
->d
.wholerow
.junkFilter
, slot
);
4126 * If first time through, obtain tuple descriptor and check compatibility.
4128 * XXX: It'd be great if this could be moved to the expression
4129 * initialization phase, but due to using slots that's currently not
4132 if (op
->d
.wholerow
.first
)
4134 /* optimistically assume we don't need slow path */
4135 op
->d
.wholerow
.slow
= false;
4138 * If the Var identifies a named composite type, we must check that
4139 * the actual tuple type is compatible with it.
4141 if (variable
->vartype
!= RECORDOID
)
4143 TupleDesc var_tupdesc
;
4144 TupleDesc slot_tupdesc
;
4147 * We really only care about numbers of attributes and data types.
4148 * Also, we can ignore type mismatch on columns that are dropped
4149 * in the destination type, so long as (1) the physical storage
4150 * matches or (2) the actual column value is NULL. Case (1) is
4151 * helpful in some cases involving out-of-date cached plans, while
4152 * case (2) is expected behavior in situations such as an INSERT
4153 * into a table with dropped columns (the planner typically
4154 * generates an INT4 NULL regardless of the dropped column type).
4155 * If we find a dropped column and cannot verify that case (1)
4156 * holds, we have to use the slow path to check (2) for each row.
4158 * If vartype is a domain over composite, just look through that
4159 * to the base composite type.
4161 var_tupdesc
= lookup_rowtype_tupdesc_domain(variable
->vartype
,
4164 slot_tupdesc
= slot
->tts_tupleDescriptor
;
4166 if (var_tupdesc
->natts
!= slot_tupdesc
->natts
)
4168 (errcode(ERRCODE_DATATYPE_MISMATCH
),
4169 errmsg("table row type and query-specified row type do not match"),
4170 errdetail_plural("Table row contains %d attribute, but query expects %d.",
4171 "Table row contains %d attributes, but query expects %d.",
4172 slot_tupdesc
->natts
,
4173 slot_tupdesc
->natts
,
4174 var_tupdesc
->natts
)));
4176 for (int i
= 0; i
< var_tupdesc
->natts
; i
++)
4178 Form_pg_attribute vattr
= TupleDescAttr(var_tupdesc
, i
);
4179 Form_pg_attribute sattr
= TupleDescAttr(slot_tupdesc
, i
);
4181 if (vattr
->atttypid
== sattr
->atttypid
)
4182 continue; /* no worries */
4183 if (!vattr
->attisdropped
)
4185 (errcode(ERRCODE_DATATYPE_MISMATCH
),
4186 errmsg("table row type and query-specified row type do not match"),
4187 errdetail("Table has type %s at ordinal position %d, but query expects %s.",
4188 format_type_be(sattr
->atttypid
),
4190 format_type_be(vattr
->atttypid
))));
4192 if (vattr
->attlen
!= sattr
->attlen
||
4193 vattr
->attalign
!= sattr
->attalign
)
4194 op
->d
.wholerow
.slow
= true; /* need to check for nulls */
4198 * Use the variable's declared rowtype as the descriptor for the
4199 * output values. In particular, we *must* absorb any
4200 * attisdropped markings.
4202 oldcontext
= MemoryContextSwitchTo(econtext
->ecxt_per_query_memory
);
4203 output_tupdesc
= CreateTupleDescCopy(var_tupdesc
);
4204 MemoryContextSwitchTo(oldcontext
);
4206 ReleaseTupleDesc(var_tupdesc
);
4211 * In the RECORD case, we use the input slot's rowtype as the
4212 * descriptor for the output values, modulo possibly assigning new
4213 * column names below.
4215 oldcontext
= MemoryContextSwitchTo(econtext
->ecxt_per_query_memory
);
4216 output_tupdesc
= CreateTupleDescCopy(slot
->tts_tupleDescriptor
);
4217 MemoryContextSwitchTo(oldcontext
);
4220 * It's possible that the input slot is a relation scan slot and
4221 * so is marked with that relation's rowtype. But we're supposed
4222 * to be returning RECORD, so reset to that.
4224 output_tupdesc
->tdtypeid
= RECORDOID
;
4225 output_tupdesc
->tdtypmod
= -1;
4228 * We already got the correct physical datatype info above, but
4229 * now we should try to find the source RTE and adopt its column
4230 * aliases, since it's unlikely that the input slot has the
4233 * If we can't locate the RTE, assume the column names we've got
4234 * are OK. (As of this writing, the only cases where we can't
4235 * locate the RTE are in execution of trigger WHEN clauses, and
4236 * then the Var will have the trigger's relation's rowtype, so its
4237 * names are fine.) Also, if the creator of the RTE didn't bother
4238 * to fill in an eref field, assume our column names are OK. (This
4239 * happens in COPY, and perhaps other places.)
4241 if (econtext
->ecxt_estate
&&
4242 variable
->varno
<= econtext
->ecxt_estate
->es_range_table_size
)
4244 RangeTblEntry
*rte
= exec_rt_fetch(variable
->varno
,
4245 econtext
->ecxt_estate
);
4248 ExecTypeSetColNames(output_tupdesc
, rte
->eref
->colnames
);
4252 /* Bless the tupdesc if needed, and save it in the execution state */
4253 op
->d
.wholerow
.tupdesc
= BlessTupleDesc(output_tupdesc
);
4255 op
->d
.wholerow
.first
= false;
4259 * Make sure all columns of the slot are accessible in the slot's
4260 * Datum/isnull arrays.
4262 slot_getallattrs(slot
);
4264 if (op
->d
.wholerow
.slow
)
4266 /* Check to see if any dropped attributes are non-null */
4267 TupleDesc tupleDesc
= slot
->tts_tupleDescriptor
;
4268 TupleDesc var_tupdesc
= op
->d
.wholerow
.tupdesc
;
4270 Assert(var_tupdesc
->natts
== tupleDesc
->natts
);
4272 for (int i
= 0; i
< var_tupdesc
->natts
; i
++)
4274 Form_pg_attribute vattr
= TupleDescAttr(var_tupdesc
, i
);
4275 Form_pg_attribute sattr
= TupleDescAttr(tupleDesc
, i
);
4277 if (!vattr
->attisdropped
)
4278 continue; /* already checked non-dropped cols */
4279 if (slot
->tts_isnull
[i
])
4280 continue; /* null is always okay */
4281 if (vattr
->attlen
!= sattr
->attlen
||
4282 vattr
->attalign
!= sattr
->attalign
)
4284 (errcode(ERRCODE_DATATYPE_MISMATCH
),
4285 errmsg("table row type and query-specified row type do not match"),
4286 errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
4292 * Build a composite datum, making sure any toasted fields get detoasted.
4294 * (Note: it is critical that we not change the slot's state here.)
4296 tuple
= toast_build_flattened_tuple(slot
->tts_tupleDescriptor
,
4299 dtuple
= tuple
->t_data
;
4302 * Label the datum with the composite type info we identified before.
4304 * (Note: we could skip doing this by passing op->d.wholerow.tupdesc to
4305 * the tuple build step; but that seems a tad risky so let's not.)
4307 HeapTupleHeaderSetTypeId(dtuple
, op
->d
.wholerow
.tupdesc
->tdtypeid
);
4308 HeapTupleHeaderSetTypMod(dtuple
, op
->d
.wholerow
.tupdesc
->tdtypmod
);
4310 *op
->resvalue
= PointerGetDatum(dtuple
);
4311 *op
->resnull
= false;
4315 ExecEvalSysVar(ExprState
*state
, ExprEvalStep
*op
, ExprContext
*econtext
,
4316 TupleTableSlot
*slot
)
4320 /* slot_getsysattr has sufficient defenses against bad attnums */
4321 d
= slot_getsysattr(slot
,
4325 /* this ought to be unreachable, but it's cheap enough to check */
4326 if (unlikely(*op
->resnull
))
4327 elog(ERROR
, "failed to fetch attribute from slot");
4331 * Transition value has not been initialized. This is the first non-NULL input
4332 * value for a group. We use it as the initial value for transValue.
4335 ExecAggInitGroup(AggState
*aggstate
, AggStatePerTrans pertrans
, AggStatePerGroup pergroup
,
4336 ExprContext
*aggcontext
)
4338 FunctionCallInfo fcinfo
= pertrans
->transfn_fcinfo
;
4339 MemoryContext oldContext
;
4342 * We must copy the datum into aggcontext if it is pass-by-ref. We do not
4343 * need to pfree the old transValue, since it's NULL. (We already checked
4344 * that the agg's input type is binary-compatible with its transtype, so
4345 * straight copy here is OK.)
4347 oldContext
= MemoryContextSwitchTo(aggcontext
->ecxt_per_tuple_memory
);
4348 pergroup
->transValue
= datumCopy(fcinfo
->args
[1].value
,
4349 pertrans
->transtypeByVal
,
4350 pertrans
->transtypeLen
);
4351 pergroup
->transValueIsNull
= false;
4352 pergroup
->noTransValue
= false;
4353 MemoryContextSwitchTo(oldContext
);
4357 * Ensure that the current transition value is a child of the aggcontext,
4358 * rather than the per-tuple context.
4360 * NB: This can change the current memory context.
4363 ExecAggTransReparent(AggState
*aggstate
, AggStatePerTrans pertrans
,
4364 Datum newValue
, bool newValueIsNull
,
4365 Datum oldValue
, bool oldValueIsNull
)
4367 Assert(newValue
!= oldValue
);
4369 if (!newValueIsNull
)
4371 MemoryContextSwitchTo(aggstate
->curaggcontext
->ecxt_per_tuple_memory
);
4372 if (DatumIsReadWriteExpandedObject(newValue
,
4374 pertrans
->transtypeLen
) &&
4375 MemoryContextGetParent(DatumGetEOHP(newValue
)->eoh_context
) == CurrentMemoryContext
)
4378 newValue
= datumCopy(newValue
,
4379 pertrans
->transtypeByVal
,
4380 pertrans
->transtypeLen
);
4385 * Ensure that AggStatePerGroup->transValue ends up being 0, so
4386 * callers can safely compare newValue/oldValue without having to
4387 * check their respective nullness.
4389 newValue
= (Datum
) 0;
4392 if (!oldValueIsNull
)
4394 if (DatumIsReadWriteExpandedObject(oldValue
,
4396 pertrans
->transtypeLen
))
4397 DeleteExpandedObject(oldValue
);
4399 pfree(DatumGetPointer(oldValue
));
4406 * Invoke ordered transition function, with a datum argument.
4409 ExecEvalAggOrderedTransDatum(ExprState
*state
, ExprEvalStep
*op
,
4410 ExprContext
*econtext
)
4412 AggStatePerTrans pertrans
= op
->d
.agg_trans
.pertrans
;
4413 int setno
= op
->d
.agg_trans
.setno
;
4415 tuplesort_putdatum(pertrans
->sortstates
[setno
],
4416 *op
->resvalue
, *op
->resnull
);
4420 * Invoke ordered transition function, with a tuple argument.
4423 ExecEvalAggOrderedTransTuple(ExprState
*state
, ExprEvalStep
*op
,
4424 ExprContext
*econtext
)
4426 AggStatePerTrans pertrans
= op
->d
.agg_trans
.pertrans
;
4427 int setno
= op
->d
.agg_trans
.setno
;
4429 ExecClearTuple(pertrans
->sortslot
);
4430 pertrans
->sortslot
->tts_nvalid
= pertrans
->numInputs
;
4431 ExecStoreVirtualTuple(pertrans
->sortslot
);
4432 tuplesort_puttupleslot(pertrans
->sortstates
[setno
], pertrans
->sortslot
);
4435 /* implementation of transition function invocation for byval types */
4436 static pg_attribute_always_inline
void
4437 ExecAggPlainTransByVal(AggState
*aggstate
, AggStatePerTrans pertrans
,
4438 AggStatePerGroup pergroup
,
4439 ExprContext
*aggcontext
, int setno
)
4441 FunctionCallInfo fcinfo
= pertrans
->transfn_fcinfo
;
4442 MemoryContext oldContext
;
4445 /* cf. select_current_set() */
4446 aggstate
->curaggcontext
= aggcontext
;
4447 aggstate
->current_set
= setno
;
4449 /* set up aggstate->curpertrans for AggGetAggref() */
4450 aggstate
->curpertrans
= pertrans
;
4452 /* invoke transition function in per-tuple context */
4453 oldContext
= MemoryContextSwitchTo(aggstate
->tmpcontext
->ecxt_per_tuple_memory
);
4455 fcinfo
->args
[0].value
= pergroup
->transValue
;
4456 fcinfo
->args
[0].isnull
= pergroup
->transValueIsNull
;
4457 fcinfo
->isnull
= false; /* just in case transfn doesn't set it */
4459 newVal
= FunctionCallInvoke(fcinfo
);
4461 pergroup
->transValue
= newVal
;
4462 pergroup
->transValueIsNull
= fcinfo
->isnull
;
4464 MemoryContextSwitchTo(oldContext
);
4467 /* implementation of transition function invocation for byref types */
4468 static pg_attribute_always_inline
void
4469 ExecAggPlainTransByRef(AggState
*aggstate
, AggStatePerTrans pertrans
,
4470 AggStatePerGroup pergroup
,
4471 ExprContext
*aggcontext
, int setno
)
4473 FunctionCallInfo fcinfo
= pertrans
->transfn_fcinfo
;
4474 MemoryContext oldContext
;
4477 /* cf. select_current_set() */
4478 aggstate
->curaggcontext
= aggcontext
;
4479 aggstate
->current_set
= setno
;
4481 /* set up aggstate->curpertrans for AggGetAggref() */
4482 aggstate
->curpertrans
= pertrans
;
4484 /* invoke transition function in per-tuple context */
4485 oldContext
= MemoryContextSwitchTo(aggstate
->tmpcontext
->ecxt_per_tuple_memory
);
4487 fcinfo
->args
[0].value
= pergroup
->transValue
;
4488 fcinfo
->args
[0].isnull
= pergroup
->transValueIsNull
;
4489 fcinfo
->isnull
= false; /* just in case transfn doesn't set it */
4491 newVal
= FunctionCallInvoke(fcinfo
);
4494 * For pass-by-ref datatype, must copy the new value into aggcontext and
4495 * free the prior transValue. But if transfn returned a pointer to its
4496 * first input, we don't need to do anything. Also, if transfn returned a
4497 * pointer to a R/W expanded object that is already a child of the
4498 * aggcontext, assume we can adopt that value without copying it.
4500 * It's safe to compare newVal with pergroup->transValue without regard
4501 * for either being NULL, because ExecAggTransReparent() takes care to set
4502 * transValue to 0 when NULL. Otherwise we could end up accidentally not
4503 * reparenting, when the transValue has the same numerical value as
4504 * newValue, despite being NULL. This is a somewhat hot path, making it
4505 * undesirable to instead solve this with another branch for the common
4506 * case of the transition function returning its (modified) input
4509 if (DatumGetPointer(newVal
) != DatumGetPointer(pergroup
->transValue
))
4510 newVal
= ExecAggTransReparent(aggstate
, pertrans
,
4511 newVal
, fcinfo
->isnull
,
4512 pergroup
->transValue
,
4513 pergroup
->transValueIsNull
);
4515 pergroup
->transValue
= newVal
;
4516 pergroup
->transValueIsNull
= fcinfo
->isnull
;
4518 MemoryContextSwitchTo(oldContext
);
4522 * Evaluate a JSON constructor expression.
4525 ExecEvalJsonConstructor(ExprState
*state
, ExprEvalStep
*op
,
4526 ExprContext
*econtext
)
4529 JsonConstructorExprState
*jcstate
= op
->d
.json_constructor
.jcstate
;
4530 JsonConstructorExpr
*ctor
= jcstate
->constructor
;
4531 bool is_jsonb
= ctor
->returning
->format
->format_type
== JS_FORMAT_JSONB
;
4532 bool isnull
= false;
4534 if (ctor
->type
== JSCTOR_JSON_ARRAY
)
4536 jsonb_build_array_worker
:
4537 json_build_array_worker
) (jcstate
->nargs
,
4538 jcstate
->arg_values
,
4541 ctor
->absent_on_null
);
4542 else if (ctor
->type
== JSCTOR_JSON_OBJECT
)
4544 jsonb_build_object_worker
:
4545 json_build_object_worker
) (jcstate
->nargs
,
4546 jcstate
->arg_values
,
4549 ctor
->absent_on_null
,
4551 else if (ctor
->type
== JSCTOR_JSON_SCALAR
)
4553 if (jcstate
->arg_nulls
[0])
4560 Datum value
= jcstate
->arg_values
[0];
4561 int category
= jcstate
->arg_type_cache
[0].category
;
4562 Oid outfuncid
= jcstate
->arg_type_cache
[0].outfuncid
;
4565 res
= to_jsonb_worker(value
, category
, outfuncid
);
4567 res
= to_json_worker(value
, category
, outfuncid
);
4570 else if (ctor
->type
== JSCTOR_JSON_PARSE
)
4572 if (jcstate
->arg_nulls
[0])
4579 Datum value
= jcstate
->arg_values
[0];
4580 text
*js
= DatumGetTextP(value
);
4583 res
= jsonb_from_text(js
, true);
4586 (void) json_validate(js
, true, true);
4594 elog(ERROR
, "invalid JsonConstructorExpr type %d", ctor
->type
);
4597 *op
->resvalue
= res
;
4598 *op
->resnull
= isnull
;
4602 * Evaluate a JSON error/empty behavior result.
4605 ExecEvalJsonBehavior(ExprContext
*econtext
, JsonBehavior
*behavior
,
4606 ExprState
*default_estate
, bool *is_null
)
4610 switch (behavior
->btype
)
4612 case JSON_BEHAVIOR_EMPTY_ARRAY
:
4613 return JsonbPGetDatum(JsonbMakeEmptyArray());
4615 case JSON_BEHAVIOR_EMPTY_OBJECT
:
4616 return JsonbPGetDatum(JsonbMakeEmptyObject());
4618 case JSON_BEHAVIOR_TRUE
:
4619 return BoolGetDatum(true);
4621 case JSON_BEHAVIOR_FALSE
:
4622 return BoolGetDatum(false);
4624 case JSON_BEHAVIOR_NULL
:
4625 case JSON_BEHAVIOR_UNKNOWN
:
4626 case JSON_BEHAVIOR_EMPTY
:
4630 case JSON_BEHAVIOR_DEFAULT
:
4631 return ExecEvalExpr(default_estate
, econtext
, is_null
);
4634 elog(ERROR
, "unrecognized SQL/JSON behavior %d", behavior
->btype
);
4640 * Evaluate a coercion of a JSON item to the target type.
4643 ExecEvalJsonExprCoercion(ExprEvalStep
*op
, ExprContext
*econtext
,
4644 Datum res
, bool *isNull
, void *p
, bool *error
)
4646 ExprState
*estate
= p
;
4647 JsonExprState
*jsestate
;
4649 if (estate
) /* coerce using specified expression */
4650 return ExecEvalExpr(estate
, econtext
, isNull
);
4652 jsestate
= op
->d
.jsonexpr
.jsestate
;
4654 if (jsestate
->jsexpr
->op
!= JSON_EXISTS_OP
)
4656 JsonCoercion
*coercion
= jsestate
->jsexpr
->result_coercion
;
4657 JsonExpr
*jexpr
= jsestate
->jsexpr
;
4658 Jsonb
*jb
= *isNull
? NULL
: DatumGetJsonbP(res
);
4660 if ((coercion
&& coercion
->via_io
) ||
4661 (jexpr
->omit_quotes
&& !*isNull
&&
4662 JB_ROOT_IS_SCALAR(jb
)))
4664 /* strip quotes and call typinput function */
4665 char *str
= *isNull
? NULL
: JsonbUnquote(jb
);
4667 return InputFunctionCall(&jsestate
->input
.func
, str
,
4668 jsestate
->input
.typioparam
,
4669 jexpr
->returning
->typmod
);
4671 else if (coercion
&& coercion
->via_populate
)
4672 return json_populate_type(res
, JSONBOID
,
4673 jexpr
->returning
->typid
,
4674 jexpr
->returning
->typmod
,
4676 econtext
->ecxt_per_query_memory
,
4680 if (jsestate
->result_expr
)
4682 jsestate
->res_expr
->value
= res
;
4683 jsestate
->res_expr
->isnull
= *isNull
;
4685 res
= ExecEvalExpr(jsestate
->result_expr
, econtext
, isNull
);
4692 * Evaluate a JSON path variable caching computed value.
4695 EvalJsonPathVar(void *cxt
, char *varName
, int varNameLen
,
4696 JsonbValue
*val
, JsonbValue
*baseObject
)
4698 JsonPathVariableEvalContext
*var
= NULL
;
4704 return list_length(vars
);
4710 if (!strncmp(var
->name
, varName
, varNameLen
))
4720 if (!var
->evaluated
)
4722 MemoryContext oldcxt
= var
->mcxt
?
4723 MemoryContextSwitchTo(var
->mcxt
) : NULL
;
4725 var
->value
= ExecEvalExpr(var
->estate
, var
->econtext
, &var
->isnull
);
4726 var
->evaluated
= true;
4729 MemoryContextSwitchTo(oldcxt
);
4734 val
->type
= jbvNull
;
4738 JsonItemFromDatum(var
->value
, var
->typid
, var
->typmod
, val
);
4745 * Prepare SQL/JSON item coercion to the output type. Returned a datum of the
4746 * corresponding SQL type and a pointer to the coercion state.
4749 ExecPrepareJsonItemCoercion(JsonbValue
*item
,
4750 JsonReturning
*returning
,
4751 struct JsonCoercionsState
*coercions
,
4752 struct JsonCoercionState
**pcoercion
)
4754 struct JsonCoercionState
*coercion
;
4758 if (item
->type
== jbvBinary
&&
4759 JsonContainerIsScalar(item
->val
.binary
.data
))
4761 bool res PG_USED_FOR_ASSERTS_ONLY
;
4763 res
= JsonbExtractScalar(item
->val
.binary
.data
, &buf
);
4768 /* get coercion state reference and datum of the corresponding SQL type */
4772 coercion
= &coercions
->null
;
4777 coercion
= &coercions
->string
;
4778 res
= PointerGetDatum(cstring_to_text_with_len(item
->val
.string
.val
,
4779 item
->val
.string
.len
));
4783 coercion
= &coercions
->numeric
;
4784 res
= NumericGetDatum(item
->val
.numeric
);
4788 coercion
= &coercions
->boolean
;
4789 res
= BoolGetDatum(item
->val
.boolean
);
4793 res
= item
->val
.datetime
.value
;
4794 switch (item
->val
.datetime
.typid
)
4797 coercion
= &coercions
->date
;
4800 coercion
= &coercions
->time
;
4803 coercion
= &coercions
->timetz
;
4806 coercion
= &coercions
->timestamp
;
4808 case TIMESTAMPTZOID
:
4809 coercion
= &coercions
->timestamptz
;
4812 elog(ERROR
, "unexpected jsonb datetime type oid %u",
4813 item
->val
.datetime
.typid
);
4821 coercion
= &coercions
->composite
;
4822 res
= JsonbPGetDatum(JsonbValueToJsonb(item
));
4826 elog(ERROR
, "unexpected jsonb value type %d", item
->type
);
4830 *pcoercion
= coercion
;
4835 typedef Datum (*JsonFunc
) (ExprEvalStep
*op
, ExprContext
*econtext
,
4836 Datum item
, bool *resnull
, void *p
, bool *error
);
4839 ExecEvalJsonExprSubtrans(JsonFunc func
, ExprEvalStep
*op
,
4840 ExprContext
*econtext
,
4841 Datum res
, bool *resnull
,
4842 void *p
, bool *error
, bool subtrans
)
4844 MemoryContext oldcontext
;
4845 ResourceOwner oldowner
;
4848 /* No need to use subtransactions. */
4849 return func(op
, econtext
, res
, resnull
, p
, error
);
4852 * We should catch exceptions of category ERRCODE_DATA_EXCEPTION and
4853 * execute the corresponding ON ERROR behavior then.
4855 oldcontext
= CurrentMemoryContext
;
4856 oldowner
= CurrentResourceOwner
;
4860 BeginInternalSubTransaction(NULL
);
4861 /* Want to execute expressions inside function's memory context */
4862 MemoryContextSwitchTo(oldcontext
);
4866 res
= func(op
, econtext
, res
, resnull
, p
, error
);
4868 /* Commit the inner transaction, return to outer xact context */
4869 ReleaseCurrentSubTransaction();
4870 MemoryContextSwitchTo(oldcontext
);
4871 CurrentResourceOwner
= oldowner
;
4878 /* Save error info in oldcontext */
4879 MemoryContextSwitchTo(oldcontext
);
4880 edata
= CopyErrorData();
4883 /* Abort the inner transaction */
4884 RollbackAndReleaseCurrentSubTransaction();
4885 MemoryContextSwitchTo(oldcontext
);
4886 CurrentResourceOwner
= oldowner
;
4888 ecategory
= ERRCODE_TO_CATEGORY(edata
->sqlerrcode
);
4890 if (ecategory
!= ERRCODE_DATA_EXCEPTION
&& /* jsonpath and other data
4892 ecategory
!= ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION
) /* domain errors */
4893 ReThrowError(edata
);
4908 bool coercionInSubtrans
;
4909 } ExecEvalJsonExprContext
;
4912 ExecEvalJsonExpr(ExprEvalStep
*op
, ExprContext
*econtext
,
4913 Datum item
, bool *resnull
, void *pcxt
,
4916 ExecEvalJsonExprContext
*cxt
= pcxt
;
4917 JsonPath
*path
= cxt
->path
;
4918 JsonExprState
*jsestate
= op
->d
.jsonexpr
.jsestate
;
4919 JsonExpr
*jexpr
= jsestate
->jsexpr
;
4920 ExprState
*estate
= NULL
;
4922 Datum res
= (Datum
) 0;
4927 res
= JsonPathQuery(item
, path
, jexpr
->wrapper
, &empty
, error
,
4929 if (error
&& *error
)
4934 *resnull
= !DatumGetPointer(res
);
4939 struct JsonCoercionState
*jcstate
;
4940 JsonbValue
*jbv
= JsonPathValue(item
, path
, &empty
, error
,
4943 if (error
&& *error
)
4946 if (!jbv
) /* NULL or empty */
4953 /* coerce scalar item to the output type */
4954 if (jexpr
->returning
->typid
== JSONOID
||
4955 jexpr
->returning
->typid
== JSONBOID
)
4957 /* Use result coercion from json[b] to the output type */
4958 res
= JsonbPGetDatum(JsonbValueToJsonb(jbv
));
4962 /* Use coercion from SQL/JSON item type to the output type */
4963 res
= ExecPrepareJsonItemCoercion(jbv
,
4964 jsestate
->jsexpr
->returning
,
4965 &jsestate
->coercions
,
4968 if (jcstate
->coercion
&&
4969 (jcstate
->coercion
->via_io
||
4970 jcstate
->coercion
->via_populate
))
4979 * Coercion via I/O means here that the cast to the target
4980 * type simply does not exist.
4985 * XXX Standard says about a separate error code
4986 * ERRCODE_SQL_JSON_ITEM_CANNOT_BE_CAST_TO_TARGET_TYPE but
4987 * does not define its number.
4989 (errcode(ERRCODE_SQL_JSON_SCALAR_REQUIRED
),
4990 errmsg("SQL/JSON item cannot be cast to target type")));
4992 else if (!jcstate
->estate
)
4993 return res
; /* no coercion */
4995 /* coerce using specific expression */
4996 estate
= jcstate
->estate
;
4997 jsestate
->coercion_expr
->value
= res
;
4998 jsestate
->coercion_expr
->isnull
= *resnull
;
5002 case JSON_EXISTS_OP
:
5004 bool exists
= JsonPathExists(item
, path
,
5008 *resnull
= error
&& *error
;
5009 res
= BoolGetDatum(exists
);
5011 if (!jsestate
->result_expr
)
5014 /* coerce using result expression */
5015 estate
= jsestate
->result_expr
;
5016 jsestate
->res_expr
->value
= res
;
5017 jsestate
->res_expr
->isnull
= *resnull
;
5026 elog(ERROR
, "unrecognized SQL/JSON expression op %d", jexpr
->op
);
5032 Assert(jexpr
->on_empty
); /* it is not JSON_EXISTS */
5034 if (jexpr
->on_empty
->btype
== JSON_BEHAVIOR_ERROR
)
5043 (errcode(ERRCODE_NO_SQL_JSON_ITEM
),
5044 errmsg("no SQL/JSON item")));
5047 if (jexpr
->on_empty
->btype
== JSON_BEHAVIOR_DEFAULT
)
5050 * Execute DEFAULT expression as a coercion expression, because
5051 * its result is already coerced to the target type.
5053 estate
= jsestate
->default_on_empty
;
5055 /* Execute ON EMPTY behavior */
5056 res
= ExecEvalJsonBehavior(econtext
, jexpr
->on_empty
,
5057 jsestate
->default_on_empty
,
5061 return ExecEvalJsonExprSubtrans(ExecEvalJsonExprCoercion
, op
, econtext
,
5062 res
, resnull
, estate
, error
,
5063 cxt
->coercionInSubtrans
);
5067 ExecEvalJsonNeedsSubTransaction(JsonExpr
*jsexpr
,
5068 struct JsonCoercionsState
*coercions
)
5070 if (jsexpr
->on_error
->btype
== JSON_BEHAVIOR_ERROR
)
5073 if (jsexpr
->op
== JSON_EXISTS_OP
&& !jsexpr
->result_coercion
)
5082 /* ----------------------------------------------------------------
5084 * ----------------------------------------------------------------
5087 ExecEvalJson(ExprState
*state
, ExprEvalStep
*op
, ExprContext
*econtext
)
5089 ExecEvalJsonExprContext cxt
;
5090 JsonExprState
*jsestate
= op
->d
.jsonexpr
.jsestate
;
5091 JsonExpr
*jexpr
= jsestate
->jsexpr
;
5093 Datum res
= (Datum
) 0;
5098 bool throwErrors
= jexpr
->on_error
->btype
== JSON_BEHAVIOR_ERROR
;
5100 *op
->resnull
= true; /* until we get a result */
5101 *op
->resvalue
= (Datum
) 0;
5103 if (jsestate
->formatted_expr
->isnull
|| jsestate
->pathspec
->isnull
)
5105 /* execute domain checks for NULLs */
5106 (void) ExecEvalJsonExprCoercion(op
, econtext
, res
, op
->resnull
,
5109 Assert(*op
->resnull
);
5113 item
= jsestate
->formatted_expr
->value
;
5114 path
= DatumGetJsonPathP(jsestate
->pathspec
->value
);
5116 /* reset JSON path variable contexts */
5117 foreach(lc
, jsestate
->args
)
5119 JsonPathVariableEvalContext
*var
= lfirst(lc
);
5121 var
->econtext
= econtext
;
5122 var
->evaluated
= false;
5125 needSubtrans
= ExecEvalJsonNeedsSubTransaction(jexpr
, &jsestate
->coercions
);
5128 cxt
.error
= throwErrors
? NULL
: &error
;
5129 cxt
.coercionInSubtrans
= !needSubtrans
&& !throwErrors
;
5130 Assert(!needSubtrans
|| cxt
.error
);
5132 res
= ExecEvalJsonExprSubtrans(ExecEvalJsonExpr
, op
, econtext
, item
,
5133 op
->resnull
, &cxt
, cxt
.error
,
5138 /* Execute ON ERROR behavior */
5139 res
= ExecEvalJsonBehavior(econtext
, jexpr
->on_error
,
5140 jsestate
->default_on_error
,
5143 /* result is already coerced in DEFAULT behavior case */
5144 if (jexpr
->on_error
->btype
!= JSON_BEHAVIOR_DEFAULT
)
5145 res
= ExecEvalJsonExprCoercion(op
, econtext
, res
,
5150 *op
->resvalue
= res
;