Coverage Report

Created: 2026-10-16 06:48

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