1 /*-------------------------------------------------------------------------
2 *
3 * execExprInterp.c
4 * Interpreted evaluation of an expression step list.
5 *
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.
12 *
13 * In either case we use ExprEvalStep->opcode to dispatch to the code block
14 * within ExecInterpExpr() that implements the specific opcode type.
15 *
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.
22 *
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).
29 *
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
33 * that's been done.
34 *
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 simple scalar Var
38 * and Const expressions using special fast-path routines (ExecJust*).
39 * Benchmarking shows anything more complex than those may as well use the
40 * "full interpreter".
41 *
42 * Complex or uncommon instructions are not implemented in-line in
43 * ExecInterpExpr(), rather we call out to a helper function appearing later
44 * in this file. For one reason, there'd not be a noticeable performance
45 * benefit, but more importantly those complex routines are intended to be
46 * shared between different expression evaluation approaches. For instance
47 * a JIT compiler would generate calls to them. (This is why they are
48 * exported rather than being "static" in this file.)
49 *
50 *
51 * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
52 * Portions Copyright (c) 1994, Regents of the University of California
53 *
54 * IDENTIFICATION
55 * src/backend/executor/execExprInterp.c
56 *
57 *-------------------------------------------------------------------------
58 */
59 #include "postgres.h"
60
61 #include "access/tuptoaster.h"
62 #include "catalog/pg_type.h"
63 #include "commands/sequence.h"
64 #include "executor/execExpr.h"
65 #include "executor/nodeSubplan.h"
66 #include "funcapi.h"
67 #include "miscadmin.h"
68 #include "nodes/nodeFuncs.h"
69 #include "parser/parsetree.h"
70 #include "pgstat.h"
71 #include "utils/builtins.h"
72 #include "utils/date.h"
73 #include "utils/lsyscache.h"
74 #include "utils/timestamp.h"
75 #include "utils/typcache.h"
76 #include "utils/xml.h"
77
78
79 /*
80 * Use computed-goto-based opcode dispatch when computed gotos are available.
81 * But use a separate symbol so that it's easy to adjust locally in this file
82 * for development and testing.
83 */
84 #ifdef HAVE_COMPUTED_GOTO
85 #define EEO_USE_COMPUTED_GOTO
86 #endif /* HAVE_COMPUTED_GOTO */
87
88 /*
89 * Macros for opcode dispatch.
90 *
91 * EEO_SWITCH - just hides the switch if not in use.
92 * EEO_CASE - labels the implementation of named expression step type.
93 * EEO_DISPATCH - jump to the implementation of the step type for 'op'.
94 * EEO_OPCODE - compute opcode required by used expression evaluation method.
95 * EEO_NEXT - increment 'op' and jump to correct next step type.
96 * EEO_JUMP - jump to the specified step number within the current expression.
97 */
98 #if defined(EEO_USE_COMPUTED_GOTO)
99
100 /* to make dispatch_table accessible outside ExecInterpExpr() */
101 static const void **dispatch_table = NULL;
102
103 #define EEO_SWITCH()
104 #define EEO_CASE(name) CASE_##name:
105 #define EEO_DISPATCH() goto *((void *) op->opcode)
106 #define EEO_OPCODE(opcode) ((intptr_t) dispatch_table[opcode])
107
108 #else /* !EEO_USE_COMPUTED_GOTO */
109
110 #define EEO_SWITCH() starteval: switch ((ExprEvalOp) op->opcode)
111 #define EEO_CASE(name) case name:
112 #define EEO_DISPATCH() goto starteval
113 #define EEO_OPCODE(opcode) (opcode)
114
115 #endif /* EEO_USE_COMPUTED_GOTO */
116
117 #define EEO_NEXT() \
118 do { \
119 op++; \
120 EEO_DISPATCH(); \
121 } while (0)
122
123 #define EEO_JUMP(stepno) \
124 do { \
125 op = &state->steps[stepno]; \
126 EEO_DISPATCH(); \
127 } while (0)
128
129
130 static Datum ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull);
131 static void ExecInitInterpreter(void);
132
133 /* support functions */
134 static void CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype);
135 static TupleDesc get_cached_rowtype(Oid type_id, int32 typmod,
136 TupleDesc *cache_field, ExprContext *econtext);
137 static void ShutdownTupleDescRef(Datum arg);
138 static void ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op,
139 ExprContext *econtext, bool checkisnull);
140
141 /* fast-path evaluation functions */
142 static Datum ExecJustInnerVarFirst(ExprState *state, ExprContext *econtext, bool *isnull);
143 static Datum ExecJustInnerVar(ExprState *state, ExprContext *econtext, bool *isnull);
144 static Datum ExecJustOuterVarFirst(ExprState *state, ExprContext *econtext, bool *isnull);
145 static Datum ExecJustOuterVar(ExprState *state, ExprContext *econtext, bool *isnull);
146 static Datum ExecJustScanVarFirst(ExprState *state, ExprContext *econtext, bool *isnull);
147 static Datum ExecJustScanVar(ExprState *state, ExprContext *econtext, bool *isnull);
148 static Datum ExecJustConst(ExprState *state, ExprContext *econtext, bool *isnull);
149 static Datum ExecJustAssignInnerVar(ExprState *state, ExprContext *econtext, bool *isnull);
150 static Datum ExecJustAssignOuterVar(ExprState *state, ExprContext *econtext, bool *isnull);
151 static Datum ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool *isnull);
152
153
154 /*
155 * Prepare ExprState for interpreted execution.
156 */
157 void
ExecReadyInterpretedExpr(ExprState * state)158 ExecReadyInterpretedExpr(ExprState *state)
159 {
160 /* Ensure one-time interpreter setup has been done */
161 ExecInitInterpreter();
162
163 /* Simple validity checks on expression */
164 Assert(state->steps_len >= 1);
165 Assert(state->steps[state->steps_len - 1].opcode == EEOP_DONE);
166
167 /*
168 * Don't perform redundant initialization. This is unreachable in current
169 * cases, but might be hit if there's additional expression evaluation
170 * methods that rely on interpreted execution to work.
171 */
172 if (state->flags & EEO_FLAG_INTERPRETER_INITIALIZED)
173 return;
174
175 /* DIRECT_THREADED should not already be set */
176 Assert((state->flags & EEO_FLAG_DIRECT_THREADED) == 0);
177
178 /*
179 * There shouldn't be any errors before the expression is fully
180 * initialized, and even if so, it'd lead to the expression being
181 * abandoned. So we can set the flag now and save some code.
182 */
183 state->flags |= EEO_FLAG_INTERPRETER_INITIALIZED;
184
185 /*
186 * Select fast-path evalfuncs for very simple expressions. "Starting up"
187 * the full interpreter is a measurable overhead for these. Plain Vars
188 * and Const seem to be the only ones where the intrinsic cost is small
189 * enough that the overhead of ExecInterpExpr matters. For more complex
190 * expressions it's cheaper to use ExecInterpExpr always.
191 */
192 if (state->steps_len == 3)
193 {
194 ExprEvalOp step0 = state->steps[0].opcode;
195 ExprEvalOp step1 = state->steps[1].opcode;
196
197 if (step0 == EEOP_INNER_FETCHSOME &&
198 step1 == EEOP_INNER_VAR_FIRST)
199 {
200 state->evalfunc = ExecJustInnerVarFirst;
201 return;
202 }
203 else if (step0 == EEOP_OUTER_FETCHSOME &&
204 step1 == EEOP_OUTER_VAR_FIRST)
205 {
206 state->evalfunc = ExecJustOuterVarFirst;
207 return;
208 }
209 else if (step0 == EEOP_SCAN_FETCHSOME &&
210 step1 == EEOP_SCAN_VAR_FIRST)
211 {
212 state->evalfunc = ExecJustScanVarFirst;
213 return;
214 }
215 else if (step0 == EEOP_INNER_FETCHSOME &&
216 step1 == EEOP_ASSIGN_INNER_VAR)
217 {
218 state->evalfunc = ExecJustAssignInnerVar;
219 return;
220 }
221 else if (step0 == EEOP_OUTER_FETCHSOME &&
222 step1 == EEOP_ASSIGN_OUTER_VAR)
223 {
224 state->evalfunc = ExecJustAssignOuterVar;
225 return;
226 }
227 else if (step0 == EEOP_SCAN_FETCHSOME &&
228 step1 == EEOP_ASSIGN_SCAN_VAR)
229 {
230 state->evalfunc = ExecJustAssignScanVar;
231 return;
232 }
233 }
234 else if (state->steps_len == 2 &&
235 state->steps[0].opcode == EEOP_CONST)
236 {
237 state->evalfunc = ExecJustConst;
238 return;
239 }
240
241 #if defined(EEO_USE_COMPUTED_GOTO)
242
243 /*
244 * In the direct-threaded implementation, replace each opcode with the
245 * address to jump to. (Use ExecEvalStepOp() to get back the opcode.)
246 */
247 {
248 int off;
249
250 for (off = 0; off < state->steps_len; off++)
251 {
252 ExprEvalStep *op = &state->steps[off];
253
254 op->opcode = EEO_OPCODE(op->opcode);
255 }
256
257 state->flags |= EEO_FLAG_DIRECT_THREADED;
258 }
259 #endif /* EEO_USE_COMPUTED_GOTO */
260
261 state->evalfunc = ExecInterpExpr;
262 }
263
264
265 /*
266 * Evaluate expression identified by "state" in the execution context
267 * given by "econtext". *isnull is set to the is-null flag for the result,
268 * and the Datum value is the function result.
269 *
270 * As a special case, return the dispatch table's address if state is NULL.
271 * This is used by ExecInitInterpreter to set up the dispatch_table global.
272 * (Only applies when EEO_USE_COMPUTED_GOTO is defined.)
273 */
274 static Datum
ExecInterpExpr(ExprState * state,ExprContext * econtext,bool * isnull)275 ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
276 {
277 ExprEvalStep *op;
278 TupleTableSlot *resultslot;
279 TupleTableSlot *innerslot;
280 TupleTableSlot *outerslot;
281 TupleTableSlot *scanslot;
282
283 /*
284 * This array has to be in the same order as enum ExprEvalOp.
285 */
286 #if defined(EEO_USE_COMPUTED_GOTO)
287 static const void *const dispatch_table[] = {
288 &&CASE_EEOP_DONE,
289 &&CASE_EEOP_INNER_FETCHSOME,
290 &&CASE_EEOP_OUTER_FETCHSOME,
291 &&CASE_EEOP_SCAN_FETCHSOME,
292 &&CASE_EEOP_INNER_VAR_FIRST,
293 &&CASE_EEOP_INNER_VAR,
294 &&CASE_EEOP_OUTER_VAR_FIRST,
295 &&CASE_EEOP_OUTER_VAR,
296 &&CASE_EEOP_SCAN_VAR_FIRST,
297 &&CASE_EEOP_SCAN_VAR,
298 &&CASE_EEOP_INNER_SYSVAR,
299 &&CASE_EEOP_OUTER_SYSVAR,
300 &&CASE_EEOP_SCAN_SYSVAR,
301 &&CASE_EEOP_WHOLEROW,
302 &&CASE_EEOP_ASSIGN_INNER_VAR,
303 &&CASE_EEOP_ASSIGN_OUTER_VAR,
304 &&CASE_EEOP_ASSIGN_SCAN_VAR,
305 &&CASE_EEOP_ASSIGN_TMP,
306 &&CASE_EEOP_ASSIGN_TMP_MAKE_RO,
307 &&CASE_EEOP_CONST,
308 &&CASE_EEOP_FUNCEXPR,
309 &&CASE_EEOP_FUNCEXPR_STRICT,
310 &&CASE_EEOP_FUNCEXPR_FUSAGE,
311 &&CASE_EEOP_FUNCEXPR_STRICT_FUSAGE,
312 &&CASE_EEOP_BOOL_AND_STEP_FIRST,
313 &&CASE_EEOP_BOOL_AND_STEP,
314 &&CASE_EEOP_BOOL_AND_STEP_LAST,
315 &&CASE_EEOP_BOOL_OR_STEP_FIRST,
316 &&CASE_EEOP_BOOL_OR_STEP,
317 &&CASE_EEOP_BOOL_OR_STEP_LAST,
318 &&CASE_EEOP_BOOL_NOT_STEP,
319 &&CASE_EEOP_QUAL,
320 &&CASE_EEOP_JUMP,
321 &&CASE_EEOP_JUMP_IF_NULL,
322 &&CASE_EEOP_JUMP_IF_NOT_NULL,
323 &&CASE_EEOP_JUMP_IF_NOT_TRUE,
324 &&CASE_EEOP_NULLTEST_ISNULL,
325 &&CASE_EEOP_NULLTEST_ISNOTNULL,
326 &&CASE_EEOP_NULLTEST_ROWISNULL,
327 &&CASE_EEOP_NULLTEST_ROWISNOTNULL,
328 &&CASE_EEOP_BOOLTEST_IS_TRUE,
329 &&CASE_EEOP_BOOLTEST_IS_NOT_TRUE,
330 &&CASE_EEOP_BOOLTEST_IS_FALSE,
331 &&CASE_EEOP_BOOLTEST_IS_NOT_FALSE,
332 &&CASE_EEOP_PARAM_EXEC,
333 &&CASE_EEOP_PARAM_EXTERN,
334 &&CASE_EEOP_CASE_TESTVAL,
335 &&CASE_EEOP_MAKE_READONLY,
336 &&CASE_EEOP_IOCOERCE,
337 &&CASE_EEOP_DISTINCT,
338 &&CASE_EEOP_NULLIF,
339 &&CASE_EEOP_SQLVALUEFUNCTION,
340 &&CASE_EEOP_CURRENTOFEXPR,
341 &&CASE_EEOP_NEXTVALUEEXPR,
342 &&CASE_EEOP_ARRAYEXPR,
343 &&CASE_EEOP_ARRAYCOERCE,
344 &&CASE_EEOP_ROW,
345 &&CASE_EEOP_ROWCOMPARE_STEP,
346 &&CASE_EEOP_ROWCOMPARE_FINAL,
347 &&CASE_EEOP_MINMAX,
348 &&CASE_EEOP_FIELDSELECT,
349 &&CASE_EEOP_FIELDSTORE_DEFORM,
350 &&CASE_EEOP_FIELDSTORE_FORM,
351 &&CASE_EEOP_ARRAYREF_SUBSCRIPT,
352 &&CASE_EEOP_ARRAYREF_OLD,
353 &&CASE_EEOP_ARRAYREF_ASSIGN,
354 &&CASE_EEOP_ARRAYREF_FETCH,
355 &&CASE_EEOP_DOMAIN_TESTVAL,
356 &&CASE_EEOP_DOMAIN_NOTNULL,
357 &&CASE_EEOP_DOMAIN_CHECK,
358 &&CASE_EEOP_CONVERT_ROWTYPE,
359 &&CASE_EEOP_SCALARARRAYOP,
360 &&CASE_EEOP_XMLEXPR,
361 &&CASE_EEOP_AGGREF,
362 &&CASE_EEOP_GROUPING_FUNC,
363 &&CASE_EEOP_WINDOW_FUNC,
364 &&CASE_EEOP_SUBPLAN,
365 &&CASE_EEOP_ALTERNATIVE_SUBPLAN,
366 &&CASE_EEOP_LAST
367 };
368
369 StaticAssertStmt(EEOP_LAST + 1 == lengthof(dispatch_table),
370 "dispatch_table out of whack with ExprEvalOp");
371
372 if (unlikely(state == NULL))
373 return PointerGetDatum(dispatch_table);
374 #else
375 Assert(state != NULL);
376 #endif /* EEO_USE_COMPUTED_GOTO */
377
378 /* setup state */
379 op = state->steps;
380 resultslot = state->resultslot;
381 innerslot = econtext->ecxt_innertuple;
382 outerslot = econtext->ecxt_outertuple;
383 scanslot = econtext->ecxt_scantuple;
384
385 #if defined(EEO_USE_COMPUTED_GOTO)
386 EEO_DISPATCH();
387 #endif
388
389 EEO_SWITCH()
390 {
391 EEO_CASE(EEOP_DONE)
392 {
393 goto out;
394 }
395
396 EEO_CASE(EEOP_INNER_FETCHSOME)
397 {
398 /* XXX: worthwhile to check tts_nvalid inline first? */
399 slot_getsomeattrs(innerslot, op->d.fetch.last_var);
400
401 EEO_NEXT();
402 }
403
404 EEO_CASE(EEOP_OUTER_FETCHSOME)
405 {
406 slot_getsomeattrs(outerslot, op->d.fetch.last_var);
407
408 EEO_NEXT();
409 }
410
411 EEO_CASE(EEOP_SCAN_FETCHSOME)
412 {
413 slot_getsomeattrs(scanslot, op->d.fetch.last_var);
414
415 EEO_NEXT();
416 }
417
418 EEO_CASE(EEOP_INNER_VAR_FIRST)
419 {
420 int attnum = op->d.var.attnum;
421
422 /*
423 * First time through, check whether attribute matches Var. Might
424 * not be ok anymore, due to schema changes.
425 */
426 CheckVarSlotCompatibility(innerslot, attnum + 1, op->d.var.vartype);
427
428 /* Skip that check on subsequent evaluations */
429 op->opcode = EEO_OPCODE(EEOP_INNER_VAR);
430
431 /* FALL THROUGH to EEOP_INNER_VAR */
432 }
433
434 EEO_CASE(EEOP_INNER_VAR)
435 {
436 int attnum = op->d.var.attnum;
437
438 /*
439 * Since we already extracted all referenced columns from the
440 * tuple with a FETCHSOME step, we can just grab the value
441 * directly out of the slot's decomposed-data arrays. But let's
442 * have an Assert to check that that did happen.
443 */
444 Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
445 *op->resvalue = innerslot->tts_values[attnum];
446 *op->resnull = innerslot->tts_isnull[attnum];
447
448 EEO_NEXT();
449 }
450
451 EEO_CASE(EEOP_OUTER_VAR_FIRST)
452 {
453 int attnum = op->d.var.attnum;
454
455 /* See EEOP_INNER_VAR_FIRST comments */
456
457 CheckVarSlotCompatibility(outerslot, attnum + 1, op->d.var.vartype);
458 op->opcode = EEO_OPCODE(EEOP_OUTER_VAR);
459
460 /* FALL THROUGH to EEOP_OUTER_VAR */
461 }
462
463 EEO_CASE(EEOP_OUTER_VAR)
464 {
465 int attnum = op->d.var.attnum;
466
467 /* See EEOP_INNER_VAR comments */
468
469 Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
470 *op->resvalue = outerslot->tts_values[attnum];
471 *op->resnull = outerslot->tts_isnull[attnum];
472
473 EEO_NEXT();
474 }
475
476 EEO_CASE(EEOP_SCAN_VAR_FIRST)
477 {
478 int attnum = op->d.var.attnum;
479
480 /* See EEOP_INNER_VAR_FIRST comments */
481
482 CheckVarSlotCompatibility(scanslot, attnum + 1, op->d.var.vartype);
483 op->opcode = EEO_OPCODE(EEOP_SCAN_VAR);
484
485 /* FALL THROUGH to EEOP_SCAN_VAR */
486 }
487
488 EEO_CASE(EEOP_SCAN_VAR)
489 {
490 int attnum = op->d.var.attnum;
491
492 /* See EEOP_INNER_VAR comments */
493
494 Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
495 *op->resvalue = scanslot->tts_values[attnum];
496 *op->resnull = scanslot->tts_isnull[attnum];
497
498 EEO_NEXT();
499 }
500
501 EEO_CASE(EEOP_INNER_SYSVAR)
502 {
503 int attnum = op->d.var.attnum;
504
505 /* these asserts must match defenses in slot_getattr */
506 Assert(innerslot->tts_tuple != NULL);
507 Assert(innerslot->tts_tuple != &(innerslot->tts_minhdr));
508 /* heap_getsysattr has sufficient defenses against bad attnums */
509
510 *op->resvalue = heap_getsysattr(innerslot->tts_tuple, attnum,
511 innerslot->tts_tupleDescriptor,
512 op->resnull);
513
514 EEO_NEXT();
515 }
516
517 EEO_CASE(EEOP_OUTER_SYSVAR)
518 {
519 int attnum = op->d.var.attnum;
520
521 /* these asserts must match defenses in slot_getattr */
522 Assert(outerslot->tts_tuple != NULL);
523 Assert(outerslot->tts_tuple != &(outerslot->tts_minhdr));
524
525 /* heap_getsysattr has sufficient defenses against bad attnums */
526 *op->resvalue = heap_getsysattr(outerslot->tts_tuple, attnum,
527 outerslot->tts_tupleDescriptor,
528 op->resnull);
529
530 EEO_NEXT();
531 }
532
533 EEO_CASE(EEOP_SCAN_SYSVAR)
534 {
535 int attnum = op->d.var.attnum;
536
537 /* these asserts must match defenses in slot_getattr */
538 Assert(scanslot->tts_tuple != NULL);
539 Assert(scanslot->tts_tuple != &(scanslot->tts_minhdr));
540 /* heap_getsysattr has sufficient defenses against bad attnums */
541
542 *op->resvalue = heap_getsysattr(scanslot->tts_tuple, attnum,
543 scanslot->tts_tupleDescriptor,
544 op->resnull);
545
546 EEO_NEXT();
547 }
548
549 EEO_CASE(EEOP_WHOLEROW)
550 {
551 /* too complex for an inline implementation */
552 ExecEvalWholeRowVar(state, op, econtext);
553
554 EEO_NEXT();
555 }
556
557 EEO_CASE(EEOP_ASSIGN_INNER_VAR)
558 {
559 int resultnum = op->d.assign_var.resultnum;
560 int attnum = op->d.assign_var.attnum;
561
562 /*
563 * We do not need CheckVarSlotCompatibility here; that was taken
564 * care of at compilation time. But see EEOP_INNER_VAR comments.
565 */
566 Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
567 Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
568 resultslot->tts_values[resultnum] = innerslot->tts_values[attnum];
569 resultslot->tts_isnull[resultnum] = innerslot->tts_isnull[attnum];
570
571 EEO_NEXT();
572 }
573
574 EEO_CASE(EEOP_ASSIGN_OUTER_VAR)
575 {
576 int resultnum = op->d.assign_var.resultnum;
577 int attnum = op->d.assign_var.attnum;
578
579 /*
580 * We do not need CheckVarSlotCompatibility here; that was taken
581 * care of at compilation time. But see EEOP_INNER_VAR comments.
582 */
583 Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
584 Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
585 resultslot->tts_values[resultnum] = outerslot->tts_values[attnum];
586 resultslot->tts_isnull[resultnum] = outerslot->tts_isnull[attnum];
587
588 EEO_NEXT();
589 }
590
591 EEO_CASE(EEOP_ASSIGN_SCAN_VAR)
592 {
593 int resultnum = op->d.assign_var.resultnum;
594 int attnum = op->d.assign_var.attnum;
595
596 /*
597 * We do not need CheckVarSlotCompatibility here; that was taken
598 * care of at compilation time. But see EEOP_INNER_VAR comments.
599 */
600 Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
601 Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
602 resultslot->tts_values[resultnum] = scanslot->tts_values[attnum];
603 resultslot->tts_isnull[resultnum] = scanslot->tts_isnull[attnum];
604
605 EEO_NEXT();
606 }
607
608 EEO_CASE(EEOP_ASSIGN_TMP)
609 {
610 int resultnum = op->d.assign_tmp.resultnum;
611
612 Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
613 resultslot->tts_values[resultnum] = state->resvalue;
614 resultslot->tts_isnull[resultnum] = state->resnull;
615
616 EEO_NEXT();
617 }
618
619 EEO_CASE(EEOP_ASSIGN_TMP_MAKE_RO)
620 {
621 int resultnum = op->d.assign_tmp.resultnum;
622
623 Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
624 resultslot->tts_isnull[resultnum] = state->resnull;
625 if (!resultslot->tts_isnull[resultnum])
626 resultslot->tts_values[resultnum] =
627 MakeExpandedObjectReadOnlyInternal(state->resvalue);
628 else
629 resultslot->tts_values[resultnum] = state->resvalue;
630
631 EEO_NEXT();
632 }
633
634 EEO_CASE(EEOP_CONST)
635 {
636 *op->resnull = op->d.constval.isnull;
637 *op->resvalue = op->d.constval.value;
638
639 EEO_NEXT();
640 }
641
642 /*
643 * Function-call implementations. Arguments have previously been
644 * evaluated directly into fcinfo->args.
645 *
646 * As both STRICT checks and function-usage are noticeable performance
647 * wise, and function calls are a very hot-path (they also back
648 * operators!), it's worth having so many separate opcodes.
649 */
650 EEO_CASE(EEOP_FUNCEXPR)
651 {
652 FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
653
654 fcinfo->isnull = false;
655 *op->resvalue = (op->d.func.fn_addr) (fcinfo);
656 *op->resnull = fcinfo->isnull;
657
658 EEO_NEXT();
659 }
660
661 EEO_CASE(EEOP_FUNCEXPR_STRICT)
662 {
663 FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
664 bool *argnull = fcinfo->argnull;
665 int argno;
666
667 /* strict function, so check for NULL args */
668 for (argno = 0; argno < op->d.func.nargs; argno++)
669 {
670 if (argnull[argno])
671 {
672 *op->resnull = true;
673 goto strictfail;
674 }
675 }
676 fcinfo->isnull = false;
677 *op->resvalue = (op->d.func.fn_addr) (fcinfo);
678 *op->resnull = fcinfo->isnull;
679
680 strictfail:
681 EEO_NEXT();
682 }
683
684 EEO_CASE(EEOP_FUNCEXPR_FUSAGE)
685 {
686 FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
687 PgStat_FunctionCallUsage fcusage;
688
689 pgstat_init_function_usage(fcinfo, &fcusage);
690
691 fcinfo->isnull = false;
692 *op->resvalue = (op->d.func.fn_addr) (fcinfo);
693 *op->resnull = fcinfo->isnull;
694
695 pgstat_end_function_usage(&fcusage, true);
696
697 EEO_NEXT();
698 }
699
700 EEO_CASE(EEOP_FUNCEXPR_STRICT_FUSAGE)
701 {
702 FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
703 PgStat_FunctionCallUsage fcusage;
704 bool *argnull = fcinfo->argnull;
705 int argno;
706
707 /* strict function, so check for NULL args */
708 for (argno = 0; argno < op->d.func.nargs; argno++)
709 {
710 if (argnull[argno])
711 {
712 *op->resnull = true;
713 goto strictfail_fusage;
714 }
715 }
716
717 pgstat_init_function_usage(fcinfo, &fcusage);
718
719 fcinfo->isnull = false;
720 *op->resvalue = (op->d.func.fn_addr) (fcinfo);
721 *op->resnull = fcinfo->isnull;
722
723 pgstat_end_function_usage(&fcusage, true);
724
725 strictfail_fusage:
726 EEO_NEXT();
727 }
728
729 /*
730 * If any of its clauses is FALSE, an AND's result is FALSE regardless
731 * of the states of the rest of the clauses, so we can stop evaluating
732 * and return FALSE immediately. If none are FALSE and one or more is
733 * NULL, we return NULL; otherwise we return TRUE. This makes sense
734 * when you interpret NULL as "don't know": perhaps one of the "don't
735 * knows" would have been FALSE if we'd known its value. Only when
736 * all the inputs are known to be TRUE can we state confidently that
737 * the AND's result is TRUE.
738 */
739 EEO_CASE(EEOP_BOOL_AND_STEP_FIRST)
740 {
741 *op->d.boolexpr.anynull = false;
742
743 /*
744 * EEOP_BOOL_AND_STEP_FIRST resets anynull, otherwise it's the
745 * same as EEOP_BOOL_AND_STEP - so fall through to that.
746 */
747
748 /* FALL THROUGH */
749 }
750
751 EEO_CASE(EEOP_BOOL_AND_STEP)
752 {
753 if (*op->resnull)
754 {
755 *op->d.boolexpr.anynull = true;
756 }
757 else if (!DatumGetBool(*op->resvalue))
758 {
759 /* result is already set to FALSE, need not change it */
760 /* bail out early */
761 EEO_JUMP(op->d.boolexpr.jumpdone);
762 }
763
764 EEO_NEXT();
765 }
766
767 EEO_CASE(EEOP_BOOL_AND_STEP_LAST)
768 {
769 if (*op->resnull)
770 {
771 /* result is already set to NULL, need not change it */
772 }
773 else if (!DatumGetBool(*op->resvalue))
774 {
775 /* result is already set to FALSE, need not change it */
776
777 /*
778 * No point jumping early to jumpdone - would be same target
779 * (as this is the last argument to the AND expression),
780 * except more expensive.
781 */
782 }
783 else if (*op->d.boolexpr.anynull)
784 {
785 *op->resvalue = (Datum) 0;
786 *op->resnull = true;
787 }
788 else
789 {
790 /* result is already set to TRUE, need not change it */
791 }
792
793 EEO_NEXT();
794 }
795
796 /*
797 * If any of its clauses is TRUE, an OR's result is TRUE regardless of
798 * the states of the rest of the clauses, so we can stop evaluating
799 * and return TRUE immediately. If none are TRUE and one or more is
800 * NULL, we return NULL; otherwise we return FALSE. This makes sense
801 * when you interpret NULL as "don't know": perhaps one of the "don't
802 * knows" would have been TRUE if we'd known its value. Only when all
803 * the inputs are known to be FALSE can we state confidently that the
804 * OR's result is FALSE.
805 */
806 EEO_CASE(EEOP_BOOL_OR_STEP_FIRST)
807 {
808 *op->d.boolexpr.anynull = false;
809
810 /*
811 * EEOP_BOOL_OR_STEP_FIRST resets anynull, otherwise it's the same
812 * as EEOP_BOOL_OR_STEP - so fall through to that.
813 */
814
815 /* FALL THROUGH */
816 }
817
818 EEO_CASE(EEOP_BOOL_OR_STEP)
819 {
820 if (*op->resnull)
821 {
822 *op->d.boolexpr.anynull = true;
823 }
824 else if (DatumGetBool(*op->resvalue))
825 {
826 /* result is already set to TRUE, need not change it */
827 /* bail out early */
828 EEO_JUMP(op->d.boolexpr.jumpdone);
829 }
830
831 EEO_NEXT();
832 }
833
834 EEO_CASE(EEOP_BOOL_OR_STEP_LAST)
835 {
836 if (*op->resnull)
837 {
838 /* result is already set to NULL, need not change it */
839 }
840 else if (DatumGetBool(*op->resvalue))
841 {
842 /* result is already set to TRUE, need not change it */
843
844 /*
845 * No point jumping to jumpdone - would be same target (as
846 * this is the last argument to the AND expression), except
847 * more expensive.
848 */
849 }
850 else if (*op->d.boolexpr.anynull)
851 {
852 *op->resvalue = (Datum) 0;
853 *op->resnull = true;
854 }
855 else
856 {
857 /* result is already set to FALSE, need not change it */
858 }
859
860 EEO_NEXT();
861 }
862
863 EEO_CASE(EEOP_BOOL_NOT_STEP)
864 {
865 /*
866 * Evaluation of 'not' is simple... if expr is false, then return
867 * 'true' and vice versa. It's safe to do this even on a
868 * nominally null value, so we ignore resnull; that means that
869 * NULL in produces NULL out, which is what we want.
870 */
871 *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
872
873 EEO_NEXT();
874 }
875
876 EEO_CASE(EEOP_QUAL)
877 {
878 /* simplified version of BOOL_AND_STEP for use by ExecQual() */
879
880 /* If argument (also result) is false or null ... */
881 if (*op->resnull ||
882 !DatumGetBool(*op->resvalue))
883 {
884 /* ... bail out early, returning FALSE */
885 *op->resnull = false;
886 *op->resvalue = BoolGetDatum(false);
887 EEO_JUMP(op->d.qualexpr.jumpdone);
888 }
889
890 /*
891 * Otherwise, leave the TRUE value in place, in case this is the
892 * last qual. Then, TRUE is the correct answer.
893 */
894
895 EEO_NEXT();
896 }
897
898 EEO_CASE(EEOP_JUMP)
899 {
900 /* Unconditionally jump to target step */
901 EEO_JUMP(op->d.jump.jumpdone);
902 }
903
904 EEO_CASE(EEOP_JUMP_IF_NULL)
905 {
906 /* Transfer control if current result is null */
907 if (*op->resnull)
908 EEO_JUMP(op->d.jump.jumpdone);
909
910 EEO_NEXT();
911 }
912
913 EEO_CASE(EEOP_JUMP_IF_NOT_NULL)
914 {
915 /* Transfer control if current result is non-null */
916 if (!*op->resnull)
917 EEO_JUMP(op->d.jump.jumpdone);
918
919 EEO_NEXT();
920 }
921
922 EEO_CASE(EEOP_JUMP_IF_NOT_TRUE)
923 {
924 /* Transfer control if current result is null or false */
925 if (*op->resnull || !DatumGetBool(*op->resvalue))
926 EEO_JUMP(op->d.jump.jumpdone);
927
928 EEO_NEXT();
929 }
930
931 EEO_CASE(EEOP_NULLTEST_ISNULL)
932 {
933 *op->resvalue = BoolGetDatum(*op->resnull);
934 *op->resnull = false;
935
936 EEO_NEXT();
937 }
938
939 EEO_CASE(EEOP_NULLTEST_ISNOTNULL)
940 {
941 *op->resvalue = BoolGetDatum(!*op->resnull);
942 *op->resnull = false;
943
944 EEO_NEXT();
945 }
946
947 EEO_CASE(EEOP_NULLTEST_ROWISNULL)
948 {
949 /* out of line implementation: too large */
950 ExecEvalRowNull(state, op, econtext);
951
952 EEO_NEXT();
953 }
954
955 EEO_CASE(EEOP_NULLTEST_ROWISNOTNULL)
956 {
957 /* out of line implementation: too large */
958 ExecEvalRowNotNull(state, op, econtext);
959
960 EEO_NEXT();
961 }
962
963 /* BooleanTest implementations for all booltesttypes */
964
965 EEO_CASE(EEOP_BOOLTEST_IS_TRUE)
966 {
967 if (*op->resnull)
968 {
969 *op->resvalue = BoolGetDatum(false);
970 *op->resnull = false;
971 }
972 /* else, input value is the correct output as well */
973
974 EEO_NEXT();
975 }
976
977 EEO_CASE(EEOP_BOOLTEST_IS_NOT_TRUE)
978 {
979 if (*op->resnull)
980 {
981 *op->resvalue = BoolGetDatum(true);
982 *op->resnull = false;
983 }
984 else
985 *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
986
987 EEO_NEXT();
988 }
989
990 EEO_CASE(EEOP_BOOLTEST_IS_FALSE)
991 {
992 if (*op->resnull)
993 {
994 *op->resvalue = BoolGetDatum(false);
995 *op->resnull = false;
996 }
997 else
998 *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
999
1000 EEO_NEXT();
1001 }
1002
1003 EEO_CASE(EEOP_BOOLTEST_IS_NOT_FALSE)
1004 {
1005 if (*op->resnull)
1006 {
1007 *op->resvalue = BoolGetDatum(true);
1008 *op->resnull = false;
1009 }
1010 /* else, input value is the correct output as well */
1011
1012 EEO_NEXT();
1013 }
1014
1015 EEO_CASE(EEOP_PARAM_EXEC)
1016 {
1017 /* out of line implementation: too large */
1018 ExecEvalParamExec(state, op, econtext);
1019
1020 EEO_NEXT();
1021 }
1022
1023 EEO_CASE(EEOP_PARAM_EXTERN)
1024 {
1025 /* out of line implementation: too large */
1026 ExecEvalParamExtern(state, op, econtext);
1027 EEO_NEXT();
1028 }
1029
1030 EEO_CASE(EEOP_CASE_TESTVAL)
1031 {
1032 /*
1033 * Normally upper parts of the expression tree have setup the
1034 * values to be returned here, but some parts of the system
1035 * currently misuse {caseValue,domainValue}_{datum,isNull} to set
1036 * run-time data. So if no values have been set-up, use
1037 * ExprContext's. This isn't pretty, but also not *that* ugly,
1038 * and this is unlikely to be performance sensitive enough to
1039 * worry about an extra branch.
1040 */
1041 if (op->d.casetest.value)
1042 {
1043 *op->resvalue = *op->d.casetest.value;
1044 *op->resnull = *op->d.casetest.isnull;
1045 }
1046 else
1047 {
1048 *op->resvalue = econtext->caseValue_datum;
1049 *op->resnull = econtext->caseValue_isNull;
1050 }
1051
1052 EEO_NEXT();
1053 }
1054
1055 EEO_CASE(EEOP_DOMAIN_TESTVAL)
1056 {
1057 /*
1058 * See EEOP_CASE_TESTVAL comment.
1059 */
1060 if (op->d.casetest.value)
1061 {
1062 *op->resvalue = *op->d.casetest.value;
1063 *op->resnull = *op->d.casetest.isnull;
1064 }
1065 else
1066 {
1067 *op->resvalue = econtext->domainValue_datum;
1068 *op->resnull = econtext->domainValue_isNull;
1069 }
1070
1071 EEO_NEXT();
1072 }
1073
1074 EEO_CASE(EEOP_MAKE_READONLY)
1075 {
1076 /*
1077 * Force a varlena value that might be read multiple times to R/O
1078 */
1079 if (!*op->d.make_readonly.isnull)
1080 *op->resvalue =
1081 MakeExpandedObjectReadOnlyInternal(*op->d.make_readonly.value);
1082 *op->resnull = *op->d.make_readonly.isnull;
1083
1084 EEO_NEXT();
1085 }
1086
1087 EEO_CASE(EEOP_IOCOERCE)
1088 {
1089 /*
1090 * Evaluate a CoerceViaIO node. This can be quite a hot path, so
1091 * inline as much work as possible. The source value is in our
1092 * result variable.
1093 */
1094 char *str;
1095
1096 /* call output function (similar to OutputFunctionCall) */
1097 if (*op->resnull)
1098 {
1099 /* output functions are not called on nulls */
1100 str = NULL;
1101 }
1102 else
1103 {
1104 FunctionCallInfo fcinfo_out;
1105
1106 fcinfo_out = op->d.iocoerce.fcinfo_data_out;
1107 fcinfo_out->arg[0] = *op->resvalue;
1108 fcinfo_out->argnull[0] = false;
1109
1110 fcinfo_out->isnull = false;
1111 str = DatumGetCString(FunctionCallInvoke(fcinfo_out));
1112
1113 /* OutputFunctionCall assumes result isn't null */
1114 Assert(!fcinfo_out->isnull);
1115 }
1116
1117 /* call input function (similar to InputFunctionCall) */
1118 if (!op->d.iocoerce.finfo_in->fn_strict || str != NULL)
1119 {
1120 FunctionCallInfo fcinfo_in;
1121
1122 fcinfo_in = op->d.iocoerce.fcinfo_data_in;
1123 fcinfo_in->arg[0] = PointerGetDatum(str);
1124 fcinfo_in->argnull[0] = *op->resnull;
1125 /* second and third arguments are already set up */
1126
1127 fcinfo_in->isnull = false;
1128 *op->resvalue = FunctionCallInvoke(fcinfo_in);
1129
1130 /* Should get null result if and only if str is NULL */
1131 if (str == NULL)
1132 {
1133 Assert(*op->resnull);
1134 Assert(fcinfo_in->isnull);
1135 }
1136 else
1137 {
1138 Assert(!*op->resnull);
1139 Assert(!fcinfo_in->isnull);
1140 }
1141 }
1142
1143 EEO_NEXT();
1144 }
1145
1146 EEO_CASE(EEOP_DISTINCT)
1147 {
1148 /*
1149 * IS DISTINCT FROM must evaluate arguments (already done into
1150 * fcinfo->arg/argnull) to determine whether they are NULL; if
1151 * either is NULL then the result is determined. If neither is
1152 * NULL, then proceed to evaluate the comparison function, which
1153 * is just the type's standard equality operator. We need not
1154 * care whether that function is strict. Because the handling of
1155 * nulls is different, we can't just reuse EEOP_FUNCEXPR.
1156 */
1157 FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1158
1159 /* check function arguments for NULLness */
1160 if (fcinfo->argnull[0] && fcinfo->argnull[1])
1161 {
1162 /* Both NULL? Then is not distinct... */
1163 *op->resvalue = BoolGetDatum(false);
1164 *op->resnull = false;
1165 }
1166 else if (fcinfo->argnull[0] || fcinfo->argnull[1])
1167 {
1168 /* Only one is NULL? Then is distinct... */
1169 *op->resvalue = BoolGetDatum(true);
1170 *op->resnull = false;
1171 }
1172 else
1173 {
1174 /* Neither null, so apply the equality function */
1175 Datum eqresult;
1176
1177 fcinfo->isnull = false;
1178 eqresult = (op->d.func.fn_addr) (fcinfo);
1179 /* Must invert result of "="; safe to do even if null */
1180 *op->resvalue = BoolGetDatum(!DatumGetBool(eqresult));
1181 *op->resnull = fcinfo->isnull;
1182 }
1183
1184 EEO_NEXT();
1185 }
1186
1187 EEO_CASE(EEOP_NULLIF)
1188 {
1189 /*
1190 * The arguments are already evaluated into fcinfo->arg/argnull.
1191 */
1192 FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1193
1194 /* if either argument is NULL they can't be equal */
1195 if (!fcinfo->argnull[0] && !fcinfo->argnull[1])
1196 {
1197 Datum result;
1198
1199 fcinfo->isnull = false;
1200 result = (op->d.func.fn_addr) (fcinfo);
1201
1202 /* if the arguments are equal return null */
1203 if (!fcinfo->isnull && DatumGetBool(result))
1204 {
1205 *op->resvalue = (Datum) 0;
1206 *op->resnull = true;
1207
1208 EEO_NEXT();
1209 }
1210 }
1211
1212 /* Arguments aren't equal, so return the first one */
1213 *op->resvalue = fcinfo->arg[0];
1214 *op->resnull = fcinfo->argnull[0];
1215
1216 EEO_NEXT();
1217 }
1218
1219 EEO_CASE(EEOP_SQLVALUEFUNCTION)
1220 {
1221 /*
1222 * Doesn't seem worthwhile to have an inline implementation
1223 * efficiency-wise.
1224 */
1225 ExecEvalSQLValueFunction(state, op);
1226
1227 EEO_NEXT();
1228 }
1229
1230 EEO_CASE(EEOP_CURRENTOFEXPR)
1231 {
1232 /* error invocation uses space, and shouldn't ever occur */
1233 ExecEvalCurrentOfExpr(state, op);
1234
1235 EEO_NEXT();
1236 }
1237
1238 EEO_CASE(EEOP_NEXTVALUEEXPR)
1239 {
1240 /*
1241 * Doesn't seem worthwhile to have an inline implementation
1242 * efficiency-wise.
1243 */
1244 ExecEvalNextValueExpr(state, op);
1245
1246 EEO_NEXT();
1247 }
1248
1249 EEO_CASE(EEOP_ARRAYEXPR)
1250 {
1251 /* too complex for an inline implementation */
1252 ExecEvalArrayExpr(state, op);
1253
1254 EEO_NEXT();
1255 }
1256
1257 EEO_CASE(EEOP_ARRAYCOERCE)
1258 {
1259 /* too complex for an inline implementation */
1260 ExecEvalArrayCoerce(state, op);
1261
1262 EEO_NEXT();
1263 }
1264
1265 EEO_CASE(EEOP_ROW)
1266 {
1267 /* too complex for an inline implementation */
1268 ExecEvalRow(state, op);
1269
1270 EEO_NEXT();
1271 }
1272
1273 EEO_CASE(EEOP_ROWCOMPARE_STEP)
1274 {
1275 FunctionCallInfo fcinfo = op->d.rowcompare_step.fcinfo_data;
1276
1277 /* force NULL result if strict fn and NULL input */
1278 if (op->d.rowcompare_step.finfo->fn_strict &&
1279 (fcinfo->argnull[0] || fcinfo->argnull[1]))
1280 {
1281 *op->resnull = true;
1282 EEO_JUMP(op->d.rowcompare_step.jumpnull);
1283 }
1284
1285 /* Apply comparison function */
1286 fcinfo->isnull = false;
1287 *op->resvalue = (op->d.rowcompare_step.fn_addr) (fcinfo);
1288
1289 /* force NULL result if NULL function result */
1290 if (fcinfo->isnull)
1291 {
1292 *op->resnull = true;
1293 EEO_JUMP(op->d.rowcompare_step.jumpnull);
1294 }
1295 *op->resnull = false;
1296
1297 /* If unequal, no need to compare remaining columns */
1298 if (DatumGetInt32(*op->resvalue) != 0)
1299 {
1300 EEO_JUMP(op->d.rowcompare_step.jumpdone);
1301 }
1302
1303 EEO_NEXT();
1304 }
1305
1306 EEO_CASE(EEOP_ROWCOMPARE_FINAL)
1307 {
1308 int32 cmpresult = DatumGetInt32(*op->resvalue);
1309 RowCompareType rctype = op->d.rowcompare_final.rctype;
1310
1311 *op->resnull = false;
1312 switch (rctype)
1313 {
1314 /* EQ and NE cases aren't allowed here */
1315 case ROWCOMPARE_LT:
1316 *op->resvalue = BoolGetDatum(cmpresult < 0);
1317 break;
1318 case ROWCOMPARE_LE:
1319 *op->resvalue = BoolGetDatum(cmpresult <= 0);
1320 break;
1321 case ROWCOMPARE_GE:
1322 *op->resvalue = BoolGetDatum(cmpresult >= 0);
1323 break;
1324 case ROWCOMPARE_GT:
1325 *op->resvalue = BoolGetDatum(cmpresult > 0);
1326 break;
1327 default:
1328 Assert(false);
1329 break;
1330 }
1331
1332 EEO_NEXT();
1333 }
1334
1335 EEO_CASE(EEOP_MINMAX)
1336 {
1337 /* too complex for an inline implementation */
1338 ExecEvalMinMax(state, op);
1339
1340 EEO_NEXT();
1341 }
1342
1343 EEO_CASE(EEOP_FIELDSELECT)
1344 {
1345 /* too complex for an inline implementation */
1346 ExecEvalFieldSelect(state, op, econtext);
1347
1348 EEO_NEXT();
1349 }
1350
1351 EEO_CASE(EEOP_FIELDSTORE_DEFORM)
1352 {
1353 /* too complex for an inline implementation */
1354 ExecEvalFieldStoreDeForm(state, op, econtext);
1355
1356 EEO_NEXT();
1357 }
1358
1359 EEO_CASE(EEOP_FIELDSTORE_FORM)
1360 {
1361 /* too complex for an inline implementation */
1362 ExecEvalFieldStoreForm(state, op, econtext);
1363
1364 EEO_NEXT();
1365 }
1366
1367 EEO_CASE(EEOP_ARRAYREF_SUBSCRIPT)
1368 {
1369 /* Process an array subscript */
1370
1371 /* too complex for an inline implementation */
1372 if (ExecEvalArrayRefSubscript(state, op))
1373 {
1374 EEO_NEXT();
1375 }
1376 else
1377 {
1378 /* Subscript is null, short-circuit ArrayRef to NULL */
1379 EEO_JUMP(op->d.arrayref_subscript.jumpdone);
1380 }
1381 }
1382
1383 EEO_CASE(EEOP_ARRAYREF_OLD)
1384 {
1385 /*
1386 * Fetch the old value in an arrayref assignment, in case it's
1387 * referenced (via a CaseTestExpr) inside the assignment
1388 * expression.
1389 */
1390
1391 /* too complex for an inline implementation */
1392 ExecEvalArrayRefOld(state, op);
1393
1394 EEO_NEXT();
1395 }
1396
1397 /*
1398 * Perform ArrayRef assignment
1399 */
1400 EEO_CASE(EEOP_ARRAYREF_ASSIGN)
1401 {
1402 /* too complex for an inline implementation */
1403 ExecEvalArrayRefAssign(state, op);
1404
1405 EEO_NEXT();
1406 }
1407
1408 /*
1409 * Fetch subset of an array.
1410 */
1411 EEO_CASE(EEOP_ARRAYREF_FETCH)
1412 {
1413 /* too complex for an inline implementation */
1414 ExecEvalArrayRefFetch(state, op);
1415
1416 EEO_NEXT();
1417 }
1418
1419 EEO_CASE(EEOP_CONVERT_ROWTYPE)
1420 {
1421 /* too complex for an inline implementation */
1422 ExecEvalConvertRowtype(state, op, econtext);
1423
1424 EEO_NEXT();
1425 }
1426
1427 EEO_CASE(EEOP_SCALARARRAYOP)
1428 {
1429 /* too complex for an inline implementation */
1430 ExecEvalScalarArrayOp(state, op);
1431
1432 EEO_NEXT();
1433 }
1434
1435 EEO_CASE(EEOP_DOMAIN_NOTNULL)
1436 {
1437 /* too complex for an inline implementation */
1438 ExecEvalConstraintNotNull(state, op);
1439
1440 EEO_NEXT();
1441 }
1442
1443 EEO_CASE(EEOP_DOMAIN_CHECK)
1444 {
1445 /* too complex for an inline implementation */
1446 ExecEvalConstraintCheck(state, op);
1447
1448 EEO_NEXT();
1449 }
1450
1451 EEO_CASE(EEOP_XMLEXPR)
1452 {
1453 /* too complex for an inline implementation */
1454 ExecEvalXmlExpr(state, op);
1455
1456 EEO_NEXT();
1457 }
1458
1459 EEO_CASE(EEOP_AGGREF)
1460 {
1461 /*
1462 * Returns a Datum whose value is the precomputed aggregate value
1463 * found in the given expression context.
1464 */
1465 AggrefExprState *aggref = op->d.aggref.astate;
1466
1467 Assert(econtext->ecxt_aggvalues != NULL);
1468
1469 *op->resvalue = econtext->ecxt_aggvalues[aggref->aggno];
1470 *op->resnull = econtext->ecxt_aggnulls[aggref->aggno];
1471
1472 EEO_NEXT();
1473 }
1474
1475 EEO_CASE(EEOP_GROUPING_FUNC)
1476 {
1477 /* too complex/uncommon for an inline implementation */
1478 ExecEvalGroupingFunc(state, op);
1479
1480 EEO_NEXT();
1481 }
1482
1483 EEO_CASE(EEOP_WINDOW_FUNC)
1484 {
1485 /*
1486 * Like Aggref, just return a precomputed value from the econtext.
1487 */
1488 WindowFuncExprState *wfunc = op->d.window_func.wfstate;
1489
1490 Assert(econtext->ecxt_aggvalues != NULL);
1491
1492 *op->resvalue = econtext->ecxt_aggvalues[wfunc->wfuncno];
1493 *op->resnull = econtext->ecxt_aggnulls[wfunc->wfuncno];
1494
1495 EEO_NEXT();
1496 }
1497
1498 EEO_CASE(EEOP_SUBPLAN)
1499 {
1500 /* too complex for an inline implementation */
1501 ExecEvalSubPlan(state, op, econtext);
1502
1503 EEO_NEXT();
1504 }
1505
1506 EEO_CASE(EEOP_ALTERNATIVE_SUBPLAN)
1507 {
1508 /* too complex for an inline implementation */
1509 ExecEvalAlternativeSubPlan(state, op, econtext);
1510
1511 EEO_NEXT();
1512 }
1513
1514 EEO_CASE(EEOP_LAST)
1515 {
1516 /* unreachable */
1517 Assert(false);
1518 goto out;
1519 }
1520 }
1521
1522 out:
1523 *isnull = state->resnull;
1524 return state->resvalue;
1525 }
1526
1527 /*
1528 * Check whether a user attribute in a slot can be referenced by a Var
1529 * expression. This should succeed unless there have been schema changes
1530 * since the expression tree has been created.
1531 */
1532 static void
CheckVarSlotCompatibility(TupleTableSlot * slot,int attnum,Oid vartype)1533 CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype)
1534 {
1535 /*
1536 * What we have to check for here is the possibility of an attribute
1537 * having been dropped or changed in type since the plan tree was created.
1538 * Ideally the plan will get invalidated and not re-used, but just in
1539 * case, we keep these defenses. Fortunately it's sufficient to check
1540 * once on the first time through.
1541 *
1542 * Note: ideally we'd check typmod as well as typid, but that seems
1543 * impractical at the moment: in many cases the tupdesc will have been
1544 * generated by ExecTypeFromTL(), and that can't guarantee to generate an
1545 * accurate typmod in all cases, because some expression node types don't
1546 * carry typmod. Fortunately, for precisely that reason, there should be
1547 * no places with a critical dependency on the typmod of a value.
1548 *
1549 * System attributes don't require checking since their types never
1550 * change.
1551 */
1552 if (attnum > 0)
1553 {
1554 TupleDesc slot_tupdesc = slot->tts_tupleDescriptor;
1555 Form_pg_attribute attr;
1556
1557 if (attnum > slot_tupdesc->natts) /* should never happen */
1558 elog(ERROR, "attribute number %d exceeds number of columns %d",
1559 attnum, slot_tupdesc->natts);
1560
1561 attr = slot_tupdesc->attrs[attnum - 1];
1562
1563 if (attr->attisdropped)
1564 ereport(ERROR,
1565 (errcode(ERRCODE_UNDEFINED_COLUMN),
1566 errmsg("attribute %d of type %s has been dropped",
1567 attnum, format_type_be(slot_tupdesc->tdtypeid))));
1568
1569 if (vartype != attr->atttypid)
1570 ereport(ERROR,
1571 (errcode(ERRCODE_DATATYPE_MISMATCH),
1572 errmsg("attribute %d of type %s has wrong type",
1573 attnum, format_type_be(slot_tupdesc->tdtypeid)),
1574 errdetail("Table has type %s, but query expects %s.",
1575 format_type_be(attr->atttypid),
1576 format_type_be(vartype))));
1577 }
1578 }
1579
1580 /*
1581 * get_cached_rowtype: utility function to lookup a rowtype tupdesc
1582 *
1583 * type_id, typmod: identity of the rowtype
1584 * cache_field: where to cache the TupleDesc pointer in expression state node
1585 * (field must be initialized to NULL)
1586 * econtext: expression context we are executing in
1587 *
1588 * NOTE: because the shutdown callback will be called during plan rescan,
1589 * must be prepared to re-do this during any node execution; cannot call
1590 * just once during expression initialization.
1591 */
1592 static TupleDesc
get_cached_rowtype(Oid type_id,int32 typmod,TupleDesc * cache_field,ExprContext * econtext)1593 get_cached_rowtype(Oid type_id, int32 typmod,
1594 TupleDesc *cache_field, ExprContext *econtext)
1595 {
1596 TupleDesc tupDesc = *cache_field;
1597
1598 /* Do lookup if no cached value or if requested type changed */
1599 if (tupDesc == NULL ||
1600 type_id != tupDesc->tdtypeid ||
1601 typmod != tupDesc->tdtypmod)
1602 {
1603 tupDesc = lookup_rowtype_tupdesc(type_id, typmod);
1604
1605 if (*cache_field)
1606 {
1607 /* Release old tupdesc; but callback is already registered */
1608 ReleaseTupleDesc(*cache_field);
1609 }
1610 else
1611 {
1612 /* Need to register shutdown callback to release tupdesc */
1613 RegisterExprContextCallback(econtext,
1614 ShutdownTupleDescRef,
1615 PointerGetDatum(cache_field));
1616 }
1617 *cache_field = tupDesc;
1618 }
1619 return tupDesc;
1620 }
1621
1622 /*
1623 * Callback function to release a tupdesc refcount at econtext shutdown
1624 */
1625 static void
ShutdownTupleDescRef(Datum arg)1626 ShutdownTupleDescRef(Datum arg)
1627 {
1628 TupleDesc *cache_field = (TupleDesc *) DatumGetPointer(arg);
1629
1630 if (*cache_field)
1631 ReleaseTupleDesc(*cache_field);
1632 *cache_field = NULL;
1633 }
1634
1635 /*
1636 * Fast-path functions, for very simple expressions
1637 */
1638
1639 /* Simple reference to inner Var, first time through */
1640 static Datum
ExecJustInnerVarFirst(ExprState * state,ExprContext * econtext,bool * isnull)1641 ExecJustInnerVarFirst(ExprState *state, ExprContext *econtext, bool *isnull)
1642 {
1643 ExprEvalStep *op = &state->steps[1];
1644 int attnum = op->d.var.attnum + 1;
1645 TupleTableSlot *slot = econtext->ecxt_innertuple;
1646
1647 /* See ExecInterpExpr()'s comments for EEOP_INNER_VAR_FIRST */
1648
1649 CheckVarSlotCompatibility(slot, attnum, op->d.var.vartype);
1650 op->opcode = EEOP_INNER_VAR; /* just for cleanliness */
1651 state->evalfunc = ExecJustInnerVar;
1652
1653 /*
1654 * Since we use slot_getattr(), we don't need to implement the FETCHSOME
1655 * step explicitly, and we also needn't Assert that the attnum is in range
1656 * --- slot_getattr() will take care of any problems.
1657 */
1658 return slot_getattr(slot, attnum, isnull);
1659 }
1660
1661 /* Simple reference to inner Var */
1662 static Datum
ExecJustInnerVar(ExprState * state,ExprContext * econtext,bool * isnull)1663 ExecJustInnerVar(ExprState *state, ExprContext *econtext, bool *isnull)
1664 {
1665 ExprEvalStep *op = &state->steps[1];
1666 int attnum = op->d.var.attnum + 1;
1667 TupleTableSlot *slot = econtext->ecxt_innertuple;
1668
1669 /* See comments in ExecJustInnerVarFirst */
1670 return slot_getattr(slot, attnum, isnull);
1671 }
1672
1673 /* Simple reference to outer Var, first time through */
1674 static Datum
ExecJustOuterVarFirst(ExprState * state,ExprContext * econtext,bool * isnull)1675 ExecJustOuterVarFirst(ExprState *state, ExprContext *econtext, bool *isnull)
1676 {
1677 ExprEvalStep *op = &state->steps[1];
1678 int attnum = op->d.var.attnum + 1;
1679 TupleTableSlot *slot = econtext->ecxt_outertuple;
1680
1681 CheckVarSlotCompatibility(slot, attnum, op->d.var.vartype);
1682 op->opcode = EEOP_OUTER_VAR; /* just for cleanliness */
1683 state->evalfunc = ExecJustOuterVar;
1684
1685 /* See comments in ExecJustInnerVarFirst */
1686 return slot_getattr(slot, attnum, isnull);
1687 }
1688
1689 /* Simple reference to outer Var */
1690 static Datum
ExecJustOuterVar(ExprState * state,ExprContext * econtext,bool * isnull)1691 ExecJustOuterVar(ExprState *state, ExprContext *econtext, bool *isnull)
1692 {
1693 ExprEvalStep *op = &state->steps[1];
1694 int attnum = op->d.var.attnum + 1;
1695 TupleTableSlot *slot = econtext->ecxt_outertuple;
1696
1697 /* See comments in ExecJustInnerVarFirst */
1698 return slot_getattr(slot, attnum, isnull);
1699 }
1700
1701 /* Simple reference to scan Var, first time through */
1702 static Datum
ExecJustScanVarFirst(ExprState * state,ExprContext * econtext,bool * isnull)1703 ExecJustScanVarFirst(ExprState *state, ExprContext *econtext, bool *isnull)
1704 {
1705 ExprEvalStep *op = &state->steps[1];
1706 int attnum = op->d.var.attnum + 1;
1707 TupleTableSlot *slot = econtext->ecxt_scantuple;
1708
1709 CheckVarSlotCompatibility(slot, attnum, op->d.var.vartype);
1710 op->opcode = EEOP_SCAN_VAR; /* just for cleanliness */
1711 state->evalfunc = ExecJustScanVar;
1712
1713 /* See comments in ExecJustInnerVarFirst */
1714 return slot_getattr(slot, attnum, isnull);
1715 }
1716
1717 /* Simple reference to scan Var */
1718 static Datum
ExecJustScanVar(ExprState * state,ExprContext * econtext,bool * isnull)1719 ExecJustScanVar(ExprState *state, ExprContext *econtext, bool *isnull)
1720 {
1721 ExprEvalStep *op = &state->steps[1];
1722 int attnum = op->d.var.attnum + 1;
1723 TupleTableSlot *slot = econtext->ecxt_scantuple;
1724
1725 /* See comments in ExecJustInnerVarFirst */
1726 return slot_getattr(slot, attnum, isnull);
1727 }
1728
1729 /* Simple Const expression */
1730 static Datum
ExecJustConst(ExprState * state,ExprContext * econtext,bool * isnull)1731 ExecJustConst(ExprState *state, ExprContext *econtext, bool *isnull)
1732 {
1733 ExprEvalStep *op = &state->steps[0];
1734
1735 *isnull = op->d.constval.isnull;
1736 return op->d.constval.value;
1737 }
1738
1739 /* Evaluate inner Var and assign to appropriate column of result tuple */
1740 static Datum
ExecJustAssignInnerVar(ExprState * state,ExprContext * econtext,bool * isnull)1741 ExecJustAssignInnerVar(ExprState *state, ExprContext *econtext, bool *isnull)
1742 {
1743 ExprEvalStep *op = &state->steps[1];
1744 int attnum = op->d.assign_var.attnum + 1;
1745 int resultnum = op->d.assign_var.resultnum;
1746 TupleTableSlot *inslot = econtext->ecxt_innertuple;
1747 TupleTableSlot *outslot = state->resultslot;
1748
1749 /*
1750 * We do not need CheckVarSlotCompatibility here; that was taken care of
1751 * at compilation time.
1752 *
1753 * Since we use slot_getattr(), we don't need to implement the FETCHSOME
1754 * step explicitly, and we also needn't Assert that the attnum is in range
1755 * --- slot_getattr() will take care of any problems. Nonetheless, check
1756 * that resultnum is in range.
1757 */
1758 Assert(resultnum >= 0 && resultnum < outslot->tts_tupleDescriptor->natts);
1759 outslot->tts_values[resultnum] =
1760 slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
1761 return 0;
1762 }
1763
1764 /* Evaluate outer Var and assign to appropriate column of result tuple */
1765 static Datum
ExecJustAssignOuterVar(ExprState * state,ExprContext * econtext,bool * isnull)1766 ExecJustAssignOuterVar(ExprState *state, ExprContext *econtext, bool *isnull)
1767 {
1768 ExprEvalStep *op = &state->steps[1];
1769 int attnum = op->d.assign_var.attnum + 1;
1770 int resultnum = op->d.assign_var.resultnum;
1771 TupleTableSlot *inslot = econtext->ecxt_outertuple;
1772 TupleTableSlot *outslot = state->resultslot;
1773
1774 /* See comments in ExecJustAssignInnerVar */
1775 Assert(resultnum >= 0 && resultnum < outslot->tts_tupleDescriptor->natts);
1776 outslot->tts_values[resultnum] =
1777 slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
1778 return 0;
1779 }
1780
1781 /* Evaluate scan Var and assign to appropriate column of result tuple */
1782 static Datum
ExecJustAssignScanVar(ExprState * state,ExprContext * econtext,bool * isnull)1783 ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool *isnull)
1784 {
1785 ExprEvalStep *op = &state->steps[1];
1786 int attnum = op->d.assign_var.attnum + 1;
1787 int resultnum = op->d.assign_var.resultnum;
1788 TupleTableSlot *inslot = econtext->ecxt_scantuple;
1789 TupleTableSlot *outslot = state->resultslot;
1790
1791 /* See comments in ExecJustAssignInnerVar */
1792 Assert(resultnum >= 0 && resultnum < outslot->tts_tupleDescriptor->natts);
1793 outslot->tts_values[resultnum] =
1794 slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
1795 return 0;
1796 }
1797
1798
1799 /*
1800 * Do one-time initialization of interpretation machinery.
1801 */
1802 static void
ExecInitInterpreter(void)1803 ExecInitInterpreter(void)
1804 {
1805 #if defined(EEO_USE_COMPUTED_GOTO)
1806 /* Set up externally-visible pointer to dispatch table */
1807 if (dispatch_table == NULL)
1808 dispatch_table = (const void **)
1809 DatumGetPointer(ExecInterpExpr(NULL, NULL, NULL));
1810 #endif
1811 }
1812
1813 /*
1814 * Function to return the opcode of an expression step.
1815 *
1816 * When direct-threading is in use, ExprState->opcode isn't easily
1817 * decipherable. This function returns the appropriate enum member.
1818 *
1819 * This currently is only supposed to be used in paths that aren't critical
1820 * performance-wise. If that changes, we could add an inverse dispatch_table
1821 * that's sorted on the address, so a binary search can be performed.
1822 */
1823 ExprEvalOp
ExecEvalStepOp(ExprState * state,ExprEvalStep * op)1824 ExecEvalStepOp(ExprState *state, ExprEvalStep *op)
1825 {
1826 #if defined(EEO_USE_COMPUTED_GOTO)
1827 if (state->flags & EEO_FLAG_DIRECT_THREADED)
1828 {
1829 int i;
1830
1831 for (i = 0; i < EEOP_LAST; i++)
1832 {
1833 if ((void *) op->opcode == dispatch_table[i])
1834 {
1835 return (ExprEvalOp) i;
1836 }
1837 }
1838 elog(ERROR, "unknown opcode");
1839 }
1840 #endif
1841 return (ExprEvalOp) op->opcode;
1842 }
1843
1844
1845 /*
1846 * Out-of-line helper functions for complex instructions.
1847 */
1848
1849 /*
1850 * Evaluate a PARAM_EXEC parameter.
1851 *
1852 * PARAM_EXEC params (internal executor parameters) are stored in the
1853 * ecxt_param_exec_vals array, and can be accessed by array index.
1854 */
1855 void
ExecEvalParamExec(ExprState * state,ExprEvalStep * op,ExprContext * econtext)1856 ExecEvalParamExec(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
1857 {
1858 ParamExecData *prm;
1859
1860 prm = &(econtext->ecxt_param_exec_vals[op->d.param.paramid]);
1861 if (unlikely(prm->execPlan != NULL))
1862 {
1863 /* Parameter not evaluated yet, so go do it */
1864 ExecSetParamPlan(prm->execPlan, econtext);
1865 /* ExecSetParamPlan should have processed this param... */
1866 Assert(prm->execPlan == NULL);
1867 }
1868 *op->resvalue = prm->value;
1869 *op->resnull = prm->isnull;
1870 }
1871
1872 /*
1873 * Evaluate a PARAM_EXTERN parameter.
1874 *
1875 * PARAM_EXTERN parameters must be sought in ecxt_param_list_info.
1876 */
1877 void
ExecEvalParamExtern(ExprState * state,ExprEvalStep * op,ExprContext * econtext)1878 ExecEvalParamExtern(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
1879 {
1880 ParamListInfo paramInfo = econtext->ecxt_param_list_info;
1881 int paramId = op->d.param.paramid;
1882
1883 if (likely(paramInfo &&
1884 paramId > 0 && paramId <= paramInfo->numParams))
1885 {
1886 ParamExternData *prm = ¶mInfo->params[paramId - 1];
1887
1888 /* give hook a chance in case parameter is dynamic */
1889 if (!OidIsValid(prm->ptype) && paramInfo->paramFetch != NULL)
1890 (*paramInfo->paramFetch) (paramInfo, paramId);
1891
1892 if (likely(OidIsValid(prm->ptype)))
1893 {
1894 /* safety check in case hook did something unexpected */
1895 if (unlikely(prm->ptype != op->d.param.paramtype))
1896 ereport(ERROR,
1897 (errcode(ERRCODE_DATATYPE_MISMATCH),
1898 errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
1899 paramId,
1900 format_type_be(prm->ptype),
1901 format_type_be(op->d.param.paramtype))));
1902 *op->resvalue = prm->value;
1903 *op->resnull = prm->isnull;
1904 return;
1905 }
1906 }
1907
1908 ereport(ERROR,
1909 (errcode(ERRCODE_UNDEFINED_OBJECT),
1910 errmsg("no value found for parameter %d", paramId)));
1911 }
1912
1913 /*
1914 * Evaluate a SQLValueFunction expression.
1915 */
1916 void
ExecEvalSQLValueFunction(ExprState * state,ExprEvalStep * op)1917 ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op)
1918 {
1919 SQLValueFunction *svf = op->d.sqlvaluefunction.svf;
1920 FunctionCallInfoData fcinfo;
1921
1922 *op->resnull = false;
1923
1924 /*
1925 * Note: current_schema() can return NULL. current_user() etc currently
1926 * cannot, but might as well code those cases the same way for safety.
1927 */
1928 switch (svf->op)
1929 {
1930 case SVFOP_CURRENT_DATE:
1931 *op->resvalue = DateADTGetDatum(GetSQLCurrentDate());
1932 break;
1933 case SVFOP_CURRENT_TIME:
1934 case SVFOP_CURRENT_TIME_N:
1935 *op->resvalue = TimeTzADTPGetDatum(GetSQLCurrentTime(svf->typmod));
1936 break;
1937 case SVFOP_CURRENT_TIMESTAMP:
1938 case SVFOP_CURRENT_TIMESTAMP_N:
1939 *op->resvalue = TimestampTzGetDatum(GetSQLCurrentTimestamp(svf->typmod));
1940 break;
1941 case SVFOP_LOCALTIME:
1942 case SVFOP_LOCALTIME_N:
1943 *op->resvalue = TimeADTGetDatum(GetSQLLocalTime(svf->typmod));
1944 break;
1945 case SVFOP_LOCALTIMESTAMP:
1946 case SVFOP_LOCALTIMESTAMP_N:
1947 *op->resvalue = TimestampGetDatum(GetSQLLocalTimestamp(svf->typmod));
1948 break;
1949 case SVFOP_CURRENT_ROLE:
1950 case SVFOP_CURRENT_USER:
1951 case SVFOP_USER:
1952 InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
1953 *op->resvalue = current_user(&fcinfo);
1954 *op->resnull = fcinfo.isnull;
1955 break;
1956 case SVFOP_SESSION_USER:
1957 InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
1958 *op->resvalue = session_user(&fcinfo);
1959 *op->resnull = fcinfo.isnull;
1960 break;
1961 case SVFOP_CURRENT_CATALOG:
1962 InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
1963 *op->resvalue = current_database(&fcinfo);
1964 *op->resnull = fcinfo.isnull;
1965 break;
1966 case SVFOP_CURRENT_SCHEMA:
1967 InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
1968 *op->resvalue = current_schema(&fcinfo);
1969 *op->resnull = fcinfo.isnull;
1970 break;
1971 }
1972 }
1973
1974 /*
1975 * Raise error if a CURRENT OF expression is evaluated.
1976 *
1977 * The planner should convert CURRENT OF into a TidScan qualification, or some
1978 * other special handling in a ForeignScan node. So we have to be able to do
1979 * ExecInitExpr on a CurrentOfExpr, but we shouldn't ever actually execute it.
1980 * If we get here, we suppose we must be dealing with CURRENT OF on a foreign
1981 * table whose FDW doesn't handle it, and complain accordingly.
1982 */
1983 void
ExecEvalCurrentOfExpr(ExprState * state,ExprEvalStep * op)1984 ExecEvalCurrentOfExpr(ExprState *state, ExprEvalStep *op)
1985 {
1986 ereport(ERROR,
1987 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1988 errmsg("WHERE CURRENT OF is not supported for this table type")));
1989 }
1990
1991 /*
1992 * Evaluate NextValueExpr.
1993 */
1994 void
ExecEvalNextValueExpr(ExprState * state,ExprEvalStep * op)1995 ExecEvalNextValueExpr(ExprState *state, ExprEvalStep *op)
1996 {
1997 int64 newval = nextval_internal(op->d.nextvalueexpr.seqid, false);
1998
1999 switch (op->d.nextvalueexpr.seqtypid)
2000 {
2001 case INT2OID:
2002 *op->resvalue = Int16GetDatum((int16) newval);
2003 break;
2004 case INT4OID:
2005 *op->resvalue = Int32GetDatum((int32) newval);
2006 break;
2007 case INT8OID:
2008 *op->resvalue = Int64GetDatum((int64) newval);
2009 break;
2010 default:
2011 elog(ERROR, "unsupported sequence type %u",
2012 op->d.nextvalueexpr.seqtypid);
2013 }
2014 *op->resnull = false;
2015 }
2016
2017 /*
2018 * Evaluate NullTest / IS NULL for rows.
2019 */
2020 void
ExecEvalRowNull(ExprState * state,ExprEvalStep * op,ExprContext * econtext)2021 ExecEvalRowNull(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
2022 {
2023 ExecEvalRowNullInt(state, op, econtext, true);
2024 }
2025
2026 /*
2027 * Evaluate NullTest / IS NOT NULL for rows.
2028 */
2029 void
ExecEvalRowNotNull(ExprState * state,ExprEvalStep * op,ExprContext * econtext)2030 ExecEvalRowNotNull(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
2031 {
2032 ExecEvalRowNullInt(state, op, econtext, false);
2033 }
2034
2035 /* Common code for IS [NOT] NULL on a row value */
2036 static void
ExecEvalRowNullInt(ExprState * state,ExprEvalStep * op,ExprContext * econtext,bool checkisnull)2037 ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op,
2038 ExprContext *econtext, bool checkisnull)
2039 {
2040 Datum value = *op->resvalue;
2041 bool isnull = *op->resnull;
2042 HeapTupleHeader tuple;
2043 Oid tupType;
2044 int32 tupTypmod;
2045 TupleDesc tupDesc;
2046 HeapTupleData tmptup;
2047 int att;
2048
2049 *op->resnull = false;
2050
2051 /* NULL row variables are treated just as NULL scalar columns */
2052 if (isnull)
2053 {
2054 *op->resvalue = BoolGetDatum(checkisnull);
2055 return;
2056 }
2057
2058 /*
2059 * The SQL standard defines IS [NOT] NULL for a non-null rowtype argument
2060 * as:
2061 *
2062 * "R IS NULL" is true if every field is the null value.
2063 *
2064 * "R IS NOT NULL" is true if no field is the null value.
2065 *
2066 * This definition is (apparently intentionally) not recursive; so our
2067 * tests on the fields are primitive attisnull tests, not recursive checks
2068 * to see if they are all-nulls or no-nulls rowtypes.
2069 *
2070 * The standard does not consider the possibility of zero-field rows, but
2071 * here we consider them to vacuously satisfy both predicates.
2072 */
2073
2074 tuple = DatumGetHeapTupleHeader(value);
2075
2076 tupType = HeapTupleHeaderGetTypeId(tuple);
2077 tupTypmod = HeapTupleHeaderGetTypMod(tuple);
2078
2079 /* Lookup tupdesc if first time through or if type changes */
2080 tupDesc = get_cached_rowtype(tupType, tupTypmod,
2081 &op->d.nulltest_row.argdesc,
2082 econtext);
2083
2084 /*
2085 * heap_attisnull needs a HeapTuple not a bare HeapTupleHeader.
2086 */
2087 tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
2088 tmptup.t_data = tuple;
2089
2090 for (att = 1; att <= tupDesc->natts; att++)
2091 {
2092 /* ignore dropped columns */
2093 if (tupDesc->attrs[att - 1]->attisdropped)
2094 continue;
2095 if (heap_attisnull(&tmptup, att))
2096 {
2097 /* null field disproves IS NOT NULL */
2098 if (!checkisnull)
2099 {
2100 *op->resvalue = BoolGetDatum(false);
2101 return;
2102 }
2103 }
2104 else
2105 {
2106 /* non-null field disproves IS NULL */
2107 if (checkisnull)
2108 {
2109 *op->resvalue = BoolGetDatum(false);
2110 return;
2111 }
2112 }
2113 }
2114
2115 *op->resvalue = BoolGetDatum(true);
2116 }
2117
2118 /*
2119 * Evaluate an ARRAY[] expression.
2120 *
2121 * The individual array elements (or subarrays) have already been evaluated
2122 * into op->d.arrayexpr.elemvalues[]/elemnulls[].
2123 */
2124 void
ExecEvalArrayExpr(ExprState * state,ExprEvalStep * op)2125 ExecEvalArrayExpr(ExprState *state, ExprEvalStep *op)
2126 {
2127 ArrayType *result;
2128 Oid element_type = op->d.arrayexpr.elemtype;
2129 int nelems = op->d.arrayexpr.nelems;
2130 int ndims = 0;
2131 int dims[MAXDIM];
2132 int lbs[MAXDIM];
2133
2134 /* Set non-null as default */
2135 *op->resnull = false;
2136
2137 if (!op->d.arrayexpr.multidims)
2138 {
2139 /* Elements are presumably of scalar type */
2140 Datum *dvalues = op->d.arrayexpr.elemvalues;
2141 bool *dnulls = op->d.arrayexpr.elemnulls;
2142
2143 /* Shouldn't happen here, but if length is 0, return empty array */
2144 if (nelems == 0)
2145 {
2146 *op->resvalue =
2147 PointerGetDatum(construct_empty_array(element_type));
2148 return;
2149 }
2150
2151 /* setup for 1-D array of the given length */
2152 ndims = 1;
2153 dims[0] = nelems;
2154 lbs[0] = 1;
2155
2156 result = construct_md_array(dvalues, dnulls, ndims, dims, lbs,
2157 element_type,
2158 op->d.arrayexpr.elemlength,
2159 op->d.arrayexpr.elembyval,
2160 op->d.arrayexpr.elemalign);
2161 }
2162 else
2163 {
2164 /* Must be nested array expressions */
2165 int nbytes = 0;
2166 int nitems = 0;
2167 int outer_nelems = 0;
2168 int elem_ndims = 0;
2169 int *elem_dims = NULL;
2170 int *elem_lbs = NULL;
2171 bool firstone = true;
2172 bool havenulls = false;
2173 bool haveempty = false;
2174 char **subdata;
2175 bits8 **subbitmaps;
2176 int *subbytes;
2177 int *subnitems;
2178 int32 dataoffset;
2179 char *dat;
2180 int iitem;
2181 int elemoff;
2182 int i;
2183
2184 subdata = (char **) palloc(nelems * sizeof(char *));
2185 subbitmaps = (bits8 **) palloc(nelems * sizeof(bits8 *));
2186 subbytes = (int *) palloc(nelems * sizeof(int));
2187 subnitems = (int *) palloc(nelems * sizeof(int));
2188
2189 /* loop through and get data area from each element */
2190 for (elemoff = 0; elemoff < nelems; elemoff++)
2191 {
2192 Datum arraydatum;
2193 bool eisnull;
2194 ArrayType *array;
2195 int this_ndims;
2196
2197 arraydatum = op->d.arrayexpr.elemvalues[elemoff];
2198 eisnull = op->d.arrayexpr.elemnulls[elemoff];
2199
2200 /* temporarily ignore null subarrays */
2201 if (eisnull)
2202 {
2203 haveempty = true;
2204 continue;
2205 }
2206
2207 array = DatumGetArrayTypeP(arraydatum);
2208
2209 /* run-time double-check on element type */
2210 if (element_type != ARR_ELEMTYPE(array))
2211 ereport(ERROR,
2212 (errcode(ERRCODE_DATATYPE_MISMATCH),
2213 errmsg("cannot merge incompatible arrays"),
2214 errdetail("Array with element type %s cannot be "
2215 "included in ARRAY construct with element type %s.",
2216 format_type_be(ARR_ELEMTYPE(array)),
2217 format_type_be(element_type))));
2218
2219 this_ndims = ARR_NDIM(array);
2220 /* temporarily ignore zero-dimensional subarrays */
2221 if (this_ndims <= 0)
2222 {
2223 haveempty = true;
2224 continue;
2225 }
2226
2227 if (firstone)
2228 {
2229 /* Get sub-array details from first member */
2230 elem_ndims = this_ndims;
2231 ndims = elem_ndims + 1;
2232 if (ndims <= 0 || ndims > MAXDIM)
2233 ereport(ERROR,
2234 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2235 errmsg("number of array dimensions (%d) exceeds " \
2236 "the maximum allowed (%d)", ndims, MAXDIM)));
2237
2238 elem_dims = (int *) palloc(elem_ndims * sizeof(int));
2239 memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int));
2240 elem_lbs = (int *) palloc(elem_ndims * sizeof(int));
2241 memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int));
2242
2243 firstone = false;
2244 }
2245 else
2246 {
2247 /* Check other sub-arrays are compatible */
2248 if (elem_ndims != this_ndims ||
2249 memcmp(elem_dims, ARR_DIMS(array),
2250 elem_ndims * sizeof(int)) != 0 ||
2251 memcmp(elem_lbs, ARR_LBOUND(array),
2252 elem_ndims * sizeof(int)) != 0)
2253 ereport(ERROR,
2254 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2255 errmsg("multidimensional arrays must have array "
2256 "expressions with matching dimensions")));
2257 }
2258
2259 subdata[outer_nelems] = ARR_DATA_PTR(array);
2260 subbitmaps[outer_nelems] = ARR_NULLBITMAP(array);
2261 subbytes[outer_nelems] = ARR_SIZE(array) - ARR_DATA_OFFSET(array);
2262 nbytes += subbytes[outer_nelems];
2263 subnitems[outer_nelems] = ArrayGetNItems(this_ndims,
2264 ARR_DIMS(array));
2265 nitems += subnitems[outer_nelems];
2266 havenulls |= ARR_HASNULL(array);
2267 outer_nelems++;
2268 }
2269
2270 /*
2271 * If all items were null or empty arrays, return an empty array;
2272 * otherwise, if some were and some weren't, raise error. (Note: we
2273 * must special-case this somehow to avoid trying to generate a 1-D
2274 * array formed from empty arrays. It's not ideal...)
2275 */
2276 if (haveempty)
2277 {
2278 if (ndims == 0) /* didn't find any nonempty array */
2279 {
2280 *op->resvalue = PointerGetDatum(construct_empty_array(element_type));
2281 return;
2282 }
2283 ereport(ERROR,
2284 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2285 errmsg("multidimensional arrays must have array "
2286 "expressions with matching dimensions")));
2287 }
2288
2289 /* setup for multi-D array */
2290 dims[0] = outer_nelems;
2291 lbs[0] = 1;
2292 for (i = 1; i < ndims; i++)
2293 {
2294 dims[i] = elem_dims[i - 1];
2295 lbs[i] = elem_lbs[i - 1];
2296 }
2297
2298 /* check for subscript overflow */
2299 (void) ArrayGetNItems(ndims, dims);
2300 ArrayCheckBounds(ndims, dims, lbs);
2301
2302 if (havenulls)
2303 {
2304 dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
2305 nbytes += dataoffset;
2306 }
2307 else
2308 {
2309 dataoffset = 0; /* marker for no null bitmap */
2310 nbytes += ARR_OVERHEAD_NONULLS(ndims);
2311 }
2312
2313 result = (ArrayType *) palloc(nbytes);
2314 SET_VARSIZE(result, nbytes);
2315 result->ndim = ndims;
2316 result->dataoffset = dataoffset;
2317 result->elemtype = element_type;
2318 memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
2319 memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
2320
2321 dat = ARR_DATA_PTR(result);
2322 iitem = 0;
2323 for (i = 0; i < outer_nelems; i++)
2324 {
2325 memcpy(dat, subdata[i], subbytes[i]);
2326 dat += subbytes[i];
2327 if (havenulls)
2328 array_bitmap_copy(ARR_NULLBITMAP(result), iitem,
2329 subbitmaps[i], 0,
2330 subnitems[i]);
2331 iitem += subnitems[i];
2332 }
2333 }
2334
2335 *op->resvalue = PointerGetDatum(result);
2336 }
2337
2338 /*
2339 * Evaluate an ArrayCoerceExpr expression.
2340 *
2341 * Source array is in step's result variable.
2342 */
2343 void
ExecEvalArrayCoerce(ExprState * state,ExprEvalStep * op)2344 ExecEvalArrayCoerce(ExprState *state, ExprEvalStep *op)
2345 {
2346 ArrayCoerceExpr *acoerce = op->d.arraycoerce.coerceexpr;
2347 Datum arraydatum;
2348 FunctionCallInfoData locfcinfo;
2349
2350 /* NULL array -> NULL result */
2351 if (*op->resnull)
2352 return;
2353
2354 arraydatum = *op->resvalue;
2355
2356 /*
2357 * If it's binary-compatible, modify the element type in the array header,
2358 * but otherwise leave the array as we received it.
2359 */
2360 if (!OidIsValid(acoerce->elemfuncid))
2361 {
2362 /* Detoast input array if necessary, and copy in any case */
2363 ArrayType *array = DatumGetArrayTypePCopy(arraydatum);
2364
2365 ARR_ELEMTYPE(array) = op->d.arraycoerce.resultelemtype;
2366 *op->resvalue = PointerGetDatum(array);
2367 return;
2368 }
2369
2370 /*
2371 * Use array_map to apply the function to each array element.
2372 *
2373 * We pass on the desttypmod and isExplicit flags whether or not the
2374 * function wants them.
2375 *
2376 * Note: coercion functions are assumed to not use collation.
2377 */
2378 InitFunctionCallInfoData(locfcinfo, op->d.arraycoerce.elemfunc, 3,
2379 InvalidOid, NULL, NULL);
2380 locfcinfo.arg[0] = arraydatum;
2381 locfcinfo.arg[1] = Int32GetDatum(acoerce->resulttypmod);
2382 locfcinfo.arg[2] = BoolGetDatum(acoerce->isExplicit);
2383 locfcinfo.argnull[0] = false;
2384 locfcinfo.argnull[1] = false;
2385 locfcinfo.argnull[2] = false;
2386
2387 *op->resvalue = array_map(&locfcinfo, op->d.arraycoerce.resultelemtype,
2388 op->d.arraycoerce.amstate);
2389 }
2390
2391 /*
2392 * Evaluate a ROW() expression.
2393 *
2394 * The individual columns have already been evaluated into
2395 * op->d.row.elemvalues[]/elemnulls[].
2396 */
2397 void
ExecEvalRow(ExprState * state,ExprEvalStep * op)2398 ExecEvalRow(ExprState *state, ExprEvalStep *op)
2399 {
2400 HeapTuple tuple;
2401
2402 /* build tuple from evaluated field values */
2403 tuple = heap_form_tuple(op->d.row.tupdesc,
2404 op->d.row.elemvalues,
2405 op->d.row.elemnulls);
2406
2407 *op->resvalue = HeapTupleGetDatum(tuple);
2408 *op->resnull = false;
2409 }
2410
2411 /*
2412 * Evaluate GREATEST() or LEAST() expression (note this is *not* MIN()/MAX()).
2413 *
2414 * All of the to-be-compared expressions have already been evaluated into
2415 * op->d.minmax.values[]/nulls[].
2416 */
2417 void
ExecEvalMinMax(ExprState * state,ExprEvalStep * op)2418 ExecEvalMinMax(ExprState *state, ExprEvalStep *op)
2419 {
2420 Datum *values = op->d.minmax.values;
2421 bool *nulls = op->d.minmax.nulls;
2422 FunctionCallInfo fcinfo = op->d.minmax.fcinfo_data;
2423 MinMaxOp operator = op->d.minmax.op;
2424 int off;
2425
2426 /* set at initialization */
2427 Assert(fcinfo->argnull[0] == false);
2428 Assert(fcinfo->argnull[1] == false);
2429
2430 /* default to null result */
2431 *op->resnull = true;
2432
2433 for (off = 0; off < op->d.minmax.nelems; off++)
2434 {
2435 /* ignore NULL inputs */
2436 if (nulls[off])
2437 continue;
2438
2439 if (*op->resnull)
2440 {
2441 /* first nonnull input, adopt value */
2442 *op->resvalue = values[off];
2443 *op->resnull = false;
2444 }
2445 else
2446 {
2447 int cmpresult;
2448
2449 /* apply comparison function */
2450 fcinfo->arg[0] = *op->resvalue;
2451 fcinfo->arg[1] = values[off];
2452
2453 fcinfo->isnull = false;
2454 cmpresult = DatumGetInt32(FunctionCallInvoke(fcinfo));
2455 if (fcinfo->isnull) /* probably should not happen */
2456 continue;
2457
2458 if (cmpresult > 0 && operator == IS_LEAST)
2459 *op->resvalue = values[off];
2460 else if (cmpresult < 0 && operator == IS_GREATEST)
2461 *op->resvalue = values[off];
2462 }
2463 }
2464 }
2465
2466 /*
2467 * Evaluate a FieldSelect node.
2468 *
2469 * Source record is in step's result variable.
2470 */
2471 void
ExecEvalFieldSelect(ExprState * state,ExprEvalStep * op,ExprContext * econtext)2472 ExecEvalFieldSelect(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
2473 {
2474 AttrNumber fieldnum = op->d.fieldselect.fieldnum;
2475 Datum tupDatum;
2476 HeapTupleHeader tuple;
2477 Oid tupType;
2478 int32 tupTypmod;
2479 TupleDesc tupDesc;
2480 Form_pg_attribute attr;
2481 HeapTupleData tmptup;
2482
2483 /* NULL record -> NULL result */
2484 if (*op->resnull)
2485 return;
2486
2487 /* Get the composite datum and extract its type fields */
2488 tupDatum = *op->resvalue;
2489 tuple = DatumGetHeapTupleHeader(tupDatum);
2490
2491 tupType = HeapTupleHeaderGetTypeId(tuple);
2492 tupTypmod = HeapTupleHeaderGetTypMod(tuple);
2493
2494 /* Lookup tupdesc if first time through or if type changes */
2495 tupDesc = get_cached_rowtype(tupType, tupTypmod,
2496 &op->d.fieldselect.argdesc,
2497 econtext);
2498
2499 /*
2500 * Find field's attr record. Note we don't support system columns here: a
2501 * datum tuple doesn't have valid values for most of the interesting
2502 * system columns anyway.
2503 */
2504 if (fieldnum <= 0) /* should never happen */
2505 elog(ERROR, "unsupported reference to system column %d in FieldSelect",
2506 fieldnum);
2507 if (fieldnum > tupDesc->natts) /* should never happen */
2508 elog(ERROR, "attribute number %d exceeds number of columns %d",
2509 fieldnum, tupDesc->natts);
2510 attr = tupDesc->attrs[fieldnum - 1];
2511
2512 /* Check for dropped column, and force a NULL result if so */
2513 if (attr->attisdropped)
2514 {
2515 *op->resnull = true;
2516 return;
2517 }
2518
2519 /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
2520 /* As in CheckVarSlotCompatibility, we should but can't check typmod */
2521 if (op->d.fieldselect.resulttype != attr->atttypid)
2522 ereport(ERROR,
2523 (errcode(ERRCODE_DATATYPE_MISMATCH),
2524 errmsg("attribute %d has wrong type", fieldnum),
2525 errdetail("Table has type %s, but query expects %s.",
2526 format_type_be(attr->atttypid),
2527 format_type_be(op->d.fieldselect.resulttype))));
2528
2529 /* heap_getattr needs a HeapTuple not a bare HeapTupleHeader */
2530 tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
2531 tmptup.t_data = tuple;
2532
2533 /* extract the field */
2534 *op->resvalue = heap_getattr(&tmptup,
2535 fieldnum,
2536 tupDesc,
2537 op->resnull);
2538 }
2539
2540 /*
2541 * Deform source tuple, filling in the step's values/nulls arrays, before
2542 * evaluating individual new values as part of a FieldStore expression.
2543 * Subsequent steps will overwrite individual elements of the values/nulls
2544 * arrays with the new field values, and then FIELDSTORE_FORM will build the
2545 * new tuple value.
2546 *
2547 * Source record is in step's result variable.
2548 */
2549 void
ExecEvalFieldStoreDeForm(ExprState * state,ExprEvalStep * op,ExprContext * econtext)2550 ExecEvalFieldStoreDeForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
2551 {
2552 TupleDesc tupDesc;
2553
2554 /* Lookup tupdesc if first time through or after rescan */
2555 tupDesc = get_cached_rowtype(op->d.fieldstore.fstore->resulttype, -1,
2556 op->d.fieldstore.argdesc, econtext);
2557
2558 /* Check that current tupdesc doesn't have more fields than we allocated */
2559 if (unlikely(tupDesc->natts > op->d.fieldstore.ncolumns))
2560 elog(ERROR, "too many columns in composite type %u",
2561 op->d.fieldstore.fstore->resulttype);
2562
2563 if (*op->resnull)
2564 {
2565 /* Convert null input tuple into an all-nulls row */
2566 memset(op->d.fieldstore.nulls, true,
2567 op->d.fieldstore.ncolumns * sizeof(bool));
2568 }
2569 else
2570 {
2571 /*
2572 * heap_deform_tuple needs a HeapTuple not a bare HeapTupleHeader. We
2573 * set all the fields in the struct just in case.
2574 */
2575 Datum tupDatum = *op->resvalue;
2576 HeapTupleHeader tuphdr;
2577 HeapTupleData tmptup;
2578
2579 tuphdr = DatumGetHeapTupleHeader(tupDatum);
2580 tmptup.t_len = HeapTupleHeaderGetDatumLength(tuphdr);
2581 ItemPointerSetInvalid(&(tmptup.t_self));
2582 tmptup.t_tableOid = InvalidOid;
2583 tmptup.t_data = tuphdr;
2584
2585 heap_deform_tuple(&tmptup, tupDesc,
2586 op->d.fieldstore.values,
2587 op->d.fieldstore.nulls);
2588 }
2589 }
2590
2591 /*
2592 * Compute the new composite datum after each individual field value of a
2593 * FieldStore expression has been evaluated.
2594 */
2595 void
ExecEvalFieldStoreForm(ExprState * state,ExprEvalStep * op,ExprContext * econtext)2596 ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
2597 {
2598 HeapTuple tuple;
2599
2600 /* argdesc should already be valid from the DeForm step */
2601 tuple = heap_form_tuple(*op->d.fieldstore.argdesc,
2602 op->d.fieldstore.values,
2603 op->d.fieldstore.nulls);
2604
2605 *op->resvalue = HeapTupleGetDatum(tuple);
2606 *op->resnull = false;
2607 }
2608
2609 /*
2610 * Process a subscript in an ArrayRef expression.
2611 *
2612 * If subscript is NULL, throw error in assignment case, or in fetch case
2613 * set result to NULL and return false (instructing caller to skip the rest
2614 * of the ArrayRef sequence).
2615 *
2616 * Subscript expression result is in subscriptvalue/subscriptnull.
2617 * On success, integer subscript value has been saved in upperindex[] or
2618 * lowerindex[] for use later.
2619 */
2620 bool
ExecEvalArrayRefSubscript(ExprState * state,ExprEvalStep * op)2621 ExecEvalArrayRefSubscript(ExprState *state, ExprEvalStep *op)
2622 {
2623 ArrayRefState *arefstate = op->d.arrayref_subscript.state;
2624 int *indexes;
2625 int off;
2626
2627 /* If any index expr yields NULL, result is NULL or error */
2628 if (arefstate->subscriptnull)
2629 {
2630 if (arefstate->isassignment)
2631 ereport(ERROR,
2632 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2633 errmsg("array subscript in assignment must not be null")));
2634 *op->resnull = true;
2635 return false;
2636 }
2637
2638 /* Convert datum to int, save in appropriate place */
2639 if (op->d.arrayref_subscript.isupper)
2640 indexes = arefstate->upperindex;
2641 else
2642 indexes = arefstate->lowerindex;
2643 off = op->d.arrayref_subscript.off;
2644
2645 indexes[off] = DatumGetInt32(arefstate->subscriptvalue);
2646
2647 return true;
2648 }
2649
2650 /*
2651 * Evaluate ArrayRef fetch.
2652 *
2653 * Source array is in step's result variable.
2654 */
2655 void
ExecEvalArrayRefFetch(ExprState * state,ExprEvalStep * op)2656 ExecEvalArrayRefFetch(ExprState *state, ExprEvalStep *op)
2657 {
2658 ArrayRefState *arefstate = op->d.arrayref.state;
2659
2660 /* Should not get here if source array (or any subscript) is null */
2661 Assert(!(*op->resnull));
2662
2663 if (arefstate->numlower == 0)
2664 {
2665 /* Scalar case */
2666 *op->resvalue = array_get_element(*op->resvalue,
2667 arefstate->numupper,
2668 arefstate->upperindex,
2669 arefstate->refattrlength,
2670 arefstate->refelemlength,
2671 arefstate->refelembyval,
2672 arefstate->refelemalign,
2673 op->resnull);
2674 }
2675 else
2676 {
2677 /* Slice case */
2678 *op->resvalue = array_get_slice(*op->resvalue,
2679 arefstate->numupper,
2680 arefstate->upperindex,
2681 arefstate->lowerindex,
2682 arefstate->upperprovided,
2683 arefstate->lowerprovided,
2684 arefstate->refattrlength,
2685 arefstate->refelemlength,
2686 arefstate->refelembyval,
2687 arefstate->refelemalign);
2688 }
2689 }
2690
2691 /*
2692 * Compute old array element/slice value for an ArrayRef assignment
2693 * expression. Will only be generated if the new-value subexpression
2694 * contains ArrayRef or FieldStore. The value is stored into the
2695 * ArrayRefState's prevvalue/prevnull fields.
2696 */
2697 void
ExecEvalArrayRefOld(ExprState * state,ExprEvalStep * op)2698 ExecEvalArrayRefOld(ExprState *state, ExprEvalStep *op)
2699 {
2700 ArrayRefState *arefstate = op->d.arrayref.state;
2701
2702 if (*op->resnull)
2703 {
2704 /* whole array is null, so any element or slice is too */
2705 arefstate->prevvalue = (Datum) 0;
2706 arefstate->prevnull = true;
2707 }
2708 else if (arefstate->numlower == 0)
2709 {
2710 /* Scalar case */
2711 arefstate->prevvalue = array_get_element(*op->resvalue,
2712 arefstate->numupper,
2713 arefstate->upperindex,
2714 arefstate->refattrlength,
2715 arefstate->refelemlength,
2716 arefstate->refelembyval,
2717 arefstate->refelemalign,
2718 &arefstate->prevnull);
2719 }
2720 else
2721 {
2722 /* Slice case */
2723 /* this is currently unreachable */
2724 arefstate->prevvalue = array_get_slice(*op->resvalue,
2725 arefstate->numupper,
2726 arefstate->upperindex,
2727 arefstate->lowerindex,
2728 arefstate->upperprovided,
2729 arefstate->lowerprovided,
2730 arefstate->refattrlength,
2731 arefstate->refelemlength,
2732 arefstate->refelembyval,
2733 arefstate->refelemalign);
2734 arefstate->prevnull = false;
2735 }
2736 }
2737
2738 /*
2739 * Evaluate ArrayRef assignment.
2740 *
2741 * Input array (possibly null) is in result area, replacement value is in
2742 * ArrayRefState's replacevalue/replacenull.
2743 */
2744 void
ExecEvalArrayRefAssign(ExprState * state,ExprEvalStep * op)2745 ExecEvalArrayRefAssign(ExprState *state, ExprEvalStep *op)
2746 {
2747 ArrayRefState *arefstate = op->d.arrayref.state;
2748
2749 /*
2750 * For an assignment to a fixed-length array type, both the original array
2751 * and the value to be assigned into it must be non-NULL, else we punt and
2752 * return the original array.
2753 */
2754 if (arefstate->refattrlength > 0) /* fixed-length array? */
2755 {
2756 if (*op->resnull || arefstate->replacenull)
2757 return;
2758 }
2759
2760 /*
2761 * For assignment to varlena arrays, we handle a NULL original array by
2762 * substituting an empty (zero-dimensional) array; insertion of the new
2763 * element will result in a singleton array value. It does not matter
2764 * whether the new element is NULL.
2765 */
2766 if (*op->resnull)
2767 {
2768 *op->resvalue = PointerGetDatum(construct_empty_array(arefstate->refelemtype));
2769 *op->resnull = false;
2770 }
2771
2772 if (arefstate->numlower == 0)
2773 {
2774 /* Scalar case */
2775 *op->resvalue = array_set_element(*op->resvalue,
2776 arefstate->numupper,
2777 arefstate->upperindex,
2778 arefstate->replacevalue,
2779 arefstate->replacenull,
2780 arefstate->refattrlength,
2781 arefstate->refelemlength,
2782 arefstate->refelembyval,
2783 arefstate->refelemalign);
2784 }
2785 else
2786 {
2787 /* Slice case */
2788 *op->resvalue = array_set_slice(*op->resvalue,
2789 arefstate->numupper,
2790 arefstate->upperindex,
2791 arefstate->lowerindex,
2792 arefstate->upperprovided,
2793 arefstate->lowerprovided,
2794 arefstate->replacevalue,
2795 arefstate->replacenull,
2796 arefstate->refattrlength,
2797 arefstate->refelemlength,
2798 arefstate->refelembyval,
2799 arefstate->refelemalign);
2800 }
2801 }
2802
2803 /*
2804 * Evaluate a rowtype coercion operation.
2805 * This may require rearranging field positions.
2806 *
2807 * Source record is in step's result variable.
2808 */
2809 void
ExecEvalConvertRowtype(ExprState * state,ExprEvalStep * op,ExprContext * econtext)2810 ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
2811 {
2812 ConvertRowtypeExpr *convert = op->d.convert_rowtype.convert;
2813 HeapTuple result;
2814 Datum tupDatum;
2815 HeapTupleHeader tuple;
2816 HeapTupleData tmptup;
2817 TupleDesc indesc,
2818 outdesc;
2819
2820 /* NULL in -> NULL out */
2821 if (*op->resnull)
2822 return;
2823
2824 tupDatum = *op->resvalue;
2825 tuple = DatumGetHeapTupleHeader(tupDatum);
2826
2827 /* Lookup tupdescs if first time through or after rescan */
2828 if (op->d.convert_rowtype.indesc == NULL)
2829 {
2830 get_cached_rowtype(exprType((Node *) convert->arg), -1,
2831 &op->d.convert_rowtype.indesc,
2832 econtext);
2833 op->d.convert_rowtype.initialized = false;
2834 }
2835 if (op->d.convert_rowtype.outdesc == NULL)
2836 {
2837 get_cached_rowtype(convert->resulttype, -1,
2838 &op->d.convert_rowtype.outdesc,
2839 econtext);
2840 op->d.convert_rowtype.initialized = false;
2841 }
2842
2843 indesc = op->d.convert_rowtype.indesc;
2844 outdesc = op->d.convert_rowtype.outdesc;
2845
2846 /*
2847 * We used to be able to assert that incoming tuples are marked with
2848 * exactly the rowtype of indesc. However, now that ExecEvalWholeRowVar
2849 * might change the tuples' marking to plain RECORD due to inserting
2850 * aliases, we can only make this weak test:
2851 */
2852 Assert(HeapTupleHeaderGetTypeId(tuple) == indesc->tdtypeid ||
2853 HeapTupleHeaderGetTypeId(tuple) == RECORDOID);
2854
2855 /* if first time through, initialize conversion map */
2856 if (!op->d.convert_rowtype.initialized)
2857 {
2858 MemoryContext old_cxt;
2859
2860 /* allocate map in long-lived memory context */
2861 old_cxt = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
2862
2863 /* prepare map from old to new attribute numbers */
2864 op->d.convert_rowtype.map =
2865 convert_tuples_by_name(indesc, outdesc,
2866 gettext_noop("could not convert row type"));
2867 op->d.convert_rowtype.initialized = true;
2868
2869 MemoryContextSwitchTo(old_cxt);
2870 }
2871
2872 /* Following steps need a HeapTuple not a bare HeapTupleHeader */
2873 tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
2874 tmptup.t_data = tuple;
2875
2876 if (op->d.convert_rowtype.map != NULL)
2877 {
2878 /* Full conversion with attribute rearrangement needed */
2879 result = do_convert_tuple(&tmptup, op->d.convert_rowtype.map);
2880 /* Result already has appropriate composite-datum header fields */
2881 *op->resvalue = HeapTupleGetDatum(result);
2882 }
2883 else
2884 {
2885 /*
2886 * The tuple is physically compatible as-is, but we need to insert the
2887 * destination rowtype OID in its composite-datum header field, so we
2888 * have to copy it anyway. heap_copy_tuple_as_datum() is convenient
2889 * for this since it will both make the physical copy and insert the
2890 * correct composite header fields. Note that we aren't expecting to
2891 * have to flatten any toasted fields: the input was a composite
2892 * datum, so it shouldn't contain any. So heap_copy_tuple_as_datum()
2893 * is overkill here, but its check for external fields is cheap.
2894 */
2895 *op->resvalue = heap_copy_tuple_as_datum(&tmptup, outdesc);
2896 }
2897 }
2898
2899 /*
2900 * Evaluate "scalar op ANY/ALL (array)".
2901 *
2902 * Source array is in our result area, scalar arg is already evaluated into
2903 * fcinfo->arg[0]/argnull[0].
2904 *
2905 * The operator always yields boolean, and we combine the results across all
2906 * array elements using OR and AND (for ANY and ALL respectively). Of course
2907 * we short-circuit as soon as the result is known.
2908 */
2909 void
ExecEvalScalarArrayOp(ExprState * state,ExprEvalStep * op)2910 ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
2911 {
2912 FunctionCallInfo fcinfo = op->d.scalararrayop.fcinfo_data;
2913 bool useOr = op->d.scalararrayop.useOr;
2914 bool strictfunc = op->d.scalararrayop.finfo->fn_strict;
2915 ArrayType *arr;
2916 int nitems;
2917 Datum result;
2918 bool resultnull;
2919 int i;
2920 int16 typlen;
2921 bool typbyval;
2922 char typalign;
2923 char *s;
2924 bits8 *bitmap;
2925 int bitmask;
2926
2927 /*
2928 * If the array is NULL then we return NULL --- it's not very meaningful
2929 * to do anything else, even if the operator isn't strict.
2930 */
2931 if (*op->resnull)
2932 return;
2933
2934 /* Else okay to fetch and detoast the array */
2935 arr = DatumGetArrayTypeP(*op->resvalue);
2936
2937 /*
2938 * If the array is empty, we return either FALSE or TRUE per the useOr
2939 * flag. This is correct even if the scalar is NULL; since we would
2940 * evaluate the operator zero times, it matters not whether it would want
2941 * to return NULL.
2942 */
2943 nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
2944 if (nitems <= 0)
2945 {
2946 *op->resvalue = BoolGetDatum(!useOr);
2947 *op->resnull = false;
2948 return;
2949 }
2950
2951 /*
2952 * If the scalar is NULL, and the function is strict, return NULL; no
2953 * point in iterating the loop.
2954 */
2955 if (fcinfo->argnull[0] && strictfunc)
2956 {
2957 *op->resnull = true;
2958 return;
2959 }
2960
2961 /*
2962 * We arrange to look up info about the element type only once per series
2963 * of calls, assuming the element type doesn't change underneath us.
2964 */
2965 if (op->d.scalararrayop.element_type != ARR_ELEMTYPE(arr))
2966 {
2967 get_typlenbyvalalign(ARR_ELEMTYPE(arr),
2968 &op->d.scalararrayop.typlen,
2969 &op->d.scalararrayop.typbyval,
2970 &op->d.scalararrayop.typalign);
2971 op->d.scalararrayop.element_type = ARR_ELEMTYPE(arr);
2972 }
2973
2974 typlen = op->d.scalararrayop.typlen;
2975 typbyval = op->d.scalararrayop.typbyval;
2976 typalign = op->d.scalararrayop.typalign;
2977
2978 /* Initialize result appropriately depending on useOr */
2979 result = BoolGetDatum(!useOr);
2980 resultnull = false;
2981
2982 /* Loop over the array elements */
2983 s = (char *) ARR_DATA_PTR(arr);
2984 bitmap = ARR_NULLBITMAP(arr);
2985 bitmask = 1;
2986
2987 for (i = 0; i < nitems; i++)
2988 {
2989 Datum elt;
2990 Datum thisresult;
2991
2992 /* Get array element, checking for NULL */
2993 if (bitmap && (*bitmap & bitmask) == 0)
2994 {
2995 fcinfo->arg[1] = (Datum) 0;
2996 fcinfo->argnull[1] = true;
2997 }
2998 else
2999 {
3000 elt = fetch_att(s, typbyval, typlen);
3001 s = att_addlength_pointer(s, typlen, s);
3002 s = (char *) att_align_nominal(s, typalign);
3003 fcinfo->arg[1] = elt;
3004 fcinfo->argnull[1] = false;
3005 }
3006
3007 /* Call comparison function */
3008 if (fcinfo->argnull[1] && strictfunc)
3009 {
3010 fcinfo->isnull = true;
3011 thisresult = (Datum) 0;
3012 }
3013 else
3014 {
3015 fcinfo->isnull = false;
3016 thisresult = (op->d.scalararrayop.fn_addr) (fcinfo);
3017 }
3018
3019 /* Combine results per OR or AND semantics */
3020 if (fcinfo->isnull)
3021 resultnull = true;
3022 else if (useOr)
3023 {
3024 if (DatumGetBool(thisresult))
3025 {
3026 result = BoolGetDatum(true);
3027 resultnull = false;
3028 break; /* needn't look at any more elements */
3029 }
3030 }
3031 else
3032 {
3033 if (!DatumGetBool(thisresult))
3034 {
3035 result = BoolGetDatum(false);
3036 resultnull = false;
3037 break; /* needn't look at any more elements */
3038 }
3039 }
3040
3041 /* advance bitmap pointer if any */
3042 if (bitmap)
3043 {
3044 bitmask <<= 1;
3045 if (bitmask == 0x100)
3046 {
3047 bitmap++;
3048 bitmask = 1;
3049 }
3050 }
3051 }
3052
3053 *op->resvalue = result;
3054 *op->resnull = resultnull;
3055 }
3056
3057 /*
3058 * Evaluate a NOT NULL domain constraint.
3059 */
3060 void
ExecEvalConstraintNotNull(ExprState * state,ExprEvalStep * op)3061 ExecEvalConstraintNotNull(ExprState *state, ExprEvalStep *op)
3062 {
3063 if (*op->resnull)
3064 ereport(ERROR,
3065 (errcode(ERRCODE_NOT_NULL_VIOLATION),
3066 errmsg("domain %s does not allow null values",
3067 format_type_be(op->d.domaincheck.resulttype)),
3068 errdatatype(op->d.domaincheck.resulttype)));
3069 }
3070
3071 /*
3072 * Evaluate a CHECK domain constraint.
3073 */
3074 void
ExecEvalConstraintCheck(ExprState * state,ExprEvalStep * op)3075 ExecEvalConstraintCheck(ExprState *state, ExprEvalStep *op)
3076 {
3077 if (!*op->d.domaincheck.checknull &&
3078 !DatumGetBool(*op->d.domaincheck.checkvalue))
3079 ereport(ERROR,
3080 (errcode(ERRCODE_CHECK_VIOLATION),
3081 errmsg("value for domain %s violates check constraint \"%s\"",
3082 format_type_be(op->d.domaincheck.resulttype),
3083 op->d.domaincheck.constraintname),
3084 errdomainconstraint(op->d.domaincheck.resulttype,
3085 op->d.domaincheck.constraintname)));
3086 }
3087
3088 /*
3089 * Evaluate the various forms of XmlExpr.
3090 *
3091 * Arguments have been evaluated into named_argvalue/named_argnull
3092 * and/or argvalue/argnull arrays.
3093 */
3094 void
ExecEvalXmlExpr(ExprState * state,ExprEvalStep * op)3095 ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op)
3096 {
3097 XmlExpr *xexpr = op->d.xmlexpr.xexpr;
3098 Datum value;
3099 int i;
3100
3101 *op->resnull = true; /* until we get a result */
3102 *op->resvalue = (Datum) 0;
3103
3104 switch (xexpr->op)
3105 {
3106 case IS_XMLCONCAT:
3107 {
3108 Datum *argvalue = op->d.xmlexpr.argvalue;
3109 bool *argnull = op->d.xmlexpr.argnull;
3110 List *values = NIL;
3111
3112 for (i = 0; i < list_length(xexpr->args); i++)
3113 {
3114 if (!argnull[i])
3115 values = lappend(values, DatumGetPointer(argvalue[i]));
3116 }
3117
3118 if (values != NIL)
3119 {
3120 *op->resvalue = PointerGetDatum(xmlconcat(values));
3121 *op->resnull = false;
3122 }
3123 }
3124 break;
3125
3126 case IS_XMLFOREST:
3127 {
3128 Datum *argvalue = op->d.xmlexpr.named_argvalue;
3129 bool *argnull = op->d.xmlexpr.named_argnull;
3130 StringInfoData buf;
3131 ListCell *lc;
3132 ListCell *lc2;
3133
3134 initStringInfo(&buf);
3135
3136 i = 0;
3137 forboth(lc, xexpr->named_args, lc2, xexpr->arg_names)
3138 {
3139 Expr *e = (Expr *) lfirst(lc);
3140 char *argname = strVal(lfirst(lc2));
3141
3142 if (!argnull[i])
3143 {
3144 value = argvalue[i];
3145 appendStringInfo(&buf, "<%s>%s</%s>",
3146 argname,
3147 map_sql_value_to_xml_value(value,
3148 exprType((Node *) e), true),
3149 argname);
3150 *op->resnull = false;
3151 }
3152 i++;
3153 }
3154
3155 if (!*op->resnull)
3156 {
3157 text *result;
3158
3159 result = cstring_to_text_with_len(buf.data, buf.len);
3160 *op->resvalue = PointerGetDatum(result);
3161 }
3162
3163 pfree(buf.data);
3164 }
3165 break;
3166
3167 case IS_XMLELEMENT:
3168 *op->resvalue = PointerGetDatum(xmlelement(xexpr,
3169 op->d.xmlexpr.named_argvalue,
3170 op->d.xmlexpr.named_argnull,
3171 op->d.xmlexpr.argvalue,
3172 op->d.xmlexpr.argnull));
3173 *op->resnull = false;
3174 break;
3175
3176 case IS_XMLPARSE:
3177 {
3178 Datum *argvalue = op->d.xmlexpr.argvalue;
3179 bool *argnull = op->d.xmlexpr.argnull;
3180 text *data;
3181 bool preserve_whitespace;
3182
3183 /* arguments are known to be text, bool */
3184 Assert(list_length(xexpr->args) == 2);
3185
3186 if (argnull[0])
3187 return;
3188 value = argvalue[0];
3189 data = DatumGetTextPP(value);
3190
3191 if (argnull[1]) /* probably can't happen */
3192 return;
3193 value = argvalue[1];
3194 preserve_whitespace = DatumGetBool(value);
3195
3196 *op->resvalue = PointerGetDatum(xmlparse(data,
3197 xexpr->xmloption,
3198 preserve_whitespace));
3199 *op->resnull = false;
3200 }
3201 break;
3202
3203 case IS_XMLPI:
3204 {
3205 text *arg;
3206 bool isnull;
3207
3208 /* optional argument is known to be text */
3209 Assert(list_length(xexpr->args) <= 1);
3210
3211 if (xexpr->args)
3212 {
3213 isnull = op->d.xmlexpr.argnull[0];
3214 if (isnull)
3215 arg = NULL;
3216 else
3217 arg = DatumGetTextPP(op->d.xmlexpr.argvalue[0]);
3218 }
3219 else
3220 {
3221 arg = NULL;
3222 isnull = false;
3223 }
3224
3225 *op->resvalue = PointerGetDatum(xmlpi(xexpr->name,
3226 arg,
3227 isnull,
3228 op->resnull));
3229 }
3230 break;
3231
3232 case IS_XMLROOT:
3233 {
3234 Datum *argvalue = op->d.xmlexpr.argvalue;
3235 bool *argnull = op->d.xmlexpr.argnull;
3236 xmltype *data;
3237 text *version;
3238 int standalone;
3239
3240 /* arguments are known to be xml, text, int */
3241 Assert(list_length(xexpr->args) == 3);
3242
3243 if (argnull[0])
3244 return;
3245 data = DatumGetXmlP(argvalue[0]);
3246
3247 if (argnull[1])
3248 version = NULL;
3249 else
3250 version = DatumGetTextPP(argvalue[1]);
3251
3252 Assert(!argnull[2]); /* always present */
3253 standalone = DatumGetInt32(argvalue[2]);
3254
3255 *op->resvalue = PointerGetDatum(xmlroot(data,
3256 version,
3257 standalone));
3258 *op->resnull = false;
3259 }
3260 break;
3261
3262 case IS_XMLSERIALIZE:
3263 {
3264 Datum *argvalue = op->d.xmlexpr.argvalue;
3265 bool *argnull = op->d.xmlexpr.argnull;
3266
3267 /* argument type is known to be xml */
3268 Assert(list_length(xexpr->args) == 1);
3269
3270 if (argnull[0])
3271 return;
3272 value = argvalue[0];
3273
3274 *op->resvalue = PointerGetDatum(
3275 xmltotext_with_xmloption(DatumGetXmlP(value),
3276 xexpr->xmloption));
3277 *op->resnull = false;
3278 }
3279 break;
3280
3281 case IS_DOCUMENT:
3282 {
3283 Datum *argvalue = op->d.xmlexpr.argvalue;
3284 bool *argnull = op->d.xmlexpr.argnull;
3285
3286 /* optional argument is known to be xml */
3287 Assert(list_length(xexpr->args) == 1);
3288
3289 if (argnull[0])
3290 return;
3291 value = argvalue[0];
3292
3293 *op->resvalue =
3294 BoolGetDatum(xml_is_document(DatumGetXmlP(value)));
3295 *op->resnull = false;
3296 }
3297 break;
3298
3299 default:
3300 elog(ERROR, "unrecognized XML operation");
3301 break;
3302 }
3303 }
3304
3305 /*
3306 * ExecEvalGroupingFunc
3307 *
3308 * Computes a bitmask with a bit for each (unevaluated) argument expression
3309 * (rightmost arg is least significant bit).
3310 *
3311 * A bit is set if the corresponding expression is NOT part of the set of
3312 * grouping expressions in the current grouping set.
3313 */
3314 void
ExecEvalGroupingFunc(ExprState * state,ExprEvalStep * op)3315 ExecEvalGroupingFunc(ExprState *state, ExprEvalStep *op)
3316 {
3317 int result = 0;
3318 Bitmapset *grouped_cols = op->d.grouping_func.parent->grouped_cols;
3319 ListCell *lc;
3320
3321 foreach(lc, op->d.grouping_func.clauses)
3322 {
3323 int attnum = lfirst_int(lc);
3324
3325 result <<= 1;
3326
3327 if (!bms_is_member(attnum, grouped_cols))
3328 result |= 1;
3329 }
3330
3331 *op->resvalue = Int32GetDatum(result);
3332 *op->resnull = false;
3333 }
3334
3335 /*
3336 * Hand off evaluation of a subplan to nodeSubplan.c
3337 */
3338 void
ExecEvalSubPlan(ExprState * state,ExprEvalStep * op,ExprContext * econtext)3339 ExecEvalSubPlan(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
3340 {
3341 SubPlanState *sstate = op->d.subplan.sstate;
3342
3343 /* could potentially be nested, so make sure there's enough stack */
3344 check_stack_depth();
3345
3346 *op->resvalue = ExecSubPlan(sstate, econtext, op->resnull);
3347 }
3348
3349 /*
3350 * Hand off evaluation of an alternative subplan to nodeSubplan.c
3351 */
3352 void
ExecEvalAlternativeSubPlan(ExprState * state,ExprEvalStep * op,ExprContext * econtext)3353 ExecEvalAlternativeSubPlan(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
3354 {
3355 AlternativeSubPlanState *asstate = op->d.alternative_subplan.asstate;
3356
3357 /* could potentially be nested, so make sure there's enough stack */
3358 check_stack_depth();
3359
3360 *op->resvalue = ExecAlternativeSubPlan(asstate, econtext, op->resnull);
3361 }
3362
3363 /*
3364 * Evaluate a wholerow Var expression.
3365 *
3366 * Returns a Datum whose value is the value of a whole-row range variable
3367 * with respect to given expression context.
3368 */
3369 void
ExecEvalWholeRowVar(ExprState * state,ExprEvalStep * op,ExprContext * econtext)3370 ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
3371 {
3372 Var *variable = op->d.wholerow.var;
3373 TupleTableSlot *slot;
3374 TupleDesc output_tupdesc;
3375 MemoryContext oldcontext;
3376 HeapTupleHeader dtuple;
3377 HeapTuple tuple;
3378
3379 /* This was checked by ExecInitExpr */
3380 Assert(variable->varattno == InvalidAttrNumber);
3381
3382 /* Get the input slot we want */
3383 switch (variable->varno)
3384 {
3385 case INNER_VAR:
3386 /* get the tuple from the inner node */
3387 slot = econtext->ecxt_innertuple;
3388 break;
3389
3390 case OUTER_VAR:
3391 /* get the tuple from the outer node */
3392 slot = econtext->ecxt_outertuple;
3393 break;
3394
3395 /* INDEX_VAR is handled by default case */
3396
3397 default:
3398 /* get the tuple from the relation being scanned */
3399 slot = econtext->ecxt_scantuple;
3400 break;
3401 }
3402
3403 /* Apply the junkfilter if any */
3404 if (op->d.wholerow.junkFilter != NULL)
3405 slot = ExecFilterJunk(op->d.wholerow.junkFilter, slot);
3406
3407 /*
3408 * If first time through, obtain tuple descriptor and check compatibility.
3409 *
3410 * XXX: It'd be great if this could be moved to the expression
3411 * initialization phase, but due to using slots that's currently not
3412 * feasible.
3413 */
3414 if (op->d.wholerow.first)
3415 {
3416 /* optimistically assume we don't need slow path */
3417 op->d.wholerow.slow = false;
3418
3419 /*
3420 * If the Var identifies a named composite type, we must check that
3421 * the actual tuple type is compatible with it.
3422 */
3423 if (variable->vartype != RECORDOID)
3424 {
3425 TupleDesc var_tupdesc;
3426 TupleDesc slot_tupdesc;
3427 int i;
3428
3429 /*
3430 * We really only care about numbers of attributes and data types.
3431 * Also, we can ignore type mismatch on columns that are dropped
3432 * in the destination type, so long as (1) the physical storage
3433 * matches or (2) the actual column value is NULL. Case (1) is
3434 * helpful in some cases involving out-of-date cached plans, while
3435 * case (2) is expected behavior in situations such as an INSERT
3436 * into a table with dropped columns (the planner typically
3437 * generates an INT4 NULL regardless of the dropped column type).
3438 * If we find a dropped column and cannot verify that case (1)
3439 * holds, we have to use the slow path to check (2) for each row.
3440 */
3441 var_tupdesc = lookup_rowtype_tupdesc(variable->vartype, -1);
3442
3443 slot_tupdesc = slot->tts_tupleDescriptor;
3444
3445 if (var_tupdesc->natts != slot_tupdesc->natts)
3446 ereport(ERROR,
3447 (errcode(ERRCODE_DATATYPE_MISMATCH),
3448 errmsg("table row type and query-specified row type do not match"),
3449 errdetail_plural("Table row contains %d attribute, but query expects %d.",
3450 "Table row contains %d attributes, but query expects %d.",
3451 slot_tupdesc->natts,
3452 slot_tupdesc->natts,
3453 var_tupdesc->natts)));
3454
3455 for (i = 0; i < var_tupdesc->natts; i++)
3456 {
3457 Form_pg_attribute vattr = var_tupdesc->attrs[i];
3458 Form_pg_attribute sattr = slot_tupdesc->attrs[i];
3459
3460 if (vattr->atttypid == sattr->atttypid)
3461 continue; /* no worries */
3462 if (!vattr->attisdropped)
3463 ereport(ERROR,
3464 (errcode(ERRCODE_DATATYPE_MISMATCH),
3465 errmsg("table row type and query-specified row type do not match"),
3466 errdetail("Table has type %s at ordinal position %d, but query expects %s.",
3467 format_type_be(sattr->atttypid),
3468 i + 1,
3469 format_type_be(vattr->atttypid))));
3470
3471 if (vattr->attlen != sattr->attlen ||
3472 vattr->attalign != sattr->attalign)
3473 op->d.wholerow.slow = true; /* need to check for nulls */
3474 }
3475
3476 /*
3477 * Use the variable's declared rowtype as the descriptor for the
3478 * output values, modulo possibly assigning new column names
3479 * below. In particular, we *must* absorb any attisdropped
3480 * markings.
3481 */
3482 oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
3483 output_tupdesc = CreateTupleDescCopy(var_tupdesc);
3484 MemoryContextSwitchTo(oldcontext);
3485
3486 ReleaseTupleDesc(var_tupdesc);
3487 }
3488 else
3489 {
3490 /*
3491 * In the RECORD case, we use the input slot's rowtype as the
3492 * descriptor for the output values, modulo possibly assigning new
3493 * column names below.
3494 */
3495 oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
3496 output_tupdesc = CreateTupleDescCopy(slot->tts_tupleDescriptor);
3497 MemoryContextSwitchTo(oldcontext);
3498 }
3499
3500 /*
3501 * Construct a tuple descriptor for the composite values we'll
3502 * produce, and make sure its record type is "blessed". The main
3503 * reason to do this is to be sure that operations such as
3504 * row_to_json() will see the desired column names when they look up
3505 * the descriptor from the type information embedded in the composite
3506 * values.
3507 *
3508 * We already got the correct physical datatype info above, but now we
3509 * should try to find the source RTE and adopt its column aliases, in
3510 * case they are different from the original rowtype's names. For
3511 * example, in "SELECT foo(t) FROM tab t(x,y)", the first two columns
3512 * in the composite output should be named "x" and "y" regardless of
3513 * tab's column names.
3514 *
3515 * If we can't locate the RTE, assume the column names we've got are
3516 * OK. (As of this writing, the only cases where we can't locate the
3517 * RTE are in execution of trigger WHEN clauses, and then the Var will
3518 * have the trigger's relation's rowtype, so its names are fine.)
3519 * Also, if the creator of the RTE didn't bother to fill in an eref
3520 * field, assume our column names are OK. (This happens in COPY, and
3521 * perhaps other places.)
3522 */
3523 if (econtext->ecxt_estate &&
3524 variable->varno <= list_length(econtext->ecxt_estate->es_range_table))
3525 {
3526 RangeTblEntry *rte = rt_fetch(variable->varno,
3527 econtext->ecxt_estate->es_range_table);
3528
3529 if (rte->eref)
3530 ExecTypeSetColNames(output_tupdesc, rte->eref->colnames);
3531 }
3532
3533 /* Bless the tupdesc if needed, and save it in the execution state */
3534 op->d.wholerow.tupdesc = BlessTupleDesc(output_tupdesc);
3535
3536 op->d.wholerow.first = false;
3537 }
3538
3539 /*
3540 * Make sure all columns of the slot are accessible in the slot's
3541 * Datum/isnull arrays.
3542 */
3543 slot_getallattrs(slot);
3544
3545 if (op->d.wholerow.slow)
3546 {
3547 /* Check to see if any dropped attributes are non-null */
3548 TupleDesc tupleDesc = slot->tts_tupleDescriptor;
3549 TupleDesc var_tupdesc = op->d.wholerow.tupdesc;
3550 int i;
3551
3552 Assert(var_tupdesc->natts == tupleDesc->natts);
3553
3554 for (i = 0; i < var_tupdesc->natts; i++)
3555 {
3556 Form_pg_attribute vattr = var_tupdesc->attrs[i];
3557 Form_pg_attribute sattr = tupleDesc->attrs[i];
3558
3559 if (!vattr->attisdropped)
3560 continue; /* already checked non-dropped cols */
3561 if (slot->tts_isnull[i])
3562 continue; /* null is always okay */
3563 if (vattr->attlen != sattr->attlen ||
3564 vattr->attalign != sattr->attalign)
3565 ereport(ERROR,
3566 (errcode(ERRCODE_DATATYPE_MISMATCH),
3567 errmsg("table row type and query-specified row type do not match"),
3568 errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
3569 i + 1)));
3570 }
3571 }
3572
3573 /*
3574 * Build a composite datum, making sure any toasted fields get detoasted.
3575 *
3576 * (Note: it is critical that we not change the slot's state here.)
3577 */
3578 tuple = toast_build_flattened_tuple(slot->tts_tupleDescriptor,
3579 slot->tts_values,
3580 slot->tts_isnull);
3581 dtuple = tuple->t_data;
3582
3583 /*
3584 * Label the datum with the composite type info we identified before.
3585 *
3586 * (Note: we could skip doing this by passing op->d.wholerow.tupdesc to
3587 * the tuple build step; but that seems a tad risky so let's not.)
3588 */
3589 HeapTupleHeaderSetTypeId(dtuple, op->d.wholerow.tupdesc->tdtypeid);
3590 HeapTupleHeaderSetTypMod(dtuple, op->d.wholerow.tupdesc->tdtypmod);
3591
3592 *op->resvalue = PointerGetDatum(dtuple);
3593 *op->resnull = false;
3594 }
3595