1 /*-------------------------------------------------------------------------
4 * miscellaneous executor utility routines
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
13 *-------------------------------------------------------------------------
17 * CreateExecutorState Create/delete executor working state
20 * CreateStandaloneExprContext
24 * ExecAssignExprContext Common code for plan node init routines.
25 * ExecAssignResultType
28 * ExecOpenScanRelation Common code for scan node init routines.
29 * ExecCloseScanRelation
32 * ExecCloseIndices | referenced by InitPlan, EndPlan,
33 * ExecInsertIndexTuples / ExecInsert, ExecUpdate
35 * RegisterExprContextCallback Register function shutdown callback
36 * UnregisterExprContextCallback Deregister function shutdown callback
39 * This file has traditionally been the place to stick misc.
40 * executor support stuff that doesn't really go anyplace else.
45 #include "access/genam.h"
46 #include "access/heapam.h"
47 #include "catalog/index.h"
48 #include "executor/execdebug.h"
49 #include "parser/parsetree.h"
50 #include "utils/memutils.h"
51 #include "utils/relcache.h"
52 #include "utils/tqual.h"
55 /* ----------------------------------------------------------------
56 * global counters for number of tuples processed, retrieved,
57 * appended, replaced, deleted.
58 * ----------------------------------------------------------------
65 int NIndexTupleInserted
;
66 int NIndexTupleProcessed
;
69 static void ShutdownExprContext(ExprContext
*econtext
);
72 /* ----------------------------------------------------------------
74 * ----------------------------------------------------------------
77 /* ----------------------------------------------------------------
79 * ----------------------------------------------------------------
90 NIndexTupleProcessed
= 0;
94 /* ----------------------------------------------------------------
96 * ----------------------------------------------------------------
100 DisplayTupleCount(FILE *statfp
)
102 if (NTupleProcessed
> 0)
103 fprintf(statfp
, "!\t%d tuple%s processed, ", NTupleProcessed
,
104 (NTupleProcessed
== 1) ? "" : "s");
107 fprintf(statfp
, "!\tno tuples processed.\n");
110 if (NIndexTupleProcessed
> 0)
111 fprintf(statfp
, "%d indextuple%s processed, ", NIndexTupleProcessed
,
112 (NIndexTupleProcessed
== 1) ? "" : "s");
113 if (NIndexTupleInserted
> 0)
114 fprintf(statfp
, "%d indextuple%s inserted, ", NIndexTupleInserted
,
115 (NIndexTupleInserted
== 1) ? "" : "s");
116 if (NTupleRetrieved
> 0)
117 fprintf(statfp
, "%d tuple%s retrieved. ", NTupleRetrieved
,
118 (NTupleRetrieved
== 1) ? "" : "s");
119 if (NTupleAppended
> 0)
120 fprintf(statfp
, "%d tuple%s appended. ", NTupleAppended
,
121 (NTupleAppended
== 1) ? "" : "s");
122 if (NTupleDeleted
> 0)
123 fprintf(statfp
, "%d tuple%s deleted. ", NTupleDeleted
,
124 (NTupleDeleted
== 1) ? "" : "s");
125 if (NTupleReplaced
> 0)
126 fprintf(statfp
, "%d tuple%s replaced. ", NTupleReplaced
,
127 (NTupleReplaced
== 1) ? "" : "s");
128 fprintf(statfp
, "\n");
133 /* ----------------------------------------------------------------
134 * Executor state and memory management functions
135 * ----------------------------------------------------------------
139 * CreateExecutorState
141 * Create and initialize an EState node, which is the root of
142 * working storage for an entire Executor invocation.
144 * Principally, this creates the per-query memory context that will be
145 * used to hold all working data that lives till the end of the query.
146 * Note that the per-query context will become a child of the caller's
147 * CurrentMemoryContext.
151 CreateExecutorState(void)
154 MemoryContext qcontext
;
155 MemoryContext oldcontext
;
158 * Create the per-query context for this Executor run.
160 qcontext
= AllocSetContextCreate(CurrentMemoryContext
,
162 ALLOCSET_DEFAULT_MINSIZE
,
163 ALLOCSET_DEFAULT_INITSIZE
,
164 ALLOCSET_DEFAULT_MAXSIZE
);
167 * Make the EState node within the per-query context. This way, we don't
168 * need a separate pfree() operation for it at shutdown.
170 oldcontext
= MemoryContextSwitchTo(qcontext
);
172 estate
= makeNode(EState
);
175 * Initialize all fields of the Executor State structure
177 estate
->es_direction
= ForwardScanDirection
;
178 estate
->es_snapshot
= SnapshotNow
;
179 estate
->es_crosscheck_snapshot
= InvalidSnapshot
; /* no crosscheck */
180 estate
->es_range_table
= NIL
;
182 estate
->es_output_cid
= (CommandId
) 0;
184 estate
->es_result_relations
= NULL
;
185 estate
->es_num_result_relations
= 0;
186 estate
->es_result_relation_info
= NULL
;
188 estate
->es_junkFilter
= NULL
;
190 estate
->es_trig_target_relations
= NIL
;
191 estate
->es_trig_tuple_slot
= NULL
;
193 estate
->es_param_list_info
= NULL
;
194 estate
->es_param_exec_vals
= NULL
;
196 estate
->es_query_cxt
= qcontext
;
198 estate
->es_tupleTable
= NULL
;
200 estate
->es_processed
= 0;
201 estate
->es_lastoid
= InvalidOid
;
202 estate
->es_rowMarks
= NIL
;
204 estate
->es_instrument
= false;
205 estate
->es_select_into
= false;
206 estate
->es_into_oids
= false;
208 estate
->es_exprcontexts
= NIL
;
210 estate
->es_subplanstates
= NIL
;
212 estate
->es_per_tuple_exprcontext
= NULL
;
214 estate
->es_plannedstmt
= NULL
;
215 estate
->es_evalPlanQual
= NULL
;
216 estate
->es_evTupleNull
= NULL
;
217 estate
->es_evTuple
= NULL
;
218 estate
->es_useEvalPlan
= false;
221 * Return the executor state structure
223 MemoryContextSwitchTo(oldcontext
);
231 * Release an EState along with all remaining working storage.
233 * Note: this is not responsible for releasing non-memory resources,
234 * such as open relations or buffer pins. But it will shut down any
235 * still-active ExprContexts within the EState. That is sufficient
236 * cleanup for situations where the EState has only been used for expression
237 * evaluation, and not to run a complete Plan.
239 * This can be called in any memory context ... so long as it's not one
240 * of the ones to be freed.
244 FreeExecutorState(EState
*estate
)
247 * Shut down and free any remaining ExprContexts. We do this explicitly
248 * to ensure that any remaining shutdown callbacks get called (since they
249 * might need to release resources that aren't simply memory within the
250 * per-query memory context).
252 while (estate
->es_exprcontexts
)
255 * XXX: seems there ought to be a faster way to implement this than
256 * repeated list_delete(), no?
258 FreeExprContext((ExprContext
*) linitial(estate
->es_exprcontexts
));
259 /* FreeExprContext removed the list link for us */
263 * Free the per-query memory context, thereby releasing all working
264 * memory, including the EState node itself.
266 MemoryContextDelete(estate
->es_query_cxt
);
272 * Create a context for expression evaluation within an EState.
274 * An executor run may require multiple ExprContexts (we usually make one
275 * for each Plan node, and a separate one for per-output-tuple processing
276 * such as constraint checking). Each ExprContext has its own "per-tuple"
279 * Note we make no assumption about the caller's memory context.
283 CreateExprContext(EState
*estate
)
285 ExprContext
*econtext
;
286 MemoryContext oldcontext
;
288 /* Create the ExprContext node within the per-query memory context */
289 oldcontext
= MemoryContextSwitchTo(estate
->es_query_cxt
);
291 econtext
= makeNode(ExprContext
);
293 /* Initialize fields of ExprContext */
294 econtext
->ecxt_scantuple
= NULL
;
295 econtext
->ecxt_innertuple
= NULL
;
296 econtext
->ecxt_outertuple
= NULL
;
298 econtext
->ecxt_per_query_memory
= estate
->es_query_cxt
;
301 * Create working memory for expression evaluation in this context.
303 econtext
->ecxt_per_tuple_memory
=
304 AllocSetContextCreate(estate
->es_query_cxt
,
306 ALLOCSET_DEFAULT_MINSIZE
,
307 ALLOCSET_DEFAULT_INITSIZE
,
308 ALLOCSET_DEFAULT_MAXSIZE
);
310 econtext
->ecxt_param_exec_vals
= estate
->es_param_exec_vals
;
311 econtext
->ecxt_param_list_info
= estate
->es_param_list_info
;
313 econtext
->ecxt_aggvalues
= NULL
;
314 econtext
->ecxt_aggnulls
= NULL
;
316 econtext
->caseValue_datum
= (Datum
) 0;
317 econtext
->caseValue_isNull
= true;
319 econtext
->domainValue_datum
= (Datum
) 0;
320 econtext
->domainValue_isNull
= true;
322 econtext
->ecxt_estate
= estate
;
324 econtext
->ecxt_callbacks
= NULL
;
327 * Link the ExprContext into the EState to ensure it is shut down when the
328 * EState is freed. Because we use lcons(), shutdowns will occur in
329 * reverse order of creation, which may not be essential but can't hurt.
331 estate
->es_exprcontexts
= lcons(econtext
, estate
->es_exprcontexts
);
333 MemoryContextSwitchTo(oldcontext
);
339 * CreateStandaloneExprContext
341 * Create a context for standalone expression evaluation.
343 * An ExprContext made this way can be used for evaluation of expressions
344 * that contain no Params, subplans, or Var references (it might work to
345 * put tuple references into the scantuple field, but it seems unwise).
347 * The ExprContext struct is allocated in the caller's current memory
348 * context, which also becomes its "per query" context.
350 * It is caller's responsibility to free the ExprContext when done,
351 * or at least ensure that any shutdown callbacks have been called
352 * (ReScanExprContext() is suitable). Otherwise, non-memory resources
357 CreateStandaloneExprContext(void)
359 ExprContext
*econtext
;
361 /* Create the ExprContext node within the caller's memory context */
362 econtext
= makeNode(ExprContext
);
364 /* Initialize fields of ExprContext */
365 econtext
->ecxt_scantuple
= NULL
;
366 econtext
->ecxt_innertuple
= NULL
;
367 econtext
->ecxt_outertuple
= NULL
;
369 econtext
->ecxt_per_query_memory
= CurrentMemoryContext
;
372 * Create working memory for expression evaluation in this context.
374 econtext
->ecxt_per_tuple_memory
=
375 AllocSetContextCreate(CurrentMemoryContext
,
377 ALLOCSET_DEFAULT_MINSIZE
,
378 ALLOCSET_DEFAULT_INITSIZE
,
379 ALLOCSET_DEFAULT_MAXSIZE
);
381 econtext
->ecxt_param_exec_vals
= NULL
;
382 econtext
->ecxt_param_list_info
= NULL
;
384 econtext
->ecxt_aggvalues
= NULL
;
385 econtext
->ecxt_aggnulls
= NULL
;
387 econtext
->caseValue_datum
= (Datum
) 0;
388 econtext
->caseValue_isNull
= true;
390 econtext
->domainValue_datum
= (Datum
) 0;
391 econtext
->domainValue_isNull
= true;
393 econtext
->ecxt_estate
= NULL
;
395 econtext
->ecxt_callbacks
= NULL
;
403 * Free an expression context, including calling any remaining
404 * shutdown callbacks.
406 * Since we free the temporary context used for expression evaluation,
407 * any previously computed pass-by-reference expression result will go away!
409 * Note we make no assumption about the caller's memory context.
413 FreeExprContext(ExprContext
*econtext
)
417 /* Call any registered callbacks */
418 ShutdownExprContext(econtext
);
419 /* And clean up the memory used */
420 MemoryContextDelete(econtext
->ecxt_per_tuple_memory
);
421 /* Unlink self from owning EState, if any */
422 estate
= econtext
->ecxt_estate
;
424 estate
->es_exprcontexts
= list_delete_ptr(estate
->es_exprcontexts
,
426 /* And delete the ExprContext node */
433 * Reset an expression context in preparation for a rescan of its
434 * plan node. This requires calling any registered shutdown callbacks,
435 * since any partially complete set-returning-functions must be canceled.
437 * Note we make no assumption about the caller's memory context.
440 ReScanExprContext(ExprContext
*econtext
)
442 /* Call any registered callbacks */
443 ShutdownExprContext(econtext
);
444 /* And clean up the memory used */
445 MemoryContextReset(econtext
->ecxt_per_tuple_memory
);
449 * Build a per-output-tuple ExprContext for an EState.
451 * This is normally invoked via GetPerTupleExprContext() macro,
455 MakePerTupleExprContext(EState
*estate
)
457 if (estate
->es_per_tuple_exprcontext
== NULL
)
458 estate
->es_per_tuple_exprcontext
= CreateExprContext(estate
);
460 return estate
->es_per_tuple_exprcontext
;
464 /* ----------------------------------------------------------------
465 * miscellaneous node-init support functions
467 * Note: all of these are expected to be called with CurrentMemoryContext
468 * equal to the per-query memory context.
469 * ----------------------------------------------------------------
473 * ExecAssignExprContext
475 * This initializes the ps_ExprContext field. It is only necessary
476 * to do this for nodes which use ExecQual or ExecProject
477 * because those routines require an econtext. Other nodes that
478 * don't have to evaluate expressions don't need to do this.
482 ExecAssignExprContext(EState
*estate
, PlanState
*planstate
)
484 planstate
->ps_ExprContext
= CreateExprContext(estate
);
488 * ExecAssignResultType
492 ExecAssignResultType(PlanState
*planstate
, TupleDesc tupDesc
)
494 TupleTableSlot
*slot
= planstate
->ps_ResultTupleSlot
;
496 ExecSetSlotDescriptor(slot
, tupDesc
);
500 * ExecAssignResultTypeFromTL
504 ExecAssignResultTypeFromTL(PlanState
*planstate
)
509 if (ExecContextForcesOids(planstate
, &hasoid
))
511 /* context forces OID choice; hasoid is now set correctly */
515 /* given free choice, don't leave space for OIDs in result tuples */
520 * ExecTypeFromTL needs the parse-time representation of the tlist, not a
521 * list of ExprStates. This is good because some plan nodes don't bother
522 * to set up planstate->targetlist ...
524 tupDesc
= ExecTypeFromTL(planstate
->plan
->targetlist
, hasoid
);
525 ExecAssignResultType(planstate
, tupDesc
);
533 ExecGetResultType(PlanState
*planstate
)
535 TupleTableSlot
*slot
= planstate
->ps_ResultTupleSlot
;
537 return slot
->tts_tupleDescriptor
;
541 * ExecBuildProjectionInfo
543 * Build a ProjectionInfo node for evaluating the given tlist in the given
544 * econtext, and storing the result into the tuple slot. (Caller must have
545 * ensured that tuple slot has a descriptor matching the tlist!) Note that
546 * the given tlist should be a list of ExprState nodes, not Expr nodes.
548 * inputDesc can be NULL, but if it is not, we check to see whether simple
549 * Vars in the tlist match the descriptor. It is important to provide
550 * inputDesc for relation-scan plan nodes, as a cross check that the relation
551 * hasn't been changed since the plan was made. At higher levels of a plan,
552 * there is no need to recheck.
556 ExecBuildProjectionInfo(List
*targetList
,
557 ExprContext
*econtext
,
558 TupleTableSlot
*slot
,
561 ProjectionInfo
*projInfo
= makeNode(ProjectionInfo
);
566 len
= ExecTargetListLength(targetList
);
568 projInfo
->pi_targetlist
= targetList
;
569 projInfo
->pi_exprContext
= econtext
;
570 projInfo
->pi_slot
= slot
;
573 * Determine whether the target list consists entirely of simple Var
574 * references (ie, references to non-system attributes) that match the
575 * input. If so, we can use the simpler ExecVariableList instead of
576 * ExecTargetList. (Note: if there is a type mismatch then ExecEvalVar
577 * will probably throw an error at runtime, but we leave that to it.)
580 foreach(tl
, targetList
)
582 GenericExprState
*gstate
= (GenericExprState
*) lfirst(tl
);
583 Var
*variable
= (Var
*) gstate
->arg
->expr
;
584 Form_pg_attribute attr
;
586 if (variable
== NULL
||
587 !IsA(variable
, Var
) ||
588 variable
->varattno
<= 0)
594 continue; /* can't check type, assume OK */
595 if (variable
->varattno
> inputDesc
->natts
)
600 attr
= inputDesc
->attrs
[variable
->varattno
- 1];
601 if (attr
->attisdropped
|| variable
->vartype
!= attr
->atttypid
)
607 projInfo
->pi_isVarList
= isVarList
;
613 AttrNumber lastInnerVar
= 0;
614 AttrNumber lastOuterVar
= 0;
615 AttrNumber lastScanVar
= 0;
617 projInfo
->pi_itemIsDone
= NULL
; /* not needed */
618 projInfo
->pi_varSlotOffsets
= varSlotOffsets
= (int *)
619 palloc0(len
* sizeof(int));
620 projInfo
->pi_varNumbers
= varNumbers
= (int *)
621 palloc0(len
* sizeof(int));
624 * Set up the data needed by ExecVariableList. The slots in which the
625 * variables can be found at runtime are denoted by the offsets of
626 * their slot pointers within the econtext. This rather grotty
627 * representation is needed because the caller may not have given us
628 * the real econtext yet (see hacks in nodeSubplan.c).
630 foreach(tl
, targetList
)
632 GenericExprState
*gstate
= (GenericExprState
*) lfirst(tl
);
633 Var
*variable
= (Var
*) gstate
->arg
->expr
;
634 AttrNumber attnum
= variable
->varattno
;
635 TargetEntry
*tle
= (TargetEntry
*) gstate
->xprstate
.expr
;
636 AttrNumber resind
= tle
->resno
- 1;
638 Assert(resind
>= 0 && resind
< len
);
639 varNumbers
[resind
] = attnum
;
641 switch (variable
->varno
)
644 varSlotOffsets
[resind
] = offsetof(ExprContext
,
646 lastInnerVar
= Max(lastInnerVar
, attnum
);
650 varSlotOffsets
[resind
] = offsetof(ExprContext
,
652 lastOuterVar
= Max(lastOuterVar
, attnum
);
656 varSlotOffsets
[resind
] = offsetof(ExprContext
,
658 lastScanVar
= Max(lastScanVar
, attnum
);
662 projInfo
->pi_lastInnerVar
= lastInnerVar
;
663 projInfo
->pi_lastOuterVar
= lastOuterVar
;
664 projInfo
->pi_lastScanVar
= lastScanVar
;
668 projInfo
->pi_itemIsDone
= (ExprDoneCond
*)
669 palloc(len
* sizeof(ExprDoneCond
));
670 projInfo
->pi_varSlotOffsets
= NULL
;
671 projInfo
->pi_varNumbers
= NULL
;
678 * ExecAssignProjectionInfo
680 * forms the projection information from the node's targetlist
682 * Notes for inputDesc are same as for ExecBuildProjectionInfo: supply it
683 * for a relation-scan node, can pass NULL for upper-level nodes
687 ExecAssignProjectionInfo(PlanState
*planstate
,
690 planstate
->ps_ProjInfo
=
691 ExecBuildProjectionInfo(planstate
->targetlist
,
692 planstate
->ps_ExprContext
,
693 planstate
->ps_ResultTupleSlot
,
699 * ExecFreeExprContext
701 * A plan node's ExprContext should be freed explicitly during executor
702 * shutdown because there may be shutdown callbacks to call. (Other resources
703 * made by the above routines, such as projection info, don't need to be freed
704 * explicitly because they're just memory in the per-query memory context.)
706 * However ... there is no particular need to do it during ExecEndNode,
707 * because FreeExecutorState will free any remaining ExprContexts within
708 * the EState. Letting FreeExecutorState do it allows the ExprContexts to
709 * be freed in reverse order of creation, rather than order of creation as
710 * will happen if we delete them here, which saves O(N^2) work in the list
711 * cleanup inside FreeExprContext.
715 ExecFreeExprContext(PlanState
*planstate
)
718 * Per above discussion, don't actually delete the ExprContext. We do
719 * unlink it from the plan node, though.
721 planstate
->ps_ExprContext
= NULL
;
724 /* ----------------------------------------------------------------
725 * the following scan type support functions are for
726 * those nodes which are stubborn and return tuples in
727 * their Scan tuple slot instead of their Result tuple
728 * slot.. luck fur us, these nodes do not do projections
729 * so we don't have to worry about getting the ProjectionInfo
730 * right for them... -cim 6/3/91
731 * ----------------------------------------------------------------
739 ExecGetScanType(ScanState
*scanstate
)
741 TupleTableSlot
*slot
= scanstate
->ss_ScanTupleSlot
;
743 return slot
->tts_tupleDescriptor
;
751 ExecAssignScanType(ScanState
*scanstate
, TupleDesc tupDesc
)
753 TupleTableSlot
*slot
= scanstate
->ss_ScanTupleSlot
;
755 ExecSetSlotDescriptor(slot
, tupDesc
);
759 * ExecAssignScanTypeFromOuterPlan
763 ExecAssignScanTypeFromOuterPlan(ScanState
*scanstate
)
765 PlanState
*outerPlan
;
768 outerPlan
= outerPlanState(scanstate
);
769 tupDesc
= ExecGetResultType(outerPlan
);
771 ExecAssignScanType(scanstate
, tupDesc
);
775 /* ----------------------------------------------------------------
777 * ----------------------------------------------------------------
780 /* ----------------------------------------------------------------
781 * ExecRelationIsTargetRelation
783 * Detect whether a relation (identified by rangetable index)
784 * is one of the target relations of the query.
785 * ----------------------------------------------------------------
788 ExecRelationIsTargetRelation(EState
*estate
, Index scanrelid
)
790 ResultRelInfo
*resultRelInfos
;
793 resultRelInfos
= estate
->es_result_relations
;
794 for (i
= 0; i
< estate
->es_num_result_relations
; i
++)
796 if (resultRelInfos
[i
].ri_RangeTableIndex
== scanrelid
)
802 /* ----------------------------------------------------------------
803 * ExecOpenScanRelation
805 * Open the heap relation to be scanned by a base-level scan plan node.
806 * This should be called during the node's ExecInit routine.
808 * By default, this acquires AccessShareLock on the relation. However,
809 * if the relation was already locked by InitPlan, we don't need to acquire
810 * any additional lock. This saves trips to the shared lock manager.
811 * ----------------------------------------------------------------
814 ExecOpenScanRelation(EState
*estate
, Index scanrelid
)
820 * Determine the lock type we need. First, scan to see if target relation
821 * is a result relation. If not, check if it's a FOR UPDATE/FOR SHARE
822 * relation. In either of those cases, we got the lock already.
824 lockmode
= AccessShareLock
;
825 if (ExecRelationIsTargetRelation(estate
, scanrelid
))
831 foreach(l
, estate
->es_rowMarks
)
833 ExecRowMark
*erm
= lfirst(l
);
835 if (erm
->rti
== scanrelid
)
843 /* OK, open the relation and acquire lock as needed */
844 reloid
= getrelid(scanrelid
, estate
->es_range_table
);
845 return heap_open(reloid
, lockmode
);
848 /* ----------------------------------------------------------------
849 * ExecCloseScanRelation
851 * Close the heap relation scanned by a base-level scan plan node.
852 * This should be called during the node's ExecEnd routine.
854 * Currently, we do not release the lock acquired by ExecOpenScanRelation.
855 * This lock should be held till end of transaction. (There is a faction
856 * that considers this too much locking, however.)
858 * If we did want to release the lock, we'd have to repeat the logic in
859 * ExecOpenScanRelation in order to figure out what to release.
860 * ----------------------------------------------------------------
863 ExecCloseScanRelation(Relation scanrel
)
865 heap_close(scanrel
, NoLock
);
869 /* ----------------------------------------------------------------
870 * ExecInsertIndexTuples support
871 * ----------------------------------------------------------------
874 /* ----------------------------------------------------------------
877 * Find the indices associated with a result relation, open them,
878 * and save information about them in the result ResultRelInfo.
880 * At entry, caller has already opened and locked
881 * resultRelInfo->ri_RelationDesc.
882 * ----------------------------------------------------------------
885 ExecOpenIndices(ResultRelInfo
*resultRelInfo
)
887 Relation resultRelation
= resultRelInfo
->ri_RelationDesc
;
892 RelationPtr relationDescs
;
893 IndexInfo
**indexInfoArray
;
895 resultRelInfo
->ri_NumIndices
= 0;
897 /* fast path if no indexes */
898 if (!RelationGetForm(resultRelation
)->relhasindex
)
902 * Get cached list of index OIDs
904 indexoidlist
= RelationGetIndexList(resultRelation
);
905 len
= list_length(indexoidlist
);
910 * allocate space for result arrays
912 relationDescs
= (RelationPtr
) palloc(len
* sizeof(Relation
));
913 indexInfoArray
= (IndexInfo
**) palloc(len
* sizeof(IndexInfo
*));
915 resultRelInfo
->ri_NumIndices
= len
;
916 resultRelInfo
->ri_IndexRelationDescs
= relationDescs
;
917 resultRelInfo
->ri_IndexRelationInfo
= indexInfoArray
;
920 * For each index, open the index relation and save pg_index info. We
921 * acquire RowExclusiveLock, signifying we will update the index.
924 foreach(l
, indexoidlist
)
926 Oid indexOid
= lfirst_oid(l
);
930 indexDesc
= index_open(indexOid
, RowExclusiveLock
);
932 /* extract index key information from the index's pg_index info */
933 ii
= BuildIndexInfo(indexDesc
);
935 relationDescs
[i
] = indexDesc
;
936 indexInfoArray
[i
] = ii
;
940 list_free(indexoidlist
);
943 /* ----------------------------------------------------------------
946 * Close the index relations stored in resultRelInfo
947 * ----------------------------------------------------------------
950 ExecCloseIndices(ResultRelInfo
*resultRelInfo
)
954 RelationPtr indexDescs
;
956 numIndices
= resultRelInfo
->ri_NumIndices
;
957 indexDescs
= resultRelInfo
->ri_IndexRelationDescs
;
959 for (i
= 0; i
< numIndices
; i
++)
961 if (indexDescs
[i
] == NULL
)
962 continue; /* shouldn't happen? */
964 /* Drop lock acquired by ExecOpenIndices */
965 index_close(indexDescs
[i
], RowExclusiveLock
);
969 * XXX should free indexInfo array here too? Currently we assume that
970 * such stuff will be cleaned up automatically in FreeExecutorState.
974 /* ----------------------------------------------------------------
975 * ExecInsertIndexTuples
977 * This routine takes care of inserting index tuples
978 * into all the relations indexing the result relation
979 * when a heap tuple is inserted into the result relation.
980 * Much of this code should be moved into the genam
981 * stuff as it only exists here because the genam stuff
982 * doesn't provide the functionality needed by the
983 * executor.. -cim 9/27/89
985 * CAUTION: this must not be called for a HOT update.
986 * We can't defend against that here for lack of info.
987 * Should we change the API to make it safer?
988 * ----------------------------------------------------------------
991 ExecInsertIndexTuples(TupleTableSlot
*slot
,
996 ResultRelInfo
*resultRelInfo
;
999 RelationPtr relationDescs
;
1000 Relation heapRelation
;
1001 IndexInfo
**indexInfoArray
;
1002 ExprContext
*econtext
;
1003 Datum values
[INDEX_MAX_KEYS
];
1004 bool isnull
[INDEX_MAX_KEYS
];
1007 * Get information from the result relation info structure.
1009 resultRelInfo
= estate
->es_result_relation_info
;
1010 numIndices
= resultRelInfo
->ri_NumIndices
;
1011 relationDescs
= resultRelInfo
->ri_IndexRelationDescs
;
1012 indexInfoArray
= resultRelInfo
->ri_IndexRelationInfo
;
1013 heapRelation
= resultRelInfo
->ri_RelationDesc
;
1016 * We will use the EState's per-tuple context for evaluating predicates
1017 * and index expressions (creating it if it's not already there).
1019 econtext
= GetPerTupleExprContext(estate
);
1021 /* Arrange for econtext's scan tuple to be the tuple under test */
1022 econtext
->ecxt_scantuple
= slot
;
1025 * for each index, form and insert the index tuple
1027 for (i
= 0; i
< numIndices
; i
++)
1029 IndexInfo
*indexInfo
;
1031 if (relationDescs
[i
] == NULL
)
1034 indexInfo
= indexInfoArray
[i
];
1036 /* If the index is marked as read-only, ignore it */
1037 if (!indexInfo
->ii_ReadyForInserts
)
1040 /* Check for partial index */
1041 if (indexInfo
->ii_Predicate
!= NIL
)
1046 * If predicate state not set up yet, create it (in the estate's
1047 * per-query context)
1049 predicate
= indexInfo
->ii_PredicateState
;
1050 if (predicate
== NIL
)
1052 predicate
= (List
*)
1053 ExecPrepareExpr((Expr
*) indexInfo
->ii_Predicate
,
1055 indexInfo
->ii_PredicateState
= predicate
;
1058 /* Skip this index-update if the predicate isn't satisfied */
1059 if (!ExecQual(predicate
, econtext
, false))
1064 * FormIndexDatum fills in its values and isnull parameters with the
1065 * appropriate values for the column(s) of the index.
1067 FormIndexDatum(indexInfo
,
1074 * The index AM does the rest. Note we suppress unique-index checks
1075 * if we are being called from VACUUM, since VACUUM may need to move
1076 * dead tuples that have the same keys as live ones.
1078 index_insert(relationDescs
[i
], /* index relation */
1079 values
, /* array of index Datums */
1080 isnull
, /* null flags */
1081 tupleid
, /* tid of heap tuple */
1083 relationDescs
[i
]->rd_index
->indisunique
&& !is_vacuum
);
1086 * keep track of index inserts for debugging
1088 IncrIndexInserted();
1093 * UpdateChangedParamSet
1094 * Add changed parameters to a plan node's chgParam set
1097 UpdateChangedParamSet(PlanState
*node
, Bitmapset
*newchg
)
1102 * The plan node only depends on params listed in its allParam set. Don't
1103 * include anything else into its chgParam set.
1105 parmset
= bms_intersect(node
->plan
->allParam
, newchg
);
1108 * Keep node->chgParam == NULL if there's not actually any members; this
1109 * allows the simplest possible tests in executor node files.
1111 if (!bms_is_empty(parmset
))
1112 node
->chgParam
= bms_join(node
->chgParam
, parmset
);
1118 * Register a shutdown callback in an ExprContext.
1120 * Shutdown callbacks will be called (in reverse order of registration)
1121 * when the ExprContext is deleted or rescanned. This provides a hook
1122 * for functions called in the context to do any cleanup needed --- it's
1123 * particularly useful for functions returning sets. Note that the
1124 * callback will *not* be called in the event that execution is aborted
1128 RegisterExprContextCallback(ExprContext
*econtext
,
1129 ExprContextCallbackFunction function
,
1132 ExprContext_CB
*ecxt_callback
;
1134 /* Save the info in appropriate memory context */
1135 ecxt_callback
= (ExprContext_CB
*)
1136 MemoryContextAlloc(econtext
->ecxt_per_query_memory
,
1137 sizeof(ExprContext_CB
));
1139 ecxt_callback
->function
= function
;
1140 ecxt_callback
->arg
= arg
;
1142 /* link to front of list for appropriate execution order */
1143 ecxt_callback
->next
= econtext
->ecxt_callbacks
;
1144 econtext
->ecxt_callbacks
= ecxt_callback
;
1148 * Deregister a shutdown callback in an ExprContext.
1150 * Any list entries matching the function and arg will be removed.
1151 * This can be used if it's no longer necessary to call the callback.
1154 UnregisterExprContextCallback(ExprContext
*econtext
,
1155 ExprContextCallbackFunction function
,
1158 ExprContext_CB
**prev_callback
;
1159 ExprContext_CB
*ecxt_callback
;
1161 prev_callback
= &econtext
->ecxt_callbacks
;
1163 while ((ecxt_callback
= *prev_callback
) != NULL
)
1165 if (ecxt_callback
->function
== function
&& ecxt_callback
->arg
== arg
)
1167 *prev_callback
= ecxt_callback
->next
;
1168 pfree(ecxt_callback
);
1171 prev_callback
= &ecxt_callback
->next
;
1176 * Call all the shutdown callbacks registered in an ExprContext.
1178 * The callback list is emptied (important in case this is only a rescan
1179 * reset, and not deletion of the ExprContext).
1182 ShutdownExprContext(ExprContext
*econtext
)
1184 ExprContext_CB
*ecxt_callback
;
1185 MemoryContext oldcontext
;
1187 /* Fast path in normal case where there's nothing to do. */
1188 if (econtext
->ecxt_callbacks
== NULL
)
1192 * Call the callbacks in econtext's per-tuple context. This ensures that
1193 * any memory they might leak will get cleaned up.
1195 oldcontext
= MemoryContextSwitchTo(econtext
->ecxt_per_tuple_memory
);
1198 * Call each callback function in reverse registration order.
1200 while ((ecxt_callback
= econtext
->ecxt_callbacks
) != NULL
)
1202 econtext
->ecxt_callbacks
= ecxt_callback
->next
;
1203 (*ecxt_callback
->function
) (ecxt_callback
->arg
);
1204 pfree(ecxt_callback
);
1207 MemoryContextSwitchTo(oldcontext
);