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