YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/postgres/src/backend/executor/execUtils.c
Line
Count
Source (jump to first uncovered line)
1
/*-------------------------------------------------------------------------
2
 *
3
 * execUtils.c
4
 *    miscellaneous executor utility routines
5
 *
6
 * Portions Copyright (c) 1996-2018, 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
 *    ExecCloseScanRelation
29
 *
30
 *    executor_errposition  Report syntactic position of an error.
31
 *
32
 *    RegisterExprContextCallback    Register function shutdown callback
33
 *    UnregisterExprContextCallback  Deregister function shutdown callback
34
 *
35
 *    GetAttributeByName    Runtime extraction of columns from tuples.
36
 *    GetAttributeByNum
37
 *
38
 *   NOTES
39
 *    This file has traditionally been the place to stick misc.
40
 *    executor support stuff that doesn't really go anyplace else.
41
 */
42
43
#include "postgres.h"
44
45
#include "access/relscan.h"
46
#include "access/transam.h"
47
#include "executor/executor.h"
48
#include "jit/jit.h"
49
#include "mb/pg_wchar.h"
50
#include "nodes/nodeFuncs.h"
51
#include "parser/parsetree.h"
52
#include "storage/lmgr.h"
53
#include "utils/builtins.h"
54
#include "utils/memutils.h"
55
#include "utils/rel.h"
56
#include "utils/typcache.h"
57
58
59
static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc);
60
static void ShutdownExprContext(ExprContext *econtext, bool isCommit);
61
62
63
/* ----------------------------------------------------------------
64
 *         Executor state and memory management functions
65
 * ----------------------------------------------------------------
66
 */
67
68
/* ----------------
69
 *    CreateExecutorState
70
 *
71
 *    Create and initialize an EState node, which is the root of
72
 *    working storage for an entire Executor invocation.
73
 *
74
 * Principally, this creates the per-query memory context that will be
75
 * used to hold all working data that lives till the end of the query.
76
 * Note that the per-query context will become a child of the caller's
77
 * GetCurrentMemoryContext().
78
 * ----------------
79
 */
80
EState *
81
CreateExecutorState(void)
82
696k
{
83
696k
  EState     *estate;
84
696k
  MemoryContext qcontext;
85
696k
  MemoryContext oldcontext;
86
87
  /*
88
   * Create the per-query context for this Executor run.
89
   */
90
696k
  qcontext = AllocSetContextCreate(GetCurrentMemoryContext(),
91
696k
                   "ExecutorState",
92
696k
                   ALLOCSET_DEFAULT_SIZES);
93
94
  /*
95
   * Make the EState node within the per-query context.  This way, we don't
96
   * need a separate pfree() operation for it at shutdown.
97
   */
98
696k
  oldcontext = MemoryContextSwitchTo(qcontext);
99
100
696k
  estate = makeNode(EState);
101
102
  /*
103
   * Initialize all fields of the Executor State structure
104
   */
105
0
  estate->es_direction = ForwardScanDirection;
106
696k
  estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */
107
696k
  estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
108
696k
  estate->es_range_table = NIL;
109
696k
  estate->es_plannedstmt = NULL;
110
111
696k
  estate->es_junkFilter = NULL;
112
113
696k
  estate->es_output_cid = (CommandId) 0;
114
115
696k
  estate->es_result_relations = NULL;
116
696k
  estate->es_num_result_relations = 0;
117
696k
  estate->es_result_relation_info = NULL;
118
119
696k
  estate->es_root_result_relations = NULL;
120
696k
  estate->es_num_root_result_relations = 0;
121
122
696k
  estate->es_tuple_routing_result_relations = NIL;
123
124
696k
  estate->es_trig_target_relations = NIL;
125
696k
  estate->es_trig_tuple_slot = NULL;
126
696k
  estate->es_trig_oldtup_slot = NULL;
127
696k
  estate->es_trig_newtup_slot = NULL;
128
129
696k
  estate->es_param_list_info = NULL;
130
696k
  estate->es_param_exec_vals = NULL;
131
132
696k
  estate->es_queryEnv = NULL;
133
134
696k
  estate->es_query_cxt = qcontext;
135
136
696k
  estate->es_tupleTable = NIL;
137
138
696k
  estate->es_rowMarks = NIL;
139
140
696k
  estate->es_processed = 0;
141
696k
  estate->es_lastoid = InvalidOid;
142
143
696k
  estate->es_top_eflags = 0;
144
696k
  estate->es_instrument = 0;
145
696k
  estate->es_finished = false;
146
147
696k
  estate->es_exprcontexts = NIL;
148
149
696k
  estate->es_subplanstates = NIL;
150
151
696k
  estate->es_auxmodifytables = NIL;
152
153
696k
  estate->es_per_tuple_exprcontext = NULL;
154
155
696k
  estate->es_epqTuple = NULL;
156
696k
  estate->es_epqTupleSet = NULL;
157
696k
  estate->es_epqScanDone = NULL;
158
696k
  estate->es_sourceText = NULL;
159
160
696k
  estate->es_use_parallel_mode = false;
161
162
696k
  estate->es_jit_flags = 0;
163
696k
  estate->es_jit = NULL;
164
165
  /*
166
   * Return the executor state structure
167
   */
168
696k
  MemoryContextSwitchTo(oldcontext);
169
170
  /*
171
   * YugaByte-specific fields
172
   */
173
696k
  estate->yb_es_is_single_row_modify_txn = false;
174
696k
  estate->yb_conflict_slot = NULL;
175
  /*
176
   * The read hybrid time used for this query. This will be initialized
177
   * by the first read operation invoked for this query, and all later
178
   * reads performed by this query will not read any data written past this time.
179
   */
180
696k
  estate->yb_es_read_ht = 0;
181
182
696k
  estate->yb_exec_params.limit_count = 0;
183
696k
  estate->yb_exec_params.limit_offset = 0;
184
696k
  estate->yb_exec_params.limit_use_default = true;
185
696k
  estate->yb_exec_params.rowmark = -1;
186
696k
  estate->yb_exec_params.is_index_backfill = false;
187
  /*
188
   * Pointer to the query read hybrid time. This pointer is passed
189
   * down to all the DocDB read operations invoked for this query. Only
190
   * the first read operation initializes its value, and all the other
191
   * operations ensure that they don't read any value written past this time.
192
   */
193
696k
  estate->yb_exec_params.statement_read_time = &estate->yb_es_read_ht;
194
195
696k
  return estate;
196
696k
}
197
198
/* ----------------
199
 *    FreeExecutorState
200
 *
201
 *    Release an EState along with all remaining working storage.
202
 *
203
 * Note: this is not responsible for releasing non-memory resources, such as
204
 * open relations or buffer pins.  But it will shut down any still-active
205
 * ExprContexts within the EState and deallocate associated JITed expressions.
206
 * That is sufficient cleanup for situations where the EState has only been
207
 * used for expression evaluation, and not to run a complete Plan.
208
 *
209
 * This can be called in any memory context ... so long as it's not one
210
 * of the ones to be freed.
211
 * ----------------
212
 */
213
void
214
FreeExecutorState(EState *estate)
215
587k
{
216
  /*
217
   * Shut down and free any remaining ExprContexts.  We do this explicitly
218
   * to ensure that any remaining shutdown callbacks get called (since they
219
   * might need to release resources that aren't simply memory within the
220
   * per-query memory context).
221
   */
222
1.37M
  while (estate->es_exprcontexts)
223
784k
  {
224
    /*
225
     * XXX: seems there ought to be a faster way to implement this than
226
     * repeated list_delete(), no?
227
     */
228
784k
    FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts),
229
784k
            true);
230
    /* FreeExprContext removed the list link for us */
231
784k
  }
232
233
  /* release JIT context, if allocated */
234
587k
  if (estate->es_jit)
235
0
  {
236
0
    jit_release_context(estate->es_jit);
237
0
    estate->es_jit = NULL;
238
0
  }
239
240
  /*
241
   * Free the per-query memory context, thereby releasing all working
242
   * memory, including the EState node itself.
243
   */
244
587k
  MemoryContextDelete(estate->es_query_cxt);
245
587k
}
246
247
/* ----------------
248
 *    CreateExprContext
249
 *
250
 *    Create a context for expression evaluation within an EState.
251
 *
252
 * An executor run may require multiple ExprContexts (we usually make one
253
 * for each Plan node, and a separate one for per-output-tuple processing
254
 * such as constraint checking).  Each ExprContext has its own "per-tuple"
255
 * memory context.
256
 *
257
 * Note we make no assumption about the caller's memory context.
258
 * ----------------
259
 */
260
ExprContext *
261
CreateExprContext(EState *estate)
262
935k
{
263
935k
  ExprContext *econtext;
264
935k
  MemoryContext oldcontext;
265
266
  /* Create the ExprContext node within the per-query memory context */
267
935k
  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
268
269
935k
  econtext = makeNode(ExprContext);
270
271
  /* Initialize fields of ExprContext */
272
0
  econtext->ecxt_scantuple = NULL;
273
935k
  econtext->ecxt_innertuple = NULL;
274
935k
  econtext->ecxt_outertuple = NULL;
275
276
935k
  econtext->ecxt_per_query_memory = estate->es_query_cxt;
277
278
  /*
279
   * Create working memory for expression evaluation in this context.
280
   */
281
935k
  econtext->ecxt_per_tuple_memory =
282
935k
    AllocSetContextCreate(estate->es_query_cxt,
283
935k
                "ExprContext",
284
935k
                ALLOCSET_DEFAULT_SIZES);
285
286
935k
  econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
287
935k
  econtext->ecxt_param_list_info = estate->es_param_list_info;
288
289
935k
  econtext->ecxt_aggvalues = NULL;
290
935k
  econtext->ecxt_aggnulls = NULL;
291
292
935k
  econtext->caseValue_datum = (Datum) 0;
293
935k
  econtext->caseValue_isNull = true;
294
295
935k
  econtext->domainValue_datum = (Datum) 0;
296
935k
  econtext->domainValue_isNull = true;
297
298
935k
  econtext->ecxt_estate = estate;
299
300
935k
  econtext->ecxt_callbacks = NULL;
301
302
  /*
303
   * Link the ExprContext into the EState to ensure it is shut down when the
304
   * EState is freed.  Because we use lcons(), shutdowns will occur in
305
   * reverse order of creation, which may not be essential but can't hurt.
306
   */
307
935k
  estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);
308
309
935k
  MemoryContextSwitchTo(oldcontext);
310
311
935k
  return econtext;
312
935k
}
313
314
/* ----------------
315
 *    CreateStandaloneExprContext
316
 *
317
 *    Create a context for standalone expression evaluation.
318
 *
319
 * An ExprContext made this way can be used for evaluation of expressions
320
 * that contain no Params, subplans, or Var references (it might work to
321
 * put tuple references into the scantuple field, but it seems unwise).
322
 *
323
 * The ExprContext struct is allocated in the caller's current memory
324
 * context, which also becomes its "per query" context.
325
 *
326
 * It is caller's responsibility to free the ExprContext when done,
327
 * or at least ensure that any shutdown callbacks have been called
328
 * (ReScanExprContext() is suitable).  Otherwise, non-memory resources
329
 * might be leaked.
330
 * ----------------
331
 */
332
ExprContext *
333
CreateStandaloneExprContext(void)
334
781
{
335
781
  ExprContext *econtext;
336
337
  /* Create the ExprContext node within the caller's memory context */
338
781
  econtext = makeNode(ExprContext);
339
340
  /* Initialize fields of ExprContext */
341
0
  econtext->ecxt_scantuple = NULL;
342
781
  econtext->ecxt_innertuple = NULL;
343
781
  econtext->ecxt_outertuple = NULL;
344
345
781
  econtext->ecxt_per_query_memory = GetCurrentMemoryContext();
346
347
  /*
348
   * Create working memory for expression evaluation in this context.
349
   */
350
781
  econtext->ecxt_per_tuple_memory =
351
781
    AllocSetContextCreate(GetCurrentMemoryContext(),
352
781
                "ExprContext",
353
781
                ALLOCSET_DEFAULT_SIZES);
354
355
781
  econtext->ecxt_param_exec_vals = NULL;
356
781
  econtext->ecxt_param_list_info = NULL;
357
358
781
  econtext->ecxt_aggvalues = NULL;
359
781
  econtext->ecxt_aggnulls = NULL;
360
361
781
  econtext->caseValue_datum = (Datum) 0;
362
781
  econtext->caseValue_isNull = true;
363
364
781
  econtext->domainValue_datum = (Datum) 0;
365
781
  econtext->domainValue_isNull = true;
366
367
781
  econtext->ecxt_estate = NULL;
368
369
781
  econtext->ecxt_callbacks = NULL;
370
371
781
  return econtext;
372
781
}
373
374
/* ----------------
375
 *    FreeExprContext
376
 *
377
 *    Free an expression context, including calling any remaining
378
 *    shutdown callbacks.
379
 *
380
 * Since we free the temporary context used for expression evaluation,
381
 * any previously computed pass-by-reference expression result will go away!
382
 *
383
 * If isCommit is false, we are being called in error cleanup, and should
384
 * not call callbacks but only release memory.  (It might be better to call
385
 * the callbacks and pass the isCommit flag to them, but that would require
386
 * more invasive code changes than currently seems justified.)
387
 *
388
 * Note we make no assumption about the caller's memory context.
389
 * ----------------
390
 */
391
void
392
FreeExprContext(ExprContext *econtext, bool isCommit)
393
792k
{
394
792k
  EState     *estate;
395
396
  /* Call any registered callbacks */
397
792k
  ShutdownExprContext(econtext, isCommit);
398
  /* And clean up the memory used */
399
792k
  MemoryContextDelete(econtext->ecxt_per_tuple_memory);
400
  /* Unlink self from owning EState, if any */
401
792k
  estate = econtext->ecxt_estate;
402
792k
  if (estate)
403
791k
    estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts,
404
791k
                          econtext);
405
  /* And delete the ExprContext node */
406
792k
  pfree(econtext);
407
792k
}
408
409
/*
410
 * ReScanExprContext
411
 *
412
 *    Reset an expression context in preparation for a rescan of its
413
 *    plan node.  This requires calling any registered shutdown callbacks,
414
 *    since any partially complete set-returning-functions must be canceled.
415
 *
416
 * Note we make no assumption about the caller's memory context.
417
 */
418
void
419
ReScanExprContext(ExprContext *econtext)
420
636k
{
421
  /* Call any registered callbacks */
422
636k
  ShutdownExprContext(econtext, true);
423
  /* And clean up the memory used */
424
636k
  MemoryContextReset(econtext->ecxt_per_tuple_memory);
425
636k
}
426
427
/*
428
 * Build a per-output-tuple ExprContext for an EState.
429
 *
430
 * This is normally invoked via GetPerTupleExprContext() macro,
431
 * not directly.
432
 */
433
ExprContext *
434
MakePerTupleExprContext(EState *estate)
435
194k
{
436
194k
  if (estate->es_per_tuple_exprcontext == NULL)
437
194k
    estate->es_per_tuple_exprcontext = CreateExprContext(estate);
438
439
194k
  return estate->es_per_tuple_exprcontext;
440
194k
}
441
442
443
/* ----------------------------------------------------------------
444
 *         miscellaneous node-init support functions
445
 *
446
 * Note: all of these are expected to be called with GetCurrentMemoryContext()
447
 * equal to the per-query memory context.
448
 * ----------------------------------------------------------------
449
 */
450
451
/* ----------------
452
 *    ExecAssignExprContext
453
 *
454
 *    This initializes the ps_ExprContext field.  It is only necessary
455
 *    to do this for nodes which use ExecQual or ExecProject
456
 *    because those routines require an econtext. Other nodes that
457
 *    don't have to evaluate expressions don't need to do this.
458
 * ----------------
459
 */
460
void
461
ExecAssignExprContext(EState *estate, PlanState *planstate)
462
727k
{
463
727k
  planstate->ps_ExprContext = CreateExprContext(estate);
464
727k
}
465
466
/* ----------------
467
 *    ExecGetResultType
468
 * ----------------
469
 */
470
TupleDesc
471
ExecGetResultType(PlanState *planstate)
472
633k
{
473
633k
  return planstate->ps_ResultTupleDesc;
474
633k
}
475
476
477
/* ----------------
478
 *    ExecAssignProjectionInfo
479
 *
480
 * forms the projection information from the node's targetlist
481
 *
482
 * Notes for inputDesc are same as for ExecBuildProjectionInfo: supply it
483
 * for a relation-scan node, can pass NULL for upper-level nodes
484
 * ----------------
485
 */
486
void
487
ExecAssignProjectionInfo(PlanState *planstate,
488
             TupleDesc inputDesc)
489
479k
{
490
479k
  planstate->ps_ProjInfo =
491
479k
    ExecBuildProjectionInfo(planstate->plan->targetlist,
492
479k
                planstate->ps_ExprContext,
493
479k
                planstate->ps_ResultTupleSlot,
494
479k
                planstate,
495
479k
                inputDesc);
496
479k
}
497
498
499
/* ----------------
500
 *    ExecConditionalAssignProjectionInfo
501
 *
502
 * as ExecAssignProjectionInfo, but store NULL rather than building projection
503
 * info if no projection is required
504
 * ----------------
505
 */
506
void
507
ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc,
508
                  Index varno)
509
231k
{
510
231k
  if (tlist_matches_tupdesc(planstate,
511
231k
                planstate->plan->targetlist,
512
231k
                varno,
513
231k
                inputDesc))
514
165k
    planstate->ps_ProjInfo = NULL;
515
65.6k
  else
516
65.6k
  {
517
65.6k
    if (!planstate->ps_ResultTupleSlot)
518
65.8k
      ExecInitResultSlot(planstate);
519
65.6k
    ExecAssignProjectionInfo(planstate, inputDesc);
520
65.6k
  }
521
231k
}
522
523
static bool
524
tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc)
525
231k
{
526
231k
  int     numattrs = tupdesc->natts;
527
231k
  int     attrno;
528
231k
  bool    hasoid;
529
231k
  ListCell   *tlist_item = list_head(tlist);
530
531
  /* Check the tlist attributes */
532
739k
  for (attrno = 1; attrno <= numattrs; 
attrno++508k
)
533
567k
  {
534
567k
    Form_pg_attribute att_tup = TupleDescAttr(tupdesc, attrno - 1);
535
567k
    Var      *var;
536
537
567k
    if (tlist_item == NULL)
538
7.50k
      return false;    /* tlist too short */
539
559k
    var = (Var *) ((TargetEntry *) lfirst(tlist_item))->expr;
540
560k
    if (
!var559k
|| !IsA(var, Var))
541
29.9k
      return false;    /* tlist item not a Var */
542
    /* if these Asserts fail, planner messed up */
543
529k
    Assert(var->varno == varno);
544
529k
    Assert(var->varlevelsup == 0);
545
529k
    if (var->varattno != attrno)
546
21.3k
      return false;    /* out of order */
547
508k
    if (att_tup->attisdropped)
548
0
      return false;   /* table contains dropped columns */
549
508k
    if (att_tup->atthasmissing)
550
0
      return false;   /* table contains cols with missing values */
551
552
    /*
553
     * Note: usually the Var's type should match the tupdesc exactly, but
554
     * in situations involving unions of columns that have different
555
     * typmods, the Var may have come from above the union and hence have
556
     * typmod -1.  This is a legitimate situation since the Var still
557
     * describes the column, just not as exactly as the tupdesc does. We
558
     * could change the planner to prevent it, but it'd then insert
559
     * projection steps just to convert from specific typmod to typmod -1,
560
     * which is pretty silly.
561
     */
562
508k
    if (var->vartype != att_tup->atttypid ||
563
508k
      
(508k
var->vartypmod != att_tup->atttypmod508k
&&
564
508k
       
var->vartypmod != -10
))
565
0
      return false;   /* type mismatch */
566
567
508k
    tlist_item = lnext(tlist_item);
568
508k
  }
569
570
172k
  if (tlist_item)
571
6.88k
    return false;      /* tlist too long */
572
573
  /*
574
   * If the plan context requires a particular hasoid setting, then that has
575
   * to match, too.
576
   */
577
165k
  if (ExecContextForcesOids(ps, &hasoid) &&
578
165k
    
hasoid != tupdesc->tdhasoid1.16k
)
579
121
    return false;
580
581
165k
  return true;
582
165k
}
583
584
/* ----------------
585
 *    ExecFreeExprContext
586
 *
587
 * A plan node's ExprContext should be freed explicitly during executor
588
 * shutdown because there may be shutdown callbacks to call.  (Other resources
589
 * made by the above routines, such as projection info, don't need to be freed
590
 * explicitly because they're just memory in the per-query memory context.)
591
 *
592
 * However ... there is no particular need to do it during ExecEndNode,
593
 * because FreeExecutorState will free any remaining ExprContexts within
594
 * the EState.  Letting FreeExecutorState do it allows the ExprContexts to
595
 * be freed in reverse order of creation, rather than order of creation as
596
 * will happen if we delete them here, which saves O(N^2) work in the list
597
 * cleanup inside FreeExprContext.
598
 * ----------------
599
 */
600
void
601
ExecFreeExprContext(PlanState *planstate)
602
801k
{
603
  /*
604
   * Per above discussion, don't actually delete the ExprContext. We do
605
   * unlink it from the plan node, though.
606
   */
607
801k
  planstate->ps_ExprContext = NULL;
608
801k
}
609
610
611
/* ----------------------------------------------------------------
612
 *          Scan node support
613
 * ----------------------------------------------------------------
614
 */
615
616
/* ----------------
617
 *    ExecAssignScanType
618
 * ----------------
619
 */
620
void
621
ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
622
43
{
623
43
  TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
624
625
43
  ExecSetSlotDescriptor(slot, tupDesc);
626
43
}
627
628
/* ----------------
629
 *    ExecCreateSlotFromOuterPlan
630
 * ----------------
631
 */
632
void
633
ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate)
634
24.4k
{
635
24.4k
  PlanState  *outerPlan;
636
24.4k
  TupleDesc tupDesc;
637
638
24.4k
  outerPlan = outerPlanState(scanstate);
639
24.4k
  tupDesc = ExecGetResultType(outerPlan);
640
641
24.4k
  ExecInitScanTupleSlot(estate, scanstate, tupDesc);
642
24.4k
}
643
644
/* ----------------------------------------------------------------
645
 *    ExecRelationIsTargetRelation
646
 *
647
 *    Detect whether a relation (identified by rangetable index)
648
 *    is one of the target relations of the query.
649
 * ----------------------------------------------------------------
650
 */
651
bool
652
ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
653
356k
{
654
356k
  ResultRelInfo *resultRelInfos;
655
356k
  int     i;
656
657
356k
  resultRelInfos = estate->es_result_relations;
658
358k
  for (i = 0; i < estate->es_num_result_relations; 
i++2.10k
)
659
46.7k
  {
660
46.7k
    if (resultRelInfos[i].ri_RangeTableIndex == scanrelid)
661
44.6k
      return true;
662
46.7k
  }
663
311k
  return false;
664
356k
}
665
666
/* ----------------------------------------------------------------
667
 *    ExecOpenScanRelation
668
 *
669
 *    Open the heap relation to be scanned by a base-level scan plan node.
670
 *    This should be called during the node's ExecInit routine.
671
 *
672
 * By default, this acquires AccessShareLock on the relation.  However,
673
 * if the relation was already locked by InitPlan, we don't need to acquire
674
 * any additional lock.  This saves trips to the shared lock manager.
675
 * ----------------------------------------------------------------
676
 */
677
Relation
678
ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
679
217k
{
680
217k
  Relation  rel;
681
217k
  Oid     reloid;
682
217k
  LOCKMODE  lockmode;
683
684
  /*
685
   * Determine the lock type we need.  First, scan to see if target relation
686
   * is a result relation.  If not, check if it's a FOR UPDATE/FOR SHARE
687
   * relation.  In either of those cases, we got the lock already.
688
   */
689
217k
  lockmode = AccessShareLock;
690
217k
  if (ExecRelationIsTargetRelation(estate, scanrelid))
691
27.1k
    lockmode = NoLock;
692
190k
  else
693
190k
  {
694
    /* Keep this check in sync with InitPlan! */
695
190k
    ExecRowMark *erm = ExecFindRowMark(estate, scanrelid, true);
696
697
190k
    if (erm != NULL && 
erm->relation != NULL5.75k
)
698
5.72k
      lockmode = NoLock;
699
190k
  }
700
701
  /* Open the relation and acquire lock as needed */
702
217k
  reloid = getrelid(scanrelid, estate->es_range_table);
703
217k
  rel = heap_open(reloid, lockmode);
704
705
  /*
706
   * Complain if we're attempting a scan of an unscannable relation, except
707
   * when the query won't actually be run.  This is a slightly klugy place
708
   * to do this, perhaps, but there is no better place.
709
   */
710
217k
  if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
711
217k
    
!214k
RelationIsScannable214k
(rel))
712
217k
    ereport(ERROR,
713
217k
        (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
714
217k
         errmsg("materialized view \"%s\" has not been populated",
715
217k
            RelationGetRelationName(rel)),
716
217k
         errhint("Use the REFRESH MATERIALIZED VIEW command.")));
717
718
217k
  return rel;
719
217k
}
720
721
/* ----------------------------------------------------------------
722
 *    ExecCloseScanRelation
723
 *
724
 *    Close the heap relation scanned by a base-level scan plan node.
725
 *    This should be called during the node's ExecEnd routine.
726
 *
727
 * Currently, we do not release the lock acquired by ExecOpenScanRelation.
728
 * This lock should be held till end of transaction.  (There is a faction
729
 * that considers this too much locking, however.)
730
 *
731
 * If we did want to release the lock, we'd have to repeat the logic in
732
 * ExecOpenScanRelation in order to figure out what to release.
733
 * ----------------------------------------------------------------
734
 */
735
void
736
ExecCloseScanRelation(Relation scanrel)
737
160k
{
738
160k
  heap_close(scanrel, NoLock);
739
160k
}
740
741
/*
742
 * UpdateChangedParamSet
743
 *    Add changed parameters to a plan node's chgParam set
744
 */
745
void
746
UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
747
134k
{
748
134k
  Bitmapset  *parmset;
749
750
  /*
751
   * The plan node only depends on params listed in its allParam set. Don't
752
   * include anything else into its chgParam set.
753
   */
754
134k
  parmset = bms_intersect(node->plan->allParam, newchg);
755
756
  /*
757
   * Keep node->chgParam == NULL if there's not actually any members; this
758
   * allows the simplest possible tests in executor node files.
759
   */
760
134k
  if (!bms_is_empty(parmset))
761
117k
    node->chgParam = bms_join(node->chgParam, parmset);
762
17.0k
  else
763
17.0k
    bms_free(parmset);
764
134k
}
765
766
/*
767
 * executor_errposition
768
 *    Report an execution-time cursor position, if possible.
769
 *
770
 * This is expected to be used within an ereport() call.  The return value
771
 * is a dummy (always 0, in fact).
772
 *
773
 * The locations stored in parsetrees are byte offsets into the source string.
774
 * We have to convert them to 1-based character indexes for reporting to
775
 * clients.  (We do things this way to avoid unnecessary overhead in the
776
 * normal non-error case: computing character indexes would be much more
777
 * expensive than storing token offsets.)
778
 */
779
int
780
executor_errposition(EState *estate, int location)
781
0
{
782
0
  int     pos;
783
784
  /* No-op if location was not provided */
785
0
  if (location < 0)
786
0
    return 0;
787
  /* Can't do anything if source text is not available */
788
0
  if (estate == NULL || estate->es_sourceText == NULL)
789
0
    return 0;
790
  /* Convert offset to character number */
791
0
  pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1;
792
  /* And pass it to the ereport mechanism */
793
0
  return errposition(pos);
794
0
}
795
796
/*
797
 * Register a shutdown callback in an ExprContext.
798
 *
799
 * Shutdown callbacks will be called (in reverse order of registration)
800
 * when the ExprContext is deleted or rescanned.  This provides a hook
801
 * for functions called in the context to do any cleanup needed --- it's
802
 * particularly useful for functions returning sets.  Note that the
803
 * callback will *not* be called in the event that execution is aborted
804
 * by an error.
805
 */
806
void
807
RegisterExprContextCallback(ExprContext *econtext,
808
              ExprContextCallbackFunction function,
809
              Datum arg)
810
64.2k
{
811
64.2k
  ExprContext_CB *ecxt_callback;
812
813
  /* Save the info in appropriate memory context */
814
64.2k
  ecxt_callback = (ExprContext_CB *)
815
64.2k
    MemoryContextAlloc(econtext->ecxt_per_query_memory,
816
64.2k
               sizeof(ExprContext_CB));
817
818
64.2k
  ecxt_callback->function = function;
819
64.2k
  ecxt_callback->arg = arg;
820
821
  /* link to front of list for appropriate execution order */
822
64.2k
  ecxt_callback->next = econtext->ecxt_callbacks;
823
64.2k
  econtext->ecxt_callbacks = ecxt_callback;
824
64.2k
}
825
826
/*
827
 * Deregister a shutdown callback in an ExprContext.
828
 *
829
 * Any list entries matching the function and arg will be removed.
830
 * This can be used if it's no longer necessary to call the callback.
831
 */
832
void
833
UnregisterExprContextCallback(ExprContext *econtext,
834
                ExprContextCallbackFunction function,
835
                Datum arg)
836
59.2k
{
837
59.2k
  ExprContext_CB **prev_callback;
838
59.2k
  ExprContext_CB *ecxt_callback;
839
840
59.2k
  prev_callback = &econtext->ecxt_callbacks;
841
842
140k
  while ((ecxt_callback = *prev_callback) != NULL)
843
81.6k
  {
844
81.6k
    if (ecxt_callback->function == function && 
ecxt_callback->arg == arg59.2k
)
845
59.2k
    {
846
59.2k
      *prev_callback = ecxt_callback->next;
847
59.2k
      pfree(ecxt_callback);
848
59.2k
    }
849
22.4k
    else
850
22.4k
      prev_callback = &ecxt_callback->next;
851
81.6k
  }
852
59.2k
}
853
854
/*
855
 * Call all the shutdown callbacks registered in an ExprContext.
856
 *
857
 * The callback list is emptied (important in case this is only a rescan
858
 * reset, and not deletion of the ExprContext).
859
 *
860
 * If isCommit is false, just clean the callback list but don't call 'em.
861
 * (See comment for FreeExprContext.)
862
 */
863
static void
864
ShutdownExprContext(ExprContext *econtext, bool isCommit)
865
1.42M
{
866
1.42M
  ExprContext_CB *ecxt_callback;
867
1.42M
  MemoryContext oldcontext;
868
869
  /* Fast path in normal case where there's nothing to do. */
870
1.42M
  if (econtext->ecxt_callbacks == NULL)
871
1.42M
    return;
872
873
  /*
874
   * Call the callbacks in econtext's per-tuple context.  This ensures that
875
   * any memory they might leak will get cleaned up.
876
   */
877
2.76k
  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
878
879
  /*
880
   * Call each callback function in reverse registration order.
881
   */
882
7.70k
  while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
883
4.93k
  {
884
4.93k
    econtext->ecxt_callbacks = ecxt_callback->next;
885
4.93k
    if (isCommit)
886
4.93k
      ecxt_callback->function(ecxt_callback->arg);
887
4.93k
    pfree(ecxt_callback);
888
4.93k
  }
889
890
2.76k
  MemoryContextSwitchTo(oldcontext);
891
2.76k
}
892
893
/*
894
 * ExecLockNonLeafAppendTables
895
 *
896
 * Locks, if necessary, the tables indicated by the RT indexes contained in
897
 * the partitioned_rels list.  These are the non-leaf tables in the partition
898
 * tree controlled by a given Append or MergeAppend node.
899
 */
900
void
901
ExecLockNonLeafAppendTables(List *partitioned_rels, EState *estate)
902
1.12k
{
903
1.12k
  PlannedStmt *stmt = estate->es_plannedstmt;
904
1.12k
  ListCell   *lc;
905
906
1.12k
  foreach(lc, partitioned_rels)
907
984
  {
908
984
    ListCell   *l;
909
984
    Index   rti = lfirst_int(lc);
910
984
    bool    is_result_rel = false;
911
984
    Oid     relid = getrelid(rti, estate->es_range_table);
912
913
    /* If this is a result relation, already locked in InitPlan */
914
984
    foreach(l, stmt->nonleafResultRelations)
915
6
    {
916
6
      if (rti == lfirst_int(l))
917
0
      {
918
0
        is_result_rel = true;
919
0
        break;
920
0
      }
921
6
    }
922
923
    /*
924
     * Not a result relation; check if there is a RowMark that requires
925
     * taking a RowShareLock on this rel.
926
     */
927
984
    if (!is_result_rel)
928
984
    {
929
984
      PlanRowMark *rc = NULL;
930
931
984
      foreach(l, stmt->rowMarks)
932
23
      {
933
23
        if (((PlanRowMark *) lfirst(l))->rti == rti)
934
13
        {
935
13
          rc = lfirst(l);
936
13
          break;
937
13
        }
938
23
      }
939
940
984
      if (rc && 
RowMarkRequiresRowShareLock13
(rc->markType))
941
7
        LockRelationOid(relid, RowShareLock);
942
977
      else
943
977
        LockRelationOid(relid, AccessShareLock);
944
984
    }
945
984
  }
946
1.12k
}
947
948
/*
949
 *    GetAttributeByName
950
 *    GetAttributeByNum
951
 *
952
 *    These functions return the value of the requested attribute
953
 *    out of the given tuple Datum.
954
 *    C functions which take a tuple as an argument are expected
955
 *    to use these.  Ex: overpaid(EMP) might call GetAttributeByNum().
956
 *    Note: these are actually rather slow because they do a typcache
957
 *    lookup on each call.
958
 */
959
Datum
960
GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
961
0
{
962
0
  AttrNumber  attrno;
963
0
  Datum   result;
964
0
  Oid     tupType;
965
0
  int32   tupTypmod;
966
0
  TupleDesc tupDesc;
967
0
  HeapTupleData tmptup;
968
0
  int     i;
969
970
0
  if (attname == NULL)
971
0
    elog(ERROR, "invalid attribute name");
972
973
0
  if (isNull == NULL)
974
0
    elog(ERROR, "a NULL isNull pointer was passed");
975
976
0
  if (tuple == NULL)
977
0
  {
978
    /* Kinda bogus but compatible with old behavior... */
979
0
    *isNull = true;
980
0
    return (Datum) 0;
981
0
  }
982
983
0
  tupType = HeapTupleHeaderGetTypeId(tuple);
984
0
  tupTypmod = HeapTupleHeaderGetTypMod(tuple);
985
0
  tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
986
987
0
  attrno = InvalidAttrNumber;
988
0
  for (i = 0; i < tupDesc->natts; i++)
989
0
  {
990
0
    Form_pg_attribute att = TupleDescAttr(tupDesc, i);
991
992
0
    if (namestrcmp(&(att->attname), attname) == 0)
993
0
    {
994
0
      attrno = att->attnum;
995
0
      break;
996
0
    }
997
0
  }
998
999
0
  if (attrno == InvalidAttrNumber)
1000
0
    elog(ERROR, "attribute \"%s\" does not exist", attname);
1001
1002
  /*
1003
   * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
1004
   * the fields in the struct just in case user tries to inspect system
1005
   * columns.
1006
   */
1007
0
  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
1008
0
  ItemPointerSetInvalid(&(tmptup.t_self));
1009
0
  tmptup.t_tableOid = InvalidOid;
1010
0
  tmptup.t_data = tuple;
1011
1012
0
  result = heap_getattr(&tmptup,
1013
0
              attrno,
1014
0
              tupDesc,
1015
0
              isNull);
1016
1017
0
  ReleaseTupleDesc(tupDesc);
1018
1019
0
  return result;
1020
0
}
1021
1022
Datum
1023
GetAttributeByNum(HeapTupleHeader tuple,
1024
          AttrNumber attrno,
1025
          bool *isNull)
1026
0
{
1027
0
  Datum   result;
1028
0
  Oid     tupType;
1029
0
  int32   tupTypmod;
1030
0
  TupleDesc tupDesc;
1031
0
  HeapTupleData tmptup;
1032
1033
0
  if (!AttributeNumberIsValid(attrno))
1034
0
    elog(ERROR, "invalid attribute number %d", attrno);
1035
1036
0
  if (isNull == NULL)
1037
0
    elog(ERROR, "a NULL isNull pointer was passed");
1038
1039
0
  if (tuple == NULL)
1040
0
  {
1041
    /* Kinda bogus but compatible with old behavior... */
1042
0
    *isNull = true;
1043
0
    return (Datum) 0;
1044
0
  }
1045
1046
0
  tupType = HeapTupleHeaderGetTypeId(tuple);
1047
0
  tupTypmod = HeapTupleHeaderGetTypMod(tuple);
1048
0
  tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
1049
1050
  /*
1051
   * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
1052
   * the fields in the struct just in case user tries to inspect system
1053
   * columns.
1054
   */
1055
0
  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
1056
0
  ItemPointerSetInvalid(&(tmptup.t_self));
1057
0
  tmptup.t_tableOid = InvalidOid;
1058
0
  tmptup.t_data = tuple;
1059
1060
0
  result = heap_getattr(&tmptup,
1061
0
              attrno,
1062
0
              tupDesc,
1063
0
              isNull);
1064
1065
0
  ReleaseTupleDesc(tupDesc);
1066
1067
0
  return result;
1068
0
}
1069
1070
/*
1071
 * Number of items in a tlist (including any resjunk items!)
1072
 */
1073
int
1074
ExecTargetListLength(List *targetlist)
1075
1.18M
{
1076
  /* This used to be more complex, but fjoins are dead */
1077
1.18M
  return list_length(targetlist);
1078
1.18M
}
1079
1080
/*
1081
 * Number of items in a tlist, not including any resjunk items
1082
 */
1083
int
1084
ExecCleanTargetListLength(List *targetlist)
1085
128k
{
1086
128k
  int     len = 0;
1087
128k
  ListCell   *tl;
1088
1089
128k
  foreach(tl, targetlist)
1090
304k
  {
1091
304k
    TargetEntry *curTle = lfirst_node(TargetEntry, tl);
1092
1093
304k
    if (!curTle->resjunk)
1094
268k
      len++;
1095
304k
  }
1096
128k
  return len;
1097
128k
}