#include "executor/execdesc.h"
#include "nodes/parsenodes.h"
Go to the source code of this file.
#define do_text_output_oneline | ( | tstate, | ||
str_to_emit | ||||
) |
do { \ Datum values_[1]; \ bool isnull_[1]; \ values_[0] = PointerGetDatum(cstring_to_text(str_to_emit)); \ isnull_[0] = false; \ do_tup_output(tstate, values_, isnull_); \ pfree(DatumGetPointer(values_[0])); \ } while (0)
Definition at line 285 of file executor.h.
Referenced by ExplainQuery(), and ShowGUCConfigOption().
#define EvalPlanQualSetSlot | ( | epqstate, | ||
slot | ||||
) | ((epqstate)->origslot = (slot)) |
Definition at line 209 of file executor.h.
Referenced by ExecLockRows(), and ExecModifyTable().
#define EXEC_FLAG_BACKWARD 0x0004 |
Definition at line 59 of file executor.h.
Referenced by begin_partition(), ExecInitAgg(), ExecInitBitmapAnd(), ExecInitBitmapHeapScan(), ExecInitBitmapIndexScan(), ExecInitBitmapOr(), ExecInitForeignScan(), ExecInitGroup(), ExecInitHash(), ExecInitHashJoin(), ExecInitMaterial(), ExecInitMergeAppend(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitNestLoop(), ExecInitRecursiveUnion(), ExecInitResult(), ExecInitSetOp(), ExecInitSort(), ExecInitUnique(), ExecInitWindowAgg(), ExecInitWorkTableScan(), FunctionNext(), tuplestore_begin_heap(), and tuplestore_gettuple().
#define EXEC_FLAG_EXPLAIN_ONLY 0x0001 |
Definition at line 57 of file executor.h.
Referenced by ExecInitBitmapIndexScan(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecOpenScanRelation(), explain_ExecutorStart(), fileBeginForeignScan(), postgresBeginForeignModify(), postgresBeginForeignScan(), standard_ExecutorEnd(), standard_ExecutorFinish(), standard_ExecutorRun(), and standard_ExecutorStart().
#define EXEC_FLAG_MARK 0x0008 |
Definition at line 60 of file executor.h.
Referenced by ExecInitAgg(), ExecInitAppend(), ExecInitBitmapAnd(), ExecInitBitmapHeapScan(), ExecInitBitmapIndexScan(), ExecInitBitmapOr(), ExecInitCteScan(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitGroup(), ExecInitHash(), ExecInitHashJoin(), ExecInitLimit(), ExecInitLockRows(), ExecInitMergeAppend(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitNestLoop(), ExecInitRecursiveUnion(), ExecInitResult(), ExecInitSetOp(), ExecInitSubqueryScan(), ExecInitUnique(), ExecInitWindowAgg(), ExecInitWorkTableScan(), ExecMaterial(), ExecMaterialMarkPos(), and ExecMaterialRestrPos().
#define EXEC_FLAG_REWIND 0x0002 |
Definition at line 58 of file executor.h.
Referenced by ExecInitMaterial(), ExecInitMergeJoin(), ExecInitSort(), ExecReScanMaterial(), InitPlan(), PortalStart(), tuplestore_begin_heap(), tuplestore_rescan(), and tuplestore_trim().
#define EXEC_FLAG_SKIP_TRIGGERS 0x0010 |
Definition at line 61 of file executor.h.
Referenced by standard_ExecutorFinish(), and standard_ExecutorStart().
#define EXEC_FLAG_WITH_NO_DATA 0x0080 |
Definition at line 64 of file executor.h.
Referenced by ExecOpenScanRelation().
#define EXEC_FLAG_WITH_OIDS 0x0020 |
Definition at line 62 of file executor.h.
Referenced by ExecContextForcesOids().
#define EXEC_FLAG_WITHOUT_OIDS 0x0040 |
Definition at line 63 of file executor.h.
Referenced by ExecContextForcesOids(), and refresh_matview_datafill().
#define ExecEvalExpr | ( | expr, | ||
econtext, | ||||
isNull, | ||||
isDone | ||||
) | ((*(expr)->evalfunc) (expr, econtext, isNull, isDone)) |
Definition at line 72 of file executor.h.
Referenced by advance_windowaggregate(), ATRewriteTable(), create_cursor(), exec_eval_simple_expr(), ExecEvalAnd(), ExecEvalArray(), ExecEvalArrayCoerceExpr(), ExecEvalArrayRef(), ExecEvalBooleanTest(), ExecEvalCase(), ExecEvalCoalesce(), ExecEvalCoerceToDomain(), ExecEvalCoerceViaIO(), ExecEvalConvertRowtype(), ExecEvalExprSwitchContext(), ExecEvalFieldSelect(), ExecEvalFieldStore(), ExecEvalFuncArgs(), ExecEvalMinMax(), ExecEvalNot(), ExecEvalNullTest(), ExecEvalOr(), ExecEvalRelabelType(), ExecEvalRow(), ExecEvalRowCompare(), ExecEvalXml(), ExecHashGetHashValue(), ExecIndexEvalArrayKeys(), ExecIndexEvalRuntimeKeys(), ExecMakeFunctionResultNoSets(), ExecMakeTableFunctionResult(), ExecQual(), ExecTargetList(), MJEvalInnerValues(), MJEvalOuterValues(), NextCopyFrom(), ValuesNext(), WinGetFuncArgCurrent(), WinGetFuncArgInFrame(), WinGetFuncArgInPartition(), and xmlelement().
#define GetPerTupleExprContext | ( | estate | ) |
((estate)->es_per_tuple_exprcontext ? \ (estate)->es_per_tuple_exprcontext : \ MakePerTupleExprContext(estate))
Definition at line 312 of file executor.h.
Referenced by ATRewriteTable(), btree_predicate_proof(), check_exclusion_constraint(), comparetup_cluster(), compute_index_stats(), CopyFrom(), evaluate_expr(), EvaluateParams(), ExecInsertIndexTuples(), ExecRelCheck(), FormIndexDatum(), get_actual_variable_range(), IndexBuildHeapScan(), IndexCheckExclusion(), TriggerEnabled(), tuplesort_begin_cluster(), tuplesort_end(), validate_index_heapscan(), validateCheckConstraint(), and validateDomainConstraint().
#define GetPerTupleMemoryContext | ( | estate | ) | (GetPerTupleExprContext(estate)->ecxt_per_tuple_memory) |
Definition at line 317 of file executor.h.
Referenced by ATRewriteTable(), CopyFrom(), CopyFromInsertBatch(), ExecBRDeleteTriggers(), ExecBRInsertTriggers(), ExecBRUpdateTriggers(), ExecBSDeleteTriggers(), ExecBSInsertTriggers(), ExecBSTruncateTriggers(), ExecBSUpdateTriggers(), ExecIRDeleteTriggers(), ExecIRInsertTriggers(), ExecIRUpdateTriggers(), and validateCheckConstraint().
#define ResetExprContext | ( | econtext | ) | MemoryContextReset((econtext)->ecxt_per_tuple_memory) |
Definition at line 306 of file executor.h.
Referenced by agg_fill_hash_table(), agg_retrieve_direct(), agg_retrieve_hash_table(), ATRewriteTable(), BitmapHeapNext(), BitmapHeapRecheck(), buildSubPlanHash(), compute_index_stats(), eval_windowaggregates(), exec_eval_cleanup(), ExecHashGetHashValue(), ExecHashJoin(), ExecMakeTableFunctionResult(), ExecMergeJoin(), ExecNestLoop(), ExecProcessReturning(), ExecReScanBitmapIndexScan(), ExecReScanIndexOnlyScan(), ExecReScanIndexScan(), ExecResult(), ExecScan(), ExecScanHashBucket(), ExecScanHashTableForUnmatched(), ExecWindowAgg(), IndexNext(), IndexOnlyNext(), IndexRecheck(), MJCompare(), MJEvalInnerValues(), MJEvalOuterValues(), MJFillInner(), MJFillOuter(), validateCheckConstraint(), and validateDomainConstraint().
#define ResetPerTupleExprContext | ( | estate | ) |
do { \ if ((estate)->es_per_tuple_exprcontext) \ ResetExprContext((estate)->es_per_tuple_exprcontext); \ } while (0)
Definition at line 321 of file executor.h.
Referenced by comparetup_cluster(), CopyFrom(), ExecModifyTable(), ExecPostprocessPlan(), and ExecutePlan().
typedef TupleTableSlot*(* ExecScanAccessMtd)(ScanState *node) |
Definition at line 247 of file executor.h.
typedef bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot) |
Definition at line 248 of file executor.h.
typedef bool(* ExecutorCheckPerms_hook_type)(List *, bool) |
Definition at line 95 of file executor.h.
typedef void(* ExecutorEnd_hook_type)(QueryDesc *queryDesc) |
Definition at line 91 of file executor.h.
typedef void(* ExecutorFinish_hook_type)(QueryDesc *queryDesc) |
Definition at line 87 of file executor.h.
typedef void(* ExecutorRun_hook_type)(QueryDesc *queryDesc, ScanDirection direction, long count) |
Definition at line 81 of file executor.h.
typedef void(* ExecutorStart_hook_type)(QueryDesc *queryDesc, int eflags) |
Definition at line 77 of file executor.h.
typedef struct TupOutputState TupOutputState |
TupOutputState* begin_tup_output_tupdesc | ( | DestReceiver * | dest, | |
TupleDesc | tupdesc | |||
) |
Definition at line 1142 of file execTuples.c.
References TupOutputState::dest, MakeSingleTupleTableSlot(), palloc(), _DestReceiver::rStartup, and TupOutputState::slot.
Referenced by ExplainQuery(), ShowAllGUCConfig(), and ShowGUCConfigOption().
{ TupOutputState *tstate; tstate = (TupOutputState *) palloc(sizeof(TupOutputState)); tstate->slot = MakeSingleTupleTableSlot(tupdesc); tstate->dest = dest; (*tstate->dest->rStartup) (tstate->dest, (int) CMD_SELECT, tupdesc); return tstate; }
TupleHashTable BuildTupleHashTable | ( | int | numCols, | |
AttrNumber * | keyColIdx, | |||
FmgrInfo * | eqfunctions, | |||
FmgrInfo * | hashfunctions, | |||
long | nbuckets, | |||
Size | entrysize, | |||
MemoryContext | tablecxt, | |||
MemoryContext | tempcxt | |||
) |
Definition at line 275 of file execGrouping.c.
References Assert, TupleHashTableData::cur_eq_funcs, HASHCTL::entrysize, TupleHashTableData::entrysize, HASHCTL::hash, HASH_COMPARE, HASH_CONTEXT, hash_create(), HASH_ELEM, HASH_FUNCTION, TupleHashTableData::hashtab, HASHCTL::hcxt, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, TupleHashTableData::keyColIdx, HASHCTL::keysize, HASHCTL::match, MemoryContextAlloc(), MemSet, Min, TupleHashTableData::numCols, TupleHashTableData::tab_eq_funcs, TupleHashTableData::tab_hash_funcs, TupleHashTableData::tablecxt, TupleHashTableData::tableslot, TupleHashTableData::tempcxt, and work_mem.
Referenced by build_hash_table(), and buildSubPlanHash().
{ TupleHashTable hashtable; HASHCTL hash_ctl; Assert(nbuckets > 0); Assert(entrysize >= sizeof(TupleHashEntryData)); /* Limit initial table size request to not more than work_mem */ nbuckets = Min(nbuckets, (long) ((work_mem * 1024L) / entrysize)); hashtable = (TupleHashTable) MemoryContextAlloc(tablecxt, sizeof(TupleHashTableData)); hashtable->numCols = numCols; hashtable->keyColIdx = keyColIdx; hashtable->tab_hash_funcs = hashfunctions; hashtable->tab_eq_funcs = eqfunctions; hashtable->tablecxt = tablecxt; hashtable->tempcxt = tempcxt; hashtable->entrysize = entrysize; hashtable->tableslot = NULL; /* will be made on first lookup */ hashtable->inputslot = NULL; hashtable->in_hash_funcs = NULL; hashtable->cur_eq_funcs = NULL; MemSet(&hash_ctl, 0, sizeof(hash_ctl)); hash_ctl.keysize = sizeof(TupleHashEntryData); hash_ctl.entrysize = entrysize; hash_ctl.hash = TupleHashTableHash; hash_ctl.match = TupleHashTableMatch; hash_ctl.hcxt = tablecxt; hashtable->hashtab = hash_create("TupleHashTable", nbuckets, &hash_ctl, HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT); return hashtable; }
bool check_exclusion_constraint | ( | Relation | heap, | |
Relation | index, | |||
IndexInfo * | indexInfo, | |||
ItemPointer | tupleid, | |||
Datum * | values, | |||
bool * | isnull, | |||
EState * | estate, | |||
bool | newIndex, | |||
bool | errorOK | |||
) |
Definition at line 1174 of file execUtils.c.
References BuildIndexValueDescription(), ExprContext::ecxt_scantuple, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, errtableconstraint(), ExecDropSingleTupleTableSlot(), ExecStoreTuple(), FormIndexDatum(), ForwardScanDirection, GetPerTupleExprContext, i, IndexInfo::ii_ExclusionProcs, IndexInfo::ii_ExclusionStrats, index_beginscan(), index_endscan(), index_getnext(), index_recheck_constraint(), index_rescan(), InitDirtySnapshot, InvalidBuffer, InvalidOid, ItemPointerEquals(), MakeSingleTupleTableSlot(), NULL, RelationData::rd_indcollation, RelationData::rd_index, RelationGetDescr, RelationGetRelationName, ScanKeyEntryInitialize(), HeapTupleData::t_self, TransactionIdIsValid, XactLockTableWait(), SnapshotData::xmax, SnapshotData::xmin, and IndexScanDescData::xs_recheck.
Referenced by ExecInsertIndexTuples(), and IndexCheckExclusion().
{ Oid *constr_procs = indexInfo->ii_ExclusionProcs; uint16 *constr_strats = indexInfo->ii_ExclusionStrats; Oid *index_collations = index->rd_indcollation; int index_natts = index->rd_index->indnatts; IndexScanDesc index_scan; HeapTuple tup; ScanKeyData scankeys[INDEX_MAX_KEYS]; SnapshotData DirtySnapshot; int i; bool conflict; bool found_self; ExprContext *econtext; TupleTableSlot *existing_slot; TupleTableSlot *save_scantuple; /* * If any of the input values are NULL, the constraint check is assumed to * pass (i.e., we assume the operators are strict). */ for (i = 0; i < index_natts; i++) { if (isnull[i]) return true; } /* * Search the tuples that are in the index for any violations, including * tuples that aren't visible yet. */ InitDirtySnapshot(DirtySnapshot); for (i = 0; i < index_natts; i++) { ScanKeyEntryInitialize(&scankeys[i], 0, i + 1, constr_strats[i], InvalidOid, index_collations[i], constr_procs[i], values[i]); } /* * Need a TupleTableSlot to put existing tuples in. * * To use FormIndexDatum, we have to make the econtext's scantuple point * to this slot. Be sure to save and restore caller's value for * scantuple. */ existing_slot = MakeSingleTupleTableSlot(RelationGetDescr(heap)); econtext = GetPerTupleExprContext(estate); save_scantuple = econtext->ecxt_scantuple; econtext->ecxt_scantuple = existing_slot; /* * May have to restart scan from this point if a potential conflict is * found. */ retry: conflict = false; found_self = false; index_scan = index_beginscan(heap, index, &DirtySnapshot, index_natts, 0); index_rescan(index_scan, scankeys, index_natts, NULL, 0); while ((tup = index_getnext(index_scan, ForwardScanDirection)) != NULL) { TransactionId xwait; Datum existing_values[INDEX_MAX_KEYS]; bool existing_isnull[INDEX_MAX_KEYS]; char *error_new; char *error_existing; /* * Ignore the entry for the tuple we're trying to check. */ if (ItemPointerEquals(tupleid, &tup->t_self)) { if (found_self) /* should not happen */ elog(ERROR, "found self tuple multiple times in index \"%s\"", RelationGetRelationName(index)); found_self = true; continue; } /* * Extract the index column values and isnull flags from the existing * tuple. */ ExecStoreTuple(tup, existing_slot, InvalidBuffer, false); FormIndexDatum(indexInfo, existing_slot, estate, existing_values, existing_isnull); /* If lossy indexscan, must recheck the condition */ if (index_scan->xs_recheck) { if (!index_recheck_constraint(index, constr_procs, existing_values, existing_isnull, values)) continue; /* tuple doesn't actually match, so no * conflict */ } /* * At this point we have either a conflict or a potential conflict. If * we're not supposed to raise error, just return the fact of the * potential conflict without waiting to see if it's real. */ if (errorOK) { conflict = true; break; } /* * If an in-progress transaction is affecting the visibility of this * tuple, we need to wait for it to complete and then recheck. For * simplicity we do rechecking by just restarting the whole scan --- * this case probably doesn't happen often enough to be worth trying * harder, and anyway we don't want to hold any index internal locks * while waiting. */ xwait = TransactionIdIsValid(DirtySnapshot.xmin) ? DirtySnapshot.xmin : DirtySnapshot.xmax; if (TransactionIdIsValid(xwait)) { index_endscan(index_scan); XactLockTableWait(xwait); goto retry; } /* * We have a definite conflict. Report it. */ error_new = BuildIndexValueDescription(index, values, isnull); error_existing = BuildIndexValueDescription(index, existing_values, existing_isnull); if (newIndex) ereport(ERROR, (errcode(ERRCODE_EXCLUSION_VIOLATION), errmsg("could not create exclusion constraint \"%s\"", RelationGetRelationName(index)), errdetail("Key %s conflicts with key %s.", error_new, error_existing), errtableconstraint(heap, RelationGetRelationName(index)))); else ereport(ERROR, (errcode(ERRCODE_EXCLUSION_VIOLATION), errmsg("conflicting key value violates exclusion constraint \"%s\"", RelationGetRelationName(index)), errdetail("Key %s conflicts with existing key %s.", error_new, error_existing), errtableconstraint(heap, RelationGetRelationName(index)))); } index_endscan(index_scan); /* * Ordinarily, at this point the search should have found the originally * inserted tuple, unless we exited the loop early because of conflict. * However, it is possible to define exclusion constraints for which that * wouldn't be true --- for instance, if the operator is <>. So we no * longer complain if found_self is still false. */ econtext->ecxt_scantuple = save_scantuple; ExecDropSingleTupleTableSlot(existing_slot); return !conflict; }
Definition at line 939 of file execMain.c.
References CMD_DELETE, CMD_INSERT, CMD_UPDATE, elog, ereport, errcode(), errhint(), errmsg(), ERROR, FdwRoutine::ExecForeignDelete, FdwRoutine::ExecForeignInsert, FdwRoutine::ExecForeignUpdate, GetFdwRoutineForRelation(), NULL, RelationData::rd_rel, RelationGetRelationName, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_TOASTVALUE, RELKIND_VIEW, TriggerDesc::trig_delete_instead_row, TriggerDesc::trig_insert_instead_row, TriggerDesc::trig_update_instead_row, and RelationData::trigdesc.
Referenced by ExecInitModifyTable().
{ TriggerDesc *trigDesc = resultRel->trigdesc; FdwRoutine *fdwroutine; switch (resultRel->rd_rel->relkind) { case RELKIND_RELATION: /* OK */ break; case RELKIND_SEQUENCE: ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot change sequence \"%s\"", RelationGetRelationName(resultRel)))); break; case RELKIND_TOASTVALUE: ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot change TOAST relation \"%s\"", RelationGetRelationName(resultRel)))); break; case RELKIND_VIEW: /* * Okay only if there's a suitable INSTEAD OF trigger. Messages * here should match rewriteHandler.c's rewriteTargetView, except * that we omit errdetail because we haven't got the information * handy (and given that we really shouldn't get here anyway, * it's not worth great exertion to get). */ switch (operation) { case CMD_INSERT: if (!trigDesc || !trigDesc->trig_insert_instead_row) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("cannot insert into view \"%s\"", RelationGetRelationName(resultRel)), errhint("To make the view insertable, provide an unconditional ON INSERT DO INSTEAD rule or an INSTEAD OF INSERT trigger."))); break; case CMD_UPDATE: if (!trigDesc || !trigDesc->trig_update_instead_row) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("cannot update view \"%s\"", RelationGetRelationName(resultRel)), errhint("To make the view updatable, provide an unconditional ON UPDATE DO INSTEAD rule or an INSTEAD OF UPDATE trigger."))); break; case CMD_DELETE: if (!trigDesc || !trigDesc->trig_delete_instead_row) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("cannot delete from view \"%s\"", RelationGetRelationName(resultRel)), errhint("To make the view updatable, provide an unconditional ON DELETE DO INSTEAD rule or an INSTEAD OF DELETE trigger."))); break; default: elog(ERROR, "unrecognized CmdType: %d", (int) operation); break; } break; case RELKIND_MATVIEW: ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot change materialized view \"%s\"", RelationGetRelationName(resultRel)))); break; case RELKIND_FOREIGN_TABLE: /* Okay only if the FDW supports it */ fdwroutine = GetFdwRoutineForRelation(resultRel, false); switch (operation) { case CMD_INSERT: if (fdwroutine->ExecForeignInsert == NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot insert into foreign table \"%s\"", RelationGetRelationName(resultRel)))); break; case CMD_UPDATE: if (fdwroutine->ExecForeignUpdate == NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot update foreign table \"%s\"", RelationGetRelationName(resultRel)))); break; case CMD_DELETE: if (fdwroutine->ExecForeignDelete == NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot delete from foreign table \"%s\"", RelationGetRelationName(resultRel)))); break; default: elog(ERROR, "unrecognized CmdType: %d", (int) operation); break; } break; default: ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot change relation \"%s\"", RelationGetRelationName(resultRel)))); break; } }
EState* CreateExecutorState | ( | void | ) |
Definition at line 81 of file execUtils.c.
References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), CurrentMemoryContext, EState::es_auxmodifytables, EState::es_crosscheck_snapshot, EState::es_direction, EState::es_epqScanDone, EState::es_epqTuple, EState::es_epqTupleSet, EState::es_exprcontexts, EState::es_finished, EState::es_instrument, EState::es_junkFilter, EState::es_lastoid, EState::es_num_result_relations, EState::es_output_cid, EState::es_param_exec_vals, EState::es_param_list_info, EState::es_per_tuple_exprcontext, EState::es_plannedstmt, EState::es_processed, EState::es_query_cxt, EState::es_range_table, EState::es_result_relation_info, EState::es_result_relations, EState::es_rowMarks, EState::es_snapshot, EState::es_subplanstates, EState::es_top_eflags, EState::es_trig_newtup_slot, EState::es_trig_oldtup_slot, EState::es_trig_target_relations, EState::es_trig_tuple_slot, EState::es_tupleTable, makeNode, and MemoryContextSwitchTo().
Referenced by afterTriggerInvokeEvents(), ATRewriteTable(), btree_predicate_proof(), compute_index_stats(), CopyFrom(), EvalPlanQualStart(), evaluate_expr(), ExecuteQuery(), ExecuteTruncate(), ExplainExecuteQuery(), get_actual_variable_range(), IndexBuildHeapScan(), IndexCheckExclusion(), plpgsql_create_econtext(), standard_ExecutorStart(), tuplesort_begin_cluster(), validate_index_heapscan(), validateCheckConstraint(), and validateDomainConstraint().
{ EState *estate; MemoryContext qcontext; MemoryContext oldcontext; /* * Create the per-query context for this Executor run. */ qcontext = AllocSetContextCreate(CurrentMemoryContext, "ExecutorState", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); /* * Make the EState node within the per-query context. This way, we don't * need a separate pfree() operation for it at shutdown. */ oldcontext = MemoryContextSwitchTo(qcontext); estate = makeNode(EState); /* * Initialize all fields of the Executor State structure */ estate->es_direction = ForwardScanDirection; estate->es_snapshot = SnapshotNow; estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */ estate->es_range_table = NIL; estate->es_plannedstmt = NULL; estate->es_junkFilter = NULL; estate->es_output_cid = (CommandId) 0; estate->es_result_relations = NULL; estate->es_num_result_relations = 0; estate->es_result_relation_info = NULL; estate->es_trig_target_relations = NIL; estate->es_trig_tuple_slot = NULL; estate->es_trig_oldtup_slot = NULL; estate->es_trig_newtup_slot = NULL; estate->es_param_list_info = NULL; estate->es_param_exec_vals = NULL; estate->es_query_cxt = qcontext; estate->es_tupleTable = NIL; estate->es_rowMarks = NIL; estate->es_processed = 0; estate->es_lastoid = InvalidOid; estate->es_top_eflags = 0; estate->es_instrument = 0; estate->es_finished = false; estate->es_exprcontexts = NIL; estate->es_subplanstates = NIL; estate->es_auxmodifytables = NIL; estate->es_per_tuple_exprcontext = NULL; estate->es_epqTuple = NULL; estate->es_epqTupleSet = NULL; estate->es_epqScanDone = NULL; /* * Return the executor state structure */ MemoryContextSwitchTo(oldcontext); return estate; }
ExprContext* CreateExprContext | ( | EState * | estate | ) |
Definition at line 218 of file execUtils.c.
References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), ExprContext::caseValue_datum, ExprContext::caseValue_isNull, ExprContext::domainValue_datum, ExprContext::domainValue_isNull, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, ExprContext::ecxt_callbacks, ExprContext::ecxt_estate, ExprContext::ecxt_innertuple, ExprContext::ecxt_outertuple, ExprContext::ecxt_param_exec_vals, ExprContext::ecxt_param_list_info, ExprContext::ecxt_per_query_memory, ExprContext::ecxt_per_tuple_memory, ExprContext::ecxt_scantuple, EState::es_exprcontexts, EState::es_param_exec_vals, EState::es_param_list_info, EState::es_query_cxt, lcons(), makeNode, and MemoryContextSwitchTo().
Referenced by ExecAssignExprContext(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitSubPlan(), MakePerTupleExprContext(), and plpgsql_create_econtext().
{ ExprContext *econtext; MemoryContext oldcontext; /* Create the ExprContext node within the per-query memory context */ oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); econtext = makeNode(ExprContext); /* Initialize fields of ExprContext */ econtext->ecxt_scantuple = NULL; econtext->ecxt_innertuple = NULL; econtext->ecxt_outertuple = NULL; econtext->ecxt_per_query_memory = estate->es_query_cxt; /* * Create working memory for expression evaluation in this context. */ econtext->ecxt_per_tuple_memory = AllocSetContextCreate(estate->es_query_cxt, "ExprContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); econtext->ecxt_param_exec_vals = estate->es_param_exec_vals; econtext->ecxt_param_list_info = estate->es_param_list_info; econtext->ecxt_aggvalues = NULL; econtext->ecxt_aggnulls = NULL; econtext->caseValue_datum = (Datum) 0; econtext->caseValue_isNull = true; econtext->domainValue_datum = (Datum) 0; econtext->domainValue_isNull = true; econtext->ecxt_estate = estate; econtext->ecxt_callbacks = NULL; /* * Link the ExprContext into the EState to ensure it is shut down when the * EState is freed. Because we use lcons(), shutdowns will occur in * reverse order of creation, which may not be essential but can't hurt. */ estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts); MemoryContextSwitchTo(oldcontext); return econtext; }
ExprContext* CreateStandaloneExprContext | ( | void | ) |
Definition at line 292 of file execUtils.c.
References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), ExprContext::caseValue_datum, ExprContext::caseValue_isNull, CurrentMemoryContext, ExprContext::domainValue_datum, ExprContext::domainValue_isNull, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, ExprContext::ecxt_callbacks, ExprContext::ecxt_estate, ExprContext::ecxt_innertuple, ExprContext::ecxt_outertuple, ExprContext::ecxt_param_exec_vals, ExprContext::ecxt_param_list_info, ExprContext::ecxt_per_query_memory, ExprContext::ecxt_per_tuple_memory, ExprContext::ecxt_scantuple, and makeNode.
Referenced by domain_check_input().
{ ExprContext *econtext; /* Create the ExprContext node within the caller's memory context */ econtext = makeNode(ExprContext); /* Initialize fields of ExprContext */ econtext->ecxt_scantuple = NULL; econtext->ecxt_innertuple = NULL; econtext->ecxt_outertuple = NULL; econtext->ecxt_per_query_memory = CurrentMemoryContext; /* * Create working memory for expression evaluation in this context. */ econtext->ecxt_per_tuple_memory = AllocSetContextCreate(CurrentMemoryContext, "ExprContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); econtext->ecxt_param_exec_vals = NULL; econtext->ecxt_param_list_info = NULL; econtext->ecxt_aggvalues = NULL; econtext->ecxt_aggnulls = NULL; econtext->caseValue_datum = (Datum) 0; econtext->caseValue_isNull = true; econtext->domainValue_datum = (Datum) 0; econtext->domainValue_isNull = true; econtext->ecxt_estate = NULL; econtext->ecxt_callbacks = NULL; return econtext; }
void do_text_output_multiline | ( | TupOutputState * | tstate, | |
char * | text | |||
) |
Definition at line 1188 of file execTuples.c.
References cstring_to_text_with_len(), DatumGetPointer, do_tup_output(), pfree(), PointerGetDatum, and values.
Referenced by ExplainQuery().
{ Datum values[1]; bool isnull[1] = {false}; while (*text) { char *eol; int len; eol = strchr(text, '\n'); if (eol) { len = eol - text; eol++; } else { len = strlen(text); eol += len; } values[0] = PointerGetDatum(cstring_to_text_with_len(text, len)); do_tup_output(tstate, values, isnull); pfree(DatumGetPointer(values[0])); text = eol; } }
void do_tup_output | ( | TupOutputState * | tstate, | |
Datum * | values, | |||
bool * | isnull | |||
) |
Definition at line 1160 of file execTuples.c.
References TupOutputState::dest, ExecClearTuple(), ExecStoreVirtualTuple(), tupleDesc::natts, _DestReceiver::receiveSlot, TupOutputState::slot, TupleTableSlot::tts_isnull, TupleTableSlot::tts_tupleDescriptor, and TupleTableSlot::tts_values.
Referenced by do_text_output_multiline(), and ShowAllGUCConfig().
{ TupleTableSlot *slot = tstate->slot; int natts = slot->tts_tupleDescriptor->natts; /* make sure the slot is clear */ ExecClearTuple(slot); /* insert data */ memcpy(slot->tts_values, values, natts * sizeof(Datum)); memcpy(slot->tts_isnull, isnull, natts * sizeof(bool)); /* mark slot as containing a virtual tuple */ ExecStoreVirtualTuple(slot); /* send the tuple to the receiver */ (*tstate->dest->receiveSlot) (slot, tstate->dest); /* clean up */ ExecClearTuple(slot); }
void end_tup_output | ( | TupOutputState * | tstate | ) |
Definition at line 1219 of file execTuples.c.
References TupOutputState::dest, ExecDropSingleTupleTableSlot(), pfree(), _DestReceiver::rShutdown, and TupOutputState::slot.
Referenced by ExplainQuery(), ShowAllGUCConfig(), and ShowGUCConfigOption().
TupleTableSlot* EvalPlanQual | ( | EState * | estate, | |
EPQState * | epqstate, | |||
Relation | relation, | |||
Index | rti, | |||
int | lockmode, | |||
ItemPointer | tid, | |||
TransactionId | priorXmax | |||
) |
Definition at line 1765 of file execMain.c.
References Assert, EvalPlanQualBegin(), EvalPlanQualFetch(), EvalPlanQualFetchRowMarks(), EvalPlanQualNext(), EvalPlanQualSetTuple(), ExecMaterializeSlot(), NULL, HeapTupleData::t_self, and TupIsNull.
Referenced by ExecDelete(), ExecUpdate(), and GetTupleForTrigger().
{ TupleTableSlot *slot; HeapTuple copyTuple; Assert(rti > 0); /* * Get and lock the updated version of the row; if fail, return NULL. */ copyTuple = EvalPlanQualFetch(estate, relation, lockmode, tid, priorXmax); if (copyTuple == NULL) return NULL; /* * For UPDATE/DELETE we have to return tid of actual row we're executing * PQ for. */ *tid = copyTuple->t_self; /* * Need to run a recheck subquery. Initialize or reinitialize EPQ state. */ EvalPlanQualBegin(epqstate, estate); /* * Free old test tuple, if any, and store new tuple where relation's scan * node will see it */ EvalPlanQualSetTuple(epqstate, rti, copyTuple); /* * Fetch any non-locked source rows */ EvalPlanQualFetchRowMarks(epqstate); /* * Run the EPQ query. We assume it will return at most one tuple. */ slot = EvalPlanQualNext(epqstate); /* * If we got a tuple, force the slot to materialize the tuple so that it * is not dependent on any local state in the EPQ query (in particular, * it's highly likely that the slot contains references to any pass-by-ref * datums that may be present in copyTuple). As with the next step, this * is to guard against early re-use of the EPQ query. */ if (!TupIsNull(slot)) (void) ExecMaterializeSlot(slot); /* * Clear out the test tuple. This is needed in case the EPQ query is * re-used to test a tuple for a different relation. (Not clear that can * really happen, but let's be safe.) */ EvalPlanQualSetTuple(epqstate, rti, NULL); return slot; }
Definition at line 2230 of file execMain.c.
References bms_add_member(), PlanState::chgParam, EPQState::epqParam, EState::es_epqScanDone, EState::es_param_exec_vals, EState::es_plannedstmt, EState::es_range_table, EPQState::estate, EvalPlanQualStart(), i, ParamExecData::isnull, list_length(), MemSet, PlannedStmt::nParamExec, NULL, EPQState::plan, EPQState::planstate, and ParamExecData::value.
Referenced by EvalPlanQual(), and ExecLockRows().
{ EState *estate = epqstate->estate; if (estate == NULL) { /* First time through, so create a child EState */ EvalPlanQualStart(epqstate, parentestate, epqstate->plan); } else { /* * We already have a suitable child EPQ tree, so just reset it. */ int rtsize = list_length(parentestate->es_range_table); PlanState *planstate = epqstate->planstate; MemSet(estate->es_epqScanDone, 0, rtsize * sizeof(bool)); /* Recopy current values of parent parameters */ if (parentestate->es_plannedstmt->nParamExec > 0) { int i = parentestate->es_plannedstmt->nParamExec; while (--i >= 0) { /* copy value if any, but not execPlan link */ estate->es_param_exec_vals[i].value = parentestate->es_param_exec_vals[i].value; estate->es_param_exec_vals[i].isnull = parentestate->es_param_exec_vals[i].isnull; } } /* * Mark child plan tree as needing rescan at all scan nodes. The * first ExecProcNode will take care of actually doing the rescan. */ planstate->chgParam = bms_add_member(planstate->chgParam, epqstate->epqParam); } }
void EvalPlanQualEnd | ( | EPQState * | epqstate | ) |
Definition at line 2402 of file execMain.c.
References EState::es_query_cxt, EState::es_subplanstates, EState::es_trig_target_relations, EState::es_tupleTable, EPQState::estate, ExecCloseIndices(), ExecEndNode(), ExecResetTupleTable(), FreeExecutorState(), heap_close, lfirst, MemoryContextSwitchTo(), NoLock, NULL, EPQState::origslot, EPQState::planstate, and ResultRelInfo::ri_RelationDesc.
Referenced by EvalPlanQualSetPlan(), ExecEndLockRows(), and ExecEndModifyTable().
{ EState *estate = epqstate->estate; MemoryContext oldcontext; ListCell *l; if (estate == NULL) return; /* idle, so nothing to do */ oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); ExecEndNode(epqstate->planstate); foreach(l, estate->es_subplanstates) { PlanState *subplanstate = (PlanState *) lfirst(l); ExecEndNode(subplanstate); } /* throw away the per-estate tuple table */ ExecResetTupleTable(estate->es_tupleTable, false); /* close any trigger target relations attached to this EState */ foreach(l, estate->es_trig_target_relations) { ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l); /* Close indices and then the relation itself */ ExecCloseIndices(resultRelInfo); heap_close(resultRelInfo->ri_RelationDesc, NoLock); } MemoryContextSwitchTo(oldcontext); FreeExecutorState(estate); /* Mark EPQState idle */ epqstate->estate = NULL; epqstate->planstate = NULL; epqstate->origslot = NULL; }
HeapTuple EvalPlanQualFetch | ( | EState * | estate, | |
Relation | relation, | |||
int | lockmode, | |||
ItemPointer | tid, | |||
TransactionId | priorXmax | |||
) |
Definition at line 1848 of file execMain.c.
References HeapUpdateFailureData::ctid, elog, ereport, errcode(), errmsg(), ERROR, EState::es_output_cid, heap_copytuple(), heap_fetch(), heap_lock_tuple(), HeapTupleHeaderGetCmin(), HeapTupleHeaderGetUpdateXid, HeapTupleHeaderGetXmin, HeapTupleMayBeUpdated, HeapTupleSelfUpdated, HeapTupleUpdated, InitDirtySnapshot, IsolationUsesXactSnapshot, ItemPointerEquals(), NULL, ReleaseBuffer(), HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleData::t_self, TransactionIdEquals, TransactionIdIsCurrentTransactionId(), TransactionIdIsValid, XactLockTableWait(), HeapUpdateFailureData::xmax, SnapshotData::xmax, and SnapshotData::xmin.
Referenced by EvalPlanQual(), and ExecLockRows().
{ HeapTuple copyTuple = NULL; HeapTupleData tuple; SnapshotData SnapshotDirty; /* * fetch target tuple * * Loop here to deal with updated or busy tuples */ InitDirtySnapshot(SnapshotDirty); tuple.t_self = *tid; for (;;) { Buffer buffer; if (heap_fetch(relation, &SnapshotDirty, &tuple, &buffer, true, NULL)) { HTSU_Result test; HeapUpdateFailureData hufd; /* * If xmin isn't what we're expecting, the slot must have been * recycled and reused for an unrelated tuple. This implies that * the latest version of the row was deleted, so we need do * nothing. (Should be safe to examine xmin without getting * buffer's content lock, since xmin never changes in an existing * tuple.) */ if (!TransactionIdEquals(HeapTupleHeaderGetXmin(tuple.t_data), priorXmax)) { ReleaseBuffer(buffer); return NULL; } /* otherwise xmin should not be dirty... */ if (TransactionIdIsValid(SnapshotDirty.xmin)) elog(ERROR, "t_xmin is uncommitted in tuple to be updated"); /* * If tuple is being updated by other transaction then we have to * wait for its commit/abort. */ if (TransactionIdIsValid(SnapshotDirty.xmax)) { ReleaseBuffer(buffer); XactLockTableWait(SnapshotDirty.xmax); continue; /* loop back to repeat heap_fetch */ } /* * If tuple was inserted by our own transaction, we have to check * cmin against es_output_cid: cmin >= current CID means our * command cannot see the tuple, so we should ignore it. * Otherwise heap_lock_tuple() will throw an error, and so would * any later attempt to update or delete the tuple. (We need not * check cmax because HeapTupleSatisfiesDirty will consider a * tuple deleted by our transaction dead, regardless of cmax.) * Wee just checked that priorXmax == xmin, so we can test that * variable instead of doing HeapTupleHeaderGetXmin again. */ if (TransactionIdIsCurrentTransactionId(priorXmax) && HeapTupleHeaderGetCmin(tuple.t_data) >= estate->es_output_cid) { ReleaseBuffer(buffer); return NULL; } /* * This is a live tuple, so now try to lock it. */ test = heap_lock_tuple(relation, &tuple, estate->es_output_cid, lockmode, false /* wait */, false, &buffer, &hufd); /* We now have two pins on the buffer, get rid of one */ ReleaseBuffer(buffer); switch (test) { case HeapTupleSelfUpdated: /* * The target tuple was already updated or deleted by the * current command, or by a later command in the current * transaction. We *must* ignore the tuple in the former * case, so as to avoid the "Halloween problem" of * repeated update attempts. In the latter case it might * be sensible to fetch the updated tuple instead, but * doing so would require changing heap_lock_tuple as well * as heap_update and heap_delete to not complain about * updating "invisible" tuples, which seems pretty scary. * So for now, treat the tuple as deleted and do not * process. */ ReleaseBuffer(buffer); return NULL; case HeapTupleMayBeUpdated: /* successfully locked */ break; case HeapTupleUpdated: ReleaseBuffer(buffer); if (IsolationUsesXactSnapshot()) ereport(ERROR, (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), errmsg("could not serialize access due to concurrent update"))); if (!ItemPointerEquals(&hufd.ctid, &tuple.t_self)) { /* it was updated, so look at the updated version */ tuple.t_self = hufd.ctid; /* updated row should have xmin matching this xmax */ priorXmax = hufd.xmax; continue; } /* tuple was deleted, so give up */ return NULL; default: ReleaseBuffer(buffer); elog(ERROR, "unrecognized heap_lock_tuple status: %u", test); return NULL; /* keep compiler quiet */ } /* * We got tuple - now copy it for use by recheck query. */ copyTuple = heap_copytuple(&tuple); ReleaseBuffer(buffer); break; } /* * If the referenced slot was actually empty, the latest version of * the row must have been deleted, so we need do nothing. */ if (tuple.t_data == NULL) { ReleaseBuffer(buffer); return NULL; } /* * As above, if xmin isn't what we're expecting, do nothing. */ if (!TransactionIdEquals(HeapTupleHeaderGetXmin(tuple.t_data), priorXmax)) { ReleaseBuffer(buffer); return NULL; } /* * If we get here, the tuple was found but failed SnapshotDirty. * Assuming the xmin is either a committed xact or our own xact (as it * certainly should be if we're trying to modify the tuple), this must * mean that the row was updated or deleted by either a committed xact * or our own xact. If it was deleted, we can ignore it; if it was * updated then chain up to the next version and repeat the whole * process. * * As above, it should be safe to examine xmax and t_ctid without the * buffer content lock, because they can't be changing. */ if (ItemPointerEquals(&tuple.t_self, &tuple.t_data->t_ctid)) { /* deleted, so forget about it */ ReleaseBuffer(buffer); return NULL; } /* updated, so look at the updated row */ tuple.t_self = tuple.t_data->t_ctid; /* updated row should have xmin matching this xmax */ priorXmax = HeapTupleHeaderGetUpdateXid(tuple.t_data); ReleaseBuffer(buffer); /* loop back to fetch next in chain */ } /* * Return the copied tuple */ return copyTuple; }
void EvalPlanQualFetchRowMarks | ( | EPQState * | epqstate | ) |
Definition at line 2115 of file execMain.c.
References EPQState::arowMarks, Assert, ExecAuxRowMark::ctidAttNo, DatumGetHeapTupleHeader, DatumGetObjectId, DatumGetPointer, elog, ERROR, EvalPlanQualSetTuple(), ExecGetJunkAttribute(), heap_copytuple(), heap_fetch(), HeapTupleHeaderGetDatumLength, ItemPointerSetInvalid, lfirst, ExecRowMark::markType, NULL, EPQState::origslot, ExecRowMark::prti, ExecRowMark::relation, RelationGetRelid, ReleaseBuffer(), ROW_MARK_COPY, ROW_MARK_REFERENCE, ExecAuxRowMark::rowmark, RowMarkRequiresRowShareLock, ExecRowMark::rti, SnapshotAny, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, ExecAuxRowMark::toidAttNo, and ExecAuxRowMark::wholeAttNo.
Referenced by EvalPlanQual(), and ExecLockRows().
{ ListCell *l; Assert(epqstate->origslot != NULL); foreach(l, epqstate->arowMarks) { ExecAuxRowMark *aerm = (ExecAuxRowMark *) lfirst(l); ExecRowMark *erm = aerm->rowmark; Datum datum; bool isNull; HeapTupleData tuple; if (RowMarkRequiresRowShareLock(erm->markType)) elog(ERROR, "EvalPlanQual doesn't support locking rowmarks"); /* clear any leftover test tuple for this rel */ EvalPlanQualSetTuple(epqstate, erm->rti, NULL); if (erm->relation) { Buffer buffer; Assert(erm->markType == ROW_MARK_REFERENCE); /* if child rel, must check whether it produced this row */ if (erm->rti != erm->prti) { Oid tableoid; datum = ExecGetJunkAttribute(epqstate->origslot, aerm->toidAttNo, &isNull); /* non-locked rels could be on the inside of outer joins */ if (isNull) continue; tableoid = DatumGetObjectId(datum); if (tableoid != RelationGetRelid(erm->relation)) { /* this child is inactive right now */ continue; } } /* fetch the tuple's ctid */ datum = ExecGetJunkAttribute(epqstate->origslot, aerm->ctidAttNo, &isNull); /* non-locked rels could be on the inside of outer joins */ if (isNull) continue; tuple.t_self = *((ItemPointer) DatumGetPointer(datum)); /* okay, fetch the tuple */ if (!heap_fetch(erm->relation, SnapshotAny, &tuple, &buffer, false, NULL)) elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck"); /* successful, copy and store tuple */ EvalPlanQualSetTuple(epqstate, erm->rti, heap_copytuple(&tuple)); ReleaseBuffer(buffer); } else { HeapTupleHeader td; Assert(erm->markType == ROW_MARK_COPY); /* fetch the whole-row Var for the relation */ datum = ExecGetJunkAttribute(epqstate->origslot, aerm->wholeAttNo, &isNull); /* non-locked rels could be on the inside of outer joins */ if (isNull) continue; td = DatumGetHeapTupleHeader(datum); /* build a temporary HeapTuple control structure */ tuple.t_len = HeapTupleHeaderGetDatumLength(td); ItemPointerSetInvalid(&(tuple.t_self)); tuple.t_tableOid = InvalidOid; tuple.t_data = td; /* copy and store tuple */ EvalPlanQualSetTuple(epqstate, erm->rti, heap_copytuple(&tuple)); } } }
Definition at line 2100 of file execMain.c.
References Assert, EState::es_epqTuple, and EPQState::estate.
Referenced by ExecLockRows().
{ EState *estate = epqstate->estate; Assert(rti > 0); return estate->es_epqTuple[rti - 1]; }
void EvalPlanQualInit | ( | EPQState * | epqstate, | |
EState * | estate, | |||
Plan * | subplan, | |||
List * | auxrowmarks, | |||
int | epqParam | |||
) |
Definition at line 2045 of file execMain.c.
References EPQState::arowMarks, EPQState::epqParam, EPQState::estate, EPQState::origslot, EPQState::plan, and EPQState::planstate.
Referenced by ExecInitLockRows(), and ExecInitModifyTable().
TupleTableSlot* EvalPlanQualNext | ( | EPQState * | epqstate | ) |
Definition at line 2214 of file execMain.c.
References EState::es_query_cxt, EPQState::estate, ExecProcNode(), MemoryContextSwitchTo(), and EPQState::planstate.
Referenced by EvalPlanQual(), and ExecLockRows().
{ MemoryContext oldcontext; TupleTableSlot *slot; oldcontext = MemoryContextSwitchTo(epqstate->estate->es_query_cxt); slot = ExecProcNode(epqstate->planstate); MemoryContextSwitchTo(oldcontext); return slot; }
Definition at line 2064 of file execMain.c.
References EPQState::arowMarks, EvalPlanQualEnd(), and EPQState::plan.
Referenced by ExecInitModifyTable(), and ExecModifyTable().
{ /* If we have a live EPQ query, shut it down */ EvalPlanQualEnd(epqstate); /* And set/change the plan pointer */ epqstate->plan = subplan; /* The rowmarks depend on the plan, too */ epqstate->arowMarks = auxrowmarks; }
Definition at line 2080 of file execMain.c.
References Assert, EState::es_epqTuple, EState::es_epqTupleSet, EPQState::estate, heap_freetuple(), and NULL.
Referenced by EvalPlanQual(), EvalPlanQualFetchRowMarks(), and ExecLockRows().
{ EState *estate = epqstate->estate; Assert(rti > 0); /* * free old test tuple, if any, and store new tuple where relation's scan * node will see it */ if (estate->es_epqTuple[rti - 1] != NULL) heap_freetuple(estate->es_epqTuple[rti - 1]); estate->es_epqTuple[rti - 1] = tuple; estate->es_epqTupleSet[rti - 1] = true; }
Definition at line 422 of file execUtils.c.
References CreateExprContext(), and PlanState::ps_ExprContext.
Referenced by ExecInitAgg(), ExecInitBitmapHeapScan(), ExecInitBitmapIndexScan(), ExecInitCteScan(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitGroup(), ExecInitHash(), ExecInitHashJoin(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitLimit(), ExecInitMergeJoin(), ExecInitNestLoop(), ExecInitResult(), ExecInitSeqScan(), ExecInitSubqueryScan(), ExecInitTidScan(), ExecInitValuesScan(), ExecInitWindowAgg(), and ExecInitWorkTableScan().
{ planstate->ps_ExprContext = CreateExprContext(estate); }
Definition at line 674 of file execUtils.c.
References ExecBuildProjectionInfo(), PlanState::ps_ExprContext, PlanState::ps_ProjInfo, PlanState::ps_ResultTupleSlot, and PlanState::targetlist.
Referenced by ExecAssignScanProjectionInfo(), ExecInitAgg(), ExecInitGroup(), ExecInitHashJoin(), ExecInitMergeJoin(), ExecInitNestLoop(), ExecInitResult(), and ExecInitWindowAgg().
{ planstate->ps_ProjInfo = ExecBuildProjectionInfo(planstate->targetlist, planstate->ps_ExprContext, planstate->ps_ResultTupleSlot, inputDesc); }
Definition at line 432 of file execUtils.c.
References ExecSetSlotDescriptor(), and PlanState::ps_ResultTupleSlot.
Referenced by ExecAssignResultTypeFromTL(), and ExecInitModifyTable().
{ TupleTableSlot *slot = planstate->ps_ResultTupleSlot; ExecSetSlotDescriptor(slot, tupDesc); }
void ExecAssignResultTypeFromTL | ( | PlanState * | planstate | ) |
Definition at line 444 of file execUtils.c.
References ExecAssignResultType(), ExecContextForcesOids(), ExecTypeFromTL(), PlanState::plan, and Plan::targetlist.
Referenced by ExecInitAgg(), ExecInitAppend(), ExecInitBitmapHeapScan(), ExecInitCteScan(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitGroup(), ExecInitHash(), ExecInitHashJoin(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitLimit(), ExecInitLockRows(), ExecInitMaterial(), ExecInitMergeAppend(), ExecInitMergeJoin(), ExecInitNestLoop(), ExecInitRecursiveUnion(), ExecInitResult(), ExecInitSeqScan(), ExecInitSetOp(), ExecInitSort(), ExecInitSubqueryScan(), ExecInitTidScan(), ExecInitUnique(), ExecInitValuesScan(), ExecInitWindowAgg(), and ExecInitWorkTableScan().
{ bool hasoid; TupleDesc tupDesc; if (ExecContextForcesOids(planstate, &hasoid)) { /* context forces OID choice; hasoid is now set correctly */ } else { /* given free choice, don't leave space for OIDs in result tuples */ hasoid = false; } /* * ExecTypeFromTL needs the parse-time representation of the tlist, not a * list of ExprStates. This is good because some plan nodes don't bother * to set up planstate->targetlist ... */ tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid); ExecAssignResultType(planstate, tupDesc); }
void ExecAssignScanProjectionInfo | ( | ScanState * | node | ) |
Definition at line 246 of file execScan.c.
References ExecAssignProjectionInfo(), INDEX_VAR, IsA, NULL, Scan::plan, PlanState::plan, ScanState::ps, PlanState::ps_ProjInfo, Scan::scanrelid, ScanState::ss_ScanTupleSlot, Plan::targetlist, tlist_matches_tupdesc(), and TupleTableSlot::tts_tupleDescriptor.
Referenced by ExecInitBitmapHeapScan(), ExecInitCteScan(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitSeqScan(), ExecInitSubqueryScan(), ExecInitTidScan(), ExecInitValuesScan(), and ExecWorkTableScan().
{ Scan *scan = (Scan *) node->ps.plan; Index varno; /* Vars in an index-only scan's tlist should be INDEX_VAR */ if (IsA(scan, IndexOnlyScan)) varno = INDEX_VAR; else varno = scan->scanrelid; if (tlist_matches_tupdesc(&node->ps, scan->plan.targetlist, varno, node->ss_ScanTupleSlot->tts_tupleDescriptor)) node->ps.ps_ProjInfo = NULL; else ExecAssignProjectionInfo(&node->ps, node->ss_ScanTupleSlot->tts_tupleDescriptor); }
Definition at line 738 of file execUtils.c.
References ExecSetSlotDescriptor(), and ScanState::ss_ScanTupleSlot.
Referenced by ExecAssignScanTypeFromOuterPlan(), ExecInitBitmapHeapScan(), ExecInitCteScan(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitSubqueryScan(), ExecInitTidScan(), ExecInitValuesScan(), ExecWorkTableScan(), and InitScanRelation().
{ TupleTableSlot *slot = scanstate->ss_ScanTupleSlot; ExecSetSlotDescriptor(slot, tupDesc); }
void ExecAssignScanTypeFromOuterPlan | ( | ScanState * | scanstate | ) |
Definition at line 750 of file execUtils.c.
References ExecAssignScanType(), ExecGetResultType(), and outerPlanState.
Referenced by ExecInitAgg(), ExecInitGroup(), ExecInitMaterial(), ExecInitSort(), and ExecInitWindowAgg().
{ PlanState *outerPlan; TupleDesc tupDesc; outerPlan = outerPlanState(scanstate); tupDesc = ExecGetResultType(outerPlan); ExecAssignScanType(scanstate, tupDesc); }
ExecAuxRowMark* ExecBuildAuxRowMark | ( | ExecRowMark * | erm, | |
List * | targetlist | |||
) |
Definition at line 1691 of file execMain.c.
References Assert, AttributeNumberIsValid, ExecAuxRowMark::ctidAttNo, elog, ERROR, ExecFindJunkAttributeInTlist(), ExecRowMark::markType, palloc0(), ExecRowMark::prti, ExecRowMark::relation, ROW_MARK_COPY, ExecAuxRowMark::rowmark, ExecRowMark::rowmarkId, ExecRowMark::rti, snprintf(), ExecAuxRowMark::toidAttNo, and ExecAuxRowMark::wholeAttNo.
Referenced by ExecInitLockRows(), and ExecInitModifyTable().
{ ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark)); char resname[32]; aerm->rowmark = erm; /* Look up the resjunk columns associated with this rowmark */ if (erm->relation) { Assert(erm->markType != ROW_MARK_COPY); /* if child rel, need tableoid */ if (erm->rti != erm->prti) { snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId); aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist, resname); if (!AttributeNumberIsValid(aerm->toidAttNo)) elog(ERROR, "could not find junk %s column", resname); } /* always need ctid for real relations */ snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId); aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist, resname); if (!AttributeNumberIsValid(aerm->ctidAttNo)) elog(ERROR, "could not find junk %s column", resname); } else { Assert(erm->markType == ROW_MARK_COPY); snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId); aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist, resname); if (!AttributeNumberIsValid(aerm->wholeAttNo)) elog(ERROR, "could not find junk %s column", resname); } return aerm; }
ProjectionInfo* ExecBuildProjectionInfo | ( | List * | targetList, | |
ExprContext * | econtext, | |||
TupleTableSlot * | slot, | |||
TupleDesc | inputDesc | |||
) |
Definition at line 496 of file execUtils.c.
References GenericExprState::arg, tupleDesc::attrs, ExecTargetListLength(), ExprState::expr, get_last_attnums(), INNER_VAR, IsA, lappend(), lfirst, makeNode, tupleDesc::natts, NIL, NULL, offsetof, OUTER_VAR, palloc(), ProjectionInfo::pi_directMap, ProjectionInfo::pi_exprContext, ProjectionInfo::pi_itemIsDone, ProjectionInfo::pi_lastInnerVar, ProjectionInfo::pi_lastOuterVar, ProjectionInfo::pi_lastScanVar, ProjectionInfo::pi_numSimpleVars, ProjectionInfo::pi_slot, ProjectionInfo::pi_targetlist, ProjectionInfo::pi_varNumbers, ProjectionInfo::pi_varOutputCols, ProjectionInfo::pi_varSlotOffsets, TargetEntry::resno, Var::varattno, Var::varno, Var::vartype, and GenericExprState::xprstate.
Referenced by ExecAssignProjectionInfo(), ExecInitAgg(), ExecInitModifyTable(), and ExecInitSubPlan().
{ ProjectionInfo *projInfo = makeNode(ProjectionInfo); int len = ExecTargetListLength(targetList); int *workspace; int *varSlotOffsets; int *varNumbers; int *varOutputCols; List *exprlist; int numSimpleVars; bool directMap; ListCell *tl; projInfo->pi_exprContext = econtext; projInfo->pi_slot = slot; /* since these are all int arrays, we need do just one palloc */ workspace = (int *) palloc(len * 3 * sizeof(int)); projInfo->pi_varSlotOffsets = varSlotOffsets = workspace; projInfo->pi_varNumbers = varNumbers = workspace + len; projInfo->pi_varOutputCols = varOutputCols = workspace + len * 2; projInfo->pi_lastInnerVar = 0; projInfo->pi_lastOuterVar = 0; projInfo->pi_lastScanVar = 0; /* * We separate the target list elements into simple Var references and * expressions which require the full ExecTargetList machinery. To be a * simple Var, a Var has to be a user attribute and not mismatch the * inputDesc. (Note: if there is a type mismatch then ExecEvalScalarVar * will probably throw an error at runtime, but we leave that to it.) */ exprlist = NIL; numSimpleVars = 0; directMap = true; foreach(tl, targetList) { GenericExprState *gstate = (GenericExprState *) lfirst(tl); Var *variable = (Var *) gstate->arg->expr; bool isSimpleVar = false; if (variable != NULL && IsA(variable, Var) && variable->varattno > 0) { if (!inputDesc) isSimpleVar = true; /* can't check type, assume OK */ else if (variable->varattno <= inputDesc->natts) { Form_pg_attribute attr; attr = inputDesc->attrs[variable->varattno - 1]; if (!attr->attisdropped && variable->vartype == attr->atttypid) isSimpleVar = true; } } if (isSimpleVar) { TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr; AttrNumber attnum = variable->varattno; varNumbers[numSimpleVars] = attnum; varOutputCols[numSimpleVars] = tle->resno; if (tle->resno != numSimpleVars + 1) directMap = false; switch (variable->varno) { case INNER_VAR: varSlotOffsets[numSimpleVars] = offsetof(ExprContext, ecxt_innertuple); if (projInfo->pi_lastInnerVar < attnum) projInfo->pi_lastInnerVar = attnum; break; case OUTER_VAR: varSlotOffsets[numSimpleVars] = offsetof(ExprContext, ecxt_outertuple); if (projInfo->pi_lastOuterVar < attnum) projInfo->pi_lastOuterVar = attnum; break; /* INDEX_VAR is handled by default case */ default: varSlotOffsets[numSimpleVars] = offsetof(ExprContext, ecxt_scantuple); if (projInfo->pi_lastScanVar < attnum) projInfo->pi_lastScanVar = attnum; break; } numSimpleVars++; } else { /* Not a simple variable, add it to generic targetlist */ exprlist = lappend(exprlist, gstate); /* Examine expr to include contained Vars in lastXXXVar counts */ get_last_attnums((Node *) variable, projInfo); } } projInfo->pi_targetlist = exprlist; projInfo->pi_numSimpleVars = numSimpleVars; projInfo->pi_directMap = directMap; if (exprlist == NIL) projInfo->pi_itemIsDone = NULL; /* not needed */ else projInfo->pi_itemIsDone = (ExprDoneCond *) palloc(len * sizeof(ExprDoneCond)); return projInfo; }
Definition at line 504 of file execMain.c.
References ACL_KIND_CLASS, aclcheck_error(), ACLCHECK_NO_PRIV, Assert, ExecCheckRTEPerms(), ExecutorCheckPerms_hook, get_rel_name(), lfirst, RangeTblEntry::relid, RTE_RELATION, and RangeTblEntry::rtekind.
Referenced by DoCopy(), InitPlan(), intorel_startup(), and RI_Initial_Check().
{ ListCell *l; bool result = true; foreach(l, rangeTable) { RangeTblEntry *rte = (RangeTblEntry *) lfirst(l); result = ExecCheckRTEPerms(rte); if (!result) { Assert(rte->rtekind == RTE_RELATION); if (ereport_on_violation) aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS, get_rel_name(rte->relid)); return false; } } if (ExecutorCheckPerms_hook) result = (*ExecutorCheckPerms_hook) (rangeTable, ereport_on_violation); return result; }
int ExecCleanTargetListLength | ( | List * | targetlist | ) |
Definition at line 5173 of file execQual.c.
References Assert, IsA, lfirst, and TargetEntry::resjunk.
Referenced by check_sql_fn_retval(), and ExecTypeFromTLInternal().
{ int len = 0; ListCell *tl; foreach(tl, targetlist) { TargetEntry *curTle = (TargetEntry *) lfirst(tl); Assert(IsA(curTle, TargetEntry)); if (!curTle->resjunk) len++; } return len; }
Definition at line 915 of file execTuples.c.
References ExecTypeFromTLInternal().
Referenced by ExecInitJunkFilter(), PlanCacheComputeResultDesc(), and PortalStart().
{ return ExecTypeFromTLInternal(targetList, hasoid, true); }
void ExecCloseIndices | ( | ResultRelInfo * | resultRelInfo | ) |
Definition at line 956 of file execUtils.c.
References i, index_close(), NULL, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_NumIndices, and RowExclusiveLock.
Referenced by afterTriggerInvokeEvents(), CatalogCloseIndexes(), CopyFrom(), EvalPlanQualEnd(), and ExecEndPlan().
{ int i; int numIndices; RelationPtr indexDescs; numIndices = resultRelInfo->ri_NumIndices; indexDescs = resultRelInfo->ri_IndexRelationDescs; for (i = 0; i < numIndices; i++) { if (indexDescs[i] == NULL) continue; /* shouldn't happen? */ /* Drop lock acquired by ExecOpenIndices */ index_close(indexDescs[i], RowExclusiveLock); } /* * XXX should free indexInfo array here too? Currently we assume that * such stuff will be cleaned up automatically in FreeExecutorState. */ }
void ExecCloseScanRelation | ( | Relation | scanrel | ) |
Definition at line 866 of file execUtils.c.
References heap_close, and NoLock.
Referenced by ExecEndBitmapHeapScan(), ExecEndForeignScan(), ExecEndIndexOnlyScan(), ExecEndIndexScan(), ExecEndSeqScan(), and ExecEndTidScan().
{ heap_close(scanrel, NoLock); }
void ExecConstraints | ( | ResultRelInfo * | resultRelInfo, | |
TupleTableSlot * | slot, | |||
EState * | estate | |||
) |
Definition at line 1562 of file execMain.c.
References Assert, tupleDesc::attrs, tupleDesc::constr, ereport, errcode(), errdetail(), errmsg(), ERROR, errtablecol(), errtableconstraint(), ExecBuildSlotValueDescription(), ExecRelCheck(), tupleConstr::has_not_null, NameStr, tupleDesc::natts, NULL, tupleConstr::num_check, RelationData::rd_att, RelationGetRelationName, ResultRelInfo::ri_RelationDesc, and slot_attisnull().
Referenced by CopyFrom(), ExecInsert(), and ExecUpdate().
{ Relation rel = resultRelInfo->ri_RelationDesc; TupleConstr *constr = rel->rd_att->constr; Assert(constr); if (constr->has_not_null) { int natts = rel->rd_att->natts; int attrChk; for (attrChk = 1; attrChk <= natts; attrChk++) { if (rel->rd_att->attrs[attrChk - 1]->attnotnull && slot_attisnull(slot, attrChk)) ereport(ERROR, (errcode(ERRCODE_NOT_NULL_VIOLATION), errmsg("null value in column \"%s\" violates not-null constraint", NameStr(rel->rd_att->attrs[attrChk - 1]->attname)), errdetail("Failing row contains %s.", ExecBuildSlotValueDescription(slot, 64)), errtablecol(rel, attrChk))); } } if (constr->num_check > 0) { const char *failed; if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL) ereport(ERROR, (errcode(ERRCODE_CHECK_VIOLATION), errmsg("new row for relation \"%s\" violates check constraint \"%s\"", RelationGetRelationName(rel), failed), errdetail("Failing row contains %s.", ExecBuildSlotValueDescription(slot, 64)), errtableconstraint(rel, failed))); } }
Definition at line 1259 of file execMain.c.
References EState::es_result_relation_info, EState::es_top_eflags, EXEC_FLAG_WITH_OIDS, EXEC_FLAG_WITHOUT_OIDS, NULL, RelationData::rd_rel, ResultRelInfo::ri_RelationDesc, and PlanState::state.
Referenced by ExecAssignResultTypeFromTL(), and tlist_matches_tupdesc().
{ ResultRelInfo *ri = planstate->state->es_result_relation_info; if (ri != NULL) { Relation rel = ri->ri_RelationDesc; if (rel != NULL) { *hasoids = rel->rd_rel->relhasoids; return true; } } if (planstate->state->es_top_eflags & EXEC_FLAG_WITH_OIDS) { *hasoids = true; return true; } if (planstate->state->es_top_eflags & EXEC_FLAG_WITHOUT_OIDS) { *hasoids = false; return true; } return false; }
bool execCurrentOf | ( | CurrentOfExpr * | cexpr, | |
ExprContext * | econtext, | |||
Oid | table_oid, | |||
ItemPointer | current_tid | |||
) |
Definition at line 41 of file execCurrent.c.
References Assert, PortalData::atEnd, PortalData::atStart, ExecRowMark::curCtid, CurrentOfExpr::cursor_name, CurrentOfExpr::cursor_param, DatumGetObjectId, DatumGetPointer, elog, ereport, errcode(), errmsg(), ERROR, EState::es_rowMarks, QueryDesc::estate, fetch_cursor_param_value(), get_rel_name(), GetPortalByName(), ItemPointerIsValid, lfirst, ExecRowMark::markType, NULL, QueryDesc::planstate, PORTAL_ONE_SELECT, PortalGetQueryDesc, PortalIsValid, ExecRowMark::relation, RelationGetRelid, RowMarkRequiresRowShareLock, search_plan_tree(), SelfItemPointerAttributeNumber, slot_getattr(), ScanState::ss_ScanTupleSlot, PortalData::strategy, TableOidAttributeNumber, and TupIsNull.
Referenced by TidListCreate().
{ char *cursor_name; char *table_name; Portal portal; QueryDesc *queryDesc; /* Get the cursor name --- may have to look up a parameter reference */ if (cexpr->cursor_name) cursor_name = cexpr->cursor_name; else cursor_name = fetch_cursor_param_value(econtext, cexpr->cursor_param); /* Fetch table name for possible use in error messages */ table_name = get_rel_name(table_oid); if (table_name == NULL) elog(ERROR, "cache lookup failed for relation %u", table_oid); /* Find the cursor's portal */ portal = GetPortalByName(cursor_name); if (!PortalIsValid(portal)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_CURSOR), errmsg("cursor \"%s\" does not exist", cursor_name))); /* * We have to watch out for non-SELECT queries as well as held cursors, * both of which may have null queryDesc. */ if (portal->strategy != PORTAL_ONE_SELECT) ereport(ERROR, (errcode(ERRCODE_INVALID_CURSOR_STATE), errmsg("cursor \"%s\" is not a SELECT query", cursor_name))); queryDesc = PortalGetQueryDesc(portal); if (queryDesc == NULL || queryDesc->estate == NULL) ereport(ERROR, (errcode(ERRCODE_INVALID_CURSOR_STATE), errmsg("cursor \"%s\" is held from a previous transaction", cursor_name))); /* * We have two different strategies depending on whether the cursor uses * FOR UPDATE/SHARE or not. The reason for supporting both is that the * FOR UPDATE code is able to identify a target table in many cases where * the other code can't, while the non-FOR-UPDATE case allows use of WHERE * CURRENT OF with an insensitive cursor. */ if (queryDesc->estate->es_rowMarks) { ExecRowMark *erm; ListCell *lc; /* * Here, the query must have exactly one FOR UPDATE/SHARE reference to * the target table, and we dig the ctid info out of that. */ erm = NULL; foreach(lc, queryDesc->estate->es_rowMarks) { ExecRowMark *thiserm = (ExecRowMark *) lfirst(lc); if (!RowMarkRequiresRowShareLock(thiserm->markType)) continue; /* ignore non-FOR UPDATE/SHARE items */ if (RelationGetRelid(thiserm->relation) == table_oid) { if (erm) ereport(ERROR, (errcode(ERRCODE_INVALID_CURSOR_STATE), errmsg("cursor \"%s\" has multiple FOR UPDATE/SHARE references to table \"%s\"", cursor_name, table_name))); erm = thiserm; } } if (erm == NULL) ereport(ERROR, (errcode(ERRCODE_INVALID_CURSOR_STATE), errmsg("cursor \"%s\" does not have a FOR UPDATE/SHARE reference to table \"%s\"", cursor_name, table_name))); /* * The cursor must have a current result row: per the SQL spec, it's * an error if not. */ if (portal->atStart || portal->atEnd) ereport(ERROR, (errcode(ERRCODE_INVALID_CURSOR_STATE), errmsg("cursor \"%s\" is not positioned on a row", cursor_name))); /* Return the currently scanned TID, if there is one */ if (ItemPointerIsValid(&(erm->curCtid))) { *current_tid = erm->curCtid; return true; } /* * This table didn't produce the cursor's current row; some other * inheritance child of the same parent must have. Signal caller to * do nothing on this table. */ return false; } else { ScanState *scanstate; bool lisnull; Oid tuple_tableoid PG_USED_FOR_ASSERTS_ONLY; ItemPointer tuple_tid; /* * Without FOR UPDATE, we dig through the cursor's plan to find the * scan node. Fail if it's not there or buried underneath * aggregation. */ scanstate = search_plan_tree(queryDesc->planstate, table_oid); if (!scanstate) ereport(ERROR, (errcode(ERRCODE_INVALID_CURSOR_STATE), errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"", cursor_name, table_name))); /* * The cursor must have a current result row: per the SQL spec, it's * an error if not. We test this at the top level, rather than at the * scan node level, because in inheritance cases any one table scan * could easily not be on a row. We want to return false, not raise * error, if the passed-in table OID is for one of the inactive scans. */ if (portal->atStart || portal->atEnd) ereport(ERROR, (errcode(ERRCODE_INVALID_CURSOR_STATE), errmsg("cursor \"%s\" is not positioned on a row", cursor_name))); /* Now OK to return false if we found an inactive scan */ if (TupIsNull(scanstate->ss_ScanTupleSlot)) return false; /* Use slot_getattr to catch any possible mistakes */ tuple_tableoid = DatumGetObjectId(slot_getattr(scanstate->ss_ScanTupleSlot, TableOidAttributeNumber, &lisnull)); Assert(!lisnull); tuple_tid = (ItemPointer) DatumGetPointer(slot_getattr(scanstate->ss_ScanTupleSlot, SelfItemPointerAttributeNumber, &lisnull)); Assert(!lisnull); Assert(tuple_tableoid == table_oid); *current_tid = *tuple_tid; return true; } }
void ExecEndNode | ( | PlanState * | node | ) |
Definition at line 583 of file execProcnode.c.
References bms_free(), PlanState::chgParam, elog, ERROR, ExecEndAgg(), ExecEndAppend(), ExecEndBitmapAnd(), ExecEndBitmapHeapScan(), ExecEndBitmapIndexScan(), ExecEndBitmapOr(), ExecEndCteScan(), ExecEndForeignScan(), ExecEndFunctionScan(), ExecEndGroup(), ExecEndHash(), ExecEndHashJoin(), ExecEndIndexOnlyScan(), ExecEndIndexScan(), ExecEndLimit(), ExecEndLockRows(), ExecEndMaterial(), ExecEndMergeAppend(), ExecEndMergeJoin(), ExecEndModifyTable(), ExecEndNestLoop(), ExecEndRecursiveUnion(), ExecEndResult(), ExecEndSeqScan(), ExecEndSetOp(), ExecEndSort(), ExecEndSubqueryScan(), ExecEndTidScan(), ExecEndUnique(), ExecEndValuesScan(), ExecEndWindowAgg(), ExecEndWorkTableScan(), nodeTag, NULL, T_AggState, T_AppendState, T_BitmapAndState, T_BitmapHeapScanState, T_BitmapIndexScanState, T_BitmapOrState, T_CteScanState, T_ForeignScanState, T_FunctionScanState, T_GroupState, T_HashJoinState, T_HashState, T_IndexOnlyScanState, T_IndexScanState, T_LimitState, T_LockRowsState, T_MaterialState, T_MergeAppendState, T_MergeJoinState, T_ModifyTableState, T_NestLoopState, T_RecursiveUnionState, T_ResultState, T_SeqScanState, T_SetOpState, T_SortState, T_SubqueryScanState, T_TidScanState, T_UniqueState, T_ValuesScanState, T_WindowAggState, and T_WorkTableScanState.
Referenced by EvalPlanQualEnd(), ExecEndAgg(), ExecEndAppend(), ExecEndBitmapAnd(), ExecEndBitmapHeapScan(), ExecEndBitmapOr(), ExecEndGroup(), ExecEndHash(), ExecEndHashJoin(), ExecEndLimit(), ExecEndLockRows(), ExecEndMaterial(), ExecEndMergeAppend(), ExecEndMergeJoin(), ExecEndModifyTable(), ExecEndNestLoop(), ExecEndPlan(), ExecEndRecursiveUnion(), ExecEndResult(), ExecEndSetOp(), ExecEndSort(), ExecEndSubqueryScan(), ExecEndUnique(), and ExecEndWindowAgg().
{ /* * do nothing when we get to the end of a leaf on tree. */ if (node == NULL) return; if (node->chgParam != NULL) { bms_free(node->chgParam); node->chgParam = NULL; } switch (nodeTag(node)) { /* * control nodes */ case T_ResultState: ExecEndResult((ResultState *) node); break; case T_ModifyTableState: ExecEndModifyTable((ModifyTableState *) node); break; case T_AppendState: ExecEndAppend((AppendState *) node); break; case T_MergeAppendState: ExecEndMergeAppend((MergeAppendState *) node); break; case T_RecursiveUnionState: ExecEndRecursiveUnion((RecursiveUnionState *) node); break; case T_BitmapAndState: ExecEndBitmapAnd((BitmapAndState *) node); break; case T_BitmapOrState: ExecEndBitmapOr((BitmapOrState *) node); break; /* * scan nodes */ case T_SeqScanState: ExecEndSeqScan((SeqScanState *) node); break; case T_IndexScanState: ExecEndIndexScan((IndexScanState *) node); break; case T_IndexOnlyScanState: ExecEndIndexOnlyScan((IndexOnlyScanState *) node); break; case T_BitmapIndexScanState: ExecEndBitmapIndexScan((BitmapIndexScanState *) node); break; case T_BitmapHeapScanState: ExecEndBitmapHeapScan((BitmapHeapScanState *) node); break; case T_TidScanState: ExecEndTidScan((TidScanState *) node); break; case T_SubqueryScanState: ExecEndSubqueryScan((SubqueryScanState *) node); break; case T_FunctionScanState: ExecEndFunctionScan((FunctionScanState *) node); break; case T_ValuesScanState: ExecEndValuesScan((ValuesScanState *) node); break; case T_CteScanState: ExecEndCteScan((CteScanState *) node); break; case T_WorkTableScanState: ExecEndWorkTableScan((WorkTableScanState *) node); break; case T_ForeignScanState: ExecEndForeignScan((ForeignScanState *) node); break; /* * join nodes */ case T_NestLoopState: ExecEndNestLoop((NestLoopState *) node); break; case T_MergeJoinState: ExecEndMergeJoin((MergeJoinState *) node); break; case T_HashJoinState: ExecEndHashJoin((HashJoinState *) node); break; /* * materialization nodes */ case T_MaterialState: ExecEndMaterial((MaterialState *) node); break; case T_SortState: ExecEndSort((SortState *) node); break; case T_GroupState: ExecEndGroup((GroupState *) node); break; case T_AggState: ExecEndAgg((AggState *) node); break; case T_WindowAggState: ExecEndWindowAgg((WindowAggState *) node); break; case T_UniqueState: ExecEndUnique((UniqueState *) node); break; case T_HashState: ExecEndHash((HashState *) node); break; case T_SetOpState: ExecEndSetOp((SetOpState *) node); break; case T_LockRowsState: ExecEndLockRows((LockRowsState *) node); break; case T_LimitState: ExecEndLimit((LimitState *) node); break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); break; } }
Datum ExecEvalExprSwitchContext | ( | ExprState * | expression, | |
ExprContext * | econtext, | |||
bool * | isNull, | |||
ExprDoneCond * | isDone | |||
) |
Definition at line 4284 of file execQual.c.
References ExprContext::ecxt_per_tuple_memory, ExecEvalExpr, and MemoryContextSwitchTo().
Referenced by btree_predicate_proof(), domain_check_input(), evaluate_expr(), EvaluateParams(), ExecScanSubPlan(), ExecWindowAgg(), FormIndexDatum(), recompute_limits(), TidListCreate(), and validateDomainConstraint().
{ Datum retDatum; MemoryContext oldContext; oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); retDatum = ExecEvalExpr(expression, econtext, isNull, isDone); MemoryContextSwitchTo(oldContext); return retDatum; }
TupleTableSlot* ExecFilterJunk | ( | JunkFilter * | junkfilter, | |
TupleTableSlot * | slot | |||
) |
Definition at line 262 of file execJunk.c.
References ExecClearTuple(), ExecStoreVirtualTuple(), i, JunkFilter::jf_cleanMap, JunkFilter::jf_cleanTupType, JunkFilter::jf_resultSlot, tupleDesc::natts, slot_getallattrs(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, and values.
Referenced by ExecBRUpdateTriggers(), ExecEvalWholeRowFast(), ExecEvalWholeRowSlow(), ExecEvalWholeRowVar(), ExecModifyTable(), ExecUpdate(), ExecutePlan(), and sqlfunction_receive().
{ TupleTableSlot *resultSlot; AttrNumber *cleanMap; TupleDesc cleanTupType; int cleanLength; int i; Datum *values; bool *isnull; Datum *old_values; bool *old_isnull; /* * Extract all the values of the old tuple. */ slot_getallattrs(slot); old_values = slot->tts_values; old_isnull = slot->tts_isnull; /* * get info from the junk filter */ cleanTupType = junkfilter->jf_cleanTupType; cleanLength = cleanTupType->natts; cleanMap = junkfilter->jf_cleanMap; resultSlot = junkfilter->jf_resultSlot; /* * Prepare to build a virtual result tuple. */ ExecClearTuple(resultSlot); values = resultSlot->tts_values; isnull = resultSlot->tts_isnull; /* * Transpose data into proper fields of the new tuple. */ for (i = 0; i < cleanLength; i++) { int j = cleanMap[i]; if (j == 0) { values[i] = (Datum) 0; isnull[i] = true; } else { values[i] = old_values[j - 1]; isnull[i] = old_isnull[j - 1]; } } /* * And return the virtual tuple. */ return ExecStoreVirtualTuple(resultSlot); }
AttrNumber ExecFindJunkAttribute | ( | JunkFilter * | junkfilter, | |
const char * | attrName | |||
) |
Definition at line 209 of file execJunk.c.
References ExecFindJunkAttributeInTlist(), and JunkFilter::jf_targetList.
Referenced by ExecInitModifyTable().
{ return ExecFindJunkAttributeInTlist(junkfilter->jf_targetList, attrName); }
AttrNumber ExecFindJunkAttributeInTlist | ( | List * | targetlist, | |
const char * | attrName | |||
) |
Definition at line 221 of file execJunk.c.
References lfirst, TargetEntry::resjunk, TargetEntry::resname, and TargetEntry::resno.
Referenced by ExecBuildAuxRowMark(), ExecFindJunkAttribute(), and postgresBeginForeignModify().
ExecRowMark* ExecFindRowMark | ( | EState * | estate, | |
Index | rti | |||
) |
Definition at line 1668 of file execMain.c.
References elog, ERROR, EState::es_rowMarks, lfirst, and ExecRowMark::rti.
Referenced by ExecInitLockRows(), and ExecInitModifyTable().
{ ListCell *lc; foreach(lc, estate->es_rowMarks) { ExecRowMark *erm = (ExecRowMark *) lfirst(lc); if (erm->rti == rti) return erm; } elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti); return NULL; /* keep compiler quiet */ }
void ExecFreeExprContext | ( | PlanState * | planstate | ) |
Definition at line 702 of file execUtils.c.
References PlanState::ps_ExprContext.
Referenced by ExecEndAgg(), ExecEndBitmapHeapScan(), ExecEndCteScan(), ExecEndForeignScan(), ExecEndFunctionScan(), ExecEndGroup(), ExecEndHash(), ExecEndHashJoin(), ExecEndIndexOnlyScan(), ExecEndIndexScan(), ExecEndLimit(), ExecEndMergeJoin(), ExecEndModifyTable(), ExecEndNestLoop(), ExecEndResult(), ExecEndSeqScan(), ExecEndSubqueryScan(), ExecEndTidScan(), ExecEndValuesScan(), ExecEndWindowAgg(), and ExecEndWorkTableScan().
{ /* * Per above discussion, don't actually delete the ExprContext. We do * unlink it from the plan node, though. */ planstate->ps_ExprContext = NULL; }
Datum ExecGetJunkAttribute | ( | TupleTableSlot * | slot, | |
AttrNumber | attno, | |||
bool * | isNull | |||
) |
Definition at line 248 of file execJunk.c.
References Assert, and slot_getattr().
Referenced by EvalPlanQualFetchRowMarks(), ExecLockRows(), ExecModifyTable(), postgresExecForeignDelete(), and postgresExecForeignUpdate().
{ Assert(attno > 0); return slot_getattr(slot, attno, isNull); }
Definition at line 473 of file execUtils.c.
References PlanState::ps_ResultTupleSlot, and TupleTableSlot::tts_tupleDescriptor.
Referenced by ExecAssignScanTypeFromOuterPlan(), ExecEvalWholeRowVar(), ExecInitCteScan(), ExecInitHashJoin(), ExecInitMergeJoin(), ExecInitNestLoop(), ExecInitSubqueryScan(), ExecSort(), ExecWorkTableScan(), and InitPlan().
{ TupleTableSlot *slot = planstate->ps_ResultTupleSlot; return slot->tts_tupleDescriptor; }
Definition at line 726 of file execUtils.c.
References ScanState::ss_ScanTupleSlot, and TupleTableSlot::tts_tupleDescriptor.
{ TupleTableSlot *slot = scanstate->ss_ScanTupleSlot; return slot->tts_tupleDescriptor; }
ResultRelInfo* ExecGetTriggerResultRel | ( | EState * | estate, | |
Oid | relid | |||
) |
Definition at line 1170 of file execMain.c.
References EState::es_instrument, EState::es_num_result_relations, EState::es_query_cxt, EState::es_result_relations, EState::es_trig_target_relations, heap_open(), InitResultRelInfo(), lappend(), lfirst, makeNode, MemoryContextSwitchTo(), NoLock, RelationGetRelid, and ResultRelInfo::ri_RelationDesc.
Referenced by afterTriggerInvokeEvents().
{ ResultRelInfo *rInfo; int nr; ListCell *l; Relation rel; MemoryContext oldcontext; /* First, search through the query result relations */ rInfo = estate->es_result_relations; nr = estate->es_num_result_relations; while (nr > 0) { if (RelationGetRelid(rInfo->ri_RelationDesc) == relid) return rInfo; rInfo++; nr--; } /* Nope, but maybe we already made an extra ResultRelInfo for it */ foreach(l, estate->es_trig_target_relations) { rInfo = (ResultRelInfo *) lfirst(l); if (RelationGetRelid(rInfo->ri_RelationDesc) == relid) return rInfo; } /* Nope, so we need a new one */ /* * Open the target relation's relcache entry. We assume that an * appropriate lock is still held by the backend from whenever the trigger * event got queued, so we need take no new lock here. Also, we need not * recheck the relkind, so no need for CheckValidResultRel. */ rel = heap_open(relid, NoLock); /* * Make the new entry in the right context. */ oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); rInfo = makeNode(ResultRelInfo); InitResultRelInfo(rInfo, rel, 0, /* dummy rangetable index */ estate->es_instrument); estate->es_trig_target_relations = lappend(estate->es_trig_target_relations, rInfo); MemoryContextSwitchTo(oldcontext); /* * Currently, we don't need any index information in ResultRelInfos used * only for triggers, so no need to call ExecOpenIndices. */ return rInfo; }
Definition at line 4332 of file execQual.c.
References AggState::aggs, ArrayCoerceExprState::amstate, AND_EXPR, CoerceToDomain::arg, CoerceToDomainState::arg, BooleanTest::arg, NullTest::arg, NullTestState::arg, arg, CaseExpr::arg, CaseExprState::arg, ConvertRowtypeExpr::arg, ConvertRowtypeExprState::arg, ArrayCoerceExpr::arg, ArrayCoerceExprState::arg, CoerceViaIO::arg, CoerceViaIOState::arg, RelabelType::arg, GenericExprState::arg, FieldStore::arg, FieldStoreState::arg, FieldSelect::arg, FieldSelectState::arg, NullTestState::argdesc, FieldStoreState::argdesc, FieldSelectState::argdesc, XmlExprState::args, XmlExpr::args, MinMaxExprState::args, MinMaxExpr::args, CoalesceExprState::args, CoalesceExpr::args, RowExprState::args, RowExpr::args, CaseExprState::args, CaseExpr::args, BoolExpr::args, BoolExprState::args, ScalarArrayOpExpr::args, OpExpr::args, FuncExpr::args, FuncExprState::args, WindowFunc::args, WindowFuncExprState::args, Aggref::args, AggrefExprState::args, Assert, tupleDesc::attrs, BlessTupleDesc(), BoolExpr::boolop, BTORDER_PROC, MinMaxExprState::cfunc, check_stack_depth(), TypeCacheEntry::cmp_proc, RowCompareExprState::collations, RowExpr::colnames, CoerceToDomainState::constraints, convert(), CaseExpr::defresult, CaseExprState::defresult, ArrayExprState::elemalign, ArrayExprState::elembyval, ScalarArrayOpExprState::element_type, ArrayExpr::element_typeid, ArrayExprState::elements, ArrayExpr::elements, ArrayCoerceExprState::elemfunc, ArrayExprState::elemlength, elog, ereport, errcode(), errmsg(), ERROR, ExprState::evalfunc, ExecEvalAggref(), ExecEvalAnd(), ExecEvalArray(), ExecEvalArrayCoerceExpr(), ExecEvalArrayRef(), ExecEvalBooleanTest(), ExecEvalCase(), ExecEvalCoalesce(), ExecEvalCoerceToDomain(), ExecEvalCoerceViaIO(), ExecEvalConvertRowtype(), ExecEvalDistinct(), ExecEvalFieldSelect(), ExecEvalFieldStore(), ExecEvalFunc(), ExecEvalMinMax(), ExecEvalNot(), ExecEvalNullIf(), ExecEvalNullTest(), ExecEvalOper(), ExecEvalOr(), ExecEvalRelabelType(), ExecEvalRow(), ExecEvalRowCompare(), ExecEvalScalarArrayOp(), ExecEvalWholeRowVar(), ExecEvalWindowFunc(), ExecEvalXml(), ExecInitAlternativeSubPlan(), ExecInitExpr(), ExecInitSubPlan(), ExecTypeFromExprList(), TargetEntry::expr, CaseWhen::expr, CaseWhenState::expr, ExprState::expr, exprType(), fmgr_info(), FmgrInfo::fn_oid, format_type_be(), forthree, FuncExprState::func, RowCompareExprState::funcs, WindowAggState::funcs, ScalarArrayOpExprState::fxprstate, get_element_type(), get_op_opfamily_properties(), get_opfamily_proc(), get_typlen(), get_typlenbyvalalign(), getBaseType(), GetDomainConstraints(), getTypeInputInfo(), getTypeOutputInfo(), i, CoerceViaIOState::infunc, RowCompareExpr::inputcollids, INT4OID, CoerceViaIOState::intypioparam, InvalidAttrNumber, InvalidOid, IsA, lappend(), RowCompareExprState::largs, RowCompareExpr::largs, lcons(), lfirst, lfirst_oid, list_length(), lookup_rowtype_tupdesc_copy(), lookup_type_cache(), makeNode, makeNullConst(), MinMaxExpr::minmaxtype, XmlExprState::named_args, XmlExpr::named_args, tupleDesc::natts, FieldStore::newvals, FieldStoreState::newvals, nodeTag, NOT_EXPR, NULL, WindowAggState::numaggs, AggState::numaggs, WindowAggState::numfuncs, OidIsValid, RowCompareExpr::opfamilies, RowCompareExpr::opnos, OR_EXPR, CoerceViaIOState::outfunc, palloc(), palloc0(), PARAM_EXEC, PARAM_EXTERN, WholeRowVarExprState::parent, RowCompareExprState::rargs, RowCompareExpr::rargs, RECORDOID, ArrayRef::refarraytype, ArrayRef::refassgnexpr, ArrayRefExprState::refassgnexpr, ArrayRefExprState::refattrlength, ArrayRefExprState::refelemalign, ArrayRefExprState::refelembyval, ArrayRefExprState::refelemlength, ArrayRef::refelemtype, ArrayRef::refexpr, ArrayRefExprState::refexpr, ArrayRef::reflowerindexpr, ArrayRefExprState::reflowerindexpr, ArrayRef::refupperindexpr, ArrayRefExprState::refupperindexpr, CaseWhen::result, CaseWhenState::result, ArrayCoerceExprState::resultelemtype, CoerceToDomain::resulttype, ArrayCoerceExpr::resulttype, CoerceViaIO::resulttype, RowExpr::row_typeid, PlanState::subPlan, T_Aggref, T_AlternativeSubPlan, T_ArrayCoerceExpr, T_ArrayExpr, T_ArrayRef, T_BooleanTest, T_BoolExpr, T_CaseExpr, T_CaseTestExpr, T_CoalesceExpr, T_CoerceToDomain, T_CoerceToDomainValue, T_CoerceViaIO, T_Const, T_ConvertRowtypeExpr, T_CurrentOfExpr, T_DistinctExpr, T_FieldSelect, T_FieldStore, T_FuncExpr, T_List, T_MinMaxExpr, T_NullIfExpr, T_NullTest, T_OpExpr, T_Param, T_RelabelType, T_RowCompareExpr, T_RowExpr, T_ScalarArrayOpExpr, T_SubPlan, T_TargetEntry, T_Var, T_WindowFunc, T_XmlExpr, RowExprState::tupdesc, TYPECACHE_CMP_PROC, WindowFunc::winagg, WholeRowVarExprState::wrv_junkFilter, CoerceToDomainState::xprstate, NullTestState::xprstate, XmlExprState::xprstate, MinMaxExprState::xprstate, CoalesceExprState::xprstate, RowCompareExprState::xprstate, RowExprState::xprstate, ArrayExprState::xprstate, CaseWhenState::xprstate, CaseExprState::xprstate, ConvertRowtypeExprState::xprstate, ArrayCoerceExprState::xprstate, CoerceViaIOState::xprstate, GenericExprState::xprstate, FieldStoreState::xprstate, FieldSelectState::xprstate, BoolExprState::xprstate, FuncExprState::xprstate, ArrayRefExprState::xprstate, WindowFuncExprState::xprstate, and AggrefExprState::xprstate.
Referenced by ATRewriteTable(), BeginCopyFrom(), btree_predicate_proof(), evaluate_expr(), exec_eval_simple_expr(), ExecIndexBuildScanKeys(), ExecInitAgg(), ExecInitAlternativeSubPlan(), ExecInitBitmapHeapScan(), ExecInitCteScan(), ExecInitExpr(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitGroup(), ExecInitHash(), ExecInitHashJoin(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitLimit(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitNestLoop(), ExecInitResult(), ExecInitSeqScan(), ExecInitSubPlan(), ExecInitSubqueryScan(), ExecInitTidScan(), ExecInitValuesScan(), ExecInitWindowAgg(), ExecInitWorkTableScan(), ExecPrepareExpr(), GetDomainConstraints(), MJExamineQuals(), postgresBeginForeignScan(), and ValuesNext().
{ ExprState *state; if (node == NULL) return NULL; /* Guard against stack overflow due to overly complex expressions */ check_stack_depth(); switch (nodeTag(node)) { case T_Var: /* varattno == InvalidAttrNumber means it's a whole-row Var */ if (((Var *) node)->varattno == InvalidAttrNumber) { WholeRowVarExprState *wstate = makeNode(WholeRowVarExprState); wstate->parent = parent; wstate->wrv_junkFilter = NULL; state = (ExprState *) wstate; state->evalfunc = (ExprStateEvalFunc) ExecEvalWholeRowVar; } else { state = (ExprState *) makeNode(ExprState); state->evalfunc = ExecEvalScalarVar; } break; case T_Const: state = (ExprState *) makeNode(ExprState); state->evalfunc = ExecEvalConst; break; case T_Param: state = (ExprState *) makeNode(ExprState); switch (((Param *) node)->paramkind) { case PARAM_EXEC: state->evalfunc = ExecEvalParamExec; break; case PARAM_EXTERN: state->evalfunc = ExecEvalParamExtern; break; default: elog(ERROR, "unrecognized paramkind: %d", (int) ((Param *) node)->paramkind); break; } break; case T_CoerceToDomainValue: state = (ExprState *) makeNode(ExprState); state->evalfunc = ExecEvalCoerceToDomainValue; break; case T_CaseTestExpr: state = (ExprState *) makeNode(ExprState); state->evalfunc = ExecEvalCaseTestExpr; break; case T_Aggref: { Aggref *aggref = (Aggref *) node; AggrefExprState *astate = makeNode(AggrefExprState); astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalAggref; if (parent && IsA(parent, AggState)) { AggState *aggstate = (AggState *) parent; int naggs; aggstate->aggs = lcons(astate, aggstate->aggs); naggs = ++aggstate->numaggs; astate->args = (List *) ExecInitExpr((Expr *) aggref->args, parent); /* * Complain if the aggregate's arguments contain any * aggregates; nested agg functions are semantically * nonsensical. (This should have been caught earlier, * but we defend against it here anyway.) */ if (naggs != aggstate->numaggs) ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), errmsg("aggregate function calls cannot be nested"))); } else { /* planner messed up */ elog(ERROR, "Aggref found in non-Agg plan node"); } state = (ExprState *) astate; } break; case T_WindowFunc: { WindowFunc *wfunc = (WindowFunc *) node; WindowFuncExprState *wfstate = makeNode(WindowFuncExprState); wfstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalWindowFunc; if (parent && IsA(parent, WindowAggState)) { WindowAggState *winstate = (WindowAggState *) parent; int nfuncs; winstate->funcs = lcons(wfstate, winstate->funcs); nfuncs = ++winstate->numfuncs; if (wfunc->winagg) winstate->numaggs++; wfstate->args = (List *) ExecInitExpr((Expr *) wfunc->args, parent); /* * Complain if the windowfunc's arguments contain any * windowfuncs; nested window functions are semantically * nonsensical. (This should have been caught earlier, * but we defend against it here anyway.) */ if (nfuncs != winstate->numfuncs) ereport(ERROR, (errcode(ERRCODE_WINDOWING_ERROR), errmsg("window function calls cannot be nested"))); } else { /* planner messed up */ elog(ERROR, "WindowFunc found in non-WindowAgg plan node"); } state = (ExprState *) wfstate; } break; case T_ArrayRef: { ArrayRef *aref = (ArrayRef *) node; ArrayRefExprState *astate = makeNode(ArrayRefExprState); astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalArrayRef; astate->refupperindexpr = (List *) ExecInitExpr((Expr *) aref->refupperindexpr, parent); astate->reflowerindexpr = (List *) ExecInitExpr((Expr *) aref->reflowerindexpr, parent); astate->refexpr = ExecInitExpr(aref->refexpr, parent); astate->refassgnexpr = ExecInitExpr(aref->refassgnexpr, parent); /* do one-time catalog lookups for type info */ astate->refattrlength = get_typlen(aref->refarraytype); get_typlenbyvalalign(aref->refelemtype, &astate->refelemlength, &astate->refelembyval, &astate->refelemalign); state = (ExprState *) astate; } break; case T_FuncExpr: { FuncExpr *funcexpr = (FuncExpr *) node; FuncExprState *fstate = makeNode(FuncExprState); fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalFunc; fstate->args = (List *) ExecInitExpr((Expr *) funcexpr->args, parent); fstate->func.fn_oid = InvalidOid; /* not initialized */ state = (ExprState *) fstate; } break; case T_OpExpr: { OpExpr *opexpr = (OpExpr *) node; FuncExprState *fstate = makeNode(FuncExprState); fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalOper; fstate->args = (List *) ExecInitExpr((Expr *) opexpr->args, parent); fstate->func.fn_oid = InvalidOid; /* not initialized */ state = (ExprState *) fstate; } break; case T_DistinctExpr: { DistinctExpr *distinctexpr = (DistinctExpr *) node; FuncExprState *fstate = makeNode(FuncExprState); fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalDistinct; fstate->args = (List *) ExecInitExpr((Expr *) distinctexpr->args, parent); fstate->func.fn_oid = InvalidOid; /* not initialized */ state = (ExprState *) fstate; } break; case T_NullIfExpr: { NullIfExpr *nullifexpr = (NullIfExpr *) node; FuncExprState *fstate = makeNode(FuncExprState); fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalNullIf; fstate->args = (List *) ExecInitExpr((Expr *) nullifexpr->args, parent); fstate->func.fn_oid = InvalidOid; /* not initialized */ state = (ExprState *) fstate; } break; case T_ScalarArrayOpExpr: { ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node; ScalarArrayOpExprState *sstate = makeNode(ScalarArrayOpExprState); sstate->fxprstate.xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalScalarArrayOp; sstate->fxprstate.args = (List *) ExecInitExpr((Expr *) opexpr->args, parent); sstate->fxprstate.func.fn_oid = InvalidOid; /* not initialized */ sstate->element_type = InvalidOid; /* ditto */ state = (ExprState *) sstate; } break; case T_BoolExpr: { BoolExpr *boolexpr = (BoolExpr *) node; BoolExprState *bstate = makeNode(BoolExprState); switch (boolexpr->boolop) { case AND_EXPR: bstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalAnd; break; case OR_EXPR: bstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalOr; break; case NOT_EXPR: bstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalNot; break; default: elog(ERROR, "unrecognized boolop: %d", (int) boolexpr->boolop); break; } bstate->args = (List *) ExecInitExpr((Expr *) boolexpr->args, parent); state = (ExprState *) bstate; } break; case T_SubPlan: { SubPlan *subplan = (SubPlan *) node; SubPlanState *sstate; if (!parent) elog(ERROR, "SubPlan found with no parent plan"); sstate = ExecInitSubPlan(subplan, parent); /* Add SubPlanState nodes to parent->subPlan */ parent->subPlan = lappend(parent->subPlan, sstate); state = (ExprState *) sstate; } break; case T_AlternativeSubPlan: { AlternativeSubPlan *asplan = (AlternativeSubPlan *) node; AlternativeSubPlanState *asstate; if (!parent) elog(ERROR, "AlternativeSubPlan found with no parent plan"); asstate = ExecInitAlternativeSubPlan(asplan, parent); state = (ExprState *) asstate; } break; case T_FieldSelect: { FieldSelect *fselect = (FieldSelect *) node; FieldSelectState *fstate = makeNode(FieldSelectState); fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalFieldSelect; fstate->arg = ExecInitExpr(fselect->arg, parent); fstate->argdesc = NULL; state = (ExprState *) fstate; } break; case T_FieldStore: { FieldStore *fstore = (FieldStore *) node; FieldStoreState *fstate = makeNode(FieldStoreState); fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalFieldStore; fstate->arg = ExecInitExpr(fstore->arg, parent); fstate->newvals = (List *) ExecInitExpr((Expr *) fstore->newvals, parent); fstate->argdesc = NULL; state = (ExprState *) fstate; } break; case T_RelabelType: { RelabelType *relabel = (RelabelType *) node; GenericExprState *gstate = makeNode(GenericExprState); gstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalRelabelType; gstate->arg = ExecInitExpr(relabel->arg, parent); state = (ExprState *) gstate; } break; case T_CoerceViaIO: { CoerceViaIO *iocoerce = (CoerceViaIO *) node; CoerceViaIOState *iostate = makeNode(CoerceViaIOState); Oid iofunc; bool typisvarlena; iostate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCoerceViaIO; iostate->arg = ExecInitExpr(iocoerce->arg, parent); /* lookup the result type's input function */ getTypeInputInfo(iocoerce->resulttype, &iofunc, &iostate->intypioparam); fmgr_info(iofunc, &iostate->infunc); /* lookup the input type's output function */ getTypeOutputInfo(exprType((Node *) iocoerce->arg), &iofunc, &typisvarlena); fmgr_info(iofunc, &iostate->outfunc); state = (ExprState *) iostate; } break; case T_ArrayCoerceExpr: { ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node; ArrayCoerceExprState *astate = makeNode(ArrayCoerceExprState); astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalArrayCoerceExpr; astate->arg = ExecInitExpr(acoerce->arg, parent); astate->resultelemtype = get_element_type(acoerce->resulttype); if (astate->resultelemtype == InvalidOid) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("target type is not an array"))); /* Arrays over domains aren't supported yet */ Assert(getBaseType(astate->resultelemtype) == astate->resultelemtype); astate->elemfunc.fn_oid = InvalidOid; /* not initialized */ astate->amstate = (ArrayMapState *) palloc0(sizeof(ArrayMapState)); state = (ExprState *) astate; } break; case T_ConvertRowtypeExpr: { ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node; ConvertRowtypeExprState *cstate = makeNode(ConvertRowtypeExprState); cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalConvertRowtype; cstate->arg = ExecInitExpr(convert->arg, parent); state = (ExprState *) cstate; } break; case T_CaseExpr: { CaseExpr *caseexpr = (CaseExpr *) node; CaseExprState *cstate = makeNode(CaseExprState); List *outlist = NIL; ListCell *l; cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCase; cstate->arg = ExecInitExpr(caseexpr->arg, parent); foreach(l, caseexpr->args) { CaseWhen *when = (CaseWhen *) lfirst(l); CaseWhenState *wstate = makeNode(CaseWhenState); Assert(IsA(when, CaseWhen)); wstate->xprstate.evalfunc = NULL; /* not used */ wstate->xprstate.expr = (Expr *) when; wstate->expr = ExecInitExpr(when->expr, parent); wstate->result = ExecInitExpr(when->result, parent); outlist = lappend(outlist, wstate); } cstate->args = outlist; cstate->defresult = ExecInitExpr(caseexpr->defresult, parent); state = (ExprState *) cstate; } break; case T_ArrayExpr: { ArrayExpr *arrayexpr = (ArrayExpr *) node; ArrayExprState *astate = makeNode(ArrayExprState); List *outlist = NIL; ListCell *l; astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalArray; foreach(l, arrayexpr->elements) { Expr *e = (Expr *) lfirst(l); ExprState *estate; estate = ExecInitExpr(e, parent); outlist = lappend(outlist, estate); } astate->elements = outlist; /* do one-time catalog lookup for type info */ get_typlenbyvalalign(arrayexpr->element_typeid, &astate->elemlength, &astate->elembyval, &astate->elemalign); state = (ExprState *) astate; } break; case T_RowExpr: { RowExpr *rowexpr = (RowExpr *) node; RowExprState *rstate = makeNode(RowExprState); Form_pg_attribute *attrs; List *outlist = NIL; ListCell *l; int i; rstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalRow; /* Build tupdesc to describe result tuples */ if (rowexpr->row_typeid == RECORDOID) { /* generic record, use runtime type assignment */ rstate->tupdesc = ExecTypeFromExprList(rowexpr->args, rowexpr->colnames); BlessTupleDesc(rstate->tupdesc); /* we won't need to redo this at runtime */ } else { /* it's been cast to a named type, use that */ rstate->tupdesc = lookup_rowtype_tupdesc_copy(rowexpr->row_typeid, -1); } /* Set up evaluation, skipping any deleted columns */ Assert(list_length(rowexpr->args) <= rstate->tupdesc->natts); attrs = rstate->tupdesc->attrs; i = 0; foreach(l, rowexpr->args) { Expr *e = (Expr *) lfirst(l); ExprState *estate; if (!attrs[i]->attisdropped) { /* * Guard against ALTER COLUMN TYPE on rowtype since * the RowExpr was created. XXX should we check * typmod too? Not sure we can be sure it'll be the * same. */ if (exprType((Node *) e) != attrs[i]->atttypid) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("ROW() column has type %s instead of type %s", format_type_be(exprType((Node *) e)), format_type_be(attrs[i]->atttypid)))); } else { /* * Ignore original expression and insert a NULL. We * don't really care what type of NULL it is, so * always make an int4 NULL. */ e = (Expr *) makeNullConst(INT4OID, -1, InvalidOid); } estate = ExecInitExpr(e, parent); outlist = lappend(outlist, estate); i++; } rstate->args = outlist; state = (ExprState *) rstate; } break; case T_RowCompareExpr: { RowCompareExpr *rcexpr = (RowCompareExpr *) node; RowCompareExprState *rstate = makeNode(RowCompareExprState); int nopers = list_length(rcexpr->opnos); List *outlist; ListCell *l; ListCell *l2; ListCell *l3; int i; rstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalRowCompare; Assert(list_length(rcexpr->largs) == nopers); outlist = NIL; foreach(l, rcexpr->largs) { Expr *e = (Expr *) lfirst(l); ExprState *estate; estate = ExecInitExpr(e, parent); outlist = lappend(outlist, estate); } rstate->largs = outlist; Assert(list_length(rcexpr->rargs) == nopers); outlist = NIL; foreach(l, rcexpr->rargs) { Expr *e = (Expr *) lfirst(l); ExprState *estate; estate = ExecInitExpr(e, parent); outlist = lappend(outlist, estate); } rstate->rargs = outlist; Assert(list_length(rcexpr->opfamilies) == nopers); rstate->funcs = (FmgrInfo *) palloc(nopers * sizeof(FmgrInfo)); rstate->collations = (Oid *) palloc(nopers * sizeof(Oid)); i = 0; forthree(l, rcexpr->opnos, l2, rcexpr->opfamilies, l3, rcexpr->inputcollids) { Oid opno = lfirst_oid(l); Oid opfamily = lfirst_oid(l2); Oid inputcollid = lfirst_oid(l3); int strategy; Oid lefttype; Oid righttype; Oid proc; get_op_opfamily_properties(opno, opfamily, false, &strategy, &lefttype, &righttype); proc = get_opfamily_proc(opfamily, lefttype, righttype, BTORDER_PROC); /* * If we enforced permissions checks on index support * functions, we'd need to make a check here. But the * index support machinery doesn't do that, and neither * does this code. */ fmgr_info(proc, &(rstate->funcs[i])); rstate->collations[i] = inputcollid; i++; } state = (ExprState *) rstate; } break; case T_CoalesceExpr: { CoalesceExpr *coalesceexpr = (CoalesceExpr *) node; CoalesceExprState *cstate = makeNode(CoalesceExprState); List *outlist = NIL; ListCell *l; cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCoalesce; foreach(l, coalesceexpr->args) { Expr *e = (Expr *) lfirst(l); ExprState *estate; estate = ExecInitExpr(e, parent); outlist = lappend(outlist, estate); } cstate->args = outlist; state = (ExprState *) cstate; } break; case T_MinMaxExpr: { MinMaxExpr *minmaxexpr = (MinMaxExpr *) node; MinMaxExprState *mstate = makeNode(MinMaxExprState); List *outlist = NIL; ListCell *l; TypeCacheEntry *typentry; mstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalMinMax; foreach(l, minmaxexpr->args) { Expr *e = (Expr *) lfirst(l); ExprState *estate; estate = ExecInitExpr(e, parent); outlist = lappend(outlist, estate); } mstate->args = outlist; /* Look up the btree comparison function for the datatype */ typentry = lookup_type_cache(minmaxexpr->minmaxtype, TYPECACHE_CMP_PROC); if (!OidIsValid(typentry->cmp_proc)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("could not identify a comparison function for type %s", format_type_be(minmaxexpr->minmaxtype)))); /* * If we enforced permissions checks on index support * functions, we'd need to make a check here. But the index * support machinery doesn't do that, and neither does this * code. */ fmgr_info(typentry->cmp_proc, &(mstate->cfunc)); state = (ExprState *) mstate; } break; case T_XmlExpr: { XmlExpr *xexpr = (XmlExpr *) node; XmlExprState *xstate = makeNode(XmlExprState); List *outlist; ListCell *arg; xstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalXml; outlist = NIL; foreach(arg, xexpr->named_args) { Expr *e = (Expr *) lfirst(arg); ExprState *estate; estate = ExecInitExpr(e, parent); outlist = lappend(outlist, estate); } xstate->named_args = outlist; outlist = NIL; foreach(arg, xexpr->args) { Expr *e = (Expr *) lfirst(arg); ExprState *estate; estate = ExecInitExpr(e, parent); outlist = lappend(outlist, estate); } xstate->args = outlist; state = (ExprState *) xstate; } break; case T_NullTest: { NullTest *ntest = (NullTest *) node; NullTestState *nstate = makeNode(NullTestState); nstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalNullTest; nstate->arg = ExecInitExpr(ntest->arg, parent); nstate->argdesc = NULL; state = (ExprState *) nstate; } break; case T_BooleanTest: { BooleanTest *btest = (BooleanTest *) node; GenericExprState *gstate = makeNode(GenericExprState); gstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalBooleanTest; gstate->arg = ExecInitExpr(btest->arg, parent); state = (ExprState *) gstate; } break; case T_CoerceToDomain: { CoerceToDomain *ctest = (CoerceToDomain *) node; CoerceToDomainState *cstate = makeNode(CoerceToDomainState); cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCoerceToDomain; cstate->arg = ExecInitExpr(ctest->arg, parent); cstate->constraints = GetDomainConstraints(ctest->resulttype); state = (ExprState *) cstate; } break; case T_CurrentOfExpr: state = (ExprState *) makeNode(ExprState); state->evalfunc = ExecEvalCurrentOfExpr; break; case T_TargetEntry: { TargetEntry *tle = (TargetEntry *) node; GenericExprState *gstate = makeNode(GenericExprState); gstate->xprstate.evalfunc = NULL; /* not used */ gstate->arg = ExecInitExpr(tle->expr, parent); state = (ExprState *) gstate; } break; case T_List: { List *outlist = NIL; ListCell *l; foreach(l, (List *) node) { outlist = lappend(outlist, ExecInitExpr((Expr *) lfirst(l), parent)); } /* Don't fall through to the "common" code below */ return (ExprState *) outlist; } default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); state = NULL; /* keep compiler quiet */ break; } /* Common code for all state-node types */ state->expr = node; return state; }
TupleTableSlot* ExecInitExtraTupleSlot | ( | EState * | estate | ) |
Definition at line 867 of file execTuples.c.
References EState::es_tupleTable, and ExecAllocTableSlot().
Referenced by CopyFrom(), ExecEvalWholeRowVar(), ExecInitAgg(), ExecInitHashJoin(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitNullTupleSlot(), ExecInitSubPlan(), ExecInitWindowAgg(), InitPlan(), and TriggerEnabled().
{ return ExecAllocTableSlot(&estate->es_tupleTable); }
JunkFilter* ExecInitJunkFilter | ( | List * | targetList, | |
bool | hasoid, | |||
TupleTableSlot * | slot | |||
) |
Definition at line 61 of file execJunk.c.
References ExecCleanTypeFromTL(), ExecSetSlotDescriptor(), JunkFilter::jf_cleanMap, JunkFilter::jf_cleanTupType, JunkFilter::jf_resultSlot, JunkFilter::jf_targetList, lfirst, makeNode, MakeSingleTupleTableSlot(), tupleDesc::natts, palloc(), TargetEntry::resjunk, and TargetEntry::resno.
Referenced by check_sql_fn_retval(), ExecEvalWholeRowVar(), ExecInitModifyTable(), and InitPlan().
{ JunkFilter *junkfilter; TupleDesc cleanTupType; int cleanLength; AttrNumber *cleanMap; ListCell *t; AttrNumber cleanResno; /* * Compute the tuple descriptor for the cleaned tuple. */ cleanTupType = ExecCleanTypeFromTL(targetList, hasoid); /* * Use the given slot, or make a new slot if we weren't given one. */ if (slot) ExecSetSlotDescriptor(slot, cleanTupType); else slot = MakeSingleTupleTableSlot(cleanTupType); /* * Now calculate the mapping between the original tuple's attributes and * the "clean" tuple's attributes. * * The "map" is an array of "cleanLength" attribute numbers, i.e. one * entry for every attribute of the "clean" tuple. The value of this entry * is the attribute number of the corresponding attribute of the * "original" tuple. (Zero indicates a NULL output attribute, but we do * not use that feature in this routine.) */ cleanLength = cleanTupType->natts; if (cleanLength > 0) { cleanMap = (AttrNumber *) palloc(cleanLength * sizeof(AttrNumber)); cleanResno = 1; foreach(t, targetList) { TargetEntry *tle = lfirst(t); if (!tle->resjunk) { cleanMap[cleanResno - 1] = tle->resno; cleanResno++; } } } else cleanMap = NULL; /* * Finally create and initialize the JunkFilter struct. */ junkfilter = makeNode(JunkFilter); junkfilter->jf_targetList = targetList; junkfilter->jf_cleanTupType = cleanTupType; junkfilter->jf_cleanMap = cleanMap; junkfilter->jf_resultSlot = slot; return junkfilter; }
JunkFilter* ExecInitJunkFilterConversion | ( | List * | targetList, | |
TupleDesc | cleanTupType, | |||
TupleTableSlot * | slot | |||
) |
Definition at line 136 of file execJunk.c.
References tupleDesc::attrs, ExecSetSlotDescriptor(), i, JunkFilter::jf_cleanMap, JunkFilter::jf_cleanTupType, JunkFilter::jf_resultSlot, JunkFilter::jf_targetList, lfirst, list_head(), lnext, makeNode, MakeSingleTupleTableSlot(), tupleDesc::natts, palloc0(), TargetEntry::resjunk, and TargetEntry::resno.
Referenced by check_sql_fn_retval().
{ JunkFilter *junkfilter; int cleanLength; AttrNumber *cleanMap; ListCell *t; int i; /* * Use the given slot, or make a new slot if we weren't given one. */ if (slot) ExecSetSlotDescriptor(slot, cleanTupType); else slot = MakeSingleTupleTableSlot(cleanTupType); /* * Calculate the mapping between the original tuple's attributes and the * "clean" tuple's attributes. * * The "map" is an array of "cleanLength" attribute numbers, i.e. one * entry for every attribute of the "clean" tuple. The value of this entry * is the attribute number of the corresponding attribute of the * "original" tuple. We store zero for any deleted attributes, marking * that a NULL is needed in the output tuple. */ cleanLength = cleanTupType->natts; if (cleanLength > 0) { cleanMap = (AttrNumber *) palloc0(cleanLength * sizeof(AttrNumber)); t = list_head(targetList); for (i = 0; i < cleanLength; i++) { if (cleanTupType->attrs[i]->attisdropped) continue; /* map entry is already zero */ for (;;) { TargetEntry *tle = lfirst(t); t = lnext(t); if (!tle->resjunk) { cleanMap[i] = tle->resno; break; } } } } else cleanMap = NULL; /* * Finally create and initialize the JunkFilter struct. */ junkfilter = makeNode(JunkFilter); junkfilter->jf_targetList = targetList; junkfilter->jf_cleanTupType = cleanTupType; junkfilter->jf_cleanMap = cleanMap; junkfilter->jf_resultSlot = slot; return junkfilter; }
Definition at line 132 of file execProcnode.c.
References Assert, elog, ERROR, EState::es_instrument, ExecInitAgg(), ExecInitAppend(), ExecInitBitmapAnd(), ExecInitBitmapHeapScan(), ExecInitBitmapIndexScan(), ExecInitBitmapOr(), ExecInitCteScan(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitGroup(), ExecInitHash(), ExecInitHashJoin(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitLimit(), ExecInitLockRows(), ExecInitMaterial(), ExecInitMergeAppend(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitNestLoop(), ExecInitRecursiveUnion(), ExecInitResult(), ExecInitSeqScan(), ExecInitSetOp(), ExecInitSort(), ExecInitSubPlan(), ExecInitSubqueryScan(), ExecInitTidScan(), ExecInitUnique(), ExecInitValuesScan(), ExecInitWindowAgg(), ExecInitWorkTableScan(), PlanState::initPlan, Plan::initPlan, InstrAlloc(), PlanState::instrument, IsA, lappend(), lfirst, nodeTag, NULL, T_Agg, T_Append, T_BitmapAnd, T_BitmapHeapScan, T_BitmapIndexScan, T_BitmapOr, T_CteScan, T_ForeignScan, T_FunctionScan, T_Group, T_Hash, T_HashJoin, T_IndexOnlyScan, T_IndexScan, T_Limit, T_LockRows, T_Material, T_MergeAppend, T_MergeJoin, T_ModifyTable, T_NestLoop, T_RecursiveUnion, T_Result, T_SeqScan, T_SetOp, T_Sort, T_SubqueryScan, T_TidScan, T_Unique, T_ValuesScan, T_WindowAgg, and T_WorkTableScan.
Referenced by EvalPlanQualStart(), ExecInitAgg(), ExecInitAppend(), ExecInitBitmapAnd(), ExecInitBitmapHeapScan(), ExecInitBitmapOr(), ExecInitGroup(), ExecInitHash(), ExecInitHashJoin(), ExecInitLimit(), ExecInitLockRows(), ExecInitMaterial(), ExecInitMergeAppend(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitNestLoop(), ExecInitRecursiveUnion(), ExecInitResult(), ExecInitSetOp(), ExecInitSort(), ExecInitSubqueryScan(), ExecInitUnique(), ExecInitWindowAgg(), and InitPlan().
{ PlanState *result; List *subps; ListCell *l; /* * do nothing when we get to the end of a leaf on tree. */ if (node == NULL) return NULL; switch (nodeTag(node)) { /* * control nodes */ case T_Result: result = (PlanState *) ExecInitResult((Result *) node, estate, eflags); break; case T_ModifyTable: result = (PlanState *) ExecInitModifyTable((ModifyTable *) node, estate, eflags); break; case T_Append: result = (PlanState *) ExecInitAppend((Append *) node, estate, eflags); break; case T_MergeAppend: result = (PlanState *) ExecInitMergeAppend((MergeAppend *) node, estate, eflags); break; case T_RecursiveUnion: result = (PlanState *) ExecInitRecursiveUnion((RecursiveUnion *) node, estate, eflags); break; case T_BitmapAnd: result = (PlanState *) ExecInitBitmapAnd((BitmapAnd *) node, estate, eflags); break; case T_BitmapOr: result = (PlanState *) ExecInitBitmapOr((BitmapOr *) node, estate, eflags); break; /* * scan nodes */ case T_SeqScan: result = (PlanState *) ExecInitSeqScan((SeqScan *) node, estate, eflags); break; case T_IndexScan: result = (PlanState *) ExecInitIndexScan((IndexScan *) node, estate, eflags); break; case T_IndexOnlyScan: result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node, estate, eflags); break; case T_BitmapIndexScan: result = (PlanState *) ExecInitBitmapIndexScan((BitmapIndexScan *) node, estate, eflags); break; case T_BitmapHeapScan: result = (PlanState *) ExecInitBitmapHeapScan((BitmapHeapScan *) node, estate, eflags); break; case T_TidScan: result = (PlanState *) ExecInitTidScan((TidScan *) node, estate, eflags); break; case T_SubqueryScan: result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node, estate, eflags); break; case T_FunctionScan: result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node, estate, eflags); break; case T_ValuesScan: result = (PlanState *) ExecInitValuesScan((ValuesScan *) node, estate, eflags); break; case T_CteScan: result = (PlanState *) ExecInitCteScan((CteScan *) node, estate, eflags); break; case T_WorkTableScan: result = (PlanState *) ExecInitWorkTableScan((WorkTableScan *) node, estate, eflags); break; case T_ForeignScan: result = (PlanState *) ExecInitForeignScan((ForeignScan *) node, estate, eflags); break; /* * join nodes */ case T_NestLoop: result = (PlanState *) ExecInitNestLoop((NestLoop *) node, estate, eflags); break; case T_MergeJoin: result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node, estate, eflags); break; case T_HashJoin: result = (PlanState *) ExecInitHashJoin((HashJoin *) node, estate, eflags); break; /* * materialization nodes */ case T_Material: result = (PlanState *) ExecInitMaterial((Material *) node, estate, eflags); break; case T_Sort: result = (PlanState *) ExecInitSort((Sort *) node, estate, eflags); break; case T_Group: result = (PlanState *) ExecInitGroup((Group *) node, estate, eflags); break; case T_Agg: result = (PlanState *) ExecInitAgg((Agg *) node, estate, eflags); break; case T_WindowAgg: result = (PlanState *) ExecInitWindowAgg((WindowAgg *) node, estate, eflags); break; case T_Unique: result = (PlanState *) ExecInitUnique((Unique *) node, estate, eflags); break; case T_Hash: result = (PlanState *) ExecInitHash((Hash *) node, estate, eflags); break; case T_SetOp: result = (PlanState *) ExecInitSetOp((SetOp *) node, estate, eflags); break; case T_LockRows: result = (PlanState *) ExecInitLockRows((LockRows *) node, estate, eflags); break; case T_Limit: result = (PlanState *) ExecInitLimit((Limit *) node, estate, eflags); break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); result = NULL; /* keep compiler quiet */ break; } /* * Initialize any initPlans present in this node. The planner put them in * a separate list for us. */ subps = NIL; foreach(l, node->initPlan) { SubPlan *subplan = (SubPlan *) lfirst(l); SubPlanState *sstate; Assert(IsA(subplan, SubPlan)); sstate = ExecInitSubPlan(subplan, result); subps = lappend(subps, sstate); } result->initPlan = subps; /* Set up instrumentation for this node if requested */ if (estate->es_instrument) result->instrument = InstrAlloc(1, estate->es_instrument); return result; }
TupleTableSlot* ExecInitNullTupleSlot | ( | EState * | estate, | |
TupleDesc | tupType | |||
) |
Definition at line 881 of file execTuples.c.
References ExecInitExtraTupleSlot(), ExecSetSlotDescriptor(), and ExecStoreAllNullTuple().
Referenced by ExecInitHashJoin(), ExecInitMergeJoin(), and ExecInitNestLoop().
{ TupleTableSlot *slot = ExecInitExtraTupleSlot(estate); ExecSetSlotDescriptor(slot, tupType); return ExecStoreAllNullTuple(slot); }
Definition at line 847 of file execTuples.c.
References EState::es_tupleTable, ExecAllocTableSlot(), and PlanState::ps_ResultTupleSlot.
Referenced by ExecInitAgg(), ExecInitAppend(), ExecInitBitmapHeapScan(), ExecInitCteScan(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitGroup(), ExecInitHash(), ExecInitHashJoin(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitLimit(), ExecInitLockRows(), ExecInitMaterial(), ExecInitMergeAppend(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitNestLoop(), ExecInitRecursiveUnion(), ExecInitResult(), ExecInitSeqScan(), ExecInitSetOp(), ExecInitSort(), ExecInitSubqueryScan(), ExecInitTidScan(), ExecInitUnique(), ExecInitValuesScan(), ExecInitWindowAgg(), and ExecInitWorkTableScan().
{ planstate->ps_ResultTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable); }
Definition at line 857 of file execTuples.c.
References EState::es_tupleTable, ExecAllocTableSlot(), and ScanState::ss_ScanTupleSlot.
Referenced by ExecInitAgg(), ExecInitBitmapHeapScan(), ExecInitCteScan(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitGroup(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitMaterial(), ExecInitSeqScan(), ExecInitSort(), ExecInitSubqueryScan(), ExecInitTidScan(), ExecInitValuesScan(), ExecInitWindowAgg(), and ExecInitWorkTableScan().
{ scanstate->ss_ScanTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable); }
List* ExecInsertIndexTuples | ( | TupleTableSlot * | slot, | |
ItemPointer | tupleid, | |||
EState * | estate | |||
) |
Definition at line 1001 of file execUtils.c.
References check_exclusion_constraint(), ExprContext::ecxt_scantuple, EState::es_result_relation_info, ExecPrepareExpr(), ExecQual(), FormIndexDatum(), GetPerTupleExprContext, i, IndexInfo::ii_ExclusionOps, IndexInfo::ii_Predicate, IndexInfo::ii_PredicateState, IndexInfo::ii_ReadyForInserts, index_insert(), lappend_oid(), NIL, NULL, RelationData::rd_index, RelationGetRelid, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_RelationDesc, UNIQUE_CHECK_PARTIAL, and values.
Referenced by CopyFrom(), CopyFromInsertBatch(), ExecInsert(), and ExecUpdate().
{ List *result = NIL; ResultRelInfo *resultRelInfo; int i; int numIndices; RelationPtr relationDescs; Relation heapRelation; IndexInfo **indexInfoArray; ExprContext *econtext; Datum values[INDEX_MAX_KEYS]; bool isnull[INDEX_MAX_KEYS]; /* * Get information from the result relation info structure. */ resultRelInfo = estate->es_result_relation_info; numIndices = resultRelInfo->ri_NumIndices; relationDescs = resultRelInfo->ri_IndexRelationDescs; indexInfoArray = resultRelInfo->ri_IndexRelationInfo; heapRelation = resultRelInfo->ri_RelationDesc; /* * We will use the EState's per-tuple context for evaluating predicates * and index expressions (creating it if it's not already there). */ econtext = GetPerTupleExprContext(estate); /* Arrange for econtext's scan tuple to be the tuple under test */ econtext->ecxt_scantuple = slot; /* * for each index, form and insert the index tuple */ for (i = 0; i < numIndices; i++) { Relation indexRelation = relationDescs[i]; IndexInfo *indexInfo; IndexUniqueCheck checkUnique; bool satisfiesConstraint; if (indexRelation == NULL) continue; indexInfo = indexInfoArray[i]; /* If the index is marked as read-only, ignore it */ if (!indexInfo->ii_ReadyForInserts) continue; /* Check for partial index */ if (indexInfo->ii_Predicate != NIL) { List *predicate; /* * If predicate state not set up yet, create it (in the estate's * per-query context) */ predicate = indexInfo->ii_PredicateState; if (predicate == NIL) { predicate = (List *) ExecPrepareExpr((Expr *) indexInfo->ii_Predicate, estate); indexInfo->ii_PredicateState = predicate; } /* Skip this index-update if the predicate isn't satisfied */ if (!ExecQual(predicate, econtext, false)) continue; } /* * FormIndexDatum fills in its values and isnull parameters with the * appropriate values for the column(s) of the index. */ FormIndexDatum(indexInfo, slot, estate, values, isnull); /* * The index AM does the actual insertion, plus uniqueness checking. * * For an immediate-mode unique index, we just tell the index AM to * throw error if not unique. * * For a deferrable unique index, we tell the index AM to just detect * possible non-uniqueness, and we add the index OID to the result * list if further checking is needed. */ if (!indexRelation->rd_index->indisunique) checkUnique = UNIQUE_CHECK_NO; else if (indexRelation->rd_index->indimmediate) checkUnique = UNIQUE_CHECK_YES; else checkUnique = UNIQUE_CHECK_PARTIAL; satisfiesConstraint = index_insert(indexRelation, /* index relation */ values, /* array of index Datums */ isnull, /* null flags */ tupleid, /* tid of heap tuple */ heapRelation, /* heap relation */ checkUnique); /* type of uniqueness check to do */ /* * If the index has an associated exclusion constraint, check that. * This is simpler than the process for uniqueness checks since we * always insert first and then check. If the constraint is deferred, * we check now anyway, but don't throw error on violation; instead * we'll queue a recheck event. * * An index for an exclusion constraint can't also be UNIQUE (not an * essential property, we just don't allow it in the grammar), so no * need to preserve the prior state of satisfiesConstraint. */ if (indexInfo->ii_ExclusionOps != NULL) { bool errorOK = !indexRelation->rd_index->indimmediate; satisfiesConstraint = check_exclusion_constraint(heapRelation, indexRelation, indexInfo, tupleid, values, isnull, estate, false, errorOK); } if ((checkUnique == UNIQUE_CHECK_PARTIAL || indexInfo->ii_ExclusionOps != NULL) && !satisfiesConstraint) { /* * The tuple potentially violates the uniqueness or exclusion * constraint, so make a note of the index so that we can re-check * it later. */ result = lappend_oid(result, RelationGetRelid(indexRelation)); } } return result; }
Tuplestorestate* ExecMakeTableFunctionResult | ( | ExprState * | funcexpr, | |
ExprContext * | econtext, | |||
TupleDesc | expectedDesc, | |||
bool | randomAccess | |||
) |
Definition at line 2012 of file execQual.c.
References ReturnSetInfo::allowedModes, FunctionCallInfoData::argnull, FuncExprState::args, CHECK_FOR_INTERRUPTS, CreateTemplateTupleDesc(), CurrentMemoryContext, DatumGetHeapTupleHeader, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, ExprContext::ecxt_per_tuple_memory, ereport, errcode(), errmsg(), ERROR, ExecEvalExpr, ExecEvalFuncArgs(), ReturnSetInfo::expectedDesc, ExprState::expr, ExprEndResult, ExprMultipleResult, ExprSingleResult, exprType(), FuncExprState::fcinfo_data, FmgrInfo::fn_oid, FmgrInfo::fn_retset, FmgrInfo::fn_strict, FunctionCallInfoData::fncollation, FreeTupleDesc(), FuncExprState::func, FuncExpr::funcid, FunctionCallInvoke, HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, i, init_fcache(), InitFunctionCallInfoData, FuncExpr::inputcollid, InvalidOid, IsA, ReturnSetInfo::isDone, FunctionCallInfoData::isnull, list_length(), lookup_rowtype_tupdesc_copy(), MemoryContextSwitchTo(), FunctionCallInfoData::nargs, tupleDesc::natts, NULL, palloc(), palloc0(), pgstat_end_function_usage(), pgstat_init_function_usage(), ResetExprContext, ReturnSetInfo::returnMode, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Preferred, SFRM_Materialize_Random, SFRM_ValuePerCall, HeapTupleData::t_data, HeapTupleData::t_len, tupleDesc::tdrefcount, tupleDesc::tdtypeid, tupleDesc::tdtypmod, tupledesc_match(), TupleDescInitEntry(), tuplestore_begin_heap(), tuplestore_puttuple(), tuplestore_putvalues(), ReturnSetInfo::type, type_is_rowtype(), work_mem, and FuncExprState::xprstate.
Referenced by FunctionNext().
{ Tuplestorestate *tupstore = NULL; TupleDesc tupdesc = NULL; Oid funcrettype; bool returnsTuple; bool returnsSet = false; FunctionCallInfoData fcinfo; PgStat_FunctionCallUsage fcusage; ReturnSetInfo rsinfo; HeapTupleData tmptup; MemoryContext callerContext; MemoryContext oldcontext; bool direct_function_call; bool first_time = true; callerContext = CurrentMemoryContext; funcrettype = exprType((Node *) funcexpr->expr); returnsTuple = type_is_rowtype(funcrettype); /* * Prepare a resultinfo node for communication. We always do this even if * not expecting a set result, so that we can pass expectedDesc. In the * generic-expression case, the expression doesn't actually get to see the * resultinfo, but set it up anyway because we use some of the fields as * our own state variables. */ rsinfo.type = T_ReturnSetInfo; rsinfo.econtext = econtext; rsinfo.expectedDesc = expectedDesc; rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize | SFRM_Materialize_Preferred); if (randomAccess) rsinfo.allowedModes |= (int) SFRM_Materialize_Random; rsinfo.returnMode = SFRM_ValuePerCall; /* isDone is filled below */ rsinfo.setResult = NULL; rsinfo.setDesc = NULL; /* * Normally the passed expression tree will be a FuncExprState, since the * grammar only allows a function call at the top level of a table * function reference. However, if the function doesn't return set then * the planner might have replaced the function call via constant-folding * or inlining. So if we see any other kind of expression node, execute * it via the general ExecEvalExpr() code; the only difference is that we * don't get a chance to pass a special ReturnSetInfo to any functions * buried in the expression. */ if (funcexpr && IsA(funcexpr, FuncExprState) && IsA(funcexpr->expr, FuncExpr)) { FuncExprState *fcache = (FuncExprState *) funcexpr; ExprDoneCond argDone; /* * This path is similar to ExecMakeFunctionResult. */ direct_function_call = true; /* * Initialize function cache if first time through */ if (fcache->func.fn_oid == InvalidOid) { FuncExpr *func = (FuncExpr *) fcache->xprstate.expr; init_fcache(func->funcid, func->inputcollid, fcache, econtext->ecxt_per_query_memory, false); } returnsSet = fcache->func.fn_retset; InitFunctionCallInfoData(fcinfo, &(fcache->func), list_length(fcache->args), fcache->fcinfo_data.fncollation, NULL, (Node *) &rsinfo); /* * Evaluate the function's argument list. * * Note: ideally, we'd do this in the per-tuple context, but then the * argument values would disappear when we reset the context in the * inner loop. So do it in caller context. Perhaps we should make a * separate context just to hold the evaluated arguments? */ argDone = ExecEvalFuncArgs(&fcinfo, fcache->args, econtext); /* We don't allow sets in the arguments of the table function */ if (argDone != ExprSingleResult) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("set-valued function called in context that cannot accept a set"))); /* * If function is strict, and there are any NULL arguments, skip * calling the function and act like it returned NULL (or an empty * set, in the returns-set case). */ if (fcache->func.fn_strict) { int i; for (i = 0; i < fcinfo.nargs; i++) { if (fcinfo.argnull[i]) goto no_function_result; } } } else { /* Treat funcexpr as a generic expression */ direct_function_call = false; InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL); } /* * Switch to short-lived context for calling the function or expression. */ MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); /* * Loop to handle the ValuePerCall protocol (which is also the same * behavior needed in the generic ExecEvalExpr path). */ for (;;) { Datum result; CHECK_FOR_INTERRUPTS(); /* * reset per-tuple memory context before each call of the function or * expression. This cleans up any local memory the function may leak * when called. */ ResetExprContext(econtext); /* Call the function or expression one time */ if (direct_function_call) { pgstat_init_function_usage(&fcinfo, &fcusage); fcinfo.isnull = false; rsinfo.isDone = ExprSingleResult; result = FunctionCallInvoke(&fcinfo); pgstat_end_function_usage(&fcusage, rsinfo.isDone != ExprMultipleResult); } else { result = ExecEvalExpr(funcexpr, econtext, &fcinfo.isnull, &rsinfo.isDone); } /* Which protocol does function want to use? */ if (rsinfo.returnMode == SFRM_ValuePerCall) { /* * Check for end of result set. */ if (rsinfo.isDone == ExprEndResult) break; /* * Can't do anything very useful with NULL rowtype values. For a * function returning set, we consider this a protocol violation * (but another alternative would be to just ignore the result and * "continue" to get another row). For a function not returning * set, we fall out of the loop; we'll cons up an all-nulls result * row below. */ if (returnsTuple && fcinfo.isnull) { if (!returnsSet) break; ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("function returning set of rows cannot return null value"))); } /* * If first time through, build tupdesc and tuplestore for result */ if (first_time) { oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory); if (returnsTuple) { /* * Use the type info embedded in the rowtype Datum to look * up the needed tupdesc. Make a copy for the query. */ HeapTupleHeader td; td = DatumGetHeapTupleHeader(result); tupdesc = lookup_rowtype_tupdesc_copy(HeapTupleHeaderGetTypeId(td), HeapTupleHeaderGetTypMod(td)); } else { /* * Scalar type, so make a single-column descriptor */ tupdesc = CreateTemplateTupleDesc(1, false); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "column", funcrettype, -1, 0); } tupstore = tuplestore_begin_heap(randomAccess, false, work_mem); MemoryContextSwitchTo(oldcontext); rsinfo.setResult = tupstore; rsinfo.setDesc = tupdesc; } /* * Store current resultset item. */ if (returnsTuple) { HeapTupleHeader td; td = DatumGetHeapTupleHeader(result); /* * Verify all returned rows have same subtype; necessary in * case the type is RECORD. */ if (HeapTupleHeaderGetTypeId(td) != tupdesc->tdtypeid || HeapTupleHeaderGetTypMod(td) != tupdesc->tdtypmod) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("rows returned by function are not all of the same row type"))); /* * tuplestore_puttuple needs a HeapTuple not a bare * HeapTupleHeader, but it doesn't need all the fields. */ tmptup.t_len = HeapTupleHeaderGetDatumLength(td); tmptup.t_data = td; tuplestore_puttuple(tupstore, &tmptup); } else tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo.isnull); /* * Are we done? */ if (rsinfo.isDone != ExprMultipleResult) break; } else if (rsinfo.returnMode == SFRM_Materialize) { /* check we're on the same page as the function author */ if (!first_time || rsinfo.isDone != ExprSingleResult) ereport(ERROR, (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED), errmsg("table-function protocol for materialize mode was not followed"))); /* Done evaluating the set result */ break; } else ereport(ERROR, (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED), errmsg("unrecognized table-function returnMode: %d", (int) rsinfo.returnMode))); first_time = false; } no_function_result: /* * If we got nothing from the function (ie, an empty-set or NULL result), * we have to create the tuplestore to return, and if it's a * non-set-returning function then insert a single all-nulls row. */ if (rsinfo.setResult == NULL) { MemoryContextSwitchTo(econtext->ecxt_per_query_memory); tupstore = tuplestore_begin_heap(randomAccess, false, work_mem); rsinfo.setResult = tupstore; if (!returnsSet) { int natts = expectedDesc->natts; Datum *nulldatums; bool *nullflags; MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); nulldatums = (Datum *) palloc0(natts * sizeof(Datum)); nullflags = (bool *) palloc(natts * sizeof(bool)); memset(nullflags, true, natts * sizeof(bool)); MemoryContextSwitchTo(econtext->ecxt_per_query_memory); tuplestore_putvalues(tupstore, expectedDesc, nulldatums, nullflags); } } /* * If function provided a tupdesc, cross-check it. We only really need to * do this for functions returning RECORD, but might as well do it always. */ if (rsinfo.setDesc) { tupledesc_match(expectedDesc, rsinfo.setDesc); /* * If it is a dynamically-allocated TupleDesc, free it: it is * typically allocated in a per-query context, so we must avoid * leaking it across multiple usages. */ if (rsinfo.setDesc->tdrefcount == -1) FreeTupleDesc(rsinfo.setDesc); } MemoryContextSwitchTo(callerContext); /* All done, pass back the tuplestore */ return rsinfo.setResult; }
void ExecMarkPos | ( | PlanState * | node | ) |
Definition at line 270 of file execAmi.c.
References DEBUG2, elog, ExecIndexMarkPos(), ExecIndexOnlyMarkPos(), ExecMaterialMarkPos(), ExecResultMarkPos(), ExecSeqMarkPos(), ExecSortMarkPos(), ExecTidMarkPos(), ExecValuesMarkPos(), nodeTag, T_IndexOnlyScanState, T_IndexScanState, T_MaterialState, T_ResultState, T_SeqScanState, T_SortState, T_TidScanState, and T_ValuesScanState.
Referenced by ExecMergeJoin(), and ExecResultMarkPos().
{ switch (nodeTag(node)) { case T_SeqScanState: ExecSeqMarkPos((SeqScanState *) node); break; case T_IndexScanState: ExecIndexMarkPos((IndexScanState *) node); break; case T_IndexOnlyScanState: ExecIndexOnlyMarkPos((IndexOnlyScanState *) node); break; case T_TidScanState: ExecTidMarkPos((TidScanState *) node); break; case T_ValuesScanState: ExecValuesMarkPos((ValuesScanState *) node); break; case T_MaterialState: ExecMaterialMarkPos((MaterialState *) node); break; case T_SortState: ExecSortMarkPos((SortState *) node); break; case T_ResultState: ExecResultMarkPos((ResultState *) node); break; default: /* don't make hard error unless caller asks to restore... */ elog(DEBUG2, "unrecognized node type: %d", (int) nodeTag(node)); break; } }
Definition at line 538 of file execAmi.c.
References T_CteScan, T_FunctionScan, T_Material, T_Sort, and T_WorkTableScan.
Referenced by build_subplan(), cost_subplan(), and match_unsorted_outer().
{ switch (plantype) { case T_Material: case T_FunctionScan: case T_CteScan: case T_WorkTableScan: case T_Sort: return true; default: break; } return false; }
void ExecOpenIndices | ( | ResultRelInfo * | resultRelInfo | ) |
Definition at line 888 of file execUtils.c.
References BuildIndexInfo(), i, index_open(), lfirst_oid, list_free(), list_length(), palloc(), RelationGetForm, RelationGetIndexList(), ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_RelationDesc, and RowExclusiveLock.
Referenced by CatalogOpenIndexes(), CopyFrom(), and ExecInitModifyTable().
{ Relation resultRelation = resultRelInfo->ri_RelationDesc; List *indexoidlist; ListCell *l; int len, i; RelationPtr relationDescs; IndexInfo **indexInfoArray; resultRelInfo->ri_NumIndices = 0; /* fast path if no indexes */ if (!RelationGetForm(resultRelation)->relhasindex) return; /* * Get cached list of index OIDs */ indexoidlist = RelationGetIndexList(resultRelation); len = list_length(indexoidlist); if (len == 0) return; /* * allocate space for result arrays */ relationDescs = (RelationPtr) palloc(len * sizeof(Relation)); indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *)); resultRelInfo->ri_NumIndices = len; resultRelInfo->ri_IndexRelationDescs = relationDescs; resultRelInfo->ri_IndexRelationInfo = indexInfoArray; /* * For each index, open the index relation and save pg_index info. We * acquire RowExclusiveLock, signifying we will update the index. * * Note: we do this even if the index is not IndexIsReady; it's not worth * the trouble to optimize for the case where it isn't. */ i = 0; foreach(l, indexoidlist) { Oid indexOid = lfirst_oid(l); Relation indexDesc; IndexInfo *ii; indexDesc = index_open(indexOid, RowExclusiveLock); /* extract index key information from the index's pg_index info */ ii = BuildIndexInfo(indexDesc); relationDescs[i] = indexDesc; indexInfoArray[i] = ii; i++; } list_free(indexoidlist); }
Definition at line 801 of file execUtils.c.
References ereport, errcode(), errhint(), errmsg(), ERROR, EState::es_range_table, EState::es_rowMarks, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_WITH_NO_DATA, ExecRelationIsTargetRelation(), getrelid, heap_open(), lfirst, RelationGetRelationName, RelationIsScannable, and ExecRowMark::rti.
Referenced by ExecInitBitmapHeapScan(), ExecInitForeignScan(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitTidScan(), and InitScanRelation().
{ Relation rel; Oid reloid; LOCKMODE lockmode; /* * Determine the lock type we need. First, scan to see if target relation * is a result relation. If not, check if it's a FOR UPDATE/FOR SHARE * relation. In either of those cases, we got the lock already. */ lockmode = AccessShareLock; if (ExecRelationIsTargetRelation(estate, scanrelid)) lockmode = NoLock; else { ListCell *l; foreach(l, estate->es_rowMarks) { ExecRowMark *erm = lfirst(l); if (erm->rti == scanrelid) { lockmode = NoLock; break; } } } /* Open the relation and acquire lock as needed */ reloid = getrelid(scanrelid, estate->es_range_table); rel = heap_open(reloid, lockmode); /* * Complain if we're attempting a scan of an unscannable relation, except * when the query won't actually be run. This is a slightly klugy place * to do this, perhaps, but there is no better place. */ if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 && !RelationIsScannable(rel)) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("materialized view \"%s\" has not been populated", RelationGetRelationName(rel)), errhint("Use the REFRESH MATERIALIZED VIEW command."))); return rel; }
Definition at line 5045 of file execQual.c.
References EState::es_query_cxt, ExecInitExpr(), expression_planner(), MemoryContextSwitchTo(), and NULL.
Referenced by ATRewriteTable(), compute_index_stats(), EvaluateParams(), ExecInsertIndexTuples(), ExecRelCheck(), FormIndexDatum(), IndexBuildHeapScan(), IndexCheckExclusion(), TriggerEnabled(), validate_index_heapscan(), validateCheckConstraint(), and validateDomainConstraint().
{ ExprState *result; MemoryContext oldcontext; oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); node = expression_planner(node); result = ExecInitExpr(node, NULL); MemoryContextSwitchTo(oldcontext); return result; }
TupleTableSlot* ExecProcNode | ( | PlanState * | node | ) |
Definition at line 355 of file execProcnode.c.
References CHECK_FOR_INTERRUPTS, PlanState::chgParam, elog, ERROR, ExecAgg(), ExecAppend(), ExecBitmapHeapScan(), ExecCteScan(), ExecForeignScan(), ExecFunctionScan(), ExecGroup(), ExecHash(), ExecHashJoin(), ExecIndexOnlyScan(), ExecIndexScan(), ExecLimit(), ExecLockRows(), ExecMaterial(), ExecMergeAppend(), ExecMergeJoin(), ExecModifyTable(), ExecNestLoop(), ExecRecursiveUnion(), ExecReScan(), ExecResult(), ExecSeqScan(), ExecSetOp(), ExecSort(), ExecSubqueryScan(), ExecTidScan(), ExecUnique(), ExecValuesScan(), ExecWindowAgg(), ExecWorkTableScan(), InstrStartNode(), InstrStopNode(), PlanState::instrument, nodeTag, NULL, T_AggState, T_AppendState, T_BitmapHeapScanState, T_CteScanState, T_ForeignScanState, T_FunctionScanState, T_GroupState, T_HashJoinState, T_HashState, T_IndexOnlyScanState, T_IndexScanState, T_LimitState, T_LockRowsState, T_MaterialState, T_MergeAppendState, T_MergeJoinState, T_ModifyTableState, T_NestLoopState, T_RecursiveUnionState, T_ResultState, T_SeqScanState, T_SetOpState, T_SortState, T_SubqueryScanState, T_TidScanState, T_UniqueState, T_ValuesScanState, T_WindowAggState, T_WorkTableScanState, and TupIsNull.
Referenced by agg_fill_hash_table(), agg_retrieve_direct(), begin_partition(), buildSubPlanHash(), CteScanNext(), EvalPlanQualNext(), ExecAppend(), ExecGroup(), ExecHashJoin(), ExecHashJoinOuterGetTuple(), ExecLimit(), ExecLockRows(), ExecMaterial(), ExecMergeAppend(), ExecMergeJoin(), ExecModifyTable(), ExecNestLoop(), ExecPostprocessPlan(), ExecRecursiveUnion(), ExecResult(), ExecScanSubPlan(), ExecSetParamPlan(), ExecSort(), ExecUnique(), ExecutePlan(), MultiExecHash(), setop_fill_hash_table(), setop_retrieve_direct(), spool_tuples(), and SubqueryNext().
{ TupleTableSlot *result; CHECK_FOR_INTERRUPTS(); if (node->chgParam != NULL) /* something changed */ ExecReScan(node); /* let ReScan handle this */ if (node->instrument) InstrStartNode(node->instrument); switch (nodeTag(node)) { /* * control nodes */ case T_ResultState: result = ExecResult((ResultState *) node); break; case T_ModifyTableState: result = ExecModifyTable((ModifyTableState *) node); break; case T_AppendState: result = ExecAppend((AppendState *) node); break; case T_MergeAppendState: result = ExecMergeAppend((MergeAppendState *) node); break; case T_RecursiveUnionState: result = ExecRecursiveUnion((RecursiveUnionState *) node); break; /* BitmapAndState does not yield tuples */ /* BitmapOrState does not yield tuples */ /* * scan nodes */ case T_SeqScanState: result = ExecSeqScan((SeqScanState *) node); break; case T_IndexScanState: result = ExecIndexScan((IndexScanState *) node); break; case T_IndexOnlyScanState: result = ExecIndexOnlyScan((IndexOnlyScanState *) node); break; /* BitmapIndexScanState does not yield tuples */ case T_BitmapHeapScanState: result = ExecBitmapHeapScan((BitmapHeapScanState *) node); break; case T_TidScanState: result = ExecTidScan((TidScanState *) node); break; case T_SubqueryScanState: result = ExecSubqueryScan((SubqueryScanState *) node); break; case T_FunctionScanState: result = ExecFunctionScan((FunctionScanState *) node); break; case T_ValuesScanState: result = ExecValuesScan((ValuesScanState *) node); break; case T_CteScanState: result = ExecCteScan((CteScanState *) node); break; case T_WorkTableScanState: result = ExecWorkTableScan((WorkTableScanState *) node); break; case T_ForeignScanState: result = ExecForeignScan((ForeignScanState *) node); break; /* * join nodes */ case T_NestLoopState: result = ExecNestLoop((NestLoopState *) node); break; case T_MergeJoinState: result = ExecMergeJoin((MergeJoinState *) node); break; case T_HashJoinState: result = ExecHashJoin((HashJoinState *) node); break; /* * materialization nodes */ case T_MaterialState: result = ExecMaterial((MaterialState *) node); break; case T_SortState: result = ExecSort((SortState *) node); break; case T_GroupState: result = ExecGroup((GroupState *) node); break; case T_AggState: result = ExecAgg((AggState *) node); break; case T_WindowAggState: result = ExecWindowAgg((WindowAggState *) node); break; case T_UniqueState: result = ExecUnique((UniqueState *) node); break; case T_HashState: result = ExecHash((HashState *) node); break; case T_SetOpState: result = ExecSetOp((SetOpState *) node); break; case T_LockRowsState: result = ExecLockRows((LockRowsState *) node); break; case T_LimitState: result = ExecLimit((LimitState *) node); break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); result = NULL; break; } if (node->instrument) InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0); return result; }
TupleTableSlot* ExecProject | ( | ProjectionInfo * | projInfo, | |
ExprDoneCond * | isDone | |||
) |
Definition at line 5352 of file execQual.c.
References Assert, ExprContext::ecxt_innertuple, ExprContext::ecxt_outertuple, ExprContext::ecxt_scantuple, ExecClearTuple(), ExecStoreVirtualTuple(), ExecTargetList(), i, NULL, ProjectionInfo::pi_directMap, ProjectionInfo::pi_exprContext, ProjectionInfo::pi_itemIsDone, ProjectionInfo::pi_lastInnerVar, ProjectionInfo::pi_lastOuterVar, ProjectionInfo::pi_lastScanVar, ProjectionInfo::pi_numSimpleVars, ProjectionInfo::pi_slot, ProjectionInfo::pi_targetlist, ProjectionInfo::pi_varNumbers, ProjectionInfo::pi_varOutputCols, ProjectionInfo::pi_varSlotOffsets, slot_getsomeattrs(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, and values.
Referenced by advance_aggregates(), agg_retrieve_direct(), agg_retrieve_hash_table(), buildSubPlanHash(), ExecAgg(), ExecGroup(), ExecHashJoin(), ExecHashSubPlan(), ExecMergeJoin(), ExecNestLoop(), ExecProcessReturning(), ExecResult(), ExecScan(), ExecWindowAgg(), MJFillInner(), and MJFillOuter().
{ TupleTableSlot *slot; ExprContext *econtext; int numSimpleVars; /* * sanity checks */ Assert(projInfo != NULL); /* * get the projection info we want */ slot = projInfo->pi_slot; econtext = projInfo->pi_exprContext; /* Assume single result row until proven otherwise */ if (isDone) *isDone = ExprSingleResult; /* * Clear any former contents of the result slot. This makes it safe for * us to use the slot's Datum/isnull arrays as workspace. (Also, we can * return the slot as-is if we decide no rows can be projected.) */ ExecClearTuple(slot); /* * Force extraction of all input values that we'll need. The * Var-extraction loops below depend on this, and we are also prefetching * all attributes that will be referenced in the generic expressions. */ if (projInfo->pi_lastInnerVar > 0) slot_getsomeattrs(econtext->ecxt_innertuple, projInfo->pi_lastInnerVar); if (projInfo->pi_lastOuterVar > 0) slot_getsomeattrs(econtext->ecxt_outertuple, projInfo->pi_lastOuterVar); if (projInfo->pi_lastScanVar > 0) slot_getsomeattrs(econtext->ecxt_scantuple, projInfo->pi_lastScanVar); /* * Assign simple Vars to result by direct extraction of fields from source * slots ... a mite ugly, but fast ... */ numSimpleVars = projInfo->pi_numSimpleVars; if (numSimpleVars > 0) { Datum *values = slot->tts_values; bool *isnull = slot->tts_isnull; int *varSlotOffsets = projInfo->pi_varSlotOffsets; int *varNumbers = projInfo->pi_varNumbers; int i; if (projInfo->pi_directMap) { /* especially simple case where vars go to output in order */ for (i = 0; i < numSimpleVars; i++) { char *slotptr = ((char *) econtext) + varSlotOffsets[i]; TupleTableSlot *varSlot = *((TupleTableSlot **) slotptr); int varNumber = varNumbers[i] - 1; values[i] = varSlot->tts_values[varNumber]; isnull[i] = varSlot->tts_isnull[varNumber]; } } else { /* we have to pay attention to varOutputCols[] */ int *varOutputCols = projInfo->pi_varOutputCols; for (i = 0; i < numSimpleVars; i++) { char *slotptr = ((char *) econtext) + varSlotOffsets[i]; TupleTableSlot *varSlot = *((TupleTableSlot **) slotptr); int varNumber = varNumbers[i] - 1; int varOutputCol = varOutputCols[i] - 1; values[varOutputCol] = varSlot->tts_values[varNumber]; isnull[varOutputCol] = varSlot->tts_isnull[varNumber]; } } } /* * If there are any generic expressions, evaluate them. It's possible * that there are set-returning functions in such expressions; if so and * we have reached the end of the set, we return the result slot, which we * already marked empty. */ if (projInfo->pi_targetlist) { if (!ExecTargetList(projInfo->pi_targetlist, econtext, slot->tts_values, slot->tts_isnull, projInfo->pi_itemIsDone, isDone)) return slot; /* no more result rows, return empty slot */ } /* * Successfully formed a result row. Mark the result slot as containing a * valid virtual tuple. */ return ExecStoreVirtualTuple(slot); }
bool ExecQual | ( | List * | qual, | |
ExprContext * | econtext, | |||
bool | resultForNull | |||
) |
Definition at line 5096 of file execQual.c.
References DatumGetBool, ExprContext::ecxt_per_tuple_memory, EV_nodeDisplay, EV_printf, ExecEvalExpr, lfirst, MemoryContextSwitchTo(), and NULL.
Referenced by agg_retrieve_direct(), agg_retrieve_hash_table(), ATRewriteTable(), BitmapHeapNext(), BitmapHeapRecheck(), compute_index_stats(), ExecGroup(), ExecHashJoin(), ExecInsertIndexTuples(), ExecMergeJoin(), ExecNestLoop(), ExecRelCheck(), ExecResult(), ExecScan(), ExecScanHashBucket(), IndexBuildHeapScan(), IndexCheckExclusion(), IndexNext(), IndexOnlyNext(), IndexRecheck(), MJFillInner(), MJFillOuter(), TriggerEnabled(), validate_index_heapscan(), and validateCheckConstraint().
{ bool result; MemoryContext oldContext; ListCell *l; /* * debugging stuff */ EV_printf("ExecQual: qual is "); EV_nodeDisplay(qual); EV_printf("\n"); /* * Run in short-lived per-tuple context while computing expressions. */ oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); /* * Evaluate the qual conditions one at a time. If we find a FALSE result, * we can stop evaluating and return FALSE --- the AND result must be * FALSE. Also, if we find a NULL result when resultForNull is FALSE, we * can stop and return FALSE --- the AND result must be FALSE or NULL in * that case, and the caller doesn't care which. * * If we get to the end of the list, we can return TRUE. This will happen * when the AND result is indeed TRUE, or when the AND result is NULL (one * or more NULL subresult, with all the rest TRUE) and the caller has * specified resultForNull = TRUE. */ result = true; foreach(l, qual) { ExprState *clause = (ExprState *) lfirst(l); Datum expr_value; bool isNull; expr_value = ExecEvalExpr(clause, econtext, &isNull, NULL); if (isNull) { if (resultForNull == false) { result = false; /* treat NULL as FALSE */ break; } } else { if (!DatumGetBool(expr_value)) { result = false; /* definitely FALSE */ break; } } } MemoryContextSwitchTo(oldContext); return result; }
Definition at line 775 of file execUtils.c.
References EState::es_num_result_relations, EState::es_result_relations, and i.
Referenced by ExecInitBitmapIndexScan(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), and ExecOpenScanRelation().
{ ResultRelInfo *resultRelInfos; int i; resultRelInfos = estate->es_result_relations; for (i = 0; i < estate->es_num_result_relations; i++) { if (resultRelInfos[i].ri_RangeTableIndex == scanrelid) return true; } return false; }
void ExecReScan | ( | PlanState * | node | ) |
Definition at line 68 of file execAmi.c.
References bms_free(), PlanState::chgParam, elog, ERROR, ExecReScanAgg(), ExecReScanAppend(), ExecReScanBitmapAnd(), ExecReScanBitmapHeapScan(), ExecReScanBitmapIndexScan(), ExecReScanBitmapOr(), ExecReScanCteScan(), ExecReScanForeignScan(), ExecReScanFunctionScan(), ExecReScanGroup(), ExecReScanHash(), ExecReScanHashJoin(), ExecReScanIndexOnlyScan(), ExecReScanIndexScan(), ExecReScanLimit(), ExecReScanLockRows(), ExecReScanMaterial(), ExecReScanMergeAppend(), ExecReScanMergeJoin(), ExecReScanModifyTable(), ExecReScanNestLoop(), ExecReScanRecursiveUnion(), ExecReScanResult(), ExecReScanSeqScan(), ExecReScanSetOp(), ExecReScanSetParamPlan(), ExecReScanSort(), ExecReScanSubqueryScan(), ExecReScanTidScan(), ExecReScanUnique(), ExecReScanValuesScan(), ExecReScanWindowAgg(), ExecReScanWorkTableScan(), Plan::extParam, PlanState::initPlan, InstrEndLoop(), PlanState::instrument, PlanState::lefttree, lfirst, nodeTag, NULL, PlanState::plan, SubPlanState::planstate, PlanState::ps_ExprContext, ReScanExprContext(), PlanState::righttree, splan, PlanState::subPlan, T_AggState, T_AppendState, T_BitmapAndState, T_BitmapHeapScanState, T_BitmapIndexScanState, T_BitmapOrState, T_CteScanState, T_ForeignScanState, T_FunctionScanState, T_GroupState, T_HashJoinState, T_HashState, T_IndexOnlyScanState, T_IndexScanState, T_LimitState, T_LockRowsState, T_MaterialState, T_MergeAppendState, T_MergeJoinState, T_ModifyTableState, T_NestLoopState, T_RecursiveUnionState, T_ResultState, T_SeqScanState, T_SetOpState, T_SortState, T_SubqueryScanState, T_TidScanState, T_UniqueState, T_ValuesScanState, T_WindowAggState, T_WorkTableScanState, and UpdateChangedParamSet().
Referenced by buildSubPlanHash(), ExecIndexOnlyScan(), ExecIndexScan(), ExecNestLoop(), ExecProcNode(), ExecReScanAgg(), ExecReScanAppend(), ExecReScanBitmapAnd(), ExecReScanBitmapHeapScan(), ExecReScanBitmapOr(), ExecReScanGroup(), ExecReScanHash(), ExecReScanHashJoin(), ExecReScanLimit(), ExecReScanLockRows(), ExecReScanMaterial(), ExecReScanMergeAppend(), ExecReScanMergeJoin(), ExecReScanNestLoop(), ExecReScanRecursiveUnion(), ExecReScanResult(), ExecReScanSetOp(), ExecReScanSort(), ExecReScanSubqueryScan(), ExecReScanUnique(), ExecReScanWindowAgg(), ExecScanSubPlan(), ExecutorRewind(), MultiExecBitmapIndexScan(), and MultiExecProcNode().
{ /* If collecting timing stats, update them */ if (node->instrument) InstrEndLoop(node->instrument); /* * If we have changed parameters, propagate that info. * * Note: ExecReScanSetParamPlan() can add bits to node->chgParam, * corresponding to the output param(s) that the InitPlan will update. * Since we make only one pass over the list, that means that an InitPlan * can depend on the output param(s) of a sibling InitPlan only if that * sibling appears earlier in the list. This is workable for now given * the limited ways in which one InitPlan could depend on another, but * eventually we might need to work harder (or else make the planner * enlarge the extParam/allParam sets to include the params of depended-on * InitPlans). */ if (node->chgParam != NULL) { ListCell *l; foreach(l, node->initPlan) { SubPlanState *sstate = (SubPlanState *) lfirst(l); PlanState *splan = sstate->planstate; if (splan->plan->extParam != NULL) /* don't care about child * local Params */ UpdateChangedParamSet(splan, node->chgParam); if (splan->chgParam != NULL) ExecReScanSetParamPlan(sstate, node); } foreach(l, node->subPlan) { SubPlanState *sstate = (SubPlanState *) lfirst(l); PlanState *splan = sstate->planstate; if (splan->plan->extParam != NULL) UpdateChangedParamSet(splan, node->chgParam); } /* Well. Now set chgParam for left/right trees. */ if (node->lefttree != NULL) UpdateChangedParamSet(node->lefttree, node->chgParam); if (node->righttree != NULL) UpdateChangedParamSet(node->righttree, node->chgParam); } /* Shut down any SRFs in the plan node's targetlist */ if (node->ps_ExprContext) ReScanExprContext(node->ps_ExprContext); /* And do node-type-specific processing */ switch (nodeTag(node)) { case T_ResultState: ExecReScanResult((ResultState *) node); break; case T_ModifyTableState: ExecReScanModifyTable((ModifyTableState *) node); break; case T_AppendState: ExecReScanAppend((AppendState *) node); break; case T_MergeAppendState: ExecReScanMergeAppend((MergeAppendState *) node); break; case T_RecursiveUnionState: ExecReScanRecursiveUnion((RecursiveUnionState *) node); break; case T_BitmapAndState: ExecReScanBitmapAnd((BitmapAndState *) node); break; case T_BitmapOrState: ExecReScanBitmapOr((BitmapOrState *) node); break; case T_SeqScanState: ExecReScanSeqScan((SeqScanState *) node); break; case T_IndexScanState: ExecReScanIndexScan((IndexScanState *) node); break; case T_IndexOnlyScanState: ExecReScanIndexOnlyScan((IndexOnlyScanState *) node); break; case T_BitmapIndexScanState: ExecReScanBitmapIndexScan((BitmapIndexScanState *) node); break; case T_BitmapHeapScanState: ExecReScanBitmapHeapScan((BitmapHeapScanState *) node); break; case T_TidScanState: ExecReScanTidScan((TidScanState *) node); break; case T_SubqueryScanState: ExecReScanSubqueryScan((SubqueryScanState *) node); break; case T_FunctionScanState: ExecReScanFunctionScan((FunctionScanState *) node); break; case T_ValuesScanState: ExecReScanValuesScan((ValuesScanState *) node); break; case T_CteScanState: ExecReScanCteScan((CteScanState *) node); break; case T_WorkTableScanState: ExecReScanWorkTableScan((WorkTableScanState *) node); break; case T_ForeignScanState: ExecReScanForeignScan((ForeignScanState *) node); break; case T_NestLoopState: ExecReScanNestLoop((NestLoopState *) node); break; case T_MergeJoinState: ExecReScanMergeJoin((MergeJoinState *) node); break; case T_HashJoinState: ExecReScanHashJoin((HashJoinState *) node); break; case T_MaterialState: ExecReScanMaterial((MaterialState *) node); break; case T_SortState: ExecReScanSort((SortState *) node); break; case T_GroupState: ExecReScanGroup((GroupState *) node); break; case T_AggState: ExecReScanAgg((AggState *) node); break; case T_WindowAggState: ExecReScanWindowAgg((WindowAggState *) node); break; case T_UniqueState: ExecReScanUnique((UniqueState *) node); break; case T_HashState: ExecReScanHash((HashState *) node); break; case T_SetOpState: ExecReScanSetOp((SetOpState *) node); break; case T_LockRowsState: ExecReScanLockRows((LockRowsState *) node); break; case T_LimitState: ExecReScanLimit((LimitState *) node); break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); break; } if (node->chgParam != NULL) { bms_free(node->chgParam); node->chgParam = NULL; } }
void ExecRestrPos | ( | PlanState * | node | ) |
Definition at line 327 of file execAmi.c.
References elog, ERROR, ExecIndexOnlyRestrPos(), ExecIndexRestrPos(), ExecMaterialRestrPos(), ExecResultRestrPos(), ExecSeqRestrPos(), ExecSortRestrPos(), ExecTidRestrPos(), ExecValuesRestrPos(), nodeTag, T_IndexOnlyScanState, T_IndexScanState, T_MaterialState, T_ResultState, T_SeqScanState, T_SortState, T_TidScanState, and T_ValuesScanState.
Referenced by ExecMergeJoin(), and ExecResultRestrPos().
{ switch (nodeTag(node)) { case T_SeqScanState: ExecSeqRestrPos((SeqScanState *) node); break; case T_IndexScanState: ExecIndexRestrPos((IndexScanState *) node); break; case T_IndexOnlyScanState: ExecIndexOnlyRestrPos((IndexOnlyScanState *) node); break; case T_TidScanState: ExecTidRestrPos((TidScanState *) node); break; case T_ValuesScanState: ExecValuesRestrPos((ValuesScanState *) node); break; case T_MaterialState: ExecMaterialRestrPos((MaterialState *) node); break; case T_SortState: ExecSortRestrPos((SortState *) node); break; case T_ResultState: ExecResultRestrPos((ResultState *) node); break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); break; } }
TupleTableSlot* ExecScan | ( | ScanState * | node, | |
ExecScanAccessMtd | accessMtd, | |||
ExecScanRecheckMtd | recheckMtd | |||
) |
Definition at line 108 of file execScan.c.
References Assert, CHECK_FOR_INTERRUPTS, ExprContext::ecxt_scantuple, ExecClearTuple(), ExecProject(), ExecQual(), ExecScanFetch(), ExprEndResult, ExprMultipleResult, InstrCountFiltered1, ProjectionInfo::pi_slot, ScanState::ps, PlanState::ps_ExprContext, PlanState::ps_ProjInfo, PlanState::ps_TupFromTlist, PlanState::qual, ResetExprContext, and TupIsNull.
Referenced by ExecBitmapHeapScan(), ExecCteScan(), ExecForeignScan(), ExecFunctionScan(), ExecIndexOnlyScan(), ExecIndexScan(), ExecSeqScan(), ExecSubqueryScan(), ExecTidScan(), ExecValuesScan(), and ExecWorkTableScan().
{ ExprContext *econtext; List *qual; ProjectionInfo *projInfo; ExprDoneCond isDone; TupleTableSlot *resultSlot; /* * Fetch data from node */ qual = node->ps.qual; projInfo = node->ps.ps_ProjInfo; econtext = node->ps.ps_ExprContext; /* * If we have neither a qual to check nor a projection to do, just skip * all the overhead and return the raw scan tuple. */ if (!qual && !projInfo) { ResetExprContext(econtext); return ExecScanFetch(node, accessMtd, recheckMtd); } /* * Check to see if we're still projecting out tuples from a previous scan * tuple (because there is a function-returning-set in the projection * expressions). If so, try to project another one. */ if (node->ps.ps_TupFromTlist) { Assert(projInfo); /* can't get here if not projecting */ resultSlot = ExecProject(projInfo, &isDone); if (isDone == ExprMultipleResult) return resultSlot; /* Done with that source tuple... */ node->ps.ps_TupFromTlist = false; } /* * Reset per-tuple memory context to free any expression evaluation * storage allocated in the previous tuple cycle. Note this can't happen * until we're done projecting out tuples from a scan tuple. */ ResetExprContext(econtext); /* * get a tuple from the access method. Loop until we obtain a tuple that * passes the qualification. */ for (;;) { TupleTableSlot *slot; CHECK_FOR_INTERRUPTS(); slot = ExecScanFetch(node, accessMtd, recheckMtd); /* * if the slot returned by the accessMtd contains NULL, then it means * there is nothing more to scan so we just return an empty slot, * being careful to use the projection result slot so it has correct * tupleDesc. */ if (TupIsNull(slot)) { if (projInfo) return ExecClearTuple(projInfo->pi_slot); else return slot; } /* * place the current tuple into the expr context */ econtext->ecxt_scantuple = slot; /* * check that the current tuple satisfies the qual-clause * * check for non-nil qual here to avoid a function call to ExecQual() * when the qual is nil ... saves only a few cycles, but they add up * ... */ if (!qual || ExecQual(qual, econtext, false)) { /* * Found a satisfactory scan tuple. */ if (projInfo) { /* * Form a projection tuple, store it in the result tuple slot * and return it --- unless we find we can project no tuples * from this scan tuple, in which case continue scan. */ resultSlot = ExecProject(projInfo, &isDone); if (isDone != ExprEndResult) { node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult); return resultSlot; } } else { /* * Here, we aren't projecting, so just return scan tuple. */ return slot; } } else InstrCountFiltered1(node, 1); /* * Tuple fails qual, so free per-tuple memory and try again. */ ResetExprContext(econtext); } }
void ExecScanReScan | ( | ScanState * | node | ) |
Definition at line 333 of file execScan.c.
References Assert, EState::es_epqScanDone, NULL, PlanState::plan, ScanState::ps, PlanState::ps_TupFromTlist, and PlanState::state.
Referenced by ExecReScanBitmapHeapScan(), ExecReScanCteScan(), ExecReScanForeignScan(), ExecReScanFunctionScan(), ExecReScanIndexOnlyScan(), ExecReScanIndexScan(), ExecReScanSeqScan(), ExecReScanSubqueryScan(), ExecReScanTidScan(), ExecReScanValuesScan(), and ExecReScanWorkTableScan().
{ EState *estate = node->ps.state; /* Stop projecting any tuples from SRFs in the targetlist */ node->ps.ps_TupFromTlist = false; /* Rescan EvalPlanQual tuple if we're inside an EvalPlanQual recheck */ if (estate->es_epqScanDone != NULL) { Index scanrelid = ((Scan *) node->ps.plan)->scanrelid; Assert(scanrelid > 0); estate->es_epqScanDone[scanrelid - 1] = false; } }
Definition at line 422 of file execAmi.c.
References ExecSupportsBackwardScan(), IndexSupportsBackwardScan(), lfirst, nodeTag, NULL, outerPlan, T_Append, T_CteScan, T_FunctionScan, T_IndexOnlyScan, T_IndexScan, T_Limit, T_LockRows, T_Material, T_Result, T_SeqScan, T_Sort, T_SubqueryScan, T_TidScan, T_ValuesScan, Plan::targetlist, and TargetListSupportsBackwardScan().
Referenced by ExecSupportsBackwardScan(), PerformCursorOpen(), SPI_cursor_open_internal(), and standard_planner().
{ if (node == NULL) return false; switch (nodeTag(node)) { case T_Result: if (outerPlan(node) != NULL) return ExecSupportsBackwardScan(outerPlan(node)) && TargetListSupportsBackwardScan(node->targetlist); else return false; case T_Append: { ListCell *l; foreach(l, ((Append *) node)->appendplans) { if (!ExecSupportsBackwardScan((Plan *) lfirst(l))) return false; } /* need not check tlist because Append doesn't evaluate it */ return true; } case T_SeqScan: case T_TidScan: case T_FunctionScan: case T_ValuesScan: case T_CteScan: return TargetListSupportsBackwardScan(node->targetlist); case T_IndexScan: return IndexSupportsBackwardScan(((IndexScan *) node)->indexid) && TargetListSupportsBackwardScan(node->targetlist); case T_IndexOnlyScan: return IndexSupportsBackwardScan(((IndexOnlyScan *) node)->indexid) && TargetListSupportsBackwardScan(node->targetlist); case T_SubqueryScan: return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan) && TargetListSupportsBackwardScan(node->targetlist); case T_Material: case T_Sort: /* these don't evaluate tlist */ return true; case T_LockRows: case T_Limit: /* these don't evaluate tlist */ return ExecSupportsBackwardScan(outerPlan(node)); default: return false; } }
Definition at line 382 of file execAmi.c.
References T_IndexOnlyScan, T_IndexScan, T_Material, T_Result, T_SeqScan, T_Sort, T_TidScan, and T_ValuesScan.
Referenced by final_cost_mergejoin().
{ switch (plantype) { case T_SeqScan: case T_IndexScan: case T_IndexOnlyScan: case T_TidScan: case T_ValuesScan: case T_Material: case T_Sort: return true; case T_Result: /* * T_Result only supports mark/restore if it has a child plan that * does, so we do not have enough information to give a really * correct answer. However, for current uses it's enough to * always say "false", because this routine is not asked about * gating Result plans, only base-case Results. */ return false; default: break; } return false; }
int ExecTargetListLength | ( | List * | targetlist | ) |
Definition at line 5163 of file execQual.c.
References list_length().
Referenced by ExecBuildProjectionInfo(), and ExecTypeFromTLInternal().
{ /* This used to be more complex, but fjoins are dead */ return list_length(targetlist); }
void execTuplesHashPrepare | ( | int | numCols, | |
Oid * | eqOperators, | |||
FmgrInfo ** | eqFunctions, | |||
FmgrInfo ** | hashFunctions | |||
) |
Definition at line 218 of file execGrouping.c.
References Assert, elog, ERROR, fmgr_info(), get_op_hash_functions(), get_opcode(), i, and palloc().
Referenced by ExecInitAgg(), ExecInitRecursiveUnion(), and ExecInitSetOp().
{ int i; *eqFunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo)); *hashFunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo)); for (i = 0; i < numCols; i++) { Oid eq_opr = eqOperators[i]; Oid eq_function; Oid left_hash_function; Oid right_hash_function; eq_function = get_opcode(eq_opr); if (!get_op_hash_functions(eq_opr, &left_hash_function, &right_hash_function)) elog(ERROR, "could not find hash function for hash operator %u", eq_opr); /* We're not supporting cross-type cases here */ Assert(left_hash_function == right_hash_function); fmgr_info(eq_function, &(*eqFunctions)[i]); fmgr_info(right_hash_function, &(*hashFunctions)[i]); } }
bool execTuplesMatch | ( | TupleTableSlot * | slot1, | |
TupleTableSlot * | slot2, | |||
int | numCols, | |||
AttrNumber * | matchColIdx, | |||
FmgrInfo * | eqfunctions, | |||
MemoryContext | evalContext | |||
) |
Definition at line 54 of file execGrouping.c.
References DatumGetBool, FunctionCall2, i, MemoryContextReset(), MemoryContextSwitchTo(), and slot_getattr().
Referenced by agg_retrieve_direct(), are_peers(), ExecGroup(), ExecUnique(), process_ordered_aggregate_multi(), setop_retrieve_direct(), spool_tuples(), and TupleHashTableMatch().
{ MemoryContext oldContext; bool result; int i; /* Reset and switch into the temp context. */ MemoryContextReset(evalContext); oldContext = MemoryContextSwitchTo(evalContext); /* * We cannot report a match without checking all the fields, but we can * report a non-match as soon as we find unequal fields. So, start * comparing at the last field (least significant sort key). That's the * most likely to be different if we are dealing with sorted input. */ result = true; for (i = numCols; --i >= 0;) { AttrNumber att = matchColIdx[i]; Datum attr1, attr2; bool isNull1, isNull2; attr1 = slot_getattr(slot1, att, &isNull1); attr2 = slot_getattr(slot2, att, &isNull2); if (isNull1 != isNull2) { result = false; /* one null and one not; they aren't equal */ break; } if (isNull1) continue; /* both are null, treat as equal */ /* Apply the type-specific equality function */ if (!DatumGetBool(FunctionCall2(&eqfunctions[i], attr1, attr2))) { result = false; /* they aren't equal */ break; } } MemoryContextSwitchTo(oldContext); return result; }
Definition at line 189 of file execGrouping.c.
References fmgr_info(), get_opcode(), i, and palloc().
Referenced by ExecInitAgg(), ExecInitGroup(), ExecInitSetOp(), ExecInitUnique(), and ExecInitWindowAgg().
bool execTuplesUnequal | ( | TupleTableSlot * | slot1, | |
TupleTableSlot * | slot2, | |||
int | numCols, | |||
AttrNumber * | matchColIdx, | |||
FmgrInfo * | eqfunctions, | |||
MemoryContext | evalContext | |||
) |
Definition at line 124 of file execGrouping.c.
References DatumGetBool, FunctionCall2, i, MemoryContextReset(), MemoryContextSwitchTo(), and slot_getattr().
Referenced by findPartialMatch().
{ MemoryContext oldContext; bool result; int i; /* Reset and switch into the temp context. */ MemoryContextReset(evalContext); oldContext = MemoryContextSwitchTo(evalContext); /* * We cannot report a match without checking all the fields, but we can * report a non-match as soon as we find unequal fields. So, start * comparing at the last field (least significant sort key). That's the * most likely to be different if we are dealing with sorted input. */ result = false; for (i = numCols; --i >= 0;) { AttrNumber att = matchColIdx[i]; Datum attr1, attr2; bool isNull1, isNull2; attr1 = slot_getattr(slot1, att, &isNull1); if (isNull1) continue; /* can't prove anything here */ attr2 = slot_getattr(slot2, att, &isNull2); if (isNull2) continue; /* can't prove anything here */ /* Apply the type-specific equality function */ if (!DatumGetBool(FunctionCall2(&eqfunctions[i], attr1, attr2))) { result = true; /* they are unequal */ break; } } MemoryContextSwitchTo(oldContext); return result; }
Definition at line 961 of file execTuples.c.
References Assert, CreateTemplateTupleDesc(), exprCollation(), exprType(), exprTypmod(), forboth, lfirst, list_length(), strVal, TupleDescInitEntry(), and TupleDescInitEntryCollation().
Referenced by ExecInitExpr(), and ExecInitValuesScan().
{ TupleDesc typeInfo; ListCell *le; ListCell *ln; int cur_resno = 1; Assert(list_length(exprList) == list_length(namesList)); typeInfo = CreateTemplateTupleDesc(list_length(exprList), false); forboth(le, exprList, ln, namesList) { Node *e = lfirst(le); char *n = strVal(lfirst(ln)); TupleDescInitEntry(typeInfo, cur_resno, n, exprType(e), exprTypmod(e), 0); TupleDescInitEntryCollation(typeInfo, cur_resno, exprCollation(e)); cur_resno++; } return typeInfo; }
Definition at line 903 of file execTuples.c.
References ExecTypeFromTLInternal().
Referenced by ExecAssignResultTypeFromTL(), ExecInitAgg(), ExecInitIndexOnlyScan(), ExecInitModifyTable(), and ExecInitSubPlan().
{ return ExecTypeFromTLInternal(targetList, hasoid, false); }
void ExecutorEnd | ( | QueryDesc * | queryDesc | ) |
Definition at line 401 of file execMain.c.
References ExecutorEnd_hook, and standard_ExecutorEnd().
Referenced by _SPI_pquery(), EndCopyTo(), ExecCreateTableAs(), execute_sql_string(), ExplainOnePlan(), PersistHoldablePortal(), PortalCleanup(), postquel_end(), ProcessQuery(), and refresh_matview_datafill().
{ if (ExecutorEnd_hook) (*ExecutorEnd_hook) (queryDesc); else standard_ExecutorEnd(queryDesc); }
void ExecutorFinish | ( | QueryDesc * | queryDesc | ) |
Definition at line 341 of file execMain.c.
References ExecutorFinish_hook, and standard_ExecutorFinish().
Referenced by _SPI_pquery(), EndCopyTo(), ExecCreateTableAs(), execute_sql_string(), ExplainOnePlan(), PersistHoldablePortal(), PortalCleanup(), postquel_end(), ProcessQuery(), and refresh_matview_datafill().
{ if (ExecutorFinish_hook) (*ExecutorFinish_hook) (queryDesc); else standard_ExecutorFinish(queryDesc); }
void ExecutorRewind | ( | QueryDesc * | queryDesc | ) |
Definition at line 467 of file execMain.c.
References Assert, CMD_SELECT, EState::es_query_cxt, QueryDesc::estate, ExecReScan(), MemoryContextSwitchTo(), NULL, QueryDesc::operation, and QueryDesc::planstate.
Referenced by DoPortalRewind(), and PersistHoldablePortal().
{ EState *estate; MemoryContext oldcontext; /* sanity checks */ Assert(queryDesc != NULL); estate = queryDesc->estate; Assert(estate != NULL); /* It's probably not sensible to rescan updating queries */ Assert(queryDesc->operation == CMD_SELECT); /* * Switch into per-query memory context */ oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); /* * rescan plan */ ExecReScan(queryDesc->planstate); MemoryContextSwitchTo(oldcontext); }
void ExecutorRun | ( | QueryDesc * | queryDesc, | |
ScanDirection | direction, | |||
long | count | |||
) |
Definition at line 248 of file execMain.c.
References ExecutorRun_hook, and standard_ExecutorRun().
Referenced by _SPI_pquery(), CopyTo(), ExecCreateTableAs(), execute_sql_string(), ExplainOnePlan(), PersistHoldablePortal(), PortalRunSelect(), postquel_getnext(), ProcessQuery(), and refresh_matview_datafill().
{ if (ExecutorRun_hook) (*ExecutorRun_hook) (queryDesc, direction, count); else standard_ExecutorRun(queryDesc, direction, count); }
void ExecutorStart | ( | QueryDesc * | queryDesc, | |
int | eflags | |||
) |
Definition at line 115 of file execMain.c.
References ExecutorStart_hook, and standard_ExecutorStart().
Referenced by _SPI_pquery(), BeginCopy(), ExecCreateTableAs(), execute_sql_string(), ExplainOnePlan(), PortalStart(), postquel_start(), ProcessQuery(), and refresh_matview_datafill().
{ if (ExecutorStart_hook) (*ExecutorStart_hook) (queryDesc, eflags); else standard_ExecutorStart(queryDesc, eflags); }
TupleHashEntry FindTupleHashEntry | ( | TupleHashTable | hashtable, | |
TupleTableSlot * | slot, | |||
FmgrInfo * | eqfunctions, | |||
FmgrInfo * | hashfunctions | |||
) |
Definition at line 422 of file execGrouping.c.
References TupleHashTableData::cur_eq_funcs, TupleHashEntryData::firstTuple, HASH_FIND, hash_search(), TupleHashTableData::hashtab, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, MemoryContextSwitchTo(), NULL, and TupleHashTableData::tempcxt.
Referenced by ExecHashSubPlan().
{ TupleHashEntry entry; MemoryContext oldContext; TupleHashTable saveCurHT; TupleHashEntryData dummy; /* Need to run the hash functions in short-lived context */ oldContext = MemoryContextSwitchTo(hashtable->tempcxt); /* * Set up data needed by hash and match functions * * We save and restore CurTupleHashTable just in case someone manages to * invoke this code re-entrantly. */ hashtable->inputslot = slot; hashtable->in_hash_funcs = hashfunctions; hashtable->cur_eq_funcs = eqfunctions; saveCurHT = CurTupleHashTable; CurTupleHashTable = hashtable; /* Search the hash table */ dummy.firstTuple = NULL; /* flag to reference inputslot */ entry = (TupleHashEntry) hash_search(hashtable->hashtab, &dummy, HASH_FIND, NULL); CurTupleHashTable = saveCurHT; MemoryContextSwitchTo(oldContext); return entry; }
void FreeExecutorState | ( | EState * | estate | ) |
Definition at line 178 of file execUtils.c.
References EState::es_exprcontexts, EState::es_query_cxt, FreeExprContext(), linitial, and MemoryContextDelete().
Referenced by afterTriggerInvokeEvents(), ATRewriteTable(), btree_predicate_proof(), compute_index_stats(), CopyFrom(), EvalPlanQualEnd(), evaluate_expr(), ExecuteQuery(), ExecuteTruncate(), ExplainExecuteQuery(), get_actual_variable_range(), IndexBuildHeapScan(), IndexCheckExclusion(), plpgsql_xact_cb(), standard_ExecutorEnd(), tuplesort_end(), validate_index_heapscan(), validateCheckConstraint(), and validateDomainConstraint().
{ /* * Shut down and free any remaining ExprContexts. We do this explicitly * to ensure that any remaining shutdown callbacks get called (since they * might need to release resources that aren't simply memory within the * per-query memory context). */ while (estate->es_exprcontexts) { /* * XXX: seems there ought to be a faster way to implement this than * repeated list_delete(), no? */ FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts), true); /* FreeExprContext removed the list link for us */ } /* * Free the per-query memory context, thereby releasing all working * memory, including the EState node itself. */ MemoryContextDelete(estate->es_query_cxt); }
void FreeExprContext | ( | ExprContext * | econtext, | |
bool | isCommit | |||
) |
Definition at line 353 of file execUtils.c.
References ExprContext::ecxt_estate, ExprContext::ecxt_per_tuple_memory, EState::es_exprcontexts, list_delete_ptr(), MemoryContextDelete(), pfree(), and ShutdownExprContext().
Referenced by ExecEndBitmapIndexScan(), ExecEndIndexOnlyScan(), ExecEndIndexScan(), FreeExecutorState(), plpgsql_destroy_econtext(), and plpgsql_subxact_cb().
{ EState *estate; /* Call any registered callbacks */ ShutdownExprContext(econtext, isCommit); /* And clean up the memory used */ MemoryContextDelete(econtext->ecxt_per_tuple_memory); /* Unlink self from owning EState, if any */ estate = econtext->ecxt_estate; if (estate) estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts, econtext); /* And delete the ExprContext node */ pfree(econtext); }
Datum GetAttributeByName | ( | HeapTupleHeader | tuple, | |
const char * | attname, | |||
bool * | isNull | |||
) |
Definition at line 1220 of file execQual.c.
References tupleDesc::attrs, elog, ERROR, heap_getattr, HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, i, InvalidAttrNumber, ItemPointerSetInvalid, lookup_rowtype_tupdesc(), namestrcmp(), tupleDesc::natts, NULL, ReleaseTupleDesc, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, and HeapTupleData::t_tableOid.
Referenced by c_overpaid(), and overpaid().
{ AttrNumber attrno; Datum result; Oid tupType; int32 tupTypmod; TupleDesc tupDesc; HeapTupleData tmptup; int i; if (attname == NULL) elog(ERROR, "invalid attribute name"); if (isNull == NULL) elog(ERROR, "a NULL isNull pointer was passed"); if (tuple == NULL) { /* Kinda bogus but compatible with old behavior... */ *isNull = true; return (Datum) 0; } tupType = HeapTupleHeaderGetTypeId(tuple); tupTypmod = HeapTupleHeaderGetTypMod(tuple); tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod); attrno = InvalidAttrNumber; for (i = 0; i < tupDesc->natts; i++) { if (namestrcmp(&(tupDesc->attrs[i]->attname), attname) == 0) { attrno = tupDesc->attrs[i]->attnum; break; } } if (attrno == InvalidAttrNumber) elog(ERROR, "attribute \"%s\" does not exist", attname); /* * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all * the fields in the struct just in case user tries to inspect system * columns. */ tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple); ItemPointerSetInvalid(&(tmptup.t_self)); tmptup.t_tableOid = InvalidOid; tmptup.t_data = tuple; result = heap_getattr(&tmptup, attrno, tupDesc, isNull); ReleaseTupleDesc(tupDesc); return result; }
Datum GetAttributeByNum | ( | HeapTupleHeader | tuple, | |
AttrNumber | attrno, | |||
bool * | isNull | |||
) |
Definition at line 1172 of file execQual.c.
References AttributeNumberIsValid, elog, ERROR, heap_getattr, HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, ItemPointerSetInvalid, lookup_rowtype_tupdesc(), NULL, ReleaseTupleDesc, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, and HeapTupleData::t_tableOid.
{ Datum result; Oid tupType; int32 tupTypmod; TupleDesc tupDesc; HeapTupleData tmptup; if (!AttributeNumberIsValid(attrno)) elog(ERROR, "invalid attribute number %d", attrno); if (isNull == NULL) elog(ERROR, "a NULL isNull pointer was passed"); if (tuple == NULL) { /* Kinda bogus but compatible with old behavior... */ *isNull = true; return (Datum) 0; } tupType = HeapTupleHeaderGetTypeId(tuple); tupTypmod = HeapTupleHeaderGetTypMod(tuple); tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod); /* * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all * the fields in the struct just in case user tries to inspect system * columns. */ tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple); ItemPointerSetInvalid(&(tmptup.t_self)); tmptup.t_tableOid = InvalidOid; tmptup.t_data = tuple; result = heap_getattr(&tmptup, attrno, tupDesc, isNull); ReleaseTupleDesc(tupDesc); return result; }
void InitResultRelInfo | ( | ResultRelInfo * | resultRelInfo, | |
Relation | resultRelationDesc, | |||
Index | resultRelationIndex, | |||
int | instrument_options | |||
) |
Definition at line 1112 of file execMain.c.
References CopyTriggerDesc(), GetFdwRoutineForRelation(), InstrAlloc(), MemSet, TriggerDesc::numtriggers, palloc0(), RelationData::rd_rel, RELKIND_FOREIGN_TABLE, ResultRelInfo::ri_ConstraintExprs, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_FdwState, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_junkFilter, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_projectReturning, ResultRelInfo::ri_RangeTableIndex, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, ResultRelInfo::ri_TrigWhenExprs, RelationData::trigdesc, and ResultRelInfo::type.
Referenced by CopyFrom(), ExecGetTriggerResultRel(), ExecuteTruncate(), and InitPlan().
{ MemSet(resultRelInfo, 0, sizeof(ResultRelInfo)); resultRelInfo->type = T_ResultRelInfo; resultRelInfo->ri_RangeTableIndex = resultRelationIndex; resultRelInfo->ri_RelationDesc = resultRelationDesc; resultRelInfo->ri_NumIndices = 0; resultRelInfo->ri_IndexRelationDescs = NULL; resultRelInfo->ri_IndexRelationInfo = NULL; /* make a copy so as not to depend on relcache info not changing... */ resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc); if (resultRelInfo->ri_TrigDesc) { int n = resultRelInfo->ri_TrigDesc->numtriggers; resultRelInfo->ri_TrigFunctions = (FmgrInfo *) palloc0(n * sizeof(FmgrInfo)); resultRelInfo->ri_TrigWhenExprs = (List **) palloc0(n * sizeof(List *)); if (instrument_options) resultRelInfo->ri_TrigInstrument = InstrAlloc(n, instrument_options); } else { resultRelInfo->ri_TrigFunctions = NULL; resultRelInfo->ri_TrigWhenExprs = NULL; resultRelInfo->ri_TrigInstrument = NULL; } if (resultRelationDesc->rd_rel->relkind == RELKIND_FOREIGN_TABLE) resultRelInfo->ri_FdwRoutine = GetFdwRoutineForRelation(resultRelationDesc, true); else resultRelInfo->ri_FdwRoutine = NULL; resultRelInfo->ri_FdwState = NULL; resultRelInfo->ri_ConstraintExprs = NULL; resultRelInfo->ri_junkFilter = NULL; resultRelInfo->ri_projectReturning = NULL; }
TupleHashEntry LookupTupleHashEntry | ( | TupleHashTable | hashtable, | |
TupleTableSlot * | slot, | |||
bool * | isnew | |||
) |
Definition at line 331 of file execGrouping.c.
References CreateTupleDescCopy(), TupleHashTableData::cur_eq_funcs, TupleHashTableData::entrysize, ExecCopySlotMinimalTuple(), TupleHashEntryData::firstTuple, HASH_ENTER, HASH_FIND, hash_search(), TupleHashTableData::hashtab, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, MakeSingleTupleTableSlot(), MemoryContextSwitchTo(), MemSet, NULL, TupleHashTableData::tab_eq_funcs, TupleHashTableData::tab_hash_funcs, TupleHashTableData::tablecxt, TupleHashTableData::tableslot, TupleHashTableData::tempcxt, and TupleTableSlot::tts_tupleDescriptor.
Referenced by buildSubPlanHash(), ExecRecursiveUnion(), lookup_hash_entry(), and setop_fill_hash_table().
{ TupleHashEntry entry; MemoryContext oldContext; TupleHashTable saveCurHT; TupleHashEntryData dummy; bool found; /* If first time through, clone the input slot to make table slot */ if (hashtable->tableslot == NULL) { TupleDesc tupdesc; oldContext = MemoryContextSwitchTo(hashtable->tablecxt); /* * We copy the input tuple descriptor just for safety --- we assume * all input tuples will have equivalent descriptors. */ tupdesc = CreateTupleDescCopy(slot->tts_tupleDescriptor); hashtable->tableslot = MakeSingleTupleTableSlot(tupdesc); MemoryContextSwitchTo(oldContext); } /* Need to run the hash functions in short-lived context */ oldContext = MemoryContextSwitchTo(hashtable->tempcxt); /* * Set up data needed by hash and match functions * * We save and restore CurTupleHashTable just in case someone manages to * invoke this code re-entrantly. */ hashtable->inputslot = slot; hashtable->in_hash_funcs = hashtable->tab_hash_funcs; hashtable->cur_eq_funcs = hashtable->tab_eq_funcs; saveCurHT = CurTupleHashTable; CurTupleHashTable = hashtable; /* Search the hash table */ dummy.firstTuple = NULL; /* flag to reference inputslot */ entry = (TupleHashEntry) hash_search(hashtable->hashtab, &dummy, isnew ? HASH_ENTER : HASH_FIND, &found); if (isnew) { if (found) { /* found pre-existing entry */ *isnew = false; } else { /* * created new entry * * Zero any caller-requested space in the entry. (This zaps the * "key data" dynahash.c copied into the new entry, but we don't * care since we're about to overwrite it anyway.) */ MemSet(entry, 0, hashtable->entrysize); /* Copy the first tuple into the table context */ MemoryContextSwitchTo(hashtable->tablecxt); entry->firstTuple = ExecCopySlotMinimalTuple(slot); *isnew = true; } } CurTupleHashTable = saveCurHT; MemoryContextSwitchTo(oldContext); return entry; }
ExprContext* MakePerTupleExprContext | ( | EState * | estate | ) |
Definition at line 395 of file execUtils.c.
References CreateExprContext(), EState::es_per_tuple_exprcontext, and NULL.
{ if (estate->es_per_tuple_exprcontext == NULL) estate->es_per_tuple_exprcontext = CreateExprContext(estate); return estate->es_per_tuple_exprcontext; }
Definition at line 530 of file execProcnode.c.
References CHECK_FOR_INTERRUPTS, PlanState::chgParam, elog, ERROR, ExecReScan(), MultiExecBitmapAnd(), MultiExecBitmapIndexScan(), MultiExecBitmapOr(), MultiExecHash(), nodeTag, NULL, T_BitmapAndState, T_BitmapIndexScanState, T_BitmapOrState, and T_HashState.
Referenced by BitmapHeapNext(), ExecHashJoin(), MultiExecBitmapAnd(), and MultiExecBitmapOr().
{ Node *result; CHECK_FOR_INTERRUPTS(); if (node->chgParam != NULL) /* something changed */ ExecReScan(node); /* let ReScan handle this */ switch (nodeTag(node)) { /* * Only node types that actually support multiexec will be listed */ case T_HashState: result = MultiExecHash((HashState *) node); break; case T_BitmapIndexScanState: result = MultiExecBitmapIndexScan((BitmapIndexScanState *) node); break; case T_BitmapAndState: result = MultiExecBitmapAnd((BitmapAndState *) node); break; case T_BitmapOrState: result = MultiExecBitmapOr((BitmapOrState *) node); break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); result = NULL; break; } return result; }
void RegisterExprContextCallback | ( | ExprContext * | econtext, | |
ExprContextCallbackFunction | function, | |||
Datum | arg | |||
) |
Definition at line 1421 of file execUtils.c.
References ExprContext_CB::arg, ExprContext::ecxt_callbacks, ExprContext::ecxt_per_query_memory, ExprContext_CB::function, MemoryContextAlloc(), and ExprContext_CB::next.
Referenced by ExecMakeFunctionResult(), ExecPrepareTuplestoreResult(), fmgr_sql(), get_cached_rowtype(), and init_MultiFuncCall().
{ ExprContext_CB *ecxt_callback; /* Save the info in appropriate memory context */ ecxt_callback = (ExprContext_CB *) MemoryContextAlloc(econtext->ecxt_per_query_memory, sizeof(ExprContext_CB)); ecxt_callback->function = function; ecxt_callback->arg = arg; /* link to front of list for appropriate execution order */ ecxt_callback->next = econtext->ecxt_callbacks; econtext->ecxt_callbacks = ecxt_callback; }
void ReScanExprContext | ( | ExprContext * | econtext | ) |
Definition at line 380 of file execUtils.c.
References ExprContext::ecxt_per_tuple_memory, MemoryContextReset(), and ShutdownExprContext().
Referenced by domain_check_input(), ExecReScan(), and ValuesNext().
{ /* Call any registered callbacks */ ShutdownExprContext(econtext, true); /* And clean up the memory used */ MemoryContextReset(econtext->ecxt_per_tuple_memory); }
void standard_ExecutorEnd | ( | QueryDesc * | queryDesc | ) |
Definition at line 410 of file execMain.c.
References Assert, EState::es_crosscheck_snapshot, EState::es_finished, EState::es_query_cxt, EState::es_snapshot, EState::es_top_eflags, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, ExecEndPlan(), FreeExecutorState(), MemoryContextSwitchTo(), NULL, QueryDesc::planstate, QueryDesc::totaltime, QueryDesc::tupDesc, and UnregisterSnapshot().
Referenced by ExecutorEnd(), explain_ExecutorEnd(), and pgss_ExecutorEnd().
{ EState *estate; MemoryContext oldcontext; /* sanity checks */ Assert(queryDesc != NULL); estate = queryDesc->estate; Assert(estate != NULL); /* * Check that ExecutorFinish was called, unless in EXPLAIN-only mode. This * Assert is needed because ExecutorFinish is new as of 9.1, and callers * might forget to call it. */ Assert(estate->es_finished || (estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY)); /* * Switch into per-query memory context to run ExecEndPlan */ oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); ExecEndPlan(queryDesc->planstate, estate); /* do away with our snapshots */ UnregisterSnapshot(estate->es_snapshot); UnregisterSnapshot(estate->es_crosscheck_snapshot); /* * Must switch out of context before destroying it */ MemoryContextSwitchTo(oldcontext); /* * Release EState and per-query memory context. This should release * everything the executor has allocated. */ FreeExecutorState(estate); /* Reset queryDesc fields that no longer point to anything */ queryDesc->tupDesc = NULL; queryDesc->estate = NULL; queryDesc->planstate = NULL; queryDesc->totaltime = NULL; }
void standard_ExecutorFinish | ( | QueryDesc * | queryDesc | ) |
Definition at line 350 of file execMain.c.
References AfterTriggerEndQuery(), Assert, EState::es_finished, EState::es_query_cxt, EState::es_top_eflags, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_SKIP_TRIGGERS, ExecPostprocessPlan(), InstrStartNode(), InstrStopNode(), MemoryContextSwitchTo(), NULL, and QueryDesc::totaltime.
Referenced by ExecutorFinish(), explain_ExecutorFinish(), and pgss_ExecutorFinish().
{ EState *estate; MemoryContext oldcontext; /* sanity checks */ Assert(queryDesc != NULL); estate = queryDesc->estate; Assert(estate != NULL); Assert(!(estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY)); /* This should be run once and only once per Executor instance */ Assert(!estate->es_finished); /* Switch into per-query memory context */ oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); /* Allow instrumentation of Executor overall runtime */ if (queryDesc->totaltime) InstrStartNode(queryDesc->totaltime); /* Run ModifyTable nodes to completion */ ExecPostprocessPlan(estate); /* Execute queued AFTER triggers, unless told not to */ if (!(estate->es_top_eflags & EXEC_FLAG_SKIP_TRIGGERS)) AfterTriggerEndQuery(estate); if (queryDesc->totaltime) InstrStopNode(queryDesc->totaltime, 0); MemoryContextSwitchTo(oldcontext); estate->es_finished = true; }
void standard_ExecutorRun | ( | QueryDesc * | queryDesc, | |
ScanDirection | direction, | |||
long | count | |||
) |
Definition at line 258 of file execMain.c.
References Assert, CMD_SELECT, QueryDesc::dest, EState::es_lastoid, EState::es_processed, EState::es_query_cxt, EState::es_top_eflags, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, ExecutePlan(), PlannedStmt::hasReturning, InstrStartNode(), InstrStopNode(), MemoryContextSwitchTo(), NULL, QueryDesc::operation, QueryDesc::plannedstmt, QueryDesc::planstate, _DestReceiver::rShutdown, _DestReceiver::rStartup, ScanDirectionIsNoMovement, QueryDesc::totaltime, and QueryDesc::tupDesc.
Referenced by ExecutorRun(), explain_ExecutorRun(), and pgss_ExecutorRun().
{ EState *estate; CmdType operation; DestReceiver *dest; bool sendTuples; MemoryContext oldcontext; /* sanity checks */ Assert(queryDesc != NULL); estate = queryDesc->estate; Assert(estate != NULL); Assert(!(estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY)); /* * Switch into per-query memory context */ oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); /* Allow instrumentation of Executor overall runtime */ if (queryDesc->totaltime) InstrStartNode(queryDesc->totaltime); /* * extract information from the query descriptor and the query feature. */ operation = queryDesc->operation; dest = queryDesc->dest; /* * startup tuple receiver, if we will be emitting tuples */ estate->es_processed = 0; estate->es_lastoid = InvalidOid; sendTuples = (operation == CMD_SELECT || queryDesc->plannedstmt->hasReturning); if (sendTuples) (*dest->rStartup) (dest, operation, queryDesc->tupDesc); /* * run plan */ if (!ScanDirectionIsNoMovement(direction)) ExecutePlan(estate, queryDesc->planstate, operation, sendTuples, count, direction, dest); /* * shutdown tuple receiver, if we started it */ if (sendTuples) (*dest->rShutdown) (dest); if (queryDesc->totaltime) InstrStopNode(queryDesc->totaltime, estate->es_processed); MemoryContextSwitchTo(oldcontext); }
void standard_ExecutorStart | ( | QueryDesc * | queryDesc, | |
int | eflags | |||
) |
Definition at line 124 of file execMain.c.
References AfterTriggerBeginQuery(), Assert, CMD_DELETE, CMD_INSERT, CMD_SELECT, CMD_UPDATE, CreateExecutorState(), QueryDesc::crosscheck_snapshot, elog, ERROR, EState::es_crosscheck_snapshot, EState::es_instrument, EState::es_output_cid, EState::es_param_exec_vals, EState::es_param_list_info, EState::es_query_cxt, EState::es_snapshot, EState::es_top_eflags, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_SKIP_TRIGGERS, ExecCheckXactReadOnly(), GetCurrentCommandId(), PlannedStmt::hasModifyingCTE, InitPlan(), QueryDesc::instrument_options, MemoryContextSwitchTo(), NIL, PlannedStmt::nParamExec, NULL, QueryDesc::operation, palloc0(), QueryDesc::params, QueryDesc::plannedstmt, RegisterSnapshot(), PlannedStmt::rowMarks, QueryDesc::snapshot, and XactReadOnly.
Referenced by ExecutorStart(), explain_ExecutorStart(), and pgss_ExecutorStart().
{ EState *estate; MemoryContext oldcontext; /* sanity checks: queryDesc must not be started already */ Assert(queryDesc != NULL); Assert(queryDesc->estate == NULL); /* * If the transaction is read-only, we need to check if any writes are * planned to non-temporary tables. EXPLAIN is considered read-only. */ if (XactReadOnly && !(eflags & EXEC_FLAG_EXPLAIN_ONLY)) ExecCheckXactReadOnly(queryDesc->plannedstmt); /* * Build EState, switch into per-query memory context for startup. */ estate = CreateExecutorState(); queryDesc->estate = estate; oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); /* * Fill in external parameters, if any, from queryDesc; and allocate * workspace for internal parameters */ estate->es_param_list_info = queryDesc->params; if (queryDesc->plannedstmt->nParamExec > 0) estate->es_param_exec_vals = (ParamExecData *) palloc0(queryDesc->plannedstmt->nParamExec * sizeof(ParamExecData)); /* * If non-read-only query, set the command ID to mark output tuples with */ switch (queryDesc->operation) { case CMD_SELECT: /* * SELECT FOR [KEY] UPDATE/SHARE and modifying CTEs need to mark * tuples */ if (queryDesc->plannedstmt->rowMarks != NIL || queryDesc->plannedstmt->hasModifyingCTE) estate->es_output_cid = GetCurrentCommandId(true); /* * A SELECT without modifying CTEs can't possibly queue triggers, * so force skip-triggers mode. This is just a marginal efficiency * hack, since AfterTriggerBeginQuery/AfterTriggerEndQuery aren't * all that expensive, but we might as well do it. */ if (!queryDesc->plannedstmt->hasModifyingCTE) eflags |= EXEC_FLAG_SKIP_TRIGGERS; break; case CMD_INSERT: case CMD_DELETE: case CMD_UPDATE: estate->es_output_cid = GetCurrentCommandId(true); break; default: elog(ERROR, "unrecognized operation code: %d", (int) queryDesc->operation); break; } /* * Copy other important information into the EState */ estate->es_snapshot = RegisterSnapshot(queryDesc->snapshot); estate->es_crosscheck_snapshot = RegisterSnapshot(queryDesc->crosscheck_snapshot); estate->es_top_eflags = eflags; estate->es_instrument = queryDesc->instrument_options; /* * Initialize the plan state tree */ InitPlan(queryDesc, eflags); /* * Set up an AFTER-trigger statement context, unless told not to, or * unless it's EXPLAIN-only mode (when ExecutorFinish won't be called). */ if (!(eflags & (EXEC_FLAG_SKIP_TRIGGERS | EXEC_FLAG_EXPLAIN_ONLY))) AfterTriggerBeginQuery(); MemoryContextSwitchTo(oldcontext); }
void UnregisterExprContextCallback | ( | ExprContext * | econtext, | |
ExprContextCallbackFunction | function, | |||
Datum | arg | |||
) |
Definition at line 1447 of file execUtils.c.
References ExprContext_CB::arg, ExprContext::ecxt_callbacks, ExprContext_CB::function, ExprContext_CB::next, NULL, and pfree().
Referenced by end_MultiFuncCall(), and fmgr_sql().
{ ExprContext_CB **prev_callback; ExprContext_CB *ecxt_callback; prev_callback = &econtext->ecxt_callbacks; while ((ecxt_callback = *prev_callback) != NULL) { if (ecxt_callback->function == function && ecxt_callback->arg == arg) { *prev_callback = ecxt_callback->next; pfree(ecxt_callback); } else prev_callback = &ecxt_callback->next; } }
Definition at line 1390 of file execUtils.c.
References Plan::allParam, bms_free(), bms_intersect(), bms_is_empty(), bms_join(), PlanState::chgParam, and PlanState::plan.
Referenced by ExecReScan(), ExecReScanAppend(), ExecReScanBitmapAnd(), ExecReScanBitmapOr(), ExecReScanMergeAppend(), and ExecReScanSubqueryScan().
{ Bitmapset *parmset; /* * The plan node only depends on params listed in its allParam set. Don't * include anything else into its chgParam set. */ parmset = bms_intersect(node->plan->allParam, newchg); /* * Keep node->chgParam == NULL if there's not actually any members; this * allows the simplest possible tests in executor node files. */ if (!bms_is_empty(parmset)) node->chgParam = bms_join(node->chgParam, parmset); else bms_free(parmset); }
PGDLLIMPORT ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook |
Definition at line 69 of file execMain.c.
Referenced by _PG_init(), and ExecCheckRTPerms().
PGDLLIMPORT ExecutorEnd_hook_type ExecutorEnd_hook |
Definition at line 66 of file execMain.c.
Referenced by _PG_fini(), _PG_init(), and ExecutorEnd().
PGDLLIMPORT ExecutorFinish_hook_type ExecutorFinish_hook |
Definition at line 65 of file execMain.c.
Referenced by _PG_fini(), _PG_init(), and ExecutorFinish().
PGDLLIMPORT ExecutorRun_hook_type ExecutorRun_hook |
Definition at line 64 of file execMain.c.
Referenced by _PG_fini(), _PG_init(), and ExecutorRun().
PGDLLIMPORT ExecutorStart_hook_type ExecutorStart_hook |
Definition at line 63 of file execMain.c.
Referenced by _PG_fini(), _PG_init(), and ExecutorStart().