| 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 | |