1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * executor.h |
4 | * support for the POSTGRES executor module |
5 | * |
6 | * |
7 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
8 | * Portions Copyright (c) 1994, Regents of the University of California |
9 | * |
10 | * src/include/executor/executor.h |
11 | * |
12 | *------------------------------------------------------------------------- |
13 | */ |
14 | #ifndef EXECUTOR_H |
15 | #define EXECUTOR_H |
16 | |
17 | #include "executor/execdesc.h" |
18 | #include "nodes/lockoptions.h" |
19 | #include "nodes/parsenodes.h" |
20 | #include "utils/memutils.h" |
21 | |
22 | |
23 | /* |
24 | * The "eflags" argument to ExecutorStart and the various ExecInitNode |
25 | * routines is a bitwise OR of the following flag bits, which tell the |
26 | * called plan node what to expect. Note that the flags will get modified |
27 | * as they are passed down the plan tree, since an upper node may require |
28 | * functionality in its subnode not demanded of the plan as a whole |
29 | * (example: MergeJoin requires mark/restore capability in its inner input), |
30 | * or an upper node may shield its input from some functionality requirement |
31 | * (example: Materialize shields its input from needing to do backward scan). |
32 | * |
33 | * EXPLAIN_ONLY indicates that the plan tree is being initialized just so |
34 | * EXPLAIN can print it out; it will not be run. Hence, no side-effects |
35 | * of startup should occur. However, error checks (such as permission checks) |
36 | * should be performed. |
37 | * |
38 | * REWIND indicates that the plan node should try to efficiently support |
39 | * rescans without parameter changes. (Nodes must support ExecReScan calls |
40 | * in any case, but if this flag was not given, they are at liberty to do it |
41 | * through complete recalculation. Note that a parameter change forces a |
42 | * full recalculation in any case.) |
43 | * |
44 | * BACKWARD indicates that the plan node must respect the es_direction flag. |
45 | * When this is not passed, the plan node will only be run forwards. |
46 | * |
47 | * MARK indicates that the plan node must support Mark/Restore calls. |
48 | * When this is not passed, no Mark/Restore will occur. |
49 | * |
50 | * SKIP_TRIGGERS tells ExecutorStart/ExecutorFinish to skip calling |
51 | * AfterTriggerBeginQuery/AfterTriggerEndQuery. This does not necessarily |
52 | * mean that the plan can't queue any AFTER triggers; just that the caller |
53 | * is responsible for there being a trigger context for them to be queued in. |
54 | */ |
55 | #define EXEC_FLAG_EXPLAIN_ONLY 0x0001 /* EXPLAIN, no ANALYZE */ |
56 | #define EXEC_FLAG_REWIND 0x0002 /* need efficient rescan */ |
57 | #define EXEC_FLAG_BACKWARD 0x0004 /* need backward scan */ |
58 | #define EXEC_FLAG_MARK 0x0008 /* need mark/restore */ |
59 | #define EXEC_FLAG_SKIP_TRIGGERS 0x0010 /* skip AfterTrigger calls */ |
60 | #define EXEC_FLAG_WITH_NO_DATA 0x0020 /* rel scannability doesn't matter */ |
61 | |
62 | |
63 | /* Hook for plugins to get control in ExecutorStart() */ |
64 | typedef void (*ExecutorStart_hook_type) (QueryDesc *queryDesc, int eflags); |
65 | extern PGDLLIMPORT ExecutorStart_hook_type ExecutorStart_hook; |
66 | |
67 | /* Hook for plugins to get control in ExecutorRun() */ |
68 | typedef void (*ExecutorRun_hook_type) (QueryDesc *queryDesc, |
69 | ScanDirection direction, |
70 | uint64 count, |
71 | bool execute_once); |
72 | extern PGDLLIMPORT ExecutorRun_hook_type ExecutorRun_hook; |
73 | |
74 | /* Hook for plugins to get control in ExecutorFinish() */ |
75 | typedef void (*ExecutorFinish_hook_type) (QueryDesc *queryDesc); |
76 | extern PGDLLIMPORT ExecutorFinish_hook_type ExecutorFinish_hook; |
77 | |
78 | /* Hook for plugins to get control in ExecutorEnd() */ |
79 | typedef void (*ExecutorEnd_hook_type) (QueryDesc *queryDesc); |
80 | extern PGDLLIMPORT ExecutorEnd_hook_type ExecutorEnd_hook; |
81 | |
82 | /* Hook for plugins to get control in ExecCheckRTPerms() */ |
83 | typedef bool (*ExecutorCheckPerms_hook_type) (List *, bool); |
84 | extern PGDLLIMPORT ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook; |
85 | |
86 | |
87 | /* |
88 | * prototypes from functions in execAmi.c |
89 | */ |
90 | struct Path; /* avoid including pathnodes.h here */ |
91 | |
92 | extern void ExecReScan(PlanState *node); |
93 | extern void ExecMarkPos(PlanState *node); |
94 | extern void ExecRestrPos(PlanState *node); |
95 | extern bool ExecSupportsMarkRestore(struct Path *pathnode); |
96 | extern bool ExecSupportsBackwardScan(Plan *node); |
97 | extern bool ExecMaterializesOutput(NodeTag plantype); |
98 | |
99 | /* |
100 | * prototypes from functions in execCurrent.c |
101 | */ |
102 | extern bool execCurrentOf(CurrentOfExpr *cexpr, |
103 | ExprContext *econtext, |
104 | Oid table_oid, |
105 | ItemPointer current_tid); |
106 | |
107 | /* |
108 | * prototypes from functions in execGrouping.c |
109 | */ |
110 | extern ExprState *execTuplesMatchPrepare(TupleDesc desc, |
111 | int numCols, |
112 | const AttrNumber *keyColIdx, |
113 | const Oid *eqOperators, |
114 | const Oid *collations, |
115 | PlanState *parent); |
116 | extern void execTuplesHashPrepare(int numCols, |
117 | const Oid *eqOperators, |
118 | Oid **eqFuncOids, |
119 | FmgrInfo **hashFunctions); |
120 | extern TupleHashTable BuildTupleHashTable(PlanState *parent, |
121 | TupleDesc inputDesc, |
122 | int numCols, AttrNumber *keyColIdx, |
123 | const Oid *eqfuncoids, |
124 | FmgrInfo *hashfunctions, |
125 | Oid *collations, |
126 | long nbuckets, Size additionalsize, |
127 | MemoryContext tablecxt, |
128 | MemoryContext tempcxt, bool use_variable_hash_iv); |
129 | extern TupleHashTable BuildTupleHashTableExt(PlanState *parent, |
130 | TupleDesc inputDesc, |
131 | int numCols, AttrNumber *keyColIdx, |
132 | const Oid *eqfuncoids, |
133 | FmgrInfo *hashfunctions, |
134 | Oid *collations, |
135 | long nbuckets, Size additionalsize, |
136 | MemoryContext metacxt, |
137 | MemoryContext tablecxt, |
138 | MemoryContext tempcxt, bool use_variable_hash_iv); |
139 | extern TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable, |
140 | TupleTableSlot *slot, |
141 | bool *isnew); |
142 | extern TupleHashEntry FindTupleHashEntry(TupleHashTable hashtable, |
143 | TupleTableSlot *slot, |
144 | ExprState *eqcomp, |
145 | FmgrInfo *hashfunctions); |
146 | extern void ResetTupleHashTable(TupleHashTable hashtable); |
147 | |
148 | /* |
149 | * prototypes from functions in execJunk.c |
150 | */ |
151 | extern JunkFilter *ExecInitJunkFilter(List *targetList, |
152 | TupleTableSlot *slot); |
153 | extern JunkFilter *ExecInitJunkFilterConversion(List *targetList, |
154 | TupleDesc cleanTupType, |
155 | TupleTableSlot *slot); |
156 | extern AttrNumber ExecFindJunkAttribute(JunkFilter *junkfilter, |
157 | const char *attrName); |
158 | extern AttrNumber ExecFindJunkAttributeInTlist(List *targetlist, |
159 | const char *attrName); |
160 | extern Datum ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, |
161 | bool *isNull); |
162 | extern TupleTableSlot *ExecFilterJunk(JunkFilter *junkfilter, |
163 | TupleTableSlot *slot); |
164 | |
165 | |
166 | /* |
167 | * prototypes from functions in execMain.c |
168 | */ |
169 | extern void ExecutorStart(QueryDesc *queryDesc, int eflags); |
170 | extern void standard_ExecutorStart(QueryDesc *queryDesc, int eflags); |
171 | extern void ExecutorRun(QueryDesc *queryDesc, |
172 | ScanDirection direction, uint64 count, bool execute_once); |
173 | extern void standard_ExecutorRun(QueryDesc *queryDesc, |
174 | ScanDirection direction, uint64 count, bool execute_once); |
175 | extern void ExecutorFinish(QueryDesc *queryDesc); |
176 | extern void standard_ExecutorFinish(QueryDesc *queryDesc); |
177 | extern void ExecutorEnd(QueryDesc *queryDesc); |
178 | extern void standard_ExecutorEnd(QueryDesc *queryDesc); |
179 | extern void ExecutorRewind(QueryDesc *queryDesc); |
180 | extern bool ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation); |
181 | extern void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation); |
182 | extern void InitResultRelInfo(ResultRelInfo *resultRelInfo, |
183 | Relation resultRelationDesc, |
184 | Index resultRelationIndex, |
185 | Relation partition_root, |
186 | int instrument_options); |
187 | extern ResultRelInfo *ExecGetTriggerResultRel(EState *estate, Oid relid); |
188 | extern void ExecCleanUpTriggerState(EState *estate); |
189 | extern void ExecConstraints(ResultRelInfo *resultRelInfo, |
190 | TupleTableSlot *slot, EState *estate); |
191 | extern bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, |
192 | TupleTableSlot *slot, EState *estate, bool emitError); |
193 | extern void ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo, |
194 | TupleTableSlot *slot, EState *estate); |
195 | extern void ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo, |
196 | TupleTableSlot *slot, EState *estate); |
197 | extern LockTupleMode ExecUpdateLockMode(EState *estate, ResultRelInfo *relinfo); |
198 | extern ExecRowMark *ExecFindRowMark(EState *estate, Index rti, bool missing_ok); |
199 | extern ExecAuxRowMark *ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist); |
200 | extern TupleTableSlot *EvalPlanQual(EPQState *epqstate, Relation relation, |
201 | Index rti, TupleTableSlot *testslot); |
202 | extern void EvalPlanQualInit(EPQState *epqstate, EState *parentestate, |
203 | Plan *subplan, List *auxrowmarks, int epqParam); |
204 | extern void EvalPlanQualSetPlan(EPQState *epqstate, |
205 | Plan *subplan, List *auxrowmarks); |
206 | extern TupleTableSlot *EvalPlanQualSlot(EPQState *epqstate, |
207 | Relation relation, Index rti); |
208 | |
209 | #define EvalPlanQualSetSlot(epqstate, slot) ((epqstate)->origslot = (slot)) |
210 | extern bool EvalPlanQualFetchRowMark(EPQState *epqstate, Index rti, TupleTableSlot *slot); |
211 | extern TupleTableSlot *EvalPlanQualNext(EPQState *epqstate); |
212 | extern void EvalPlanQualBegin(EPQState *epqstate); |
213 | extern void EvalPlanQualEnd(EPQState *epqstate); |
214 | |
215 | /* |
216 | * functions in execProcnode.c |
217 | */ |
218 | extern PlanState *ExecInitNode(Plan *node, EState *estate, int eflags); |
219 | extern void ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function); |
220 | extern Node *MultiExecProcNode(PlanState *node); |
221 | extern void ExecEndNode(PlanState *node); |
222 | extern bool ExecShutdownNode(PlanState *node); |
223 | extern void ExecSetTupleBound(int64 tuples_needed, PlanState *child_node); |
224 | |
225 | |
226 | /* ---------------------------------------------------------------- |
227 | * ExecProcNode |
228 | * |
229 | * Execute the given node to return a(nother) tuple. |
230 | * ---------------------------------------------------------------- |
231 | */ |
232 | #ifndef FRONTEND |
233 | static inline TupleTableSlot * |
234 | ExecProcNode(PlanState *node) |
235 | { |
236 | if (node->chgParam != NULL) /* something changed? */ |
237 | ExecReScan(node); /* let ReScan handle this */ |
238 | |
239 | return node->ExecProcNode(node); |
240 | } |
241 | #endif |
242 | |
243 | /* |
244 | * prototypes from functions in execExpr.c |
245 | */ |
246 | extern ExprState *ExecInitExpr(Expr *node, PlanState *parent); |
247 | extern ExprState *ExecInitExprWithParams(Expr *node, ParamListInfo ext_params); |
248 | extern ExprState *ExecInitQual(List *qual, PlanState *parent); |
249 | extern ExprState *ExecInitCheck(List *qual, PlanState *parent); |
250 | extern List *ExecInitExprList(List *nodes, PlanState *parent); |
251 | extern ExprState *ExecBuildAggTrans(AggState *aggstate, struct AggStatePerPhaseData *phase, |
252 | bool doSort, bool doHash); |
253 | extern ExprState *ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc, |
254 | const TupleTableSlotOps *lops, const TupleTableSlotOps *rops, |
255 | int numCols, |
256 | const AttrNumber *keyColIdx, |
257 | const Oid *eqfunctions, |
258 | const Oid *collations, |
259 | PlanState *parent); |
260 | extern ProjectionInfo *ExecBuildProjectionInfo(List *targetList, |
261 | ExprContext *econtext, |
262 | TupleTableSlot *slot, |
263 | PlanState *parent, |
264 | TupleDesc inputDesc); |
265 | extern ExprState *ExecPrepareExpr(Expr *node, EState *estate); |
266 | extern ExprState *ExecPrepareQual(List *qual, EState *estate); |
267 | extern ExprState *ExecPrepareCheck(List *qual, EState *estate); |
268 | extern List *ExecPrepareExprList(List *nodes, EState *estate); |
269 | |
270 | /* |
271 | * ExecEvalExpr |
272 | * |
273 | * Evaluate expression identified by "state" in the execution context |
274 | * given by "econtext". *isNull is set to the is-null flag for the result, |
275 | * and the Datum value is the function result. |
276 | * |
277 | * The caller should already have switched into the temporary memory |
278 | * context econtext->ecxt_per_tuple_memory. The convenience entry point |
279 | * ExecEvalExprSwitchContext() is provided for callers who don't prefer to |
280 | * do the switch in an outer loop. |
281 | */ |
282 | #ifndef FRONTEND |
283 | static inline Datum |
284 | ExecEvalExpr(ExprState *state, |
285 | ExprContext *econtext, |
286 | bool *isNull) |
287 | { |
288 | return state->evalfunc(state, econtext, isNull); |
289 | } |
290 | #endif |
291 | |
292 | /* |
293 | * ExecEvalExprSwitchContext |
294 | * |
295 | * Same as ExecEvalExpr, but get into the right allocation context explicitly. |
296 | */ |
297 | #ifndef FRONTEND |
298 | static inline Datum |
299 | ExecEvalExprSwitchContext(ExprState *state, |
300 | ExprContext *econtext, |
301 | bool *isNull) |
302 | { |
303 | Datum retDatum; |
304 | MemoryContext oldContext; |
305 | |
306 | oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); |
307 | retDatum = state->evalfunc(state, econtext, isNull); |
308 | MemoryContextSwitchTo(oldContext); |
309 | return retDatum; |
310 | } |
311 | #endif |
312 | |
313 | /* |
314 | * ExecProject |
315 | * |
316 | * Projects a tuple based on projection info and stores it in the slot passed |
317 | * to ExecBuildProjectInfo(). |
318 | * |
319 | * Note: the result is always a virtual tuple; therefore it may reference |
320 | * the contents of the exprContext's scan tuples and/or temporary results |
321 | * constructed in the exprContext. If the caller wishes the result to be |
322 | * valid longer than that data will be valid, he must call ExecMaterializeSlot |
323 | * on the result slot. |
324 | */ |
325 | #ifndef FRONTEND |
326 | static inline TupleTableSlot * |
327 | ExecProject(ProjectionInfo *projInfo) |
328 | { |
329 | ExprContext *econtext = projInfo->pi_exprContext; |
330 | ExprState *state = &projInfo->pi_state; |
331 | TupleTableSlot *slot = state->resultslot; |
332 | bool isnull; |
333 | |
334 | /* |
335 | * Clear any former contents of the result slot. This makes it safe for |
336 | * us to use the slot's Datum/isnull arrays as workspace. |
337 | */ |
338 | ExecClearTuple(slot); |
339 | |
340 | /* Run the expression, discarding scalar result from the last column. */ |
341 | (void) ExecEvalExprSwitchContext(state, econtext, &isnull); |
342 | |
343 | /* |
344 | * Successfully formed a result row. Mark the result slot as containing a |
345 | * valid virtual tuple (inlined version of ExecStoreVirtualTuple()). |
346 | */ |
347 | slot->tts_flags &= ~TTS_FLAG_EMPTY; |
348 | slot->tts_nvalid = slot->tts_tupleDescriptor->natts; |
349 | |
350 | return slot; |
351 | } |
352 | #endif |
353 | |
354 | /* |
355 | * ExecQual - evaluate a qual prepared with ExecInitQual (possibly via |
356 | * ExecPrepareQual). Returns true if qual is satisfied, else false. |
357 | * |
358 | * Note: ExecQual used to have a third argument "resultForNull". The |
359 | * behavior of this function now corresponds to resultForNull == false. |
360 | * If you want the resultForNull == true behavior, see ExecCheck. |
361 | */ |
362 | #ifndef FRONTEND |
363 | static inline bool |
364 | ExecQual(ExprState *state, ExprContext *econtext) |
365 | { |
366 | Datum ret; |
367 | bool isnull; |
368 | |
369 | /* short-circuit (here and in ExecInitQual) for empty restriction list */ |
370 | if (state == NULL) |
371 | return true; |
372 | |
373 | /* verify that expression was compiled using ExecInitQual */ |
374 | Assert(state->flags & EEO_FLAG_IS_QUAL); |
375 | |
376 | ret = ExecEvalExprSwitchContext(state, econtext, &isnull); |
377 | |
378 | /* EEOP_QUAL should never return NULL */ |
379 | Assert(!isnull); |
380 | |
381 | return DatumGetBool(ret); |
382 | } |
383 | #endif |
384 | |
385 | /* |
386 | * ExecQualAndReset() - evaluate qual with ExecQual() and reset expression |
387 | * context. |
388 | */ |
389 | #ifndef FRONTEND |
390 | static inline bool |
391 | ExecQualAndReset(ExprState *state, ExprContext *econtext) |
392 | { |
393 | bool ret = ExecQual(state, econtext); |
394 | |
395 | /* inline ResetExprContext, to avoid ordering issue in this file */ |
396 | MemoryContextReset(econtext->ecxt_per_tuple_memory); |
397 | return ret; |
398 | } |
399 | #endif |
400 | |
401 | extern bool ExecCheck(ExprState *state, ExprContext *context); |
402 | |
403 | /* |
404 | * prototypes from functions in execSRF.c |
405 | */ |
406 | extern SetExprState *ExecInitTableFunctionResult(Expr *expr, |
407 | ExprContext *econtext, PlanState *parent); |
408 | extern Tuplestorestate *ExecMakeTableFunctionResult(SetExprState *setexpr, |
409 | ExprContext *econtext, |
410 | MemoryContext argContext, |
411 | TupleDesc expectedDesc, |
412 | bool randomAccess); |
413 | extern SetExprState *ExecInitFunctionResultSet(Expr *expr, |
414 | ExprContext *econtext, PlanState *parent); |
415 | extern Datum ExecMakeFunctionResultSet(SetExprState *fcache, |
416 | ExprContext *econtext, |
417 | MemoryContext argContext, |
418 | bool *isNull, |
419 | ExprDoneCond *isDone); |
420 | |
421 | /* |
422 | * prototypes from functions in execScan.c |
423 | */ |
424 | typedef TupleTableSlot *(*ExecScanAccessMtd) (ScanState *node); |
425 | typedef bool (*ExecScanRecheckMtd) (ScanState *node, TupleTableSlot *slot); |
426 | |
427 | extern TupleTableSlot *ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, |
428 | ExecScanRecheckMtd recheckMtd); |
429 | extern void ExecAssignScanProjectionInfo(ScanState *node); |
430 | extern void ExecAssignScanProjectionInfoWithVarno(ScanState *node, Index varno); |
431 | extern void ExecScanReScan(ScanState *node); |
432 | |
433 | /* |
434 | * prototypes from functions in execTuples.c |
435 | */ |
436 | extern void ExecInitResultTypeTL(PlanState *planstate); |
437 | extern void ExecInitResultSlot(PlanState *planstate, |
438 | const TupleTableSlotOps *tts_ops); |
439 | extern void ExecInitResultTupleSlotTL(PlanState *planstate, |
440 | const TupleTableSlotOps *tts_ops); |
441 | extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, |
442 | TupleDesc tupleDesc, |
443 | const TupleTableSlotOps *tts_ops); |
444 | extern TupleTableSlot *(EState *estate, |
445 | TupleDesc tupledesc, |
446 | const TupleTableSlotOps *tts_ops); |
447 | extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate, TupleDesc tupType, |
448 | const TupleTableSlotOps *tts_ops); |
449 | extern TupleDesc ExecTypeFromTL(List *targetList); |
450 | extern TupleDesc ExecCleanTypeFromTL(List *targetList); |
451 | extern TupleDesc ExecTypeFromExprList(List *exprList); |
452 | extern void ExecTypeSetColNames(TupleDesc typeInfo, List *namesList); |
453 | extern void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg); |
454 | |
455 | typedef struct TupOutputState |
456 | { |
457 | TupleTableSlot *slot; |
458 | DestReceiver *dest; |
459 | } TupOutputState; |
460 | |
461 | extern TupOutputState *begin_tup_output_tupdesc(DestReceiver *dest, |
462 | TupleDesc tupdesc, |
463 | const TupleTableSlotOps *tts_ops); |
464 | extern void do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull); |
465 | extern void do_text_output_multiline(TupOutputState *tstate, const char *txt); |
466 | extern void end_tup_output(TupOutputState *tstate); |
467 | |
468 | /* |
469 | * Write a single line of text given as a C string. |
470 | * |
471 | * Should only be used with a single-TEXT-attribute tupdesc. |
472 | */ |
473 | #define do_text_output_oneline(tstate, str_to_emit) \ |
474 | do { \ |
475 | Datum values_[1]; \ |
476 | bool isnull_[1]; \ |
477 | values_[0] = PointerGetDatum(cstring_to_text(str_to_emit)); \ |
478 | isnull_[0] = false; \ |
479 | do_tup_output(tstate, values_, isnull_); \ |
480 | pfree(DatumGetPointer(values_[0])); \ |
481 | } while (0) |
482 | |
483 | |
484 | /* |
485 | * prototypes from functions in execUtils.c |
486 | */ |
487 | extern EState *CreateExecutorState(void); |
488 | extern void FreeExecutorState(EState *estate); |
489 | extern ExprContext *CreateExprContext(EState *estate); |
490 | extern ExprContext *CreateStandaloneExprContext(void); |
491 | extern void FreeExprContext(ExprContext *econtext, bool isCommit); |
492 | extern void ReScanExprContext(ExprContext *econtext); |
493 | |
494 | #define ResetExprContext(econtext) \ |
495 | MemoryContextReset((econtext)->ecxt_per_tuple_memory) |
496 | |
497 | extern ExprContext *MakePerTupleExprContext(EState *estate); |
498 | |
499 | /* Get an EState's per-output-tuple exprcontext, making it if first use */ |
500 | #define GetPerTupleExprContext(estate) \ |
501 | ((estate)->es_per_tuple_exprcontext ? \ |
502 | (estate)->es_per_tuple_exprcontext : \ |
503 | MakePerTupleExprContext(estate)) |
504 | |
505 | #define GetPerTupleMemoryContext(estate) \ |
506 | (GetPerTupleExprContext(estate)->ecxt_per_tuple_memory) |
507 | |
508 | /* Reset an EState's per-output-tuple exprcontext, if one's been created */ |
509 | #define ResetPerTupleExprContext(estate) \ |
510 | do { \ |
511 | if ((estate)->es_per_tuple_exprcontext) \ |
512 | ResetExprContext((estate)->es_per_tuple_exprcontext); \ |
513 | } while (0) |
514 | |
515 | extern void ExecAssignExprContext(EState *estate, PlanState *planstate); |
516 | extern TupleDesc ExecGetResultType(PlanState *planstate); |
517 | extern const TupleTableSlotOps *ExecGetResultSlotOps(PlanState *planstate, |
518 | bool *isfixed); |
519 | extern void ExecAssignProjectionInfo(PlanState *planstate, |
520 | TupleDesc inputDesc); |
521 | extern void ExecConditionalAssignProjectionInfo(PlanState *planstate, |
522 | TupleDesc inputDesc, Index varno); |
523 | extern void ExecFreeExprContext(PlanState *planstate); |
524 | extern void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc); |
525 | extern void ExecCreateScanSlotFromOuterPlan(EState *estate, |
526 | ScanState *scanstate, |
527 | const TupleTableSlotOps *tts_ops); |
528 | |
529 | extern bool ExecRelationIsTargetRelation(EState *estate, Index scanrelid); |
530 | |
531 | extern Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags); |
532 | |
533 | extern void ExecInitRangeTable(EState *estate, List *rangeTable); |
534 | |
535 | static inline RangeTblEntry * |
536 | exec_rt_fetch(Index rti, EState *estate) |
537 | { |
538 | Assert(rti > 0 && rti <= estate->es_range_table_size); |
539 | return estate->es_range_table_array[rti - 1]; |
540 | } |
541 | |
542 | extern Relation ExecGetRangeTableRelation(EState *estate, Index rti); |
543 | |
544 | extern int executor_errposition(EState *estate, int location); |
545 | |
546 | extern void RegisterExprContextCallback(ExprContext *econtext, |
547 | ExprContextCallbackFunction function, |
548 | Datum arg); |
549 | extern void UnregisterExprContextCallback(ExprContext *econtext, |
550 | ExprContextCallbackFunction function, |
551 | Datum arg); |
552 | |
553 | extern Datum GetAttributeByName(HeapTupleHeader tuple, const char *attname, |
554 | bool *isNull); |
555 | extern Datum GetAttributeByNum(HeapTupleHeader tuple, AttrNumber attrno, |
556 | bool *isNull); |
557 | |
558 | extern int ExecTargetListLength(List *targetlist); |
559 | extern int ExecCleanTargetListLength(List *targetlist); |
560 | |
561 | extern TupleTableSlot *ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo); |
562 | extern TupleTableSlot *ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo); |
563 | extern TupleTableSlot *ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo); |
564 | |
565 | /* |
566 | * prototypes from functions in execIndexing.c |
567 | */ |
568 | extern void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative); |
569 | extern void ExecCloseIndices(ResultRelInfo *resultRelInfo); |
570 | extern List *ExecInsertIndexTuples(TupleTableSlot *slot, EState *estate, bool noDupErr, |
571 | bool *specConflict, List *arbiterIndexes); |
572 | extern bool ExecCheckIndexConstraints(TupleTableSlot *slot, EState *estate, |
573 | ItemPointer conflictTid, List *arbiterIndexes); |
574 | extern void check_exclusion_constraint(Relation heap, Relation index, |
575 | IndexInfo *indexInfo, |
576 | ItemPointer tupleid, |
577 | Datum *values, bool *isnull, |
578 | EState *estate, bool newIndex); |
579 | |
580 | /* |
581 | * prototypes from functions in execReplication.c |
582 | */ |
583 | extern bool RelationFindReplTupleByIndex(Relation rel, Oid idxoid, |
584 | LockTupleMode lockmode, |
585 | TupleTableSlot *searchslot, |
586 | TupleTableSlot *outslot); |
587 | extern bool RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, |
588 | TupleTableSlot *searchslot, TupleTableSlot *outslot); |
589 | |
590 | extern void ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot); |
591 | extern void ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, |
592 | TupleTableSlot *searchslot, TupleTableSlot *slot); |
593 | extern void ExecSimpleRelationDelete(EState *estate, EPQState *epqstate, |
594 | TupleTableSlot *searchslot); |
595 | extern void CheckCmdReplicaIdentity(Relation rel, CmdType cmd); |
596 | |
597 | extern void CheckSubscriptionRelkind(char relkind, const char *nspname, |
598 | const char *relname); |
599 | |
600 | #endif /* EXECUTOR_H */ |
601 | |