Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * execUtils.c
4 : * miscellaneous executor utility routines
5 : *
6 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/executor/execUtils.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : /*
16 : * INTERFACE ROUTINES
17 : * CreateExecutorState Create/delete executor working state
18 : * FreeExecutorState
19 : * CreateExprContext
20 : * CreateStandaloneExprContext
21 : * FreeExprContext
22 : * ReScanExprContext
23 : *
24 : * ExecAssignExprContext Common code for plan node init routines.
25 : * etc
26 : *
27 : * ExecOpenScanRelation Common code for scan node init routines.
28 : *
29 : * ExecInitRangeTable Set up executor's range-table-related data.
30 : *
31 : * ExecGetRangeTableRelation Fetch Relation for a rangetable entry.
32 : *
33 : * executor_errposition Report syntactic position of an error.
34 : *
35 : * RegisterExprContextCallback Register function shutdown callback
36 : * UnregisterExprContextCallback Deregister function shutdown callback
37 : *
38 : * GetAttributeByName Runtime extraction of columns from tuples.
39 : * GetAttributeByNum
40 : *
41 : * NOTES
42 : * This file has traditionally been the place to stick misc.
43 : * executor support stuff that doesn't really go anyplace else.
44 : */
45 :
46 : #include "postgres.h"
47 :
48 : #include "access/parallel.h"
49 : #include "access/relscan.h"
50 : #include "access/table.h"
51 : #include "access/tableam.h"
52 : #include "access/transam.h"
53 : #include "executor/executor.h"
54 : #include "executor/execPartition.h"
55 : #include "executor/nodeModifyTable.h"
56 : #include "jit/jit.h"
57 : #include "mb/pg_wchar.h"
58 : #include "miscadmin.h"
59 : #include "nodes/nodeFuncs.h"
60 : #include "parser/parsetree.h"
61 : #include "parser/parse_relation.h"
62 : #include "partitioning/partdesc.h"
63 : #include "storage/lmgr.h"
64 : #include "utils/builtins.h"
65 : #include "utils/memutils.h"
66 : #include "utils/rel.h"
67 : #include "utils/typcache.h"
68 :
69 :
70 : static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc);
71 : static void ShutdownExprContext(ExprContext *econtext, bool isCommit);
72 : static RTEPermissionInfo *GetResultRTEPermissionInfo(ResultRelInfo *relinfo, EState *estate);
73 :
74 :
75 : /* ----------------------------------------------------------------
76 : * Executor state and memory management functions
77 : * ----------------------------------------------------------------
78 : */
79 :
80 : /* ----------------
81 : * CreateExecutorState
82 : *
83 : * Create and initialize an EState node, which is the root of
84 : * working storage for an entire Executor invocation.
85 : *
86 : * Principally, this creates the per-query memory context that will be
87 : * used to hold all working data that lives till the end of the query.
88 : * Note that the per-query context will become a child of the caller's
89 : * CurrentMemoryContext.
90 : * ----------------
91 : */
92 : EState *
7420 tgl 93 GIC 609142 : CreateExecutorState(void)
94 : {
5885 tgl 95 ECB : EState *estate;
96 : MemoryContext qcontext;
97 : MemoryContext oldcontext;
98 :
99 : /*
100 : * Create the per-query context for this Executor run.
101 : */
7420 tgl 102 GIC 609142 : qcontext = AllocSetContextCreate(CurrentMemoryContext,
103 : "ExecutorState",
2416 tgl 104 ECB : ALLOCSET_DEFAULT_SIZES);
105 :
106 : /*
107 : * Make the EState node within the per-query context. This way, we don't
108 : * need a separate pfree() operation for it at shutdown.
109 : */
7420 tgl 110 GIC 609142 : oldcontext = MemoryContextSwitchTo(qcontext);
111 :
7420 tgl 112 CBC 609142 : estate = makeNode(EState);
113 :
7420 tgl 114 ECB : /*
115 : * Initialize all fields of the Executor State structure
116 : */
7420 tgl 117 GIC 609142 : estate->es_direction = ForwardScanDirection;
2118 118 609142 : estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */
6784 tgl 119 CBC 609142 : estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
7420 120 609142 : estate->es_range_table = NIL;
1648 121 609142 : estate->es_range_table_size = 0;
122 609142 : estate->es_relations = NULL;
1644 123 609142 : estate->es_rowmarks = NULL;
34 tgl 124 GNC 609142 : estate->es_rteperminfos = NIL;
4913 tgl 125 CBC 609142 : estate->es_plannedstmt = NULL;
129 alvherre 126 GNC 609142 : estate->es_part_prune_infos = NIL;
7420 tgl 127 ECB :
4927 tgl 128 CBC 609142 : estate->es_junkFilter = NULL;
4927 tgl 129 ECB :
5609 tgl 130 CBC 609142 : estate->es_output_cid = (CommandId) 0;
131 :
7420 132 609142 : estate->es_result_relations = NULL;
908 heikki.linnakangas 133 GIC 609142 : estate->es_opened_result_relations = NIL;
1886 rhaas 134 CBC 609142 : estate->es_tuple_routing_result_relations = NIL;
5716 tgl 135 GIC 609142 : estate->es_trig_target_relations = NIL;
6355 tgl 136 ECB :
122 efujita 137 CBC 609142 : estate->es_insert_pending_result_relations = NIL;
138 609142 : estate->es_insert_pending_modifytables = NIL;
122 efujita 139 ECB :
7420 tgl 140 CBC 609142 : estate->es_param_list_info = NULL;
7420 tgl 141 GIC 609142 : estate->es_param_exec_vals = NULL;
7420 tgl 142 ECB :
2200 kgrittn 143 CBC 609142 : estate->es_queryEnv = NULL;
144 :
7420 tgl 145 609142 : estate->es_query_cxt = qcontext;
146 :
4942 147 609142 : estate->es_tupleTable = NIL;
148 :
7420 149 609142 : estate->es_processed = 0;
3 michael 150 GNC 609142 : estate->es_total_processed = 0;
151 :
4424 tgl 152 CBC 609142 : estate->es_top_eflags = 0;
153 609142 : estate->es_instrument = 0;
4424 tgl 154 GIC 609142 : estate->es_finished = false;
7420 tgl 155 ECB :
7420 tgl 156 CBC 609142 : estate->es_exprcontexts = NIL;
7420 tgl 157 ECB :
5885 tgl 158 GIC 609142 : estate->es_subplanstates = NIL;
5885 tgl 159 ECB :
4426 tgl 160 GIC 609142 : estate->es_auxmodifytables = NIL;
4426 tgl 161 ECB :
7420 tgl 162 GIC 609142 : estate->es_per_tuple_exprcontext = NULL;
7420 tgl 163 ECB :
2237 rhaas 164 GIC 609142 : estate->es_sourceText = NULL;
7420 tgl 165 ECB :
1990 rhaas 166 GIC 609142 : estate->es_use_parallel_mode = false;
1990 rhaas 167 ECB :
1844 andres 168 GIC 609142 : estate->es_jit_flags = 0;
1844 andres 169 CBC 609142 : estate->es_jit = NULL;
170 :
7420 tgl 171 ECB : /*
172 : * Return the executor state structure
173 : */
7420 tgl 174 GIC 609142 : MemoryContextSwitchTo(oldcontext);
175 :
176 609142 : return estate;
7420 tgl 177 ECB : }
178 :
179 : /* ----------------
180 : * FreeExecutorState
181 : *
182 : * Release an EState along with all remaining working storage.
183 : *
184 : * Note: this is not responsible for releasing non-memory resources, such as
185 : * open relations or buffer pins. But it will shut down any still-active
186 : * ExprContexts within the EState and deallocate associated JITed expressions.
187 : * That is sufficient cleanup for situations where the EState has only been
188 : * used for expression evaluation, and not to run a complete Plan.
189 : *
190 : * This can be called in any memory context ... so long as it's not one
191 : * of the ones to be freed.
192 : * ----------------
193 : */
194 : void
7420 tgl 195 GIC 594215 : FreeExecutorState(EState *estate)
196 : {
197 : /*
6385 bruce 198 ECB : * Shut down and free any remaining ExprContexts. We do this explicitly
199 : * to ensure that any remaining shutdown callbacks get called (since they
200 : * might need to release resources that aren't simply memory within the
201 : * per-query memory context).
202 : */
7420 tgl 203 GIC 1484069 : while (estate->es_exprcontexts)
204 : {
205 : /*
6385 bruce 206 ECB : * XXX: seems there ought to be a faster way to implement this than
207 : * repeated list_delete(), no?
208 : */
5013 tgl 209 GIC 889854 : FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts),
210 : true);
211 : /* FreeExprContext removed the list link for us */
7420 tgl 212 ECB : }
213 :
214 : /* release JIT context, if allocated */
1719 andres 215 GIC 594215 : if (estate->es_jit)
216 : {
217 831 : jit_release_context(estate->es_jit);
1719 andres 218 CBC 831 : estate->es_jit = NULL;
219 : }
1719 andres 220 ECB :
1494 rhaas 221 : /* release partition directory, if allocated */
1494 rhaas 222 GIC 594215 : if (estate->es_partition_directory)
223 : {
224 3103 : DestroyPartitionDirectory(estate->es_partition_directory);
1494 rhaas 225 CBC 3103 : estate->es_partition_directory = NULL;
226 : }
1494 rhaas 227 ECB :
7420 tgl 228 : /*
229 : * Free the per-query memory context, thereby releasing all working
230 : * memory, including the EState node itself.
231 : */
5885 tgl 232 GIC 594215 : MemoryContextDelete(estate->es_query_cxt);
9770 scrappy 233 594215 : }
234 :
1097 jdavis 235 ECB : /*
236 : * Internal implementation for CreateExprContext() and CreateWorkExprContext()
237 : * that allows control over the AllocSet parameters.
238 : */
239 : static ExprContext *
1097 jdavis 240 GIC 952634 : CreateExprContextInternal(EState *estate, Size minContextSize,
241 : Size initBlockSize, Size maxBlockSize)
242 : {
7420 tgl 243 ECB : ExprContext *econtext;
244 : MemoryContext oldcontext;
245 :
246 : /* Create the ExprContext node within the per-query memory context */
7420 tgl 247 GIC 952634 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
248 :
249 952634 : econtext = makeNode(ExprContext);
7420 tgl 250 ECB :
251 : /* Initialize fields of ExprContext */
7420 tgl 252 CBC 952634 : econtext->ecxt_scantuple = NULL;
8306 tgl 253 GIC 952634 : econtext->ecxt_innertuple = NULL;
254 952634 : econtext->ecxt_outertuple = NULL;
7420 tgl 255 ECB :
7420 tgl 256 CBC 952634 : econtext->ecxt_per_query_memory = estate->es_query_cxt;
8053 bruce 257 ECB :
258 : /*
7420 tgl 259 : * Create working memory for expression evaluation in this context.
260 : */
8306 tgl 261 GIC 952634 : econtext->ecxt_per_tuple_memory =
7420 262 952634 : AllocSetContextCreate(estate->es_query_cxt,
263 : "ExprContext",
1097 jdavis 264 ECB : minContextSize,
265 : initBlockSize,
266 : maxBlockSize);
267 :
7420 tgl 268 GIC 952634 : econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
269 952634 : econtext->ecxt_param_list_info = estate->es_param_list_info;
270 :
8306 tgl 271 CBC 952634 : econtext->ecxt_aggvalues = NULL;
272 952634 : econtext->ecxt_aggnulls = NULL;
273 :
6962 274 952634 : econtext->caseValue_datum = (Datum) 0;
275 952634 : econtext->caseValue_isNull = true;
276 :
7420 277 952634 : econtext->domainValue_datum = (Datum) 0;
278 952634 : econtext->domainValue_isNull = true;
279 :
280 952634 : econtext->ecxt_estate = estate;
7420 tgl 281 ECB :
7637 tgl 282 GIC 952634 : econtext->ecxt_callbacks = NULL;
8306 tgl 283 ECB :
284 : /*
6385 bruce 285 : * Link the ExprContext into the EState to ensure it is shut down when the
286 : * EState is freed. Because we use lcons(), shutdowns will occur in
287 : * reverse order of creation, which may not be essential but can't hurt.
288 : */
7420 tgl 289 GIC 952634 : estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);
290 :
291 952634 : MemoryContextSwitchTo(oldcontext);
7420 tgl 292 ECB :
8306 tgl 293 GIC 952634 : return econtext;
8306 tgl 294 ECB : }
295 :
1097 jdavis 296 : /* ----------------
297 : * CreateExprContext
298 : *
299 : * Create a context for expression evaluation within an EState.
300 : *
301 : * An executor run may require multiple ExprContexts (we usually make one
302 : * for each Plan node, and a separate one for per-output-tuple processing
303 : * such as constraint checking). Each ExprContext has its own "per-tuple"
304 : * memory context.
305 : *
306 : * Note we make no assumption about the caller's memory context.
307 : * ----------------
308 : */
309 : ExprContext *
1097 jdavis 310 GIC 948644 : CreateExprContext(EState *estate)
311 : {
312 948644 : return CreateExprContextInternal(estate, ALLOCSET_DEFAULT_SIZES);
1097 jdavis 313 ECB : }
314 :
315 :
316 : /* ----------------
317 : * CreateWorkExprContext
318 : *
319 : * Like CreateExprContext, but specifies the AllocSet sizes to be reasonable
320 : * in proportion to work_mem. If the maximum block allocation size is too
321 : * large, it's easy to skip right past work_mem with a single allocation.
322 : * ----------------
323 : */
324 : ExprContext *
1097 jdavis 325 GIC 3990 : CreateWorkExprContext(EState *estate)
326 : {
1060 tgl 327 3990 : Size minContextSize = ALLOCSET_DEFAULT_MINSIZE;
1060 tgl 328 CBC 3990 : Size initBlockSize = ALLOCSET_DEFAULT_INITSIZE;
1060 tgl 329 GIC 3990 : Size maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE;
1097 jdavis 330 ECB :
331 : /* choose the maxBlockSize to be no larger than 1/16 of work_mem */
1097 jdavis 332 CBC 24210 : while (16 * maxBlockSize > work_mem * 1024L)
1097 jdavis 333 GIC 20220 : maxBlockSize >>= 1;
334 :
1097 jdavis 335 CBC 3990 : if (maxBlockSize < ALLOCSET_DEFAULT_INITSIZE)
336 39 : maxBlockSize = ALLOCSET_DEFAULT_INITSIZE;
337 :
338 3990 : return CreateExprContextInternal(estate, minContextSize,
1097 jdavis 339 ECB : initBlockSize, maxBlockSize);
340 : }
341 :
342 : /* ----------------
343 : * CreateStandaloneExprContext
344 : *
345 : * Create a context for standalone expression evaluation.
346 : *
347 : * An ExprContext made this way can be used for evaluation of expressions
348 : * that contain no Params, subplans, or Var references (it might work to
349 : * put tuple references into the scantuple field, but it seems unwise).
350 : *
351 : * The ExprContext struct is allocated in the caller's current memory
352 : * context, which also becomes its "per query" context.
353 : *
354 : * It is caller's responsibility to free the ExprContext when done,
355 : * or at least ensure that any shutdown callbacks have been called
356 : * (ReScanExprContext() is suitable). Otherwise, non-memory resources
357 : * might be leaked.
358 : * ----------------
359 : */
360 : ExprContext *
6092 tgl 361 GIC 5757 : CreateStandaloneExprContext(void)
362 : {
363 : ExprContext *econtext;
6092 tgl 364 ECB :
365 : /* Create the ExprContext node within the caller's memory context */
6092 tgl 366 GIC 5757 : econtext = makeNode(ExprContext);
367 :
368 : /* Initialize fields of ExprContext */
6092 tgl 369 CBC 5757 : econtext->ecxt_scantuple = NULL;
6092 tgl 370 GIC 5757 : econtext->ecxt_innertuple = NULL;
371 5757 : econtext->ecxt_outertuple = NULL;
6092 tgl 372 ECB :
6092 tgl 373 CBC 5757 : econtext->ecxt_per_query_memory = CurrentMemoryContext;
6092 tgl 374 ECB :
375 : /*
376 : * Create working memory for expression evaluation in this context.
377 : */
6092 tgl 378 GIC 5757 : econtext->ecxt_per_tuple_memory =
379 5757 : AllocSetContextCreate(CurrentMemoryContext,
380 : "ExprContext",
2416 tgl 381 ECB : ALLOCSET_DEFAULT_SIZES);
6092 382 :
6092 tgl 383 GIC 5757 : econtext->ecxt_param_exec_vals = NULL;
384 5757 : econtext->ecxt_param_list_info = NULL;
385 :
6092 tgl 386 CBC 5757 : econtext->ecxt_aggvalues = NULL;
387 5757 : econtext->ecxt_aggnulls = NULL;
388 :
389 5757 : econtext->caseValue_datum = (Datum) 0;
390 5757 : econtext->caseValue_isNull = true;
391 :
392 5757 : econtext->domainValue_datum = (Datum) 0;
393 5757 : econtext->domainValue_isNull = true;
394 :
395 5757 : econtext->ecxt_estate = NULL;
6092 tgl 396 ECB :
6092 tgl 397 GIC 5757 : econtext->ecxt_callbacks = NULL;
6092 tgl 398 ECB :
6092 tgl 399 GIC 5757 : return econtext;
6092 tgl 400 ECB : }
401 :
7420 402 : /* ----------------
403 : * FreeExprContext
404 : *
405 : * Free an expression context, including calling any remaining
406 : * shutdown callbacks.
407 : *
408 : * Since we free the temporary context used for expression evaluation,
409 : * any previously computed pass-by-reference expression result will go away!
410 : *
411 : * If isCommit is false, we are being called in error cleanup, and should
412 : * not call callbacks but only release memory. (It might be better to call
413 : * the callbacks and pass the isCommit flag to them, but that would require
414 : * more invasive code changes than currently seems justified.)
415 : *
416 : * Note we make no assumption about the caller's memory context.
417 : * ----------------
418 : */
419 : void
5013 tgl 420 GIC 935636 : FreeExprContext(ExprContext *econtext, bool isCommit)
421 : {
422 : EState *estate;
7420 tgl 423 ECB :
424 : /* Call any registered callbacks */
5013 tgl 425 GIC 935636 : ShutdownExprContext(econtext, isCommit);
426 : /* And clean up the memory used */
8306 427 935636 : MemoryContextDelete(econtext->ecxt_per_tuple_memory);
6092 tgl 428 ECB : /* Unlink self from owning EState, if any */
7420 tgl 429 GIC 935636 : estate = econtext->ecxt_estate;
6092 tgl 430 CBC 935636 : if (estate)
6092 tgl 431 GIC 935636 : estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts,
6092 tgl 432 ECB : econtext);
7420 433 : /* And delete the ExprContext node */
8306 tgl 434 CBC 935636 : pfree(econtext);
9770 scrappy 435 GIC 935636 : }
436 :
7052 tgl 437 ECB : /*
438 : * ReScanExprContext
439 : *
440 : * Reset an expression context in preparation for a rescan of its
441 : * plan node. This requires calling any registered shutdown callbacks,
442 : * since any partially complete set-returning-functions must be canceled.
443 : *
444 : * Note we make no assumption about the caller's memory context.
445 : */
446 : void
7052 tgl 447 GIC 2012784 : ReScanExprContext(ExprContext *econtext)
448 : {
449 : /* Call any registered callbacks */
5013 tgl 450 CBC 2012784 : ShutdownExprContext(econtext, true);
451 : /* And clean up the memory used */
7052 tgl 452 GIC 2012784 : MemoryContextReset(econtext->ecxt_per_tuple_memory);
7052 tgl 453 CBC 2012784 : }
454 :
8112 tgl 455 ECB : /*
456 : * Build a per-output-tuple ExprContext for an EState.
457 : *
458 : * This is normally invoked via GetPerTupleExprContext() macro,
459 : * not directly.
460 : */
461 : ExprContext *
8112 tgl 462 GIC 356389 : MakePerTupleExprContext(EState *estate)
463 : {
464 356389 : if (estate->es_per_tuple_exprcontext == NULL)
7420 tgl 465 CBC 356389 : estate->es_per_tuple_exprcontext = CreateExprContext(estate);
466 :
8112 467 356389 : return estate->es_per_tuple_exprcontext;
8112 tgl 468 ECB : }
469 :
7420 470 :
471 : /* ----------------------------------------------------------------
472 : * miscellaneous node-init support functions
473 : *
474 : * Note: all of these are expected to be called with CurrentMemoryContext
475 : * equal to the per-query memory context.
476 : * ----------------------------------------------------------------
477 : */
478 :
479 : /* ----------------
480 : * ExecAssignExprContext
481 : *
482 : * This initializes the ps_ExprContext field. It is only necessary
483 : * to do this for nodes which use ExecQual or ExecProject
484 : * because those routines require an econtext. Other nodes that
485 : * don't have to evaluate expressions don't need to do this.
486 : * ----------------
487 : */
488 : void
7184 bruce 489 GIC 538683 : ExecAssignExprContext(EState *estate, PlanState *planstate)
490 : {
7420 tgl 491 538683 : planstate->ps_ExprContext = CreateExprContext(estate);
7420 tgl 492 CBC 538683 : }
493 :
9770 scrappy 494 ECB : /* ----------------
9345 bruce 495 : * ExecGetResultType
496 : * ----------------
497 : */
498 : TupleDesc
7184 bruce 499 GIC 641496 : ExecGetResultType(PlanState *planstate)
500 : {
1612 andres 501 641496 : return planstate->ps_ResultTupleDesc;
9770 scrappy 502 ECB : }
503 :
1606 andres 504 : /*
505 : * ExecGetResultSlotOps - information about node's type of result slot
506 : */
507 : const TupleTableSlotOps *
1606 andres 508 GIC 240729 : ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
509 : {
510 240729 : if (planstate->resultopsset && planstate->resultops)
1606 andres 511 ECB : {
1606 andres 512 GIC 240023 : if (isfixed)
1606 andres 513 CBC 218677 : *isfixed = planstate->resultopsfixed;
1606 andres 514 GIC 240023 : return planstate->resultops;
1606 andres 515 ECB : }
516 :
1606 andres 517 CBC 706 : if (isfixed)
518 : {
1606 andres 519 GIC 688 : if (planstate->resultopsset)
1606 andres 520 CBC 688 : *isfixed = planstate->resultopsfixed;
1606 andres 521 UIC 0 : else if (planstate->ps_ResultTupleSlot)
1606 andres 522 LBC 0 : *isfixed = TTS_FIXED(planstate->ps_ResultTupleSlot);
1606 andres 523 ECB : else
1606 andres 524 UBC 0 : *isfixed = false;
1606 andres 525 EUB : }
526 :
1606 andres 527 GBC 706 : if (!planstate->ps_ResultTupleSlot)
1606 andres 528 GIC 706 : return &TTSOpsVirtual;
529 :
1606 andres 530 LBC 0 : return planstate->ps_ResultTupleSlot->tts_ops;
1606 andres 531 ECB : }
532 :
5120 tgl 533 EUB :
534 : /* ----------------
535 : * ExecAssignProjectionInfo
536 : *
537 : * forms the projection information from the node's targetlist
538 : *
539 : * Notes for inputDesc are same as for ExecBuildProjectionInfo: supply it
540 : * for a relation-scan node, can pass NULL for upper-level nodes
541 : * ----------------
542 : */
543 : void
5910 tgl 544 GIC 321760 : ExecAssignProjectionInfo(PlanState *planstate,
545 : TupleDesc inputDesc)
546 : {
7392 tgl 547 CBC 321725 : planstate->ps_ProjInfo =
2217 andres 548 GIC 321760 : ExecBuildProjectionInfo(planstate->plan->targetlist,
549 : planstate->ps_ExprContext,
5910 tgl 550 ECB : planstate->ps_ResultTupleSlot,
2217 andres 551 : planstate,
552 : inputDesc);
9770 scrappy 553 GIC 321725 : }
554 :
555 :
1961 rhaas 556 ECB : /* ----------------
557 : * ExecConditionalAssignProjectionInfo
558 : *
559 : * as ExecAssignProjectionInfo, but store NULL rather than building projection
560 : * info if no projection is required
561 : * ----------------
562 : */
563 : void
1961 rhaas 564 GIC 210337 : ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc,
565 : int varno)
566 : {
1961 rhaas 567 CBC 210337 : if (tlist_matches_tupdesc(planstate,
1961 rhaas 568 GIC 210337 : planstate->plan->targetlist,
569 : varno,
1961 rhaas 570 ECB : inputDesc))
1606 andres 571 : {
1961 rhaas 572 GIC 109463 : planstate->ps_ProjInfo = NULL;
1606 andres 573 109463 : planstate->resultopsset = planstate->scanopsset;
574 109463 : planstate->resultopsfixed = planstate->scanopsfixed;
1606 andres 575 CBC 109463 : planstate->resultops = planstate->scanops;
1606 andres 576 ECB : }
1961 rhaas 577 : else
1612 andres 578 : {
1612 andres 579 GIC 100874 : if (!planstate->ps_ResultTupleSlot)
580 : {
1606 581 100874 : ExecInitResultSlot(planstate, &TTSOpsVirtual);
1606 andres 582 CBC 100874 : planstate->resultops = &TTSOpsVirtual;
1606 andres 583 GIC 100874 : planstate->resultopsfixed = true;
1606 andres 584 CBC 100874 : planstate->resultopsset = true;
1606 andres 585 ECB : }
1961 rhaas 586 CBC 100874 : ExecAssignProjectionInfo(planstate, inputDesc);
1612 andres 587 ECB : }
1961 rhaas 588 GIC 210337 : }
1961 rhaas 589 ECB :
590 : static bool
571 tgl 591 CBC 210337 : tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc)
592 : {
1961 rhaas 593 GIC 210337 : int numattrs = tupdesc->natts;
1961 rhaas 594 ECB : int attrno;
1961 rhaas 595 GIC 210337 : ListCell *tlist_item = list_head(tlist);
1961 rhaas 596 ECB :
597 : /* Check the tlist attributes */
1961 rhaas 598 CBC 1445430 : for (attrno = 1; attrno <= numattrs; attrno++)
599 : {
1961 rhaas 600 GIC 1330048 : Form_pg_attribute att_tup = TupleDescAttr(tupdesc, attrno - 1);
1961 rhaas 601 ECB : Var *var;
602 :
1961 rhaas 603 CBC 1330048 : if (tlist_item == NULL)
1961 rhaas 604 GIC 15106 : return false; /* tlist too short */
605 1314942 : var = (Var *) ((TargetEntry *) lfirst(tlist_item))->expr;
1961 rhaas 606 CBC 1314942 : if (!var || !IsA(var, Var))
607 29680 : return false; /* tlist item not a Var */
1961 rhaas 608 ECB : /* if these Asserts fail, planner messed up */
1961 rhaas 609 CBC 1285262 : Assert(var->varno == varno);
610 1285262 : Assert(var->varlevelsup == 0);
1961 rhaas 611 GIC 1285262 : if (var->varattno != attrno)
1961 rhaas 612 CBC 50025 : return false; /* out of order */
613 1235237 : if (att_tup->attisdropped)
1961 rhaas 614 LBC 0 : return false; /* table contains dropped columns */
1838 andrew 615 CBC 1235237 : if (att_tup->atthasmissing)
616 141 : return false; /* table contains cols with missing values */
1961 rhaas 617 EUB :
1961 rhaas 618 ECB : /*
619 : * Note: usually the Var's type should match the tupdesc exactly, but
620 : * in situations involving unions of columns that have different
621 : * typmods, the Var may have come from above the union and hence have
622 : * typmod -1. This is a legitimate situation since the Var still
623 : * describes the column, just not as exactly as the tupdesc does. We
624 : * could change the planner to prevent it, but it'd then insert
625 : * projection steps just to convert from specific typmod to typmod -1,
626 : * which is pretty silly.
627 : */
1961 rhaas 628 GIC 1235096 : if (var->vartype != att_tup->atttypid ||
629 1235093 : (var->vartypmod != att_tup->atttypmod &&
630 3 : var->vartypmod != -1))
1961 rhaas 631 CBC 3 : return false; /* type mismatch */
1961 rhaas 632 ECB :
1364 tgl 633 CBC 1235093 : tlist_item = lnext(tlist, tlist_item);
1961 rhaas 634 ECB : }
635 :
1961 rhaas 636 CBC 115382 : if (tlist_item)
1961 rhaas 637 GIC 5919 : return false; /* tlist too long */
638 :
1961 rhaas 639 CBC 109463 : return true;
1961 rhaas 640 ECB : }
641 :
8786 bruce 642 : /* ----------------
643 : * ExecFreeExprContext
644 : *
645 : * A plan node's ExprContext should be freed explicitly during executor
646 : * shutdown because there may be shutdown callbacks to call. (Other resources
647 : * made by the above routines, such as projection info, don't need to be freed
648 : * explicitly because they're just memory in the per-query memory context.)
649 : *
650 : * However ... there is no particular need to do it during ExecEndNode,
651 : * because FreeExecutorState will free any remaining ExprContexts within
652 : * the EState. Letting FreeExecutorState do it allows the ExprContexts to
653 : * be freed in reverse order of creation, rather than order of creation as
654 : * will happen if we delete them here, which saves O(N^2) work in the list
655 : * cleanup inside FreeExprContext.
656 : * ----------------
657 : */
658 : void
7184 bruce 659 GIC 442939 : ExecFreeExprContext(PlanState *planstate)
660 : {
661 : /*
6385 bruce 662 ECB : * Per above discussion, don't actually delete the ExprContext. We do
663 : * unlink it from the plan node, though.
664 : */
7430 tgl 665 GIC 442939 : planstate->ps_ExprContext = NULL;
8786 bruce 666 442939 : }
667 :
1878 andres 668 ECB :
9770 scrappy 669 : /* ----------------------------------------------------------------
670 : * Scan node support
671 : * ----------------------------------------------------------------
672 : */
673 :
674 : /* ----------------
675 : * ExecAssignScanType
676 : * ----------------
677 : */
678 : void
6141 tgl 679 GIC 327 : ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
680 : {
7430 681 327 : TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
9345 bruce 682 ECB :
6141 tgl 683 GIC 327 : ExecSetSlotDescriptor(slot, tupDesc);
9770 scrappy 684 CBC 327 : }
685 :
9770 scrappy 686 ECB : /* ----------------
1392 michael 687 : * ExecCreateScanSlotFromOuterPlan
688 : * ----------------
689 : */
690 : void
1606 andres 691 GIC 51125 : ExecCreateScanSlotFromOuterPlan(EState *estate,
692 : ScanState *scanstate,
693 : const TupleTableSlotOps *tts_ops)
9770 scrappy 694 ECB : {
695 : PlanState *outerPlan;
696 : TupleDesc tupDesc;
697 :
7430 tgl 698 GIC 51125 : outerPlan = outerPlanState(scanstate);
7279 699 51125 : tupDesc = ExecGetResultType(outerPlan);
700 :
1606 andres 701 CBC 51125 : ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops);
9770 scrappy 702 51125 : }
703 :
6336 tgl 704 ECB : /* ----------------------------------------------------------------
705 : * ExecRelationIsTargetRelation
706 : *
707 : * Detect whether a relation (identified by rangetable index)
708 : * is one of the target relations of the query.
709 : *
710 : * Note: This is currently no longer used in core. We keep it around
711 : * because FDWs may wish to use it to determine if their foreign table
712 : * is a target relation.
713 : * ----------------------------------------------------------------
714 : */
715 : bool
6336 tgl 716 UIC 0 : ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
717 : {
908 heikki.linnakangas 718 0 : return list_member_int(estate->es_plannedstmt->resultRelations, scanrelid);
6336 tgl 719 EUB : }
720 :
6337 721 : /* ----------------------------------------------------------------
722 : * ExecOpenScanRelation
723 : *
724 : * Open the heap relation to be scanned by a base-level scan plan node.
725 : * This should be called during the node's ExecInit routine.
726 : * ----------------------------------------------------------------
727 : */
728 : Relation
3634 tgl 729 GIC 172025 : ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
730 : {
731 : Relation rel;
6337 tgl 732 ECB :
733 : /* Open the relation. */
1648 tgl 734 GIC 172025 : rel = ExecGetRangeTableRelation(estate, scanrelid);
735 :
736 : /*
3634 tgl 737 ECB : * Complain if we're attempting a scan of an unscannable relation, except
738 : * when the query won't actually be run. This is a slightly klugy place
739 : * to do this, perhaps, but there is no better place.
740 : */
3634 tgl 741 GIC 172025 : if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
742 158722 : !RelationIsScannable(rel))
743 6 : ereport(ERROR,
3634 tgl 744 ECB : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
745 : errmsg("materialized view \"%s\" has not been populated",
746 : RelationGetRelationName(rel)),
747 : errhint("Use the REFRESH MATERIALIZED VIEW command.")));
748 :
3634 tgl 749 GIC 172019 : return rel;
750 : }
751 :
1648 tgl 752 ECB : /*
753 : * ExecInitRangeTable
754 : * Set up executor's range-table-related data
755 : *
756 : * In addition to the range table proper, initialize arrays that are
757 : * indexed by rangetable index.
758 : */
759 : void
34 tgl 760 GNC 414272 : ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos)
761 : {
762 : /* Remember the range table List as-is */
1648 tgl 763 CBC 414272 : estate->es_range_table = rangeTable;
764 :
765 : /* ... and the RTEPermissionInfo List too */
34 tgl 766 GNC 414272 : estate->es_rteperminfos = permInfos;
767 :
768 : /* Set size of associated arrays */
1648 tgl 769 CBC 414272 : estate->es_range_table_size = list_length(rangeTable);
770 :
771 : /*
1648 tgl 772 ECB : * Allocate an array to store an open Relation corresponding to each
773 : * rangetable entry, and initialize entries to NULL. Relations are opened
774 : * and stored here as needed.
775 : */
1648 tgl 776 GIC 414272 : estate->es_relations = (Relation *)
777 414272 : palloc0(estate->es_range_table_size * sizeof(Relation));
778 :
779 : /*
780 : * es_result_relations and es_rowmarks are also parallel to
781 : * es_range_table, but are allocated only if needed.
1644 tgl 782 ECB : */
908 heikki.linnakangas 783 CBC 414272 : estate->es_result_relations = NULL;
1644 tgl 784 GIC 414272 : estate->es_rowmarks = NULL;
1648 785 414272 : }
786 :
787 : /*
788 : * ExecGetRangeTableRelation
1648 tgl 789 ECB : * Open the Relation for a range table entry, if not already done
6337 790 : *
1648 791 : * The Relations will be closed again in ExecEndPlan().
792 : */
793 : Relation
1648 tgl 794 GIC 248256 : ExecGetRangeTableRelation(EState *estate, Index rti)
795 : {
796 : Relation rel;
797 :
798 248256 : Assert(rti > 0 && rti <= estate->es_range_table_size);
799 :
1648 tgl 800 CBC 248256 : rel = estate->es_relations[rti - 1];
1648 tgl 801 GIC 248256 : if (rel == NULL)
802 : {
803 : /* First time through, so open the relation */
1648 tgl 804 CBC 226313 : RangeTblEntry *rte = exec_rt_fetch(rti, estate);
805 :
806 226313 : Assert(rte->rtekind == RTE_RELATION);
1648 tgl 807 ECB :
1646 tgl 808 GIC 226313 : if (!IsParallelWorker())
809 : {
1646 tgl 810 ECB : /*
811 : * In a normal query, we should already have the appropriate lock,
812 : * but verify that through an Assert. Since there's already an
813 : * Assert inside table_open that insists on holding some lock, it
814 : * seems sufficient to check this only when rellockmode is higher
815 : * than the minimum.
816 : */
1539 andres 817 GIC 224050 : rel = table_open(rte->relid, NoLock);
1646 tgl 818 224050 : Assert(rte->rellockmode == AccessShareLock ||
819 : CheckRelationLockedByMe(rel, rte->rellockmode, false));
820 : }
821 : else
822 : {
1646 tgl 823 ECB : /*
824 : * If we are a parallel worker, we need to obtain our own local
825 : * lock on the relation. This ensures sane behavior in case the
826 : * parent process exits before we do.
827 : */
1539 andres 828 GIC 2263 : rel = table_open(rte->relid, rte->rellockmode);
829 : }
830 :
1646 tgl 831 226313 : estate->es_relations[rti - 1] = rel;
832 : }
833 :
1648 tgl 834 CBC 248256 : return rel;
835 : }
836 :
908 heikki.linnakangas 837 ECB : /*
838 : * ExecInitResultRelation
839 : * Open relation given by the passed-in RT index and fill its
840 : * ResultRelInfo node
841 : *
842 : * Here, we also save the ResultRelInfo in estate->es_result_relations array
843 : * such that it can be accessed later using the RT index.
844 : */
845 : void
908 heikki.linnakangas 846 GIC 71295 : ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo,
847 : Index rti)
848 : {
849 : Relation resultRelationDesc;
850 :
851 71295 : resultRelationDesc = ExecGetRangeTableRelation(estate, rti);
908 heikki.linnakangas 852 CBC 71295 : InitResultRelInfo(resultRelInfo,
853 : resultRelationDesc,
854 : rti,
855 : NULL,
856 : estate->es_instrument);
908 heikki.linnakangas 857 ECB :
908 heikki.linnakangas 858 CBC 71295 : if (estate->es_result_relations == NULL)
908 heikki.linnakangas 859 GIC 66553 : estate->es_result_relations = (ResultRelInfo **)
860 66553 : palloc0(estate->es_range_table_size * sizeof(ResultRelInfo *));
861 71295 : estate->es_result_relations[rti - 1] = resultRelInfo;
862 :
863 : /*
908 heikki.linnakangas 864 ECB : * Saving in the list allows to avoid needlessly traversing the whole
865 : * array when only a few of its entries are possibly non-NULL.
866 : */
908 heikki.linnakangas 867 CBC 71295 : estate->es_opened_result_relations =
908 heikki.linnakangas 868 GIC 71295 : lappend(estate->es_opened_result_relations, resultRelInfo);
869 71295 : }
870 :
871 : /*
872 : * UpdateChangedParamSet
7364 tgl 873 ECB : * Add changed parameters to a plan node's chgParam set
874 : */
9173 bruce 875 : void
7184 bruce 876 GIC 474470 : UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
877 : {
878 : Bitmapset *parmset;
879 :
880 : /*
881 : * The plan node only depends on params listed in its allParam set. Don't
6385 bruce 882 ECB : * include anything else into its chgParam set.
883 : */
7364 tgl 884 GIC 474470 : parmset = bms_intersect(node->plan->allParam, newchg);
38 tgl 885 GNC 474470 : node->chgParam = bms_join(node->chgParam, parmset);
9186 vadim4o 886 GIC 474470 : }
887 :
888 : /*
889 : * executor_errposition
890 : * Report an execution-time cursor position, if possible.
891 : *
892 : * This is expected to be used within an ereport() call. The return value
893 : * is a dummy (always 0, in fact).
894 : *
895 : * The locations stored in parsetrees are byte offsets into the source string.
896 : * We have to convert them to 1-based character indexes for reporting to
897 : * clients. (We do things this way to avoid unnecessary overhead in the
898 : * normal non-error case: computing character indexes would be much more
899 : * expensive than storing token offsets.)
2182 tgl 900 EUB : */
901 : int
2182 tgl 902 UIC 0 : executor_errposition(EState *estate, int location)
903 : {
904 : int pos;
2182 tgl 905 EUB :
906 : /* No-op if location was not provided */
2182 tgl 907 UIC 0 : if (location < 0)
1110 tgl 908 UBC 0 : return 0;
2182 tgl 909 EUB : /* Can't do anything if source text is not available */
2182 tgl 910 UIC 0 : if (estate == NULL || estate->es_sourceText == NULL)
1110 tgl 911 UBC 0 : return 0;
912 : /* Convert offset to character number */
2182 913 0 : pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1;
914 : /* And pass it to the ereport mechanism */
1110 tgl 915 UIC 0 : return errposition(pos);
916 : }
917 :
918 : /*
919 : * Register a shutdown callback in an ExprContext.
920 : *
921 : * Shutdown callbacks will be called (in reverse order of registration)
922 : * when the ExprContext is deleted or rescanned. This provides a hook
923 : * for functions called in the context to do any cleanup needed --- it's
924 : * particularly useful for functions returning sets. Note that the
925 : * callback will *not* be called in the event that execution is aborted
926 : * by an error.
7637 tgl 927 ECB : */
928 : void
7637 tgl 929 GIC 123404 : RegisterExprContextCallback(ExprContext *econtext,
930 : ExprContextCallbackFunction function,
931 : Datum arg)
932 : {
933 : ExprContext_CB *ecxt_callback;
934 :
7637 tgl 935 ECB : /* Save the info in appropriate memory context */
936 : ecxt_callback = (ExprContext_CB *)
7637 tgl 937 GIC 123404 : MemoryContextAlloc(econtext->ecxt_per_query_memory,
7637 tgl 938 ECB : sizeof(ExprContext_CB));
939 :
7637 tgl 940 GIC 123404 : ecxt_callback->function = function;
941 123404 : ecxt_callback->arg = arg;
7637 tgl 942 ECB :
943 : /* link to front of list for appropriate execution order */
7637 tgl 944 CBC 123404 : ecxt_callback->next = econtext->ecxt_callbacks;
7637 tgl 945 GIC 123404 : econtext->ecxt_callbacks = ecxt_callback;
946 123404 : }
947 :
948 : /*
949 : * Deregister a shutdown callback in an ExprContext.
950 : *
951 : * Any list entries matching the function and arg will be removed.
952 : * This can be used if it's no longer necessary to call the callback.
7637 tgl 953 ECB : */
954 : void
7637 tgl 955 GIC 81046 : UnregisterExprContextCallback(ExprContext *econtext,
956 : ExprContextCallbackFunction function,
957 : Datum arg)
958 : {
959 : ExprContext_CB **prev_callback;
7522 bruce 960 ECB : ExprContext_CB *ecxt_callback;
961 :
7637 tgl 962 CBC 81046 : prev_callback = &econtext->ecxt_callbacks;
963 :
964 244146 : while ((ecxt_callback = *prev_callback) != NULL)
965 : {
966 163100 : if (ecxt_callback->function == function && ecxt_callback->arg == arg)
7637 tgl 967 ECB : {
7637 tgl 968 GIC 81046 : *prev_callback = ecxt_callback->next;
969 81046 : pfree(ecxt_callback);
7637 tgl 970 ECB : }
971 : else
7637 tgl 972 CBC 82054 : prev_callback = &ecxt_callback->next;
973 : }
7637 tgl 974 GIC 81046 : }
975 :
976 : /*
977 : * Call all the shutdown callbacks registered in an ExprContext.
978 : *
979 : * The callback list is emptied (important in case this is only a rescan
980 : * reset, and not deletion of the ExprContext).
981 : *
982 : * If isCommit is false, just clean the callback list but don't call 'em.
983 : * (See comment for FreeExprContext.)
7637 tgl 984 ECB : */
985 : static void
5013 tgl 986 GIC 2948420 : ShutdownExprContext(ExprContext *econtext, bool isCommit)
987 : {
988 : ExprContext_CB *ecxt_callback;
989 : MemoryContext oldcontext;
7420 tgl 990 ECB :
991 : /* Fast path in normal case where there's nothing to do. */
7420 tgl 992 GIC 2948420 : if (econtext->ecxt_callbacks == NULL)
993 2906670 : return;
994 :
995 : /*
996 : * Call the callbacks in econtext's per-tuple context. This ensures that
6385 bruce 997 ECB : * any memory they might leak will get cleaned up.
998 : */
7420 tgl 999 GIC 41750 : oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
1000 :
1001 : /*
7637 tgl 1002 ECB : * Call each callback function in reverse registration order.
1003 : */
7637 tgl 1004 CBC 83702 : while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
7637 tgl 1005 ECB : {
7637 tgl 1006 CBC 41952 : econtext->ecxt_callbacks = ecxt_callback->next;
5013 1007 41952 : if (isCommit)
2040 peter_e 1008 GIC 41952 : ecxt_callback->function(ecxt_callback->arg);
7637 tgl 1009 41952 : pfree(ecxt_callback);
7637 tgl 1010 ECB : }
1011 :
7420 tgl 1012 GIC 41750 : MemoryContextSwitchTo(oldcontext);
1013 : }
1014 :
1015 : /*
1016 : * GetAttributeByName
1017 : * GetAttributeByNum
1018 : *
1019 : * These functions return the value of the requested attribute
1020 : * out of the given tuple Datum.
1021 : * C functions which take a tuple as an argument are expected
1022 : * to use these. Ex: overpaid(EMP) might call GetAttributeByNum().
1023 : * Note: these are actually rather slow because they do a typcache
1024 : * lookup on each call.
2217 andres 1025 ECB : */
1026 : Datum
2217 andres 1027 GIC 18 : GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
1028 : {
1029 : AttrNumber attrno;
1030 : Datum result;
1031 : Oid tupType;
1032 : int32 tupTypmod;
1033 : TupleDesc tupDesc;
1034 : HeapTupleData tmptup;
2217 andres 1035 ECB : int i;
2217 andres 1036 EUB :
2217 andres 1037 GIC 18 : if (attname == NULL)
2217 andres 1038 LBC 0 : elog(ERROR, "invalid attribute name");
2217 andres 1039 EUB :
2217 andres 1040 GIC 18 : if (isNull == NULL)
2217 andres 1041 LBC 0 : elog(ERROR, "a NULL isNull pointer was passed");
1042 :
2217 andres 1043 GIC 18 : if (tuple == NULL)
2217 andres 1044 EUB : {
1045 : /* Kinda bogus but compatible with old behavior... */
2217 andres 1046 UIC 0 : *isNull = true;
1047 0 : return (Datum) 0;
2217 andres 1048 ECB : }
1049 :
2217 andres 1050 CBC 18 : tupType = HeapTupleHeaderGetTypeId(tuple);
2217 andres 1051 GIC 18 : tupTypmod = HeapTupleHeaderGetTypMod(tuple);
2217 andres 1052 CBC 18 : tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2217 andres 1053 ECB :
2217 andres 1054 GIC 18 : attrno = InvalidAttrNumber;
2217 andres 1055 CBC 72 : for (i = 0; i < tupDesc->natts; i++)
1056 : {
2058 1057 72 : Form_pg_attribute att = TupleDescAttr(tupDesc, i);
1058 :
1059 72 : if (namestrcmp(&(att->attname), attname) == 0)
2217 andres 1060 ECB : {
2058 andres 1061 GIC 18 : attrno = att->attnum;
2217 1062 18 : break;
1063 : }
2217 andres 1064 ECB : }
2217 andres 1065 EUB :
2217 andres 1066 GIC 18 : if (attrno == InvalidAttrNumber)
2217 andres 1067 UIC 0 : elog(ERROR, "attribute \"%s\" does not exist", attname);
1068 :
1069 : /*
1070 : * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
1071 : * the fields in the struct just in case user tries to inspect system
2217 andres 1072 ECB : * columns.
1073 : */
2217 andres 1074 CBC 18 : tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
1075 18 : ItemPointerSetInvalid(&(tmptup.t_self));
2217 andres 1076 GIC 18 : tmptup.t_tableOid = InvalidOid;
2217 andres 1077 CBC 18 : tmptup.t_data = tuple;
1078 :
2217 andres 1079 GIC 18 : result = heap_getattr(&tmptup,
1080 : attrno,
1081 : tupDesc,
2217 andres 1082 ECB : isNull);
1083 :
2217 andres 1084 CBC 18 : ReleaseTupleDesc(tupDesc);
1085 :
2217 andres 1086 GIC 18 : return result;
1087 : }
2217 andres 1088 EUB :
1089 : Datum
2217 andres 1090 UIC 0 : GetAttributeByNum(HeapTupleHeader tuple,
1091 : AttrNumber attrno,
1092 : bool *isNull)
1093 : {
1094 : Datum result;
1095 : Oid tupType;
1096 : int32 tupTypmod;
1097 : TupleDesc tupDesc;
2217 andres 1098 EUB : HeapTupleData tmptup;
1099 :
2217 andres 1100 UIC 0 : if (!AttributeNumberIsValid(attrno))
2217 andres 1101 UBC 0 : elog(ERROR, "invalid attribute number %d", attrno);
2217 andres 1102 EUB :
2217 andres 1103 UIC 0 : if (isNull == NULL)
2217 andres 1104 UBC 0 : elog(ERROR, "a NULL isNull pointer was passed");
1105 :
2217 andres 1106 UIC 0 : if (tuple == NULL)
2217 andres 1107 EUB : {
1108 : /* Kinda bogus but compatible with old behavior... */
2217 andres 1109 UIC 0 : *isNull = true;
1110 0 : return (Datum) 0;
2217 andres 1111 EUB : }
1112 :
2217 andres 1113 UBC 0 : tupType = HeapTupleHeaderGetTypeId(tuple);
2217 andres 1114 UIC 0 : tupTypmod = HeapTupleHeaderGetTypMod(tuple);
1115 0 : tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
1116 :
1117 : /*
1118 : * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
1119 : * the fields in the struct just in case user tries to inspect system
2217 andres 1120 EUB : * columns.
1121 : */
2217 andres 1122 UBC 0 : tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
1123 0 : ItemPointerSetInvalid(&(tmptup.t_self));
2217 andres 1124 UIC 0 : tmptup.t_tableOid = InvalidOid;
2217 andres 1125 UBC 0 : tmptup.t_data = tuple;
1126 :
2217 andres 1127 UIC 0 : result = heap_getattr(&tmptup,
1128 : attrno,
1129 : tupDesc,
2217 andres 1130 EUB : isNull);
1131 :
2217 andres 1132 UBC 0 : ReleaseTupleDesc(tupDesc);
1133 :
2217 andres 1134 UIC 0 : return result;
1135 : }
1136 :
1137 : /*
1138 : * Number of items in a tlist (including any resjunk items!)
2217 andres 1139 ECB : */
1140 : int
2217 andres 1141 GIC 569995 : ExecTargetListLength(List *targetlist)
2217 andres 1142 ECB : {
1143 : /* This used to be more complex, but fjoins are dead */
2217 andres 1144 GIC 569995 : return list_length(targetlist);
1145 : }
1146 :
1147 : /*
1148 : * Number of items in a tlist, not including any resjunk items
2217 andres 1149 ECB : */
1150 : int
2217 andres 1151 CBC 80402 : ExecCleanTargetListLength(List *targetlist)
1152 : {
2217 andres 1153 GIC 80402 : int len = 0;
2217 andres 1154 ECB : ListCell *tl;
1155 :
2217 andres 1156 CBC 264933 : foreach(tl, targetlist)
1157 : {
2190 tgl 1158 184531 : TargetEntry *curTle = lfirst_node(TargetEntry, tl);
2217 andres 1159 ECB :
2217 andres 1160 GIC 184531 : if (!curTle->resjunk)
2217 andres 1161 CBC 171067 : len++;
1162 : }
2217 andres 1163 GIC 80402 : return len;
1164 : }
1165 :
1166 : /*
1167 : * Return a relInfo's tuple slot for a trigger's OLD tuples.
1503 andres 1168 ECB : */
1169 : TupleTableSlot *
1503 andres 1170 CBC 11145 : ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo)
1171 : {
1172 11145 : if (relInfo->ri_TrigOldSlot == NULL)
1503 andres 1173 ECB : {
1503 andres 1174 GIC 4475 : Relation rel = relInfo->ri_RelationDesc;
1503 andres 1175 CBC 4475 : MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1503 andres 1176 ECB :
1503 andres 1177 GIC 4475 : relInfo->ri_TrigOldSlot =
1178 4475 : ExecInitExtraTupleSlot(estate,
1179 : RelationGetDescr(rel),
1490 andres 1180 ECB : table_slot_callbacks(rel));
1181 :
1503 andres 1182 GIC 4475 : MemoryContextSwitchTo(oldcontext);
1503 andres 1183 ECB : }
1184 :
1503 andres 1185 GIC 11145 : return relInfo->ri_TrigOldSlot;
1186 : }
1187 :
1188 : /*
1189 : * Return a relInfo's tuple slot for a trigger's NEW tuples.
1503 andres 1190 ECB : */
1191 : TupleTableSlot *
1503 andres 1192 CBC 1593 : ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo)
1193 : {
1194 1593 : if (relInfo->ri_TrigNewSlot == NULL)
1503 andres 1195 ECB : {
1503 andres 1196 GIC 956 : Relation rel = relInfo->ri_RelationDesc;
1503 andres 1197 CBC 956 : MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1503 andres 1198 ECB :
1503 andres 1199 GIC 956 : relInfo->ri_TrigNewSlot =
1200 956 : ExecInitExtraTupleSlot(estate,
1201 : RelationGetDescr(rel),
1490 andres 1202 ECB : table_slot_callbacks(rel));
1203 :
1503 andres 1204 GIC 956 : MemoryContextSwitchTo(oldcontext);
1503 andres 1205 ECB : }
1206 :
1503 andres 1207 GIC 1593 : return relInfo->ri_TrigNewSlot;
1208 : }
1209 :
1210 : /*
1211 : * Return a relInfo's tuple slot for processing returning tuples.
1503 andres 1212 ECB : */
1213 : TupleTableSlot *
1503 andres 1214 CBC 545 : ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo)
1215 : {
1216 545 : if (relInfo->ri_ReturningSlot == NULL)
1503 andres 1217 ECB : {
1503 andres 1218 GIC 241 : Relation rel = relInfo->ri_RelationDesc;
1503 andres 1219 CBC 241 : MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1503 andres 1220 ECB :
1503 andres 1221 GIC 241 : relInfo->ri_ReturningSlot =
1222 241 : ExecInitExtraTupleSlot(estate,
1223 : RelationGetDescr(rel),
1490 andres 1224 ECB : table_slot_callbacks(rel));
1225 :
1503 andres 1226 GIC 241 : MemoryContextSwitchTo(oldcontext);
1503 andres 1227 ECB : }
1228 :
1503 andres 1229 GIC 545 : return relInfo->ri_ReturningSlot;
1230 : }
1231 :
1232 : /*
1233 : * Return the map needed to convert given child result relation's tuples to
1234 : * the rowtype of the query's main target ("root") relation. Note that a
1235 : * NULL result is valid and means that no conversion is needed.
733 tgl 1236 ECB : */
1237 : TupleConversionMap *
733 tgl 1238 GIC 33772 : ExecGetChildToRootMap(ResultRelInfo *resultRelInfo)
733 tgl 1239 ECB : {
1240 : /* If we didn't already do so, compute the map for this child. */
733 tgl 1241 CBC 33772 : if (!resultRelInfo->ri_ChildToRootMapValid)
1242 : {
1243 752 : ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
733 tgl 1244 ECB :
733 tgl 1245 CBC 752 : if (rootRelInfo)
1246 566 : resultRelInfo->ri_ChildToRootMap =
733 tgl 1247 GIC 566 : convert_tuples_by_name(RelationGetDescr(resultRelInfo->ri_RelationDesc),
733 tgl 1248 CBC 566 : RelationGetDescr(rootRelInfo->ri_RelationDesc));
1249 : else /* this isn't a child result rel */
1250 186 : resultRelInfo->ri_ChildToRootMap = NULL;
1251 :
733 tgl 1252 GIC 752 : resultRelInfo->ri_ChildToRootMapValid = true;
733 tgl 1253 ECB : }
1254 :
733 tgl 1255 GIC 33772 : return resultRelInfo->ri_ChildToRootMap;
1256 : }
1257 :
1258 : /*
1259 : * Returns the map needed to convert given root result relation's tuples to
1260 : * the rowtype of the given child relation. Note that a NULL result is valid
1261 : * and means that no conversion is needed.
1262 : */
1263 : TupleConversionMap *
128 alvherre 1264 GNC 472699 : ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
1265 : {
1266 : /* Mustn't get called for a non-child result relation. */
1267 472699 : Assert(resultRelInfo->ri_RootResultRelInfo);
1268 :
1269 : /* If we didn't already do so, compute the map for this child. */
1270 472699 : if (!resultRelInfo->ri_RootToChildMapValid)
1271 : {
1272 4331 : ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
1273 4331 : TupleDesc indesc = RelationGetDescr(rootRelInfo->ri_RelationDesc);
1274 4331 : TupleDesc outdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1275 4331 : Relation childrel = resultRelInfo->ri_RelationDesc;
1276 : AttrMap *attrMap;
1277 : MemoryContext oldcontext;
1278 :
1279 : /*
1280 : * When this child table is not a partition (!relispartition), it may
1281 : * have columns that are not present in the root table, which we ask
1282 : * to ignore by passing true for missing_ok.
1283 : */
1284 4331 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1285 4331 : attrMap = build_attrmap_by_name_if_req(indesc, outdesc,
1286 4331 : !childrel->rd_rel->relispartition);
1287 4331 : if (attrMap)
1288 689 : resultRelInfo->ri_RootToChildMap =
1289 689 : convert_tuples_by_name_attrmap(indesc, outdesc, attrMap);
1290 4331 : MemoryContextSwitchTo(oldcontext);
1291 4331 : resultRelInfo->ri_RootToChildMapValid = true;
1292 : }
1293 :
1294 472699 : return resultRelInfo->ri_RootToChildMap;
1295 : }
1296 :
1297 : /* Return a bitmap representing columns being inserted */
1298 : Bitmapset *
790 heikki.linnakangas 1299 GIC 536 : ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
1300 : {
124 alvherre 1301 GNC 536 : RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relinfo, estate);
790 heikki.linnakangas 1302 ECB :
124 alvherre 1303 GNC 536 : if (perminfo == NULL)
124 alvherre 1304 UIC 0 : return NULL;
1305 :
1306 : /* Map the columns to child's attribute numbers if needed. */
124 alvherre 1307 GNC 536 : if (relinfo->ri_RootResultRelInfo)
1308 : {
128 1309 59 : TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
1310 :
124 1311 59 : if (map)
124 alvherre 1312 UNC 0 : return execute_attr_map_cols(map->attrMap, perminfo->insertedCols);
1313 : }
1314 :
124 alvherre 1315 GNC 536 : return perminfo->insertedCols;
1316 : }
1317 :
790 heikki.linnakangas 1318 ECB : /* Return a bitmap representing columns being updated */
1319 : Bitmapset *
790 heikki.linnakangas 1320 CBC 29963 : ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
1321 : {
124 alvherre 1322 GNC 29963 : RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relinfo, estate);
790 heikki.linnakangas 1323 ECB :
124 alvherre 1324 GNC 29963 : if (perminfo == NULL)
124 alvherre 1325 LBC 0 : return NULL;
1326 :
1327 : /* Map the columns to child's attribute numbers if needed. */
124 alvherre 1328 GNC 29963 : if (relinfo->ri_RootResultRelInfo)
1329 : {
128 1330 833 : TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
1331 :
124 1332 833 : if (map)
1333 243 : return execute_attr_map_cols(map->attrMap, perminfo->updatedCols);
1334 : }
1335 :
1336 29720 : return perminfo->updatedCols;
1337 : }
790 heikki.linnakangas 1338 ECB :
790 heikki.linnakangas 1339 EUB : /* Return a bitmap representing generated columns being updated */
1340 : Bitmapset *
790 heikki.linnakangas 1341 GIC 29334 : ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
790 heikki.linnakangas 1342 ECB : {
1343 : /* Compute the info if we didn't already */
34 tgl 1344 GNC 29334 : if (relinfo->ri_GeneratedExprsU == NULL)
84 1345 29277 : ExecInitStoredGenerated(relinfo, estate, CMD_UPDATE);
94 1346 29334 : return relinfo->ri_extraUpdatedCols;
1347 : }
1348 :
790 heikki.linnakangas 1349 ECB : /* Return columns being updated, including generated columns */
1350 : Bitmapset *
790 heikki.linnakangas 1351 CBC 7071 : ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
790 heikki.linnakangas 1352 ECB : {
790 heikki.linnakangas 1353 GIC 7071 : return bms_union(ExecGetUpdatedCols(relinfo, estate),
1354 7071 : ExecGetExtraUpdatedCols(relinfo, estate));
1355 : }
1356 :
1357 : /*
1358 : * GetResultRTEPermissionInfo
1359 : * Looks up RTEPermissionInfo for ExecGet*Cols() routines
1360 : */
1361 : static RTEPermissionInfo *
124 alvherre 1362 GNC 30668 : GetResultRTEPermissionInfo(ResultRelInfo *relinfo, EState *estate)
1363 : {
1364 : Index rti;
1365 : RangeTblEntry *rte;
1366 30668 : RTEPermissionInfo *perminfo = NULL;
1367 :
1368 30668 : if (relinfo->ri_RootResultRelInfo)
1369 : {
1370 : /*
1371 : * For inheritance child result relations (a partition routing target
1372 : * of an INSERT or a child UPDATE target), this returns the root
1373 : * parent's RTE to fetch the RTEPermissionInfo because that's the only
1374 : * one that has one assigned.
1375 : */
1376 939 : rti = relinfo->ri_RootResultRelInfo->ri_RangeTableIndex;
1377 : }
1378 29729 : else if (relinfo->ri_RangeTableIndex != 0)
1379 : {
1380 : /*
1381 : * Non-child result relation should have their own RTEPermissionInfo.
1382 : */
1383 29729 : rti = relinfo->ri_RangeTableIndex;
1384 : }
1385 : else
1386 : {
1387 : /*
1388 : * The relation isn't in the range table and it isn't a partition
1389 : * routing target. This ResultRelInfo must've been created only for
1390 : * firing triggers and the relation is not being inserted into. (See
1391 : * ExecGetTriggerResultRel.)
1392 : */
124 alvherre 1393 UNC 0 : rti = 0;
1394 : }
1395 :
124 alvherre 1396 GNC 30668 : if (rti > 0)
1397 : {
1398 30668 : rte = exec_rt_fetch(rti, estate);
1399 30668 : perminfo = getRTEPermissionInfo(estate->es_rteperminfos, rte);
1400 : }
1401 :
1402 30668 : return perminfo;
1403 : }
1404 :
1405 : /*
1406 : * GetResultRelCheckAsUser
1407 : * Returns the user to modify passed-in result relation as
1408 : *
1409 : * The user is chosen by looking up the relation's or, if a child table, its
1410 : * root parent's RTEPermissionInfo.
1411 : */
1412 : Oid
1413 169 : ExecGetResultRelCheckAsUser(ResultRelInfo *relInfo, EState *estate)
1414 : {
1415 169 : RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relInfo, estate);
1416 :
1417 : /* XXX - maybe ok to return GetUserId() in this case? */
1418 169 : if (perminfo == NULL)
124 alvherre 1419 UNC 0 : elog(ERROR, "no RTEPermissionInfo found for result relation with OID %u",
1420 : RelationGetRelid(relInfo->ri_RelationDesc));
1421 :
124 alvherre 1422 GNC 169 : return perminfo->checkAsUser ? perminfo->checkAsUser : GetUserId();
1423 : }
|