From f81a91db4d1c2032632aa5df9fc14be24f5fe5ec Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Mon, 17 Jul 2017 21:29:45 -0400 Subject: Use a real RT index when setting up partition tuple routing. Before, we always used a dummy value of 1, but that's not right when the partitioned table being modified is inside of a WITH clause rather than part of the main query. Amit Langote, reported and reviewd by Etsuro Fujita, with a comment change by me. Discussion: http://postgr.es/m/ee12f648-8907-77b5-afc0-2980bcb0aa37@lab.ntt.co.jp --- src/backend/executor/nodeModifyTable.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/backend/executor/nodeModifyTable.c') diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 8d17425abe..77ba15dd90 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -1914,6 +1914,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) num_partitions; ExecSetupPartitionTupleRouting(rel, + node->nominalRelation, &partition_dispatch_info, &partitions, &partition_tupconv_maps, -- cgit v1.2.3 From d47cfef7116fb36349949f5c757aa2112c249804 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Tue, 25 Jul 2017 17:37:17 -0700 Subject: Move interrupt checking from ExecProcNode() to executor nodes. In a followup commit ExecProcNode(), and especially the large switch it contains, will largely be replaced by a function pointer directly to the correct node. The node functions will then get invoked by a thin inline function wrapper. To avoid having to include miscadmin.h in headers - CHECK_FOR_INTERRUPTS() - move the interrupt checks into the individual executor routines. While looking through all executor nodes, I noticed a number of arguably missing interrupt checks, add these too. Author: Andres Freund, Tom Lane Reviewed-By: Tom Lane Discussion: https://postgr.es/m/22833.1490390175@sss.pgh.pa.us --- src/backend/executor/execProcnode.c | 2 -- src/backend/executor/nodeAgg.c | 8 ++++++++ src/backend/executor/nodeAppend.c | 3 +++ src/backend/executor/nodeBitmapHeapscan.c | 3 +++ src/backend/executor/nodeCustom.c | 3 +++ src/backend/executor/nodeGather.c | 4 ++++ src/backend/executor/nodeGatherMerge.c | 4 ++++ src/backend/executor/nodeGroup.c | 3 +++ src/backend/executor/nodeHash.c | 6 ++++++ src/backend/executor/nodeHashjoin.c | 15 ++++++++------- src/backend/executor/nodeIndexonlyscan.c | 3 +++ src/backend/executor/nodeIndexscan.c | 7 +++++++ src/backend/executor/nodeLimit.c | 3 +++ src/backend/executor/nodeLockRows.c | 3 +++ src/backend/executor/nodeMaterial.c | 2 ++ src/backend/executor/nodeMergeAppend.c | 4 +++- src/backend/executor/nodeMergejoin.c | 3 +++ src/backend/executor/nodeModifyTable.c | 2 ++ src/backend/executor/nodeNestloop.c | 3 +++ src/backend/executor/nodeProjectSet.c | 3 +++ src/backend/executor/nodeRecursiveunion.c | 2 ++ src/backend/executor/nodeResult.c | 3 +++ src/backend/executor/nodeSetOp.c | 5 +++++ src/backend/executor/nodeSort.c | 2 ++ src/backend/executor/nodeSubplan.c | 5 +++++ src/backend/executor/nodeTableFuncscan.c | 2 ++ src/backend/executor/nodeTidscan.c | 3 +++ src/backend/executor/nodeUnique.c | 3 +++ src/backend/executor/nodeWindowAgg.c | 5 +++++ 29 files changed, 104 insertions(+), 10 deletions(-) (limited to 'src/backend/executor/nodeModifyTable.c') diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 294ad2cff9..20fd9f822e 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -399,8 +399,6 @@ ExecProcNode(PlanState *node) { TupleTableSlot *result; - CHECK_FOR_INTERRUPTS(); - if (node->chgParam != NULL) /* something changed */ ExecReScan(node); /* let ReScan handle this */ diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index de9a18e71c..377916dae7 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -677,6 +677,8 @@ fetch_input_tuple(AggState *aggstate) if (aggstate->sort_in) { + /* make sure we check for interrupts in either path through here */ + CHECK_FOR_INTERRUPTS(); if (!tuplesort_gettupleslot(aggstate->sort_in, true, false, aggstate->sort_slot, NULL)) return NULL; @@ -1414,6 +1416,8 @@ process_ordered_aggregate_multi(AggState *aggstate, while (tuplesort_gettupleslot(pertrans->sortstates[aggstate->current_set], true, true, slot1, &newAbbrevVal)) { + CHECK_FOR_INTERRUPTS(); + /* * Extract the first numTransInputs columns as datums to pass to the * transfn. (This will help execTuplesMatch too, so we do it @@ -2100,6 +2104,8 @@ ExecAgg(AggState *node) { TupleTableSlot *result = NULL; + CHECK_FOR_INTERRUPTS(); + if (!node->agg_done) { /* Dispatch based on strategy */ @@ -2563,6 +2569,8 @@ agg_retrieve_hash_table(AggState *aggstate) TupleTableSlot *hashslot = perhash->hashslot; int i; + CHECK_FOR_INTERRUPTS(); + /* * Find the next entry in the hash table */ diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index aae5e3fa63..58045e05e5 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -59,6 +59,7 @@ #include "executor/execdebug.h" #include "executor/nodeAppend.h" +#include "miscadmin.h" static bool exec_append_initialize_next(AppendState *appendstate); @@ -204,6 +205,8 @@ ExecAppend(AppendState *node) PlanState *subnode; TupleTableSlot *result; + CHECK_FOR_INTERRUPTS(); + /* * figure out which subplan we are currently processing */ diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index 7e0ba030b7..cf109d5049 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -41,6 +41,7 @@ #include "access/transam.h" #include "executor/execdebug.h" #include "executor/nodeBitmapHeapscan.h" +#include "miscadmin.h" #include "pgstat.h" #include "storage/bufmgr.h" #include "storage/predicate.h" @@ -192,6 +193,8 @@ BitmapHeapNext(BitmapHeapScanState *node) Page dp; ItemId lp; + CHECK_FOR_INTERRUPTS(); + /* * Get next page of results if needed */ diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c index 69e27047f1..fc15974a2d 100644 --- a/src/backend/executor/nodeCustom.c +++ b/src/backend/executor/nodeCustom.c @@ -15,6 +15,7 @@ #include "executor/nodeCustom.h" #include "nodes/execnodes.h" #include "nodes/plannodes.h" +#include "miscadmin.h" #include "parser/parsetree.h" #include "utils/hsearch.h" #include "utils/memutils.h" @@ -104,6 +105,8 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags) TupleTableSlot * ExecCustomScan(CustomScanState *node) { + CHECK_FOR_INTERRUPTS(); + Assert(node->methods->ExecCustomScan != NULL); return node->methods->ExecCustomScan(node); } diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c index f83cd584d7..5dbe19c056 100644 --- a/src/backend/executor/nodeGather.c +++ b/src/backend/executor/nodeGather.c @@ -128,6 +128,8 @@ ExecGather(GatherState *node) TupleTableSlot *slot; ExprContext *econtext; + CHECK_FOR_INTERRUPTS(); + /* * Initialize the parallel context and workers on first execution. We do * this on first execution rather than during node initialization, as it @@ -247,6 +249,8 @@ gather_getnext(GatherState *gatherstate) while (gatherstate->reader != NULL || gatherstate->need_to_scan_locally) { + CHECK_FOR_INTERRUPTS(); + if (gatherstate->reader != NULL) { MemoryContext oldContext; diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c index 80ee1fc89b..0aff3798f7 100644 --- a/src/backend/executor/nodeGatherMerge.c +++ b/src/backend/executor/nodeGatherMerge.c @@ -164,6 +164,8 @@ ExecGatherMerge(GatherMergeState *node) ExprContext *econtext; int i; + CHECK_FOR_INTERRUPTS(); + /* * As with Gather, we don't launch workers until this node is actually * executed. @@ -393,6 +395,8 @@ gather_merge_init(GatherMergeState *gm_state) reread: for (i = 0; i < nreaders + 1; i++) { + CHECK_FOR_INTERRUPTS(); + if (!gm_state->gm_tuple_buffers[i].done && (TupIsNull(gm_state->gm_slots[i]) || gm_state->gm_slots[i]->tts_isempty)) diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c index af9ba4905e..fc5e0e59bc 100644 --- a/src/backend/executor/nodeGroup.c +++ b/src/backend/executor/nodeGroup.c @@ -24,6 +24,7 @@ #include "executor/executor.h" #include "executor/nodeGroup.h" +#include "miscadmin.h" /* @@ -40,6 +41,8 @@ ExecGroup(GroupState *node) TupleTableSlot *firsttupleslot; TupleTableSlot *outerslot; + CHECK_FOR_INTERRUPTS(); + /* * get state info from node */ diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c index 075f4ed11c..fbeb562489 100644 --- a/src/backend/executor/nodeHash.c +++ b/src/backend/executor/nodeHash.c @@ -810,6 +810,9 @@ ExecHashIncreaseNumBuckets(HashJoinTable hashtable) idx += MAXALIGN(HJTUPLE_OVERHEAD + HJTUPLE_MINTUPLE(hashTuple)->t_len); } + + /* allow this loop to be cancellable */ + CHECK_FOR_INTERRUPTS(); } } @@ -1192,6 +1195,9 @@ ExecScanHashTableForUnmatched(HashJoinState *hjstate, ExprContext *econtext) hashTuple = hashTuple->next; } + + /* allow this loop to be cancellable */ + CHECK_FOR_INTERRUPTS(); } /* diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c index 668ed871e1..252960c81c 100644 --- a/src/backend/executor/nodeHashjoin.c +++ b/src/backend/executor/nodeHashjoin.c @@ -92,6 +92,14 @@ ExecHashJoin(HashJoinState *node) */ for (;;) { + /* + * It's possible to iterate this loop many times before returning a + * tuple, in some pathological cases such as needing to move much of + * the current batch to a later batch. So let's check for interrupts + * each time through. + */ + CHECK_FOR_INTERRUPTS(); + switch (node->hj_JoinState) { case HJ_BUILD_HASHTABLE: @@ -246,13 +254,6 @@ ExecHashJoin(HashJoinState *node) case HJ_SCAN_BUCKET: - /* - * We check for interrupts here because this corresponds to - * where we'd fetch a row from a child plan node in other join - * types. - */ - CHECK_FOR_INTERRUPTS(); - /* * Scan the selected hash bucket for matches to current outer */ diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index 890e54416a..e2000764a4 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -34,6 +34,7 @@ #include "executor/execdebug.h" #include "executor/nodeIndexonlyscan.h" #include "executor/nodeIndexscan.h" +#include "miscadmin.h" #include "storage/bufmgr.h" #include "storage/predicate.h" #include "utils/memutils.h" @@ -117,6 +118,8 @@ IndexOnlyNext(IndexOnlyScanState *node) { HeapTuple tuple = NULL; + CHECK_FOR_INTERRUPTS(); + /* * We can skip the heap fetch if the TID references a heap page on * which all tuples are known visible to everybody. In any case, diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index 75b10115f5..6704ede995 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -34,6 +34,7 @@ #include "executor/execdebug.h" #include "executor/nodeIndexscan.h" #include "lib/pairingheap.h" +#include "miscadmin.h" #include "nodes/nodeFuncs.h" #include "optimizer/clauses.h" #include "utils/array.h" @@ -131,6 +132,8 @@ IndexNext(IndexScanState *node) */ while ((tuple = index_getnext(scandesc, direction)) != NULL) { + CHECK_FOR_INTERRUPTS(); + /* * Store the scanned tuple in the scan tuple slot of the scan state. * Note: we pass 'false' because tuples returned by amgetnext are @@ -233,6 +236,8 @@ IndexNextWithReorder(IndexScanState *node) for (;;) { + CHECK_FOR_INTERRUPTS(); + /* * Check the reorder queue first. If the topmost tuple in the queue * has an ORDER BY value smaller than (or equal to) the value last @@ -299,6 +304,8 @@ next_indextuple: { /* Fails recheck, so drop it and loop back for another */ InstrCountFiltered2(node, 1); + /* allow this loop to be cancellable */ + CHECK_FOR_INTERRUPTS(); goto next_indextuple; } } diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c index abd060d75f..2ed3523257 100644 --- a/src/backend/executor/nodeLimit.c +++ b/src/backend/executor/nodeLimit.c @@ -23,6 +23,7 @@ #include "executor/executor.h" #include "executor/nodeLimit.h" +#include "miscadmin.h" #include "nodes/nodeFuncs.h" static void recompute_limits(LimitState *node); @@ -43,6 +44,8 @@ ExecLimit(LimitState *node) TupleTableSlot *slot; PlanState *outerPlan; + CHECK_FOR_INTERRUPTS(); + /* * get information from the node */ diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c index f519794cf3..dd4e2c5f2f 100644 --- a/src/backend/executor/nodeLockRows.c +++ b/src/backend/executor/nodeLockRows.c @@ -26,6 +26,7 @@ #include "executor/executor.h" #include "executor/nodeLockRows.h" #include "foreign/fdwapi.h" +#include "miscadmin.h" #include "storage/bufmgr.h" #include "utils/rel.h" #include "utils/tqual.h" @@ -44,6 +45,8 @@ ExecLockRows(LockRowsState *node) bool epq_needed; ListCell *lc; + CHECK_FOR_INTERRUPTS(); + /* * get information from the node */ diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c index 32b7269cda..3342949590 100644 --- a/src/backend/executor/nodeMaterial.c +++ b/src/backend/executor/nodeMaterial.c @@ -45,6 +45,8 @@ ExecMaterial(MaterialState *node) bool eof_tuplestore; TupleTableSlot *slot; + CHECK_FOR_INTERRUPTS(); + /* * get state info from node */ diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c index fef83dbdbd..d41def1350 100644 --- a/src/backend/executor/nodeMergeAppend.c +++ b/src/backend/executor/nodeMergeAppend.c @@ -40,8 +40,8 @@ #include "executor/execdebug.h" #include "executor/nodeMergeAppend.h" - #include "lib/binaryheap.h" +#include "miscadmin.h" /* * We have one slot for each item in the heap array. We use SlotNumber @@ -175,6 +175,8 @@ ExecMergeAppend(MergeAppendState *node) TupleTableSlot *result; SlotNumber i; + CHECK_FOR_INTERRUPTS(); + if (!node->ms_initialized) { /* diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c index 6a145ee33a..324b61b8c0 100644 --- a/src/backend/executor/nodeMergejoin.c +++ b/src/backend/executor/nodeMergejoin.c @@ -95,6 +95,7 @@ #include "access/nbtree.h" #include "executor/execdebug.h" #include "executor/nodeMergejoin.h" +#include "miscadmin.h" #include "utils/lsyscache.h" #include "utils/memutils.h" @@ -610,6 +611,8 @@ ExecMergeJoin(MergeJoinState *node) bool doFillOuter; bool doFillInner; + CHECK_FOR_INTERRUPTS(); + /* * get information from node */ diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 77ba15dd90..637a582e1c 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -1551,6 +1551,8 @@ ExecModifyTable(ModifyTableState *node) HeapTupleData oldtupdata; HeapTuple oldtuple; + CHECK_FOR_INTERRUPTS(); + /* * This should NOT get called during EvalPlanQual; we should have passed a * subplan tree to EvalPlanQual, instead. Use a runtime test not just diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c index 0065fe601e..bedc374ef0 100644 --- a/src/backend/executor/nodeNestloop.c +++ b/src/backend/executor/nodeNestloop.c @@ -23,6 +23,7 @@ #include "executor/execdebug.h" #include "executor/nodeNestloop.h" +#include "miscadmin.h" #include "utils/memutils.h" @@ -69,6 +70,8 @@ ExecNestLoop(NestLoopState *node) ExprContext *econtext; ListCell *lc; + CHECK_FOR_INTERRUPTS(); + /* * get information from the node */ diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c index 01048cc826..3b69c7adee 100644 --- a/src/backend/executor/nodeProjectSet.c +++ b/src/backend/executor/nodeProjectSet.c @@ -24,6 +24,7 @@ #include "executor/executor.h" #include "executor/nodeProjectSet.h" +#include "miscadmin.h" #include "nodes/nodeFuncs.h" #include "utils/memutils.h" @@ -46,6 +47,8 @@ ExecProjectSet(ProjectSetState *node) PlanState *outerPlan; ExprContext *econtext; + CHECK_FOR_INTERRUPTS(); + econtext = node->ps.ps_ExprContext; /* diff --git a/src/backend/executor/nodeRecursiveunion.c b/src/backend/executor/nodeRecursiveunion.c index fc1c00d68f..2802fffa2b 100644 --- a/src/backend/executor/nodeRecursiveunion.c +++ b/src/backend/executor/nodeRecursiveunion.c @@ -75,6 +75,8 @@ ExecRecursiveUnion(RecursiveUnionState *node) TupleTableSlot *slot; bool isnew; + CHECK_FOR_INTERRUPTS(); + /* 1. Evaluate non-recursive term */ if (!node->recursing) { diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c index a753a53419..f007f46784 100644 --- a/src/backend/executor/nodeResult.c +++ b/src/backend/executor/nodeResult.c @@ -47,6 +47,7 @@ #include "executor/executor.h" #include "executor/nodeResult.h" +#include "miscadmin.h" #include "utils/memutils.h" @@ -70,6 +71,8 @@ ExecResult(ResultState *node) PlanState *outerPlan; ExprContext *econtext; + CHECK_FOR_INTERRUPTS(); + econtext = node->ps.ps_ExprContext; /* diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c index 9c7812e519..56c5643f17 100644 --- a/src/backend/executor/nodeSetOp.c +++ b/src/backend/executor/nodeSetOp.c @@ -47,6 +47,7 @@ #include "access/htup_details.h" #include "executor/executor.h" #include "executor/nodeSetOp.h" +#include "miscadmin.h" #include "utils/memutils.h" @@ -185,6 +186,8 @@ ExecSetOp(SetOpState *node) SetOp *plannode = (SetOp *) node->ps.plan; TupleTableSlot *resultTupleSlot = node->ps.ps_ResultTupleSlot; + CHECK_FOR_INTERRUPTS(); + /* * If the previously-returned tuple needs to be returned more than once, * keep returning it. @@ -428,6 +431,8 @@ setop_retrieve_hash_table(SetOpState *setopstate) */ while (!setopstate->setop_done) { + CHECK_FOR_INTERRUPTS(); + /* * Find the next entry in the hash table */ diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c index 924b458df8..799a4e9204 100644 --- a/src/backend/executor/nodeSort.c +++ b/src/backend/executor/nodeSort.c @@ -43,6 +43,8 @@ ExecSort(SortState *node) Tuplesortstate *tuplesortstate; TupleTableSlot *slot; + CHECK_FOR_INTERRUPTS(); + /* * get state info from node */ diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index e8fa4c8547..fe10e809df 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -33,6 +33,7 @@ #include "executor/executor.h" #include "executor/nodeSubplan.h" #include "nodes/makefuncs.h" +#include "miscadmin.h" #include "optimizer/clauses.h" #include "utils/array.h" #include "utils/lsyscache.h" @@ -65,6 +66,8 @@ ExecSubPlan(SubPlanState *node, { SubPlan *subplan = node->subplan; + CHECK_FOR_INTERRUPTS(); + /* Set non-null as default */ *isNull = false; @@ -618,6 +621,8 @@ findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot, InitTupleHashIterator(hashtable, &hashiter); while ((entry = ScanTupleHashTable(hashtable, &hashiter)) != NULL) { + CHECK_FOR_INTERRUPTS(); + ExecStoreMinimalTuple(entry->firstTuple, hashtable->tableslot, false); if (!execTuplesUnequal(slot, hashtable->tableslot, numCols, keyColIdx, diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c index bb016ec8f6..2859363fe2 100644 --- a/src/backend/executor/nodeTableFuncscan.c +++ b/src/backend/executor/nodeTableFuncscan.c @@ -440,6 +440,8 @@ tfuncLoadRows(TableFuncScanState *tstate, ExprContext *econtext) ListCell *cell = list_head(tstate->coldefexprs); int colno; + CHECK_FOR_INTERRUPTS(); + ExecClearTuple(tstate->ss.ss_ScanTupleSlot); /* diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c index 96af2d21d9..c122473bdf 100644 --- a/src/backend/executor/nodeTidscan.c +++ b/src/backend/executor/nodeTidscan.c @@ -26,6 +26,7 @@ #include "catalog/pg_type.h" #include "executor/execdebug.h" #include "executor/nodeTidscan.h" +#include "miscadmin.h" #include "optimizer/clauses.h" #include "storage/bufmgr.h" #include "utils/array.h" @@ -400,6 +401,8 @@ TidNext(TidScanState *node) node->tss_TidPtr--; else node->tss_TidPtr++; + + CHECK_FOR_INTERRUPTS(); } /* diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c index 28cc1e90f8..db78c88368 100644 --- a/src/backend/executor/nodeUnique.c +++ b/src/backend/executor/nodeUnique.c @@ -35,6 +35,7 @@ #include "executor/executor.h" #include "executor/nodeUnique.h" +#include "miscadmin.h" #include "utils/memutils.h" @@ -50,6 +51,8 @@ ExecUnique(UniqueState *node) TupleTableSlot *slot; PlanState *outerPlan; + CHECK_FOR_INTERRUPTS(); + /* * get information from the node */ diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index 8f13fe0c73..9da35ac506 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -1594,6 +1594,8 @@ ExecWindowAgg(WindowAggState *winstate) int i; int numfuncs; + CHECK_FOR_INTERRUPTS(); + if (winstate->all_done) return NULL; @@ -2371,6 +2373,9 @@ window_gettupleslot(WindowObject winobj, int64 pos, TupleTableSlot *slot) WindowAggState *winstate = winobj->winstate; MemoryContext oldcontext; + /* often called repeatedly in a row */ + CHECK_FOR_INTERRUPTS(); + /* Don't allow passing -1 to spool_tuples here */ if (pos < 0) return false; -- cgit v1.2.3 From cc9f08b6b813e30789100b6b34110d8be1090ba0 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Mon, 17 Jul 2017 00:33:49 -0700 Subject: Move ExecProcNode from dispatch to function pointer based model. This allows us to add stack-depth checks the first time an executor node is called, and skip that overhead on following calls. Additionally it yields a nice speedup. While it'd probably have been a good idea to have that check all along, it has become more important after the new expression evaluation framework in b8d7f053c5c2bf2a7e - there's no stack depth check in common paths anymore now. We previously relied on ExecEvalExpr() being executed somewhere. We should move towards that model for further routines, but as this is required for v10, it seems better to only do the necessary (which already is quite large). Author: Andres Freund, Tom Lane Reported-By: Julien Rouhaud Discussion: https://postgr.es/m/22833.1490390175@sss.pgh.pa.us https://postgr.es/m/b0af9eaa-130c-60d0-9e4e-7a135b1e0c76@dalibo.com --- src/backend/executor/execProcnode.c | 252 +++++++------------------ src/backend/executor/nodeAgg.c | 6 +- src/backend/executor/nodeAppend.c | 8 +- src/backend/executor/nodeBitmapAnd.c | 14 ++ src/backend/executor/nodeBitmapHeapscan.c | 7 +- src/backend/executor/nodeBitmapIndexscan.c | 14 ++ src/backend/executor/nodeBitmapOr.c | 14 ++ src/backend/executor/nodeCtescan.c | 7 +- src/backend/executor/nodeCustom.c | 11 +- src/backend/executor/nodeForeignscan.c | 9 +- src/backend/executor/nodeFunctionscan.c | 7 +- src/backend/executor/nodeGather.c | 7 +- src/backend/executor/nodeGatherMerge.c | 7 +- src/backend/executor/nodeGroup.c | 6 +- src/backend/executor/nodeHash.c | 5 +- src/backend/executor/nodeHashjoin.c | 6 +- src/backend/executor/nodeIndexonlyscan.c | 7 +- src/backend/executor/nodeIndexscan.c | 7 +- src/backend/executor/nodeLimit.c | 6 +- src/backend/executor/nodeLockRows.c | 6 +- src/backend/executor/nodeMaterial.c | 6 +- src/backend/executor/nodeMergeAppend.c | 7 +- src/backend/executor/nodeMergejoin.c | 6 +- src/backend/executor/nodeModifyTable.c | 6 +- src/backend/executor/nodeNamedtuplestorescan.c | 7 +- src/backend/executor/nodeNestloop.c | 6 +- src/backend/executor/nodeProjectSet.c | 6 +- src/backend/executor/nodeRecursiveunion.c | 6 +- src/backend/executor/nodeResult.c | 6 +- src/backend/executor/nodeSamplescan.c | 9 +- src/backend/executor/nodeSeqscan.c | 9 +- src/backend/executor/nodeSetOp.c | 6 +- src/backend/executor/nodeSort.c | 6 +- src/backend/executor/nodeSubqueryscan.c | 7 +- src/backend/executor/nodeTableFuncscan.c | 7 +- src/backend/executor/nodeTidscan.c | 7 +- src/backend/executor/nodeUnique.c | 6 +- src/backend/executor/nodeValuesscan.c | 7 +- src/backend/executor/nodeWindowAgg.c | 6 +- src/backend/executor/nodeWorktablescan.c | 7 +- src/include/executor/executor.h | 21 ++- src/include/executor/nodeAgg.h | 1 - src/include/executor/nodeAppend.h | 1 - src/include/executor/nodeBitmapHeapscan.h | 1 - src/include/executor/nodeCtescan.h | 1 - src/include/executor/nodeCustom.h | 1 - src/include/executor/nodeForeignscan.h | 1 - src/include/executor/nodeFunctionscan.h | 1 - src/include/executor/nodeGather.h | 1 - src/include/executor/nodeGatherMerge.h | 1 - src/include/executor/nodeGroup.h | 1 - src/include/executor/nodeHash.h | 1 - src/include/executor/nodeHashjoin.h | 1 - src/include/executor/nodeIndexonlyscan.h | 1 - src/include/executor/nodeIndexscan.h | 1 - src/include/executor/nodeLimit.h | 1 - src/include/executor/nodeLockRows.h | 1 - src/include/executor/nodeMaterial.h | 1 - src/include/executor/nodeMergeAppend.h | 1 - src/include/executor/nodeMergejoin.h | 1 - src/include/executor/nodeModifyTable.h | 1 - src/include/executor/nodeNamedtuplestorescan.h | 1 - src/include/executor/nodeNestloop.h | 1 - src/include/executor/nodeProjectSet.h | 1 - src/include/executor/nodeRecursiveunion.h | 1 - src/include/executor/nodeResult.h | 1 - src/include/executor/nodeSamplescan.h | 1 - src/include/executor/nodeSeqscan.h | 1 - src/include/executor/nodeSetOp.h | 1 - src/include/executor/nodeSort.h | 1 - src/include/executor/nodeSubqueryscan.h | 1 - src/include/executor/nodeTableFuncscan.h | 1 - src/include/executor/nodeTidscan.h | 1 - src/include/executor/nodeUnique.h | 1 - src/include/executor/nodeValuesscan.h | 1 - src/include/executor/nodeWindowAgg.h | 1 - src/include/executor/nodeWorktablescan.h | 1 - src/include/nodes/execnodes.h | 16 ++ 78 files changed, 313 insertions(+), 299 deletions(-) (limited to 'src/backend/executor/nodeModifyTable.c') diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 20fd9f822e..396920c0a2 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -17,15 +17,10 @@ *------------------------------------------------------------------------- */ /* - * INTERFACE ROUTINES - * ExecInitNode - initialize a plan node and its subplans - * ExecProcNode - get a tuple by executing the plan node - * ExecEndNode - shut down a plan node and its subplans - * * NOTES * This used to be three files. It is now all combined into - * one file so that it is easier to keep ExecInitNode, ExecProcNode, - * and ExecEndNode in sync when new nodes are added. + * one file so that it is easier to keep the dispatch routines + * in sync when new nodes are added. * * EXAMPLE * Suppose we want the age of the manager of the shoe department and @@ -122,6 +117,10 @@ #include "miscadmin.h" +static TupleTableSlot *ExecProcNodeFirst(PlanState *node); +static TupleTableSlot *ExecProcNodeInstr(PlanState *node); + + /* ------------------------------------------------------------------------ * ExecInitNode * @@ -149,6 +148,13 @@ ExecInitNode(Plan *node, EState *estate, int eflags) if (node == NULL) return NULL; + /* + * Make sure there's enough stack available. Need to check here, in + * addition to ExecProcNode() (via ExecProcNodeFirst()), to ensure the + * stack isn't overrun while initializing the node tree. + */ + check_stack_depth(); + switch (nodeTag(node)) { /* @@ -364,6 +370,13 @@ ExecInitNode(Plan *node, EState *estate, int eflags) break; } + /* + * Add a wrapper around the ExecProcNode callback that checks stack depth + * during the first execution. + */ + result->ExecProcNodeReal = result->ExecProcNode; + result->ExecProcNode = ExecProcNodeFirst; + /* * Initialize any initPlans present in this node. The planner put them in * a separate list for us. @@ -388,195 +401,51 @@ ExecInitNode(Plan *node, EState *estate, int eflags) } -/* ---------------------------------------------------------------- - * ExecProcNode - * - * Execute the given node to return a(nother) tuple. - * ---------------------------------------------------------------- +/* + * ExecProcNode wrapper that performs some one-time checks, before calling + * the relevant node method (possibly via an instrumentation wrapper). */ -TupleTableSlot * -ExecProcNode(PlanState *node) +static TupleTableSlot * +ExecProcNodeFirst(PlanState *node) { - TupleTableSlot *result; - - if (node->chgParam != NULL) /* something changed */ - ExecReScan(node); /* let ReScan handle this */ + /* + * Perform stack depth check during the first execution of the node. We + * only do so the first time round because it turns out to not be cheap on + * some common architectures (eg. x86). This relies on the assumption that + * ExecProcNode calls for a given plan node will always be made at roughly + * the same stack depth. + */ + check_stack_depth(); + /* + * If instrumentation is required, change the wrapper to one that just + * does instrumentation. Otherwise we can dispense with all wrappers and + * have ExecProcNode() directly call the relevant function from now on. + */ if (node->instrument) - InstrStartNode(node->instrument); - - switch (nodeTag(node)) - { - /* - * control nodes - */ - case T_ResultState: - result = ExecResult((ResultState *) node); - break; - - case T_ProjectSetState: - result = ExecProjectSet((ProjectSetState *) 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_SampleScanState: - result = ExecSampleScan((SampleScanState *) 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_TableFuncScanState: - result = ExecTableFuncScan((TableFuncScanState *) node); - break; - - case T_ValuesScanState: - result = ExecValuesScan((ValuesScanState *) node); - break; - - case T_CteScanState: - result = ExecCteScan((CteScanState *) node); - break; - - case T_NamedTuplestoreScanState: - result = ExecNamedTuplestoreScan((NamedTuplestoreScanState *) node); - break; - - case T_WorkTableScanState: - result = ExecWorkTableScan((WorkTableScanState *) node); - break; - - case T_ForeignScanState: - result = ExecForeignScan((ForeignScanState *) node); - break; - - case T_CustomScanState: - result = ExecCustomScan((CustomScanState *) 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; + node->ExecProcNode = ExecProcNodeInstr; + else + node->ExecProcNode = node->ExecProcNodeReal; - 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_GatherState: - result = ExecGather((GatherState *) node); - break; - - case T_GatherMergeState: - result = ExecGatherMerge((GatherMergeState *) node); - break; - - case T_HashState: - result = ExecHash((HashState *) node); - break; + return node->ExecProcNode(node); +} - case T_SetOpState: - result = ExecSetOp((SetOpState *) node); - break; - case T_LockRowsState: - result = ExecLockRows((LockRowsState *) node); - break; +/* + * ExecProcNode wrapper that performs instrumentation calls. By keeping + * this a separate function, we avoid overhead in the normal case where + * no instrumentation is wanted. + */ +static TupleTableSlot * +ExecProcNodeInstr(PlanState *node) +{ + TupleTableSlot *result; - case T_LimitState: - result = ExecLimit((LimitState *) node); - break; + InstrStartNode(node->instrument); - default: - elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); - result = NULL; - break; - } + result = node->ExecProcNodeReal(node); - if (node->instrument) - InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0); + InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0); return result; } @@ -600,6 +469,8 @@ MultiExecProcNode(PlanState *node) { Node *result; + check_stack_depth(); + CHECK_FOR_INTERRUPTS(); if (node->chgParam != NULL) /* something changed */ @@ -657,6 +528,13 @@ ExecEndNode(PlanState *node) if (node == NULL) return; + /* + * Make sure there's enough stack available. Need to check here, in + * addition to ExecProcNode() (via ExecProcNodeFirst()), because it's not + * guaranteed that ExecProcNode() is reached for all nodes. + */ + check_stack_depth(); + if (node->chgParam != NULL) { bms_free(node->chgParam); @@ -855,6 +733,8 @@ ExecShutdownNode(PlanState *node) if (node == NULL) return false; + check_stack_depth(); + planstate_tree_walker(node, ExecShutdownNode, NULL); switch (nodeTag(node)) diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 377916dae7..6a26773a49 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -2099,9 +2099,10 @@ lookup_hash_entries(AggState *aggstate) * stored in the expression context to be used when ExecProject evaluates * the result tuple. */ -TupleTableSlot * -ExecAgg(AggState *node) +static TupleTableSlot * +ExecAgg(PlanState *pstate) { + AggState *node = castNode(AggState, pstate); TupleTableSlot *result = NULL; CHECK_FOR_INTERRUPTS(); @@ -2695,6 +2696,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) aggstate = makeNode(AggState); aggstate->ss.ps.plan = (Plan *) node; aggstate->ss.ps.state = estate; + aggstate->ss.ps.ExecProcNode = ExecAgg; aggstate->aggs = NIL; aggstate->numaggs = 0; diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index 58045e05e5..bed9bb8713 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -61,6 +61,7 @@ #include "executor/nodeAppend.h" #include "miscadmin.h" +static TupleTableSlot *ExecAppend(PlanState *pstate); static bool exec_append_initialize_next(AppendState *appendstate); @@ -147,6 +148,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags) */ appendstate->ps.plan = (Plan *) node; appendstate->ps.state = estate; + appendstate->ps.ExecProcNode = ExecAppend; appendstate->appendplans = appendplanstates; appendstate->as_nplans = nplans; @@ -197,9 +199,11 @@ ExecInitAppend(Append *node, EState *estate, int eflags) * Handles iteration over multiple subplans. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecAppend(AppendState *node) +static TupleTableSlot * +ExecAppend(PlanState *pstate) { + AppendState *node = castNode(AppendState, pstate); + for (;;) { PlanState *subnode; diff --git a/src/backend/executor/nodeBitmapAnd.c b/src/backend/executor/nodeBitmapAnd.c index e4eb028ff9..1c5c312c95 100644 --- a/src/backend/executor/nodeBitmapAnd.c +++ b/src/backend/executor/nodeBitmapAnd.c @@ -32,6 +32,19 @@ #include "executor/nodeBitmapAnd.h" +/* ---------------------------------------------------------------- + * ExecBitmapAnd + * + * stub for pro forma compliance + * ---------------------------------------------------------------- + */ +static TupleTableSlot * +ExecBitmapAnd(PlanState *pstate) +{ + elog(ERROR, "BitmapAnd node does not support ExecProcNode call convention"); + return NULL; +} + /* ---------------------------------------------------------------- * ExecInitBitmapAnd * @@ -63,6 +76,7 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags) */ bitmapandstate->ps.plan = (Plan *) node; bitmapandstate->ps.state = estate; + bitmapandstate->ps.ExecProcNode = ExecBitmapAnd; bitmapandstate->bitmapplans = bitmapplanstates; bitmapandstate->nplans = nplans; diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index cf109d5049..79f534e4e9 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -665,9 +665,11 @@ BitmapHeapRecheck(BitmapHeapScanState *node, TupleTableSlot *slot) * ExecBitmapHeapScan(node) * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecBitmapHeapScan(BitmapHeapScanState *node) +static TupleTableSlot * +ExecBitmapHeapScan(PlanState *pstate) { + BitmapHeapScanState *node = castNode(BitmapHeapScanState, pstate); + return ExecScan(&node->ss, (ExecScanAccessMtd) BitmapHeapNext, (ExecScanRecheckMtd) BitmapHeapRecheck); @@ -815,6 +817,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags) scanstate = makeNode(BitmapHeapScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; + scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan; scanstate->tbm = NULL; scanstate->tbmiterator = NULL; diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c index 2411a2e5c1..6feb70f4ae 100644 --- a/src/backend/executor/nodeBitmapIndexscan.c +++ b/src/backend/executor/nodeBitmapIndexscan.c @@ -28,6 +28,19 @@ #include "utils/memutils.h" +/* ---------------------------------------------------------------- + * ExecBitmapIndexScan + * + * stub for pro forma compliance + * ---------------------------------------------------------------- + */ +static TupleTableSlot * +ExecBitmapIndexScan(PlanState *pstate) +{ + elog(ERROR, "BitmapIndexScan node does not support ExecProcNode call convention"); + return NULL; +} + /* ---------------------------------------------------------------- * MultiExecBitmapIndexScan(node) * ---------------------------------------------------------------- @@ -208,6 +221,7 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags) indexstate = makeNode(BitmapIndexScanState); indexstate->ss.ps.plan = (Plan *) node; indexstate->ss.ps.state = estate; + indexstate->ss.ps.ExecProcNode = ExecBitmapIndexScan; /* normally we don't make the result bitmap till runtime */ indexstate->biss_result = NULL; diff --git a/src/backend/executor/nodeBitmapOr.c b/src/backend/executor/nodeBitmapOr.c index 4f0ddc6dff..66a7a89a8b 100644 --- a/src/backend/executor/nodeBitmapOr.c +++ b/src/backend/executor/nodeBitmapOr.c @@ -33,6 +33,19 @@ #include "miscadmin.h" +/* ---------------------------------------------------------------- + * ExecBitmapOr + * + * stub for pro forma compliance + * ---------------------------------------------------------------- + */ +static TupleTableSlot * +ExecBitmapOr(PlanState *pstate) +{ + elog(ERROR, "BitmapOr node does not support ExecProcNode call convention"); + return NULL; +} + /* ---------------------------------------------------------------- * ExecInitBitmapOr * @@ -64,6 +77,7 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags) */ bitmaporstate->ps.plan = (Plan *) node; bitmaporstate->ps.state = estate; + bitmaporstate->ps.ExecProcNode = ExecBitmapOr; bitmaporstate->bitmapplans = bitmapplanstates; bitmaporstate->nplans = nplans; diff --git a/src/backend/executor/nodeCtescan.c b/src/backend/executor/nodeCtescan.c index bed7949c5a..79676ca978 100644 --- a/src/backend/executor/nodeCtescan.c +++ b/src/backend/executor/nodeCtescan.c @@ -149,9 +149,11 @@ CteScanRecheck(CteScanState *node, TupleTableSlot *slot) * access method functions. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecCteScan(CteScanState *node) +static TupleTableSlot * +ExecCteScan(PlanState *pstate) { + CteScanState *node = castNode(CteScanState, pstate); + return ExecScan(&node->ss, (ExecScanAccessMtd) CteScanNext, (ExecScanRecheckMtd) CteScanRecheck); @@ -191,6 +193,7 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags) scanstate = makeNode(CteScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; + scanstate->ss.ps.ExecProcNode = ExecCteScan; scanstate->eflags = eflags; scanstate->cte_table = NULL; scanstate->eof_cte = false; diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c index fc15974a2d..fb7645b1f4 100644 --- a/src/backend/executor/nodeCustom.c +++ b/src/backend/executor/nodeCustom.c @@ -21,6 +21,10 @@ #include "utils/memutils.h" #include "utils/rel.h" + +static TupleTableSlot *ExecCustomScan(PlanState *pstate); + + CustomScanState * ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags) { @@ -45,6 +49,7 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags) /* fill up fields of ScanState */ css->ss.ps.plan = &cscan->scan.plan; css->ss.ps.state = estate; + css->ss.ps.ExecProcNode = ExecCustomScan; /* create expression context for node */ ExecAssignExprContext(estate, &css->ss.ps); @@ -102,9 +107,11 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags) return css; } -TupleTableSlot * -ExecCustomScan(CustomScanState *node) +static TupleTableSlot * +ExecCustomScan(PlanState *pstate) { + CustomScanState *node = castNode(CustomScanState, pstate); + CHECK_FOR_INTERRUPTS(); Assert(node->methods->ExecCustomScan != NULL); diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c index 9cde112554..140e82ef5e 100644 --- a/src/backend/executor/nodeForeignscan.c +++ b/src/backend/executor/nodeForeignscan.c @@ -113,10 +113,12 @@ ForeignRecheck(ForeignScanState *node, TupleTableSlot *slot) * access method functions. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecForeignScan(ForeignScanState *node) +static TupleTableSlot * +ExecForeignScan(PlanState *pstate) { - return ExecScan((ScanState *) node, + ForeignScanState *node = castNode(ForeignScanState, pstate); + + return ExecScan(&node->ss, (ExecScanAccessMtd) ForeignNext, (ExecScanRecheckMtd) ForeignRecheck); } @@ -144,6 +146,7 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags) scanstate = makeNode(ForeignScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; + scanstate->ss.ps.ExecProcNode = ExecForeignScan; /* * Miscellaneous initialization diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c index 3217d641d7..9f87a7e5cd 100644 --- a/src/backend/executor/nodeFunctionscan.c +++ b/src/backend/executor/nodeFunctionscan.c @@ -262,9 +262,11 @@ FunctionRecheck(FunctionScanState *node, TupleTableSlot *slot) * access method functions. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecFunctionScan(FunctionScanState *node) +static TupleTableSlot * +ExecFunctionScan(PlanState *pstate) { + FunctionScanState *node = castNode(FunctionScanState, pstate); + return ExecScan(&node->ss, (ExecScanAccessMtd) FunctionNext, (ExecScanRecheckMtd) FunctionRecheck); @@ -299,6 +301,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) scanstate = makeNode(FunctionScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; + scanstate->ss.ps.ExecProcNode = ExecFunctionScan; scanstate->eflags = eflags; /* diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c index 5dbe19c056..e8d94ee6f3 100644 --- a/src/backend/executor/nodeGather.c +++ b/src/backend/executor/nodeGather.c @@ -43,6 +43,7 @@ #include "utils/rel.h" +static TupleTableSlot *ExecGather(PlanState *pstate); static TupleTableSlot *gather_getnext(GatherState *gatherstate); static HeapTuple gather_readnext(GatherState *gatherstate); static void ExecShutdownGatherWorkers(GatherState *node); @@ -69,6 +70,7 @@ ExecInitGather(Gather *node, EState *estate, int eflags) gatherstate = makeNode(GatherState); gatherstate->ps.plan = (Plan *) node; gatherstate->ps.state = estate; + gatherstate->ps.ExecProcNode = ExecGather; gatherstate->need_to_scan_locally = !node->single_copy; /* @@ -120,9 +122,10 @@ ExecInitGather(Gather *node, EState *estate, int eflags) * the next qualifying tuple. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecGather(GatherState *node) +static TupleTableSlot * +ExecGather(PlanState *pstate) { + GatherState *node = castNode(GatherState, pstate); TupleTableSlot *fslot = node->funnel_slot; int i; TupleTableSlot *slot; diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c index 0aff3798f7..9a81e22510 100644 --- a/src/backend/executor/nodeGatherMerge.c +++ b/src/backend/executor/nodeGatherMerge.c @@ -44,6 +44,7 @@ typedef struct GMReaderTupleBuffer */ #define MAX_TUPLE_STORE 10 +static TupleTableSlot *ExecGatherMerge(PlanState *pstate); static int32 heap_compare_slots(Datum a, Datum b, void *arg); static TupleTableSlot *gather_merge_getnext(GatherMergeState *gm_state); static HeapTuple gm_readnext_tuple(GatherMergeState *gm_state, int nreader, @@ -75,6 +76,7 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags) gm_state = makeNode(GatherMergeState); gm_state->ps.plan = (Plan *) node; gm_state->ps.state = estate; + gm_state->ps.ExecProcNode = ExecGatherMerge; /* * Miscellaneous initialization @@ -157,9 +159,10 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags) * the next qualifying tuple. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecGatherMerge(GatherMergeState *node) +static TupleTableSlot * +ExecGatherMerge(PlanState *pstate) { + GatherMergeState *node = castNode(GatherMergeState, pstate); TupleTableSlot *slot; ExprContext *econtext; int i; diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c index fc5e0e59bc..ab4ae24a6b 100644 --- a/src/backend/executor/nodeGroup.c +++ b/src/backend/executor/nodeGroup.c @@ -32,9 +32,10 @@ * * Return one tuple for each group of matching input tuples. */ -TupleTableSlot * -ExecGroup(GroupState *node) +static TupleTableSlot * +ExecGroup(PlanState *pstate) { + GroupState *node = castNode(GroupState, pstate); ExprContext *econtext; int numCols; AttrNumber *grpColIdx; @@ -175,6 +176,7 @@ ExecInitGroup(Group *node, EState *estate, int eflags) grpstate = makeNode(GroupState); grpstate->ss.ps.plan = (Plan *) node; grpstate->ss.ps.state = estate; + grpstate->ss.ps.ExecProcNode = ExecGroup; grpstate->grp_done = FALSE; /* diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c index fbeb562489..d10d94ccc2 100644 --- a/src/backend/executor/nodeHash.c +++ b/src/backend/executor/nodeHash.c @@ -56,8 +56,8 @@ static void *dense_alloc(HashJoinTable hashtable, Size size); * stub for pro forma compliance * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecHash(HashState *node) +static TupleTableSlot * +ExecHash(PlanState *pstate) { elog(ERROR, "Hash node does not support ExecProcNode call convention"); return NULL; @@ -172,6 +172,7 @@ ExecInitHash(Hash *node, EState *estate, int eflags) hashstate = makeNode(HashState); hashstate->ps.plan = (Plan *) node; hashstate->ps.state = estate; + hashstate->ps.ExecProcNode = ExecHash; hashstate->hashtable = NULL; hashstate->hashkeys = NIL; /* will be set by parent HashJoin */ diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c index 252960c81c..ab1632cc13 100644 --- a/src/backend/executor/nodeHashjoin.c +++ b/src/backend/executor/nodeHashjoin.c @@ -58,9 +58,10 @@ static bool ExecHashJoinNewBatch(HashJoinState *hjstate); * the other one is "outer". * ---------------------------------------------------------------- */ -TupleTableSlot * /* return: a tuple or NULL */ -ExecHashJoin(HashJoinState *node) +static TupleTableSlot * /* return: a tuple or NULL */ +ExecHashJoin(PlanState *pstate) { + HashJoinState *node = castNode(HashJoinState, pstate); PlanState *outerNode; HashState *hashNode; ExprState *joinqual; @@ -399,6 +400,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags) hjstate = makeNode(HashJoinState); hjstate->js.ps.plan = (Plan *) node; hjstate->js.ps.state = estate; + hjstate->js.ps.ExecProcNode = ExecHashJoin; /* * Miscellaneous initialization diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index e2000764a4..fe7ba3f1a4 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -306,9 +306,11 @@ IndexOnlyRecheck(IndexOnlyScanState *node, TupleTableSlot *slot) * ExecIndexOnlyScan(node) * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecIndexOnlyScan(IndexOnlyScanState *node) +static TupleTableSlot * +ExecIndexOnlyScan(PlanState *pstate) { + IndexOnlyScanState *node = castNode(IndexOnlyScanState, pstate); + /* * If we have runtime keys and they've not already been set up, do it now. */ @@ -476,6 +478,7 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags) indexstate = makeNode(IndexOnlyScanState); indexstate->ss.ps.plan = (Plan *) node; indexstate->ss.ps.state = estate; + indexstate->ss.ps.ExecProcNode = ExecIndexOnlyScan; indexstate->ioss_HeapFetches = 0; /* diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index 6704ede995..404076d593 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -542,9 +542,11 @@ reorderqueue_pop(IndexScanState *node) * ExecIndexScan(node) * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecIndexScan(IndexScanState *node) +static TupleTableSlot * +ExecIndexScan(PlanState *pstate) { + IndexScanState *node = castNode(IndexScanState, pstate); + /* * If we have runtime keys and they've not already been set up, do it now. */ @@ -910,6 +912,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags) indexstate = makeNode(IndexScanState); indexstate->ss.ps.plan = (Plan *) node; indexstate->ss.ps.state = estate; + indexstate->ss.ps.ExecProcNode = ExecIndexScan; /* * Miscellaneous initialization diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c index 2ed3523257..ac5a2ff0e6 100644 --- a/src/backend/executor/nodeLimit.c +++ b/src/backend/executor/nodeLimit.c @@ -37,9 +37,10 @@ static void pass_down_bound(LimitState *node, PlanState *child_node); * filtering on the stream of tuples returned by a subplan. * ---------------------------------------------------------------- */ -TupleTableSlot * /* return: a tuple or NULL */ -ExecLimit(LimitState *node) +static TupleTableSlot * /* return: a tuple or NULL */ +ExecLimit(PlanState *pstate) { + LimitState *node = castNode(LimitState, pstate); ScanDirection direction; TupleTableSlot *slot; PlanState *outerPlan; @@ -378,6 +379,7 @@ ExecInitLimit(Limit *node, EState *estate, int eflags) limitstate = makeNode(LimitState); limitstate->ps.plan = (Plan *) node; limitstate->ps.state = estate; + limitstate->ps.ExecProcNode = ExecLimit; limitstate->lstate = LIMIT_INITIAL; diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c index dd4e2c5f2f..93895600a5 100644 --- a/src/backend/executor/nodeLockRows.c +++ b/src/backend/executor/nodeLockRows.c @@ -36,9 +36,10 @@ * ExecLockRows * ---------------------------------------------------------------- */ -TupleTableSlot * /* return: a tuple or NULL */ -ExecLockRows(LockRowsState *node) +static TupleTableSlot * /* return: a tuple or NULL */ +ExecLockRows(PlanState *pstate) { + LockRowsState *node = castNode(LockRowsState, pstate); TupleTableSlot *slot; EState *estate; PlanState *outerPlan; @@ -364,6 +365,7 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags) lrstate = makeNode(LockRowsState); lrstate->ps.plan = (Plan *) node; lrstate->ps.state = estate; + lrstate->ps.ExecProcNode = ExecLockRows; /* * Miscellaneous initialization diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c index 3342949590..91178f1019 100644 --- a/src/backend/executor/nodeMaterial.c +++ b/src/backend/executor/nodeMaterial.c @@ -35,9 +35,10 @@ * * ---------------------------------------------------------------- */ -TupleTableSlot * /* result tuple from subplan */ -ExecMaterial(MaterialState *node) +static TupleTableSlot * /* result tuple from subplan */ +ExecMaterial(PlanState *pstate) { + MaterialState *node = castNode(MaterialState, pstate); EState *estate; ScanDirection dir; bool forward; @@ -173,6 +174,7 @@ ExecInitMaterial(Material *node, EState *estate, int eflags) matstate = makeNode(MaterialState); matstate->ss.ps.plan = (Plan *) node; matstate->ss.ps.state = estate; + matstate->ss.ps.ExecProcNode = ExecMaterial; /* * We must have a tuplestore buffering the subplan output to do backward diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c index d41def1350..6bf490bd70 100644 --- a/src/backend/executor/nodeMergeAppend.c +++ b/src/backend/executor/nodeMergeAppend.c @@ -50,6 +50,7 @@ */ typedef int32 SlotNumber; +static TupleTableSlot *ExecMergeAppend(PlanState *pstate); static int heap_compare_slots(Datum a, Datum b, void *arg); @@ -89,6 +90,7 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags) */ mergestate->ps.plan = (Plan *) node; mergestate->ps.state = estate; + mergestate->ps.ExecProcNode = ExecMergeAppend; mergestate->mergeplans = mergeplanstates; mergestate->ms_nplans = nplans; @@ -169,9 +171,10 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags) * Handles iteration over multiple subplans. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecMergeAppend(MergeAppendState *node) +static TupleTableSlot * +ExecMergeAppend(PlanState *pstate) { + MergeAppendState *node = castNode(MergeAppendState, pstate); TupleTableSlot *result; SlotNumber i; diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c index 324b61b8c0..925b4cf553 100644 --- a/src/backend/executor/nodeMergejoin.c +++ b/src/backend/executor/nodeMergejoin.c @@ -596,9 +596,10 @@ ExecMergeTupleDump(MergeJoinState *mergestate) * ExecMergeJoin * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecMergeJoin(MergeJoinState *node) +static TupleTableSlot * +ExecMergeJoin(PlanState *pstate) { + MergeJoinState *node = castNode(MergeJoinState, pstate); ExprState *joinqual; ExprState *otherqual; bool qualResult; @@ -1448,6 +1449,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags) mergestate = makeNode(MergeJoinState); mergestate->js.ps.plan = (Plan *) node; mergestate->js.ps.state = estate; + mergestate->js.ps.ExecProcNode = ExecMergeJoin; /* * Miscellaneous initialization diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 637a582e1c..0dde0ed6eb 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -1535,9 +1535,10 @@ ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate) * if needed. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecModifyTable(ModifyTableState *node) +static TupleTableSlot * +ExecModifyTable(PlanState *pstate) { + ModifyTableState *node = castNode(ModifyTableState, pstate); EState *estate = node->ps.state; CmdType operation = node->operation; ResultRelInfo *saved_resultRelInfo; @@ -1806,6 +1807,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) mtstate = makeNode(ModifyTableState); mtstate->ps.plan = (Plan *) node; mtstate->ps.state = estate; + mtstate->ps.ExecProcNode = ExecModifyTable; mtstate->operation = operation; mtstate->canSetTag = node->canSetTag; diff --git a/src/backend/executor/nodeNamedtuplestorescan.c b/src/backend/executor/nodeNamedtuplestorescan.c index 62234869ab..3a65b9f5dc 100644 --- a/src/backend/executor/nodeNamedtuplestorescan.c +++ b/src/backend/executor/nodeNamedtuplestorescan.c @@ -63,9 +63,11 @@ NamedTuplestoreScanRecheck(NamedTuplestoreScanState *node, TupleTableSlot *slot) * access method functions. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecNamedTuplestoreScan(NamedTuplestoreScanState *node) +static TupleTableSlot * +ExecNamedTuplestoreScan(PlanState *pstate) { + NamedTuplestoreScanState *node = castNode(NamedTuplestoreScanState, pstate); + return ExecScan(&node->ss, (ExecScanAccessMtd) NamedTuplestoreScanNext, (ExecScanRecheckMtd) NamedTuplestoreScanRecheck); @@ -97,6 +99,7 @@ ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflag scanstate = makeNode(NamedTuplestoreScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; + scanstate->ss.ps.ExecProcNode = ExecNamedTuplestoreScan; enr = get_ENR(estate->es_queryEnv, node->enrname); if (!enr) diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c index bedc374ef0..4447b7c051 100644 --- a/src/backend/executor/nodeNestloop.c +++ b/src/backend/executor/nodeNestloop.c @@ -57,9 +57,10 @@ * are prepared to return the first tuple. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecNestLoop(NestLoopState *node) +static TupleTableSlot * +ExecNestLoop(PlanState *pstate) { + NestLoopState *node = castNode(NestLoopState, pstate); NestLoop *nl; PlanState *innerPlan; PlanState *outerPlan; @@ -275,6 +276,7 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags) nlstate = makeNode(NestLoopState); nlstate->js.ps.plan = (Plan *) node; nlstate->js.ps.state = estate; + nlstate->js.ps.ExecProcNode = ExecNestLoop; /* * Miscellaneous initialization diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c index 3b69c7adee..d93462c542 100644 --- a/src/backend/executor/nodeProjectSet.c +++ b/src/backend/executor/nodeProjectSet.c @@ -39,9 +39,10 @@ static TupleTableSlot *ExecProjectSRF(ProjectSetState *node, bool continuing); * returning functions). * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecProjectSet(ProjectSetState *node) +static TupleTableSlot * +ExecProjectSet(PlanState *pstate) { + ProjectSetState *node = castNode(ProjectSetState, pstate); TupleTableSlot *outerTupleSlot; TupleTableSlot *resultSlot; PlanState *outerPlan; @@ -215,6 +216,7 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags) state = makeNode(ProjectSetState); state->ps.plan = (Plan *) node; state->ps.state = estate; + state->ps.ExecProcNode = ExecProjectSet; state->pending_srf_tuples = false; diff --git a/src/backend/executor/nodeRecursiveunion.c b/src/backend/executor/nodeRecursiveunion.c index 2802fffa2b..a64dd1397a 100644 --- a/src/backend/executor/nodeRecursiveunion.c +++ b/src/backend/executor/nodeRecursiveunion.c @@ -66,9 +66,10 @@ build_hash_table(RecursiveUnionState *rustate) * 2.6 go back to 2.2 * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecRecursiveUnion(RecursiveUnionState *node) +static TupleTableSlot * +ExecRecursiveUnion(PlanState *pstate) { + RecursiveUnionState *node = castNode(RecursiveUnionState, pstate); PlanState *outerPlan = outerPlanState(node); PlanState *innerPlan = innerPlanState(node); RecursiveUnion *plan = (RecursiveUnion *) node->ps.plan; @@ -172,6 +173,7 @@ ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags) rustate = makeNode(RecursiveUnionState); rustate->ps.plan = (Plan *) node; rustate->ps.state = estate; + rustate->ps.ExecProcNode = ExecRecursiveUnion; rustate->eqfunctions = NULL; rustate->hashfunctions = NULL; diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c index f007f46784..4c879d8765 100644 --- a/src/backend/executor/nodeResult.c +++ b/src/backend/executor/nodeResult.c @@ -64,9 +64,10 @@ * 'nil' if the constant qualification is not satisfied. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecResult(ResultState *node) +static TupleTableSlot * +ExecResult(PlanState *pstate) { + ResultState *node = castNode(ResultState, pstate); TupleTableSlot *outerTupleSlot; PlanState *outerPlan; ExprContext *econtext; @@ -191,6 +192,7 @@ ExecInitResult(Result *node, EState *estate, int eflags) resstate = makeNode(ResultState); resstate->ps.plan = (Plan *) node; resstate->ps.state = estate; + resstate->ps.ExecProcNode = ExecResult; resstate->rs_done = false; resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true; diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c index b710ef7edf..9c74a836e4 100644 --- a/src/backend/executor/nodeSamplescan.c +++ b/src/backend/executor/nodeSamplescan.c @@ -96,10 +96,12 @@ SampleRecheck(SampleScanState *node, TupleTableSlot *slot) * access method functions. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecSampleScan(SampleScanState *node) +static TupleTableSlot * +ExecSampleScan(PlanState *pstate) { - return ExecScan((ScanState *) node, + SampleScanState *node = castNode(SampleScanState, pstate); + + return ExecScan(&node->ss, (ExecScanAccessMtd) SampleNext, (ExecScanRecheckMtd) SampleRecheck); } @@ -153,6 +155,7 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags) scanstate = makeNode(SampleScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; + scanstate->ss.ps.ExecProcNode = ExecSampleScan; /* * Miscellaneous initialization diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c index 307df87c82..5c49d4ca8a 100644 --- a/src/backend/executor/nodeSeqscan.c +++ b/src/backend/executor/nodeSeqscan.c @@ -121,10 +121,12 @@ SeqRecheck(SeqScanState *node, TupleTableSlot *slot) * access method functions. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecSeqScan(SeqScanState *node) +static TupleTableSlot * +ExecSeqScan(PlanState *pstate) { - return ExecScan((ScanState *) node, + SeqScanState *node = castNode(SeqScanState, pstate); + + return ExecScan(&node->ss, (ExecScanAccessMtd) SeqNext, (ExecScanRecheckMtd) SeqRecheck); } @@ -177,6 +179,7 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags) scanstate = makeNode(SeqScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; + scanstate->ss.ps.ExecProcNode = ExecSeqScan; /* * Miscellaneous initialization diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c index 56c5643f17..571cbf86b1 100644 --- a/src/backend/executor/nodeSetOp.c +++ b/src/backend/executor/nodeSetOp.c @@ -180,9 +180,10 @@ set_output_count(SetOpState *setopstate, SetOpStatePerGroup pergroup) * ExecSetOp * ---------------------------------------------------------------- */ -TupleTableSlot * /* return: a tuple or NULL */ -ExecSetOp(SetOpState *node) +static TupleTableSlot * /* return: a tuple or NULL */ +ExecSetOp(PlanState *pstate) { + SetOpState *node = castNode(SetOpState, pstate); SetOp *plannode = (SetOp *) node->ps.plan; TupleTableSlot *resultTupleSlot = node->ps.ps_ResultTupleSlot; @@ -485,6 +486,7 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags) setopstate = makeNode(SetOpState); setopstate->ps.plan = (Plan *) node; setopstate->ps.state = estate; + setopstate->ps.ExecProcNode = ExecSetOp; setopstate->eqfunctions = NULL; setopstate->hashfunctions = NULL; diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c index 799a4e9204..aae4150e2c 100644 --- a/src/backend/executor/nodeSort.c +++ b/src/backend/executor/nodeSort.c @@ -35,9 +35,10 @@ * -- the outer child is prepared to return the first tuple. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecSort(SortState *node) +static TupleTableSlot * +ExecSort(PlanState *pstate) { + SortState *node = castNode(SortState, pstate); EState *estate; ScanDirection dir; Tuplesortstate *tuplesortstate; @@ -165,6 +166,7 @@ ExecInitSort(Sort *node, EState *estate, int eflags) sortstate = makeNode(SortState); sortstate->ss.ps.plan = (Plan *) node; sortstate->ss.ps.state = estate; + sortstate->ss.ps.ExecProcNode = ExecSort; /* * We must have random access to the sort output to do backward scan or diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c index ae184700a6..088c92992e 100644 --- a/src/backend/executor/nodeSubqueryscan.c +++ b/src/backend/executor/nodeSubqueryscan.c @@ -79,9 +79,11 @@ SubqueryRecheck(SubqueryScanState *node, TupleTableSlot *slot) * access method functions. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecSubqueryScan(SubqueryScanState *node) +static TupleTableSlot * +ExecSubqueryScan(PlanState *pstate) { + SubqueryScanState *node = castNode(SubqueryScanState, pstate); + return ExecScan(&node->ss, (ExecScanAccessMtd) SubqueryNext, (ExecScanRecheckMtd) SubqueryRecheck); @@ -109,6 +111,7 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags) subquerystate = makeNode(SubqueryScanState); subquerystate->ss.ps.plan = (Plan *) node; subquerystate->ss.ps.state = estate; + subquerystate->ss.ps.ExecProcNode = ExecSubqueryScan; /* * Miscellaneous initialization diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c index 2859363fe2..b03d2ef762 100644 --- a/src/backend/executor/nodeTableFuncscan.c +++ b/src/backend/executor/nodeTableFuncscan.c @@ -93,9 +93,11 @@ TableFuncRecheck(TableFuncScanState *node, TupleTableSlot *slot) * access method functions. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecTableFuncScan(TableFuncScanState *node) +static TupleTableSlot * +ExecTableFuncScan(PlanState *pstate) { + TableFuncScanState *node = castNode(TableFuncScanState, pstate); + return ExecScan(&node->ss, (ExecScanAccessMtd) TableFuncNext, (ExecScanRecheckMtd) TableFuncRecheck); @@ -128,6 +130,7 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags) scanstate = makeNode(TableFuncScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; + scanstate->ss.ps.ExecProcNode = ExecTableFuncScan; /* * Miscellaneous initialization diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c index c122473bdf..0ee76e7d25 100644 --- a/src/backend/executor/nodeTidscan.c +++ b/src/backend/executor/nodeTidscan.c @@ -445,9 +445,11 @@ TidRecheck(TidScanState *node, TupleTableSlot *slot) * -- tidPtr is -1. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecTidScan(TidScanState *node) +static TupleTableSlot * +ExecTidScan(PlanState *pstate) { + TidScanState *node = castNode(TidScanState, pstate); + return ExecScan(&node->ss, (ExecScanAccessMtd) TidNext, (ExecScanRecheckMtd) TidRecheck); @@ -519,6 +521,7 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags) tidstate = makeNode(TidScanState); tidstate->ss.ps.plan = (Plan *) node; tidstate->ss.ps.state = estate; + tidstate->ss.ps.ExecProcNode = ExecTidScan; /* * Miscellaneous initialization diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c index db78c88368..621fdd9b9c 100644 --- a/src/backend/executor/nodeUnique.c +++ b/src/backend/executor/nodeUnique.c @@ -43,9 +43,10 @@ * ExecUnique * ---------------------------------------------------------------- */ -TupleTableSlot * /* return: a tuple or NULL */ -ExecUnique(UniqueState *node) +static TupleTableSlot * /* return: a tuple or NULL */ +ExecUnique(PlanState *pstate) { + UniqueState *node = castNode(UniqueState, pstate); Unique *plannode = (Unique *) node->ps.plan; TupleTableSlot *resultTupleSlot; TupleTableSlot *slot; @@ -125,6 +126,7 @@ ExecInitUnique(Unique *node, EState *estate, int eflags) uniquestate = makeNode(UniqueState); uniquestate->ps.plan = (Plan *) node; uniquestate->ps.state = estate; + uniquestate->ps.ExecProcNode = ExecUnique; /* * Miscellaneous initialization diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c index 9ee776c4c3..6eacaed8bb 100644 --- a/src/backend/executor/nodeValuesscan.c +++ b/src/backend/executor/nodeValuesscan.c @@ -185,9 +185,11 @@ ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot) * access method functions. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecValuesScan(ValuesScanState *node) +static TupleTableSlot * +ExecValuesScan(PlanState *pstate) { + ValuesScanState *node = castNode(ValuesScanState, pstate); + return ExecScan(&node->ss, (ExecScanAccessMtd) ValuesNext, (ExecScanRecheckMtd) ValuesRecheck); @@ -218,6 +220,7 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags) scanstate = makeNode(ValuesScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; + scanstate->ss.ps.ExecProcNode = ExecValuesScan; /* * Miscellaneous initialization diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index 9da35ac506..80be46029f 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -1587,9 +1587,10 @@ update_frametailpos(WindowObject winobj, TupleTableSlot *slot) * returned rows is exactly the same as its outer subplan's result. * ----------------- */ -TupleTableSlot * -ExecWindowAgg(WindowAggState *winstate) +static TupleTableSlot * +ExecWindowAgg(PlanState *pstate) { + WindowAggState *winstate = castNode(WindowAggState, pstate); ExprContext *econtext; int i; int numfuncs; @@ -1790,6 +1791,7 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags) winstate = makeNode(WindowAggState); winstate->ss.ps.plan = (Plan *) node; winstate->ss.ps.state = estate; + winstate->ss.ps.ExecProcNode = ExecWindowAgg; /* * Create expression contexts. We need two, one for per-input-tuple diff --git a/src/backend/executor/nodeWorktablescan.c b/src/backend/executor/nodeWorktablescan.c index d7616be065..d5ffadda3e 100644 --- a/src/backend/executor/nodeWorktablescan.c +++ b/src/backend/executor/nodeWorktablescan.c @@ -77,9 +77,11 @@ WorkTableScanRecheck(WorkTableScanState *node, TupleTableSlot *slot) * access method functions. * ---------------------------------------------------------------- */ -TupleTableSlot * -ExecWorkTableScan(WorkTableScanState *node) +static TupleTableSlot * +ExecWorkTableScan(PlanState *pstate) { + WorkTableScanState *node = castNode(WorkTableScanState, pstate); + /* * On the first call, find the ancestor RecursiveUnion's state via the * Param slot reserved for it. (We can't do this during node init because @@ -144,6 +146,7 @@ ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags) scanstate = makeNode(WorkTableScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; + scanstate->ss.ps.ExecProcNode = ExecWorkTableScan; scanstate->rustate = NULL; /* we'll set this later */ /* diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 59c28b709e..60326f9d03 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -225,14 +225,31 @@ extern void EvalPlanQualBegin(EPQState *epqstate, EState *parentestate); extern void EvalPlanQualEnd(EPQState *epqstate); /* - * prototypes from functions in execProcnode.c + * functions in execProcnode.c */ extern PlanState *ExecInitNode(Plan *node, EState *estate, int eflags); -extern TupleTableSlot *ExecProcNode(PlanState *node); extern Node *MultiExecProcNode(PlanState *node); extern void ExecEndNode(PlanState *node); extern bool ExecShutdownNode(PlanState *node); + +/* ---------------------------------------------------------------- + * ExecProcNode + * + * Execute the given node to return a(nother) tuple. + * ---------------------------------------------------------------- + */ +#ifndef FRONTEND +static inline TupleTableSlot * +ExecProcNode(PlanState *node) +{ + if (node->chgParam != NULL) /* something changed? */ + ExecReScan(node); /* let ReScan handle this */ + + return node->ExecProcNode(node); +} +#endif + /* * prototypes from functions in execExpr.c */ diff --git a/src/include/executor/nodeAgg.h b/src/include/executor/nodeAgg.h index fa11ba93a6..eff5af9c2a 100644 --- a/src/include/executor/nodeAgg.h +++ b/src/include/executor/nodeAgg.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern AggState *ExecInitAgg(Agg *node, EState *estate, int eflags); -extern TupleTableSlot *ExecAgg(AggState *node); extern void ExecEndAgg(AggState *node); extern void ExecReScanAgg(AggState *node); diff --git a/src/include/executor/nodeAppend.h b/src/include/executor/nodeAppend.h index ee0b6ad23d..4e38a1380e 100644 --- a/src/include/executor/nodeAppend.h +++ b/src/include/executor/nodeAppend.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern AppendState *ExecInitAppend(Append *node, EState *estate, int eflags); -extern TupleTableSlot *ExecAppend(AppendState *node); extern void ExecEndAppend(AppendState *node); extern void ExecReScanAppend(AppendState *node); diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h index f477d1c772..c77694cf22 100644 --- a/src/include/executor/nodeBitmapHeapscan.h +++ b/src/include/executor/nodeBitmapHeapscan.h @@ -18,7 +18,6 @@ #include "access/parallel.h" extern BitmapHeapScanState *ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags); -extern TupleTableSlot *ExecBitmapHeapScan(BitmapHeapScanState *node); extern void ExecEndBitmapHeapScan(BitmapHeapScanState *node); extern void ExecReScanBitmapHeapScan(BitmapHeapScanState *node); extern void ExecBitmapHeapEstimate(BitmapHeapScanState *node, diff --git a/src/include/executor/nodeCtescan.h b/src/include/executor/nodeCtescan.h index 397bdfdd1c..d2fbcbd586 100644 --- a/src/include/executor/nodeCtescan.h +++ b/src/include/executor/nodeCtescan.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern CteScanState *ExecInitCteScan(CteScan *node, EState *estate, int eflags); -extern TupleTableSlot *ExecCteScan(CteScanState *node); extern void ExecEndCteScan(CteScanState *node); extern void ExecReScanCteScan(CteScanState *node); diff --git a/src/include/executor/nodeCustom.h b/src/include/executor/nodeCustom.h index e81bcf7f21..a1cc63ae1f 100644 --- a/src/include/executor/nodeCustom.h +++ b/src/include/executor/nodeCustom.h @@ -21,7 +21,6 @@ */ extern CustomScanState *ExecInitCustomScan(CustomScan *custom_scan, EState *estate, int eflags); -extern TupleTableSlot *ExecCustomScan(CustomScanState *node); extern void ExecEndCustomScan(CustomScanState *node); extern void ExecReScanCustomScan(CustomScanState *node); diff --git a/src/include/executor/nodeForeignscan.h b/src/include/executor/nodeForeignscan.h index 3ff4ecd8c9..0b662597d8 100644 --- a/src/include/executor/nodeForeignscan.h +++ b/src/include/executor/nodeForeignscan.h @@ -18,7 +18,6 @@ #include "nodes/execnodes.h" extern ForeignScanState *ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags); -extern TupleTableSlot *ExecForeignScan(ForeignScanState *node); extern void ExecEndForeignScan(ForeignScanState *node); extern void ExecReScanForeignScan(ForeignScanState *node); diff --git a/src/include/executor/nodeFunctionscan.h b/src/include/executor/nodeFunctionscan.h index 5e830ebdea..aaa9d8c316 100644 --- a/src/include/executor/nodeFunctionscan.h +++ b/src/include/executor/nodeFunctionscan.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern FunctionScanState *ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags); -extern TupleTableSlot *ExecFunctionScan(FunctionScanState *node); extern void ExecEndFunctionScan(FunctionScanState *node); extern void ExecReScanFunctionScan(FunctionScanState *node); diff --git a/src/include/executor/nodeGather.h b/src/include/executor/nodeGather.h index b0006934d4..189bd70041 100644 --- a/src/include/executor/nodeGather.h +++ b/src/include/executor/nodeGather.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern GatherState *ExecInitGather(Gather *node, EState *estate, int eflags); -extern TupleTableSlot *ExecGather(GatherState *node); extern void ExecEndGather(GatherState *node); extern void ExecShutdownGather(GatherState *node); extern void ExecReScanGather(GatherState *node); diff --git a/src/include/executor/nodeGatherMerge.h b/src/include/executor/nodeGatherMerge.h index 14b31a086c..0154d73312 100644 --- a/src/include/executor/nodeGatherMerge.h +++ b/src/include/executor/nodeGatherMerge.h @@ -19,7 +19,6 @@ extern GatherMergeState *ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags); -extern TupleTableSlot *ExecGatherMerge(GatherMergeState *node); extern void ExecEndGatherMerge(GatherMergeState *node); extern void ExecReScanGatherMerge(GatherMergeState *node); extern void ExecShutdownGatherMerge(GatherMergeState *node); diff --git a/src/include/executor/nodeGroup.h b/src/include/executor/nodeGroup.h index 7358b61707..b0d7e312c9 100644 --- a/src/include/executor/nodeGroup.h +++ b/src/include/executor/nodeGroup.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern GroupState *ExecInitGroup(Group *node, EState *estate, int eflags); -extern TupleTableSlot *ExecGroup(GroupState *node); extern void ExecEndGroup(GroupState *node); extern void ExecReScanGroup(GroupState *node); diff --git a/src/include/executor/nodeHash.h b/src/include/executor/nodeHash.h index 8052f27d0b..3ae556fb6c 100644 --- a/src/include/executor/nodeHash.h +++ b/src/include/executor/nodeHash.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern HashState *ExecInitHash(Hash *node, EState *estate, int eflags); -extern TupleTableSlot *ExecHash(HashState *node); extern Node *MultiExecHash(HashState *node); extern void ExecEndHash(HashState *node); extern void ExecReScanHash(HashState *node); diff --git a/src/include/executor/nodeHashjoin.h b/src/include/executor/nodeHashjoin.h index 541c81edc7..7469bfbf60 100644 --- a/src/include/executor/nodeHashjoin.h +++ b/src/include/executor/nodeHashjoin.h @@ -18,7 +18,6 @@ #include "storage/buffile.h" extern HashJoinState *ExecInitHashJoin(HashJoin *node, EState *estate, int eflags); -extern TupleTableSlot *ExecHashJoin(HashJoinState *node); extern void ExecEndHashJoin(HashJoinState *node); extern void ExecReScanHashJoin(HashJoinState *node); diff --git a/src/include/executor/nodeIndexonlyscan.h b/src/include/executor/nodeIndexonlyscan.h index cf227daae0..c8a709c26e 100644 --- a/src/include/executor/nodeIndexonlyscan.h +++ b/src/include/executor/nodeIndexonlyscan.h @@ -18,7 +18,6 @@ #include "access/parallel.h" extern IndexOnlyScanState *ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags); -extern TupleTableSlot *ExecIndexOnlyScan(IndexOnlyScanState *node); extern void ExecEndIndexOnlyScan(IndexOnlyScanState *node); extern void ExecIndexOnlyMarkPos(IndexOnlyScanState *node); extern void ExecIndexOnlyRestrPos(IndexOnlyScanState *node); diff --git a/src/include/executor/nodeIndexscan.h b/src/include/executor/nodeIndexscan.h index 0118234eca..1668e347ee 100644 --- a/src/include/executor/nodeIndexscan.h +++ b/src/include/executor/nodeIndexscan.h @@ -18,7 +18,6 @@ #include "nodes/execnodes.h" extern IndexScanState *ExecInitIndexScan(IndexScan *node, EState *estate, int eflags); -extern TupleTableSlot *ExecIndexScan(IndexScanState *node); extern void ExecEndIndexScan(IndexScanState *node); extern void ExecIndexMarkPos(IndexScanState *node); extern void ExecIndexRestrPos(IndexScanState *node); diff --git a/src/include/executor/nodeLimit.h b/src/include/executor/nodeLimit.h index 7bb20d9978..db65b5524c 100644 --- a/src/include/executor/nodeLimit.h +++ b/src/include/executor/nodeLimit.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern LimitState *ExecInitLimit(Limit *node, EState *estate, int eflags); -extern TupleTableSlot *ExecLimit(LimitState *node); extern void ExecEndLimit(LimitState *node); extern void ExecReScanLimit(LimitState *node); diff --git a/src/include/executor/nodeLockRows.h b/src/include/executor/nodeLockRows.h index 6b90756e4c..c9d05b87f1 100644 --- a/src/include/executor/nodeLockRows.h +++ b/src/include/executor/nodeLockRows.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern LockRowsState *ExecInitLockRows(LockRows *node, EState *estate, int eflags); -extern TupleTableSlot *ExecLockRows(LockRowsState *node); extern void ExecEndLockRows(LockRowsState *node); extern void ExecReScanLockRows(LockRowsState *node); diff --git a/src/include/executor/nodeMaterial.h b/src/include/executor/nodeMaterial.h index f69abbca82..4b3c2578c9 100644 --- a/src/include/executor/nodeMaterial.h +++ b/src/include/executor/nodeMaterial.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern MaterialState *ExecInitMaterial(Material *node, EState *estate, int eflags); -extern TupleTableSlot *ExecMaterial(MaterialState *node); extern void ExecEndMaterial(MaterialState *node); extern void ExecMaterialMarkPos(MaterialState *node); extern void ExecMaterialRestrPos(MaterialState *node); diff --git a/src/include/executor/nodeMergeAppend.h b/src/include/executor/nodeMergeAppend.h index 3cc6ef549b..a0ccbae965 100644 --- a/src/include/executor/nodeMergeAppend.h +++ b/src/include/executor/nodeMergeAppend.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern MergeAppendState *ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags); -extern TupleTableSlot *ExecMergeAppend(MergeAppendState *node); extern void ExecEndMergeAppend(MergeAppendState *node); extern void ExecReScanMergeAppend(MergeAppendState *node); diff --git a/src/include/executor/nodeMergejoin.h b/src/include/executor/nodeMergejoin.h index 32df25ae8b..d20e41505d 100644 --- a/src/include/executor/nodeMergejoin.h +++ b/src/include/executor/nodeMergejoin.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern MergeJoinState *ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags); -extern TupleTableSlot *ExecMergeJoin(MergeJoinState *node); extern void ExecEndMergeJoin(MergeJoinState *node); extern void ExecReScanMergeJoin(MergeJoinState *node); diff --git a/src/include/executor/nodeModifyTable.h b/src/include/executor/nodeModifyTable.h index 5a406f236d..a2e7af98de 100644 --- a/src/include/executor/nodeModifyTable.h +++ b/src/include/executor/nodeModifyTable.h @@ -16,7 +16,6 @@ #include "nodes/execnodes.h" extern ModifyTableState *ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags); -extern TupleTableSlot *ExecModifyTable(ModifyTableState *node); extern void ExecEndModifyTable(ModifyTableState *node); extern void ExecReScanModifyTable(ModifyTableState *node); diff --git a/src/include/executor/nodeNamedtuplestorescan.h b/src/include/executor/nodeNamedtuplestorescan.h index 7f72fbe98a..395d978f62 100644 --- a/src/include/executor/nodeNamedtuplestorescan.h +++ b/src/include/executor/nodeNamedtuplestorescan.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern NamedTuplestoreScanState *ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflags); -extern TupleTableSlot *ExecNamedTuplestoreScan(NamedTuplestoreScanState *node); extern void ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node); extern void ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node); diff --git a/src/include/executor/nodeNestloop.h b/src/include/executor/nodeNestloop.h index 8e0fcc1922..0d6486cc57 100644 --- a/src/include/executor/nodeNestloop.h +++ b/src/include/executor/nodeNestloop.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern NestLoopState *ExecInitNestLoop(NestLoop *node, EState *estate, int eflags); -extern TupleTableSlot *ExecNestLoop(NestLoopState *node); extern void ExecEndNestLoop(NestLoopState *node); extern void ExecReScanNestLoop(NestLoopState *node); diff --git a/src/include/executor/nodeProjectSet.h b/src/include/executor/nodeProjectSet.h index 2f6999e8db..a0b0521f8d 100644 --- a/src/include/executor/nodeProjectSet.h +++ b/src/include/executor/nodeProjectSet.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern ProjectSetState *ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags); -extern TupleTableSlot *ExecProjectSet(ProjectSetState *node); extern void ExecEndProjectSet(ProjectSetState *node); extern void ExecReScanProjectSet(ProjectSetState *node); diff --git a/src/include/executor/nodeRecursiveunion.h b/src/include/executor/nodeRecursiveunion.h index f0eba05bee..e6ce1b4783 100644 --- a/src/include/executor/nodeRecursiveunion.h +++ b/src/include/executor/nodeRecursiveunion.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern RecursiveUnionState *ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags); -extern TupleTableSlot *ExecRecursiveUnion(RecursiveUnionState *node); extern void ExecEndRecursiveUnion(RecursiveUnionState *node); extern void ExecReScanRecursiveUnion(RecursiveUnionState *node); diff --git a/src/include/executor/nodeResult.h b/src/include/executor/nodeResult.h index 61d3cb2cc2..20e0063410 100644 --- a/src/include/executor/nodeResult.h +++ b/src/include/executor/nodeResult.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern ResultState *ExecInitResult(Result *node, EState *estate, int eflags); -extern TupleTableSlot *ExecResult(ResultState *node); extern void ExecEndResult(ResultState *node); extern void ExecResultMarkPos(ResultState *node); extern void ExecResultRestrPos(ResultState *node); diff --git a/src/include/executor/nodeSamplescan.h b/src/include/executor/nodeSamplescan.h index ed06e77e4e..607bbd9412 100644 --- a/src/include/executor/nodeSamplescan.h +++ b/src/include/executor/nodeSamplescan.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern SampleScanState *ExecInitSampleScan(SampleScan *node, EState *estate, int eflags); -extern TupleTableSlot *ExecSampleScan(SampleScanState *node); extern void ExecEndSampleScan(SampleScanState *node); extern void ExecReScanSampleScan(SampleScanState *node); diff --git a/src/include/executor/nodeSeqscan.h b/src/include/executor/nodeSeqscan.h index 06e0686b0b..0fba79f8de 100644 --- a/src/include/executor/nodeSeqscan.h +++ b/src/include/executor/nodeSeqscan.h @@ -18,7 +18,6 @@ #include "nodes/execnodes.h" extern SeqScanState *ExecInitSeqScan(SeqScan *node, EState *estate, int eflags); -extern TupleTableSlot *ExecSeqScan(SeqScanState *node); extern void ExecEndSeqScan(SeqScanState *node); extern void ExecReScanSeqScan(SeqScanState *node); diff --git a/src/include/executor/nodeSetOp.h b/src/include/executor/nodeSetOp.h index af85977183..c15f945046 100644 --- a/src/include/executor/nodeSetOp.h +++ b/src/include/executor/nodeSetOp.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern SetOpState *ExecInitSetOp(SetOp *node, EState *estate, int eflags); -extern TupleTableSlot *ExecSetOp(SetOpState *node); extern void ExecEndSetOp(SetOpState *node); extern void ExecReScanSetOp(SetOpState *node); diff --git a/src/include/executor/nodeSort.h b/src/include/executor/nodeSort.h index 1d2b7130b3..ed0e9dbb53 100644 --- a/src/include/executor/nodeSort.h +++ b/src/include/executor/nodeSort.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern SortState *ExecInitSort(Sort *node, EState *estate, int eflags); -extern TupleTableSlot *ExecSort(SortState *node); extern void ExecEndSort(SortState *node); extern void ExecSortMarkPos(SortState *node); extern void ExecSortRestrPos(SortState *node); diff --git a/src/include/executor/nodeSubqueryscan.h b/src/include/executor/nodeSubqueryscan.h index c852e2947f..710e050285 100644 --- a/src/include/executor/nodeSubqueryscan.h +++ b/src/include/executor/nodeSubqueryscan.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern SubqueryScanState *ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags); -extern TupleTableSlot *ExecSubqueryScan(SubqueryScanState *node); extern void ExecEndSubqueryScan(SubqueryScanState *node); extern void ExecReScanSubqueryScan(SubqueryScanState *node); diff --git a/src/include/executor/nodeTableFuncscan.h b/src/include/executor/nodeTableFuncscan.h index c58156e99c..c4672c0ac0 100644 --- a/src/include/executor/nodeTableFuncscan.h +++ b/src/include/executor/nodeTableFuncscan.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern TableFuncScanState *ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags); -extern TupleTableSlot *ExecTableFuncScan(TableFuncScanState *node); extern void ExecEndTableFuncScan(TableFuncScanState *node); extern void ExecReScanTableFuncScan(TableFuncScanState *node); diff --git a/src/include/executor/nodeTidscan.h b/src/include/executor/nodeTidscan.h index d07ed7c864..e68aaf3829 100644 --- a/src/include/executor/nodeTidscan.h +++ b/src/include/executor/nodeTidscan.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern TidScanState *ExecInitTidScan(TidScan *node, EState *estate, int eflags); -extern TupleTableSlot *ExecTidScan(TidScanState *node); extern void ExecEndTidScan(TidScanState *node); extern void ExecReScanTidScan(TidScanState *node); diff --git a/src/include/executor/nodeUnique.h b/src/include/executor/nodeUnique.h index 3d0ac9dde1..008774ae0f 100644 --- a/src/include/executor/nodeUnique.h +++ b/src/include/executor/nodeUnique.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern UniqueState *ExecInitUnique(Unique *node, EState *estate, int eflags); -extern TupleTableSlot *ExecUnique(UniqueState *node); extern void ExecEndUnique(UniqueState *node); extern void ExecReScanUnique(UniqueState *node); diff --git a/src/include/executor/nodeValuesscan.h b/src/include/executor/nodeValuesscan.h index c28bb1acce..772a5e9705 100644 --- a/src/include/executor/nodeValuesscan.h +++ b/src/include/executor/nodeValuesscan.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern ValuesScanState *ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags); -extern TupleTableSlot *ExecValuesScan(ValuesScanState *node); extern void ExecEndValuesScan(ValuesScanState *node); extern void ExecReScanValuesScan(ValuesScanState *node); diff --git a/src/include/executor/nodeWindowAgg.h b/src/include/executor/nodeWindowAgg.h index db1ad60677..1c177309ae 100644 --- a/src/include/executor/nodeWindowAgg.h +++ b/src/include/executor/nodeWindowAgg.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern WindowAggState *ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags); -extern TupleTableSlot *ExecWindowAgg(WindowAggState *node); extern void ExecEndWindowAgg(WindowAggState *node); extern void ExecReScanWindowAgg(WindowAggState *node); diff --git a/src/include/executor/nodeWorktablescan.h b/src/include/executor/nodeWorktablescan.h index c222d9f6b4..df05e75111 100644 --- a/src/include/executor/nodeWorktablescan.h +++ b/src/include/executor/nodeWorktablescan.h @@ -17,7 +17,6 @@ #include "nodes/execnodes.h" extern WorkTableScanState *ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags); -extern TupleTableSlot *ExecWorkTableScan(WorkTableScanState *node); extern void ExecEndWorkTableScan(WorkTableScanState *node); extern void ExecReScanWorkTableScan(WorkTableScanState *node); diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 85fac8ab91..35c28a6143 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -818,6 +818,18 @@ typedef struct DomainConstraintState * ---------------------------------------------------------------- */ +struct PlanState; + +/* ---------------- + * ExecProcNodeMtd + * + * This is the method called by ExecProcNode to return the next tuple + * from an executor node. It returns NULL, or an empty TupleTableSlot, + * if no more tuples are available. + * ---------------- + */ +typedef TupleTableSlot *(*ExecProcNodeMtd) (struct PlanState *pstate); + /* ---------------- * PlanState node * @@ -835,6 +847,10 @@ typedef struct PlanState * nodes point to one EState for the whole * top-level plan */ + ExecProcNodeMtd ExecProcNode; /* function to return next tuple */ + ExecProcNodeMtd ExecProcNodeReal; /* actual function, if above is a + * wrapper */ + Instrumentation *instrument; /* Optional runtime stats for this node */ WorkerInstrumentation *worker_instrument; /* per-worker instrumentation */ -- cgit v1.2.3 From 610e8ebb0fadd7a738c2ad07fef6c5ea86b11f8d Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Thu, 3 Aug 2017 11:21:29 -0400 Subject: Teach map_partition_varattnos to handle whole-row expressions. Otherwise, partitioned tables with RETURNING expressions or subject to a WITH CHECK OPTION do not work properly. Amit Langote, reviewed by Amit Khandekar and Etsuro Fujita. A few comment changes by me. Discussion: http://postgr.es/m/9a39df80-871e-6212-0684-f93c83be4097@lab.ntt.co.jp --- src/backend/catalog/partition.c | 21 ++++++++---- src/backend/commands/tablecmds.c | 12 +++++-- src/backend/executor/nodeModifyTable.c | 4 +-- src/backend/parser/parse_utilcmd.c | 6 ++-- src/backend/rewrite/rewriteManip.c | 47 ++++++++++++++++++++++----- src/include/catalog/partition.h | 3 +- src/include/rewrite/rewriteManip.h | 2 +- src/test/regress/expected/insert.out | 21 ++++++++++++ src/test/regress/expected/updatable_views.out | 26 +++++++++++++++ src/test/regress/sql/insert.sql | 13 ++++++++ src/test/regress/sql/updatable_views.sql | 27 +++++++++++++++ 11 files changed, 157 insertions(+), 25 deletions(-) (limited to 'src/backend/executor/nodeModifyTable.c') diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index 9d50efb6a0..dcc7f8af27 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -898,16 +898,20 @@ get_qual_from_partbound(Relation rel, Relation parent, * We must allow for cases where physical attnos of a partition can be * different from the parent's. * + * If found_whole_row is not NULL, *found_whole_row returns whether a + * whole-row variable was found in the input expression. + * * Note: this will work on any node tree, so really the argument and result * should be declared "Node *". But a substantial majority of the callers * are working on Lists, so it's less messy to do the casts internally. */ List * map_partition_varattnos(List *expr, int target_varno, - Relation partrel, Relation parent) + Relation partrel, Relation parent, + bool *found_whole_row) { AttrNumber *part_attnos; - bool found_whole_row; + bool my_found_whole_row; if (expr == NIL) return NIL; @@ -919,10 +923,10 @@ map_partition_varattnos(List *expr, int target_varno, target_varno, 0, part_attnos, RelationGetDescr(parent)->natts, - &found_whole_row); - /* There can never be a whole-row reference here */ + RelationGetForm(partrel)->reltype, + &my_found_whole_row); if (found_whole_row) - elog(ERROR, "unexpected whole-row reference found in partition key"); + *found_whole_row = my_found_whole_row; return expr; } @@ -1783,6 +1787,7 @@ generate_partition_qual(Relation rel) List *my_qual = NIL, *result = NIL; Relation parent; + bool found_whole_row; /* Guard against stack overflow due to overly deep partition tree */ check_stack_depth(); @@ -1825,7 +1830,11 @@ generate_partition_qual(Relation rel) * in it to bear this relation's attnos. It's safe to assume varno = 1 * here. */ - result = map_partition_varattnos(result, 1, rel, parent); + result = map_partition_varattnos(result, 1, rel, parent, + &found_whole_row); + /* There can never be a whole-row reference here */ + if (found_whole_row) + elog(ERROR, "unexpected whole-row reference found in partition key"); /* Save a copy in the relcache */ oldcxt = MemoryContextSwitchTo(CacheMemoryContext); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index bb00858ad1..b58c92d846 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -1989,7 +1989,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, expr = map_variable_attnos(stringToNode(check[i].ccbin), 1, 0, newattno, tupleDesc->natts, - &found_whole_row); + InvalidOid, &found_whole_row); /* * For the moment we have to reject whole-row variables. We @@ -8874,7 +8874,7 @@ ATPrepAlterColumnType(List **wqueue, map_variable_attnos(def->cooked_default, 1, 0, attmap, RelationGetDescr(rel)->natts, - &found_whole_row); + InvalidOid, &found_whole_row); if (found_whole_row) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), @@ -13713,6 +13713,7 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) Oid part_relid = lfirst_oid(lc); Relation part_rel; Expr *constr; + bool found_whole_row; /* Lock already taken */ if (part_relid != RelationGetRelid(attachRel)) @@ -13738,7 +13739,12 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) constr = linitial(partConstraint); tab->partition_constraint = (Expr *) map_partition_varattnos((List *) constr, 1, - part_rel, rel); + part_rel, rel, + &found_whole_row); + /* There can never be a whole-row reference here */ + if (found_whole_row) + elog(ERROR, "unexpected whole-row reference found in partition key"); + /* keep our lock until commit */ if (part_rel != attachRel) heap_close(part_rel, NoLock); diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 0dde0ed6eb..435aed3b8b 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -1996,7 +1996,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) /* varno = node->nominalRelation */ mapped_wcoList = map_partition_varattnos(wcoList, node->nominalRelation, - partrel, rel); + partrel, rel, NULL); foreach(ll, mapped_wcoList) { WithCheckOption *wco = castNode(WithCheckOption, lfirst(ll)); @@ -2069,7 +2069,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) /* varno = node->nominalRelation */ rlist = map_partition_varattnos(returningList, node->nominalRelation, - partrel, rel); + partrel, rel, NULL); resultRelInfo->ri_projectReturning = ExecBuildProjectionInfo(rlist, econtext, slot, &mtstate->ps, resultRelInfo->ri_RelationDesc->rd_att); diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 9f37f1b920..a86c2341f5 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -1107,7 +1107,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla ccbin_node = map_variable_attnos(stringToNode(ccbin), 1, 0, attmap, tupleDesc->natts, - &found_whole_row); + InvalidOid, &found_whole_row); /* * We reject whole-row variables because the whole point of LIKE @@ -1463,7 +1463,7 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx, indexkey = map_variable_attnos(indexkey, 1, 0, attmap, attmap_length, - &found_whole_row); + InvalidOid, &found_whole_row); /* As in transformTableLikeClause, reject whole-row variables */ if (found_whole_row) @@ -1539,7 +1539,7 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx, pred_tree = map_variable_attnos(pred_tree, 1, 0, attmap, attmap_length, - &found_whole_row); + InvalidOid, &found_whole_row); /* As in transformTableLikeClause, reject whole-row variables */ if (found_whole_row) diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index b89b435da0..ba706b25b4 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -1203,14 +1203,12 @@ replace_rte_variables_mutator(Node *node, * appear in the expression. * * If the expression tree contains a whole-row Var for the target RTE, - * the Var is not changed but *found_whole_row is returned as TRUE. - * For most callers this is an error condition, but we leave it to the caller - * to report the error so that useful context can be provided. (In some - * usages it would be appropriate to modify the Var's vartype and insert a - * ConvertRowtypeExpr node to map back to the original vartype. We might - * someday extend this function's API to support that. For now, the only - * concession to that future need is that this function is a tree mutator - * not just a walker.) + * *found_whole_row is returned as TRUE. In addition, if to_rowtype is + * not InvalidOid, we modify the Var's vartype and insert a ConvertRowTypeExpr + * to map back to the orignal rowtype. Callers that don't provide to_rowtype + * should report an error if *found_row_type is true; we don't do that here + * because we don't know exactly what wording for the error message would + * be most appropriate. The caller will be aware of the context. * * This could be built using replace_rte_variables and a callback function, * but since we don't ever need to insert sublinks, replace_rte_variables is @@ -1223,6 +1221,8 @@ typedef struct int sublevels_up; /* (current) nesting depth */ const AttrNumber *attno_map; /* map array for user attnos */ int map_length; /* number of entries in attno_map[] */ + /* Target type when converting whole-row vars */ + Oid to_rowtype; bool *found_whole_row; /* output flag */ } map_variable_attnos_context; @@ -1257,6 +1257,34 @@ map_variable_attnos_mutator(Node *node, { /* whole-row variable, warn caller */ *(context->found_whole_row) = true; + + /* If the callers expects us to convert the same, do so. */ + if (OidIsValid(context->to_rowtype)) + { + /* No support for RECORDOID. */ + Assert(var->vartype != RECORDOID); + + /* Don't convert unless necessary. */ + if (context->to_rowtype != var->vartype) + { + ConvertRowtypeExpr *r; + + /* Var itself is converted to the requested type. */ + newvar->vartype = context->to_rowtype; + + /* + * And a conversion node on top to convert back to the + * original type. + */ + r = makeNode(ConvertRowtypeExpr); + r->arg = (Expr *) newvar; + r->resulttype = var->vartype; + r->convertformat = COERCE_IMPLICIT_CAST; + r->location = -1; + + return (Node *) r; + } + } } return (Node *) newvar; } @@ -1283,7 +1311,7 @@ Node * map_variable_attnos(Node *node, int target_varno, int sublevels_up, const AttrNumber *attno_map, int map_length, - bool *found_whole_row) + Oid to_rowtype, bool *found_whole_row) { map_variable_attnos_context context; @@ -1291,6 +1319,7 @@ map_variable_attnos(Node *node, context.sublevels_up = sublevels_up; context.attno_map = attno_map; context.map_length = map_length; + context.to_rowtype = to_rowtype; context.found_whole_row = found_whole_row; *found_whole_row = false; diff --git a/src/include/catalog/partition.h b/src/include/catalog/partition.h index f10879a162..434ded37d7 100644 --- a/src/include/catalog/partition.h +++ b/src/include/catalog/partition.h @@ -80,7 +80,8 @@ extern Oid get_partition_parent(Oid relid); extern List *get_qual_from_partbound(Relation rel, Relation parent, PartitionBoundSpec *spec); extern List *map_partition_varattnos(List *expr, int target_varno, - Relation partrel, Relation parent); + Relation partrel, Relation parent, + bool *found_whole_row); extern List *RelationGetPartitionQual(Relation rel); extern Expr *get_partition_qual_relid(Oid relid); diff --git a/src/include/rewrite/rewriteManip.h b/src/include/rewrite/rewriteManip.h index 282ff9967f..f0a7a8b2cd 100644 --- a/src/include/rewrite/rewriteManip.h +++ b/src/include/rewrite/rewriteManip.h @@ -72,7 +72,7 @@ extern Node *replace_rte_variables_mutator(Node *node, extern Node *map_variable_attnos(Node *node, int target_varno, int sublevels_up, const AttrNumber *attno_map, int map_length, - bool *found_whole_row); + Oid to_rowtype, bool *found_whole_row); extern Node *ReplaceVarsFromTargetList(Node *node, int target_varno, int sublevels_up, diff --git a/src/test/regress/expected/insert.out b/src/test/regress/expected/insert.out index 0dcc86fef4..a2d9469592 100644 --- a/src/test/regress/expected/insert.out +++ b/src/test/regress/expected/insert.out @@ -659,3 +659,24 @@ select tableoid::regclass, * from mcrparted order by a, b; (11 rows) drop table mcrparted; +-- check that wholerow vars in the RETURNING list work with partitioned tables +create table returningwrtest (a int) partition by list (a); +create table returningwrtest1 partition of returningwrtest for values in (1); +insert into returningwrtest values (1) returning returningwrtest; + returningwrtest +----------------- + (1) +(1 row) + +-- check also that the wholerow vars in RETURNING list are converted as needed +alter table returningwrtest add b text; +create table returningwrtest2 (b text, c int, a int); +alter table returningwrtest2 drop c; +alter table returningwrtest attach partition returningwrtest2 for values in (2); +insert into returningwrtest values (2, 'foo') returning returningwrtest; + returningwrtest +----------------- + (2,foo) +(1 row) + +drop table returningwrtest; diff --git a/src/test/regress/expected/updatable_views.out b/src/test/regress/expected/updatable_views.out index eab5c0334c..2090a411fe 100644 --- a/src/test/regress/expected/updatable_views.out +++ b/src/test/regress/expected/updatable_views.out @@ -2428,3 +2428,29 @@ ERROR: new row violates check option for view "ptv_wco" DETAIL: Failing row contains (1, 2, null). drop view ptv, ptv_wco; drop table pt, pt1, pt11; +-- check that wholerow vars appearing in WITH CHECK OPTION constraint expressions +-- work fine with partitioned tables +create table wcowrtest (a int) partition by list (a); +create table wcowrtest1 partition of wcowrtest for values in (1); +create view wcowrtest_v as select * from wcowrtest where wcowrtest = '(2)'::wcowrtest with check option; +insert into wcowrtest_v values (1); +ERROR: new row violates check option for view "wcowrtest_v" +DETAIL: Failing row contains (1). +alter table wcowrtest add b text; +create table wcowrtest2 (b text, c int, a int); +alter table wcowrtest2 drop c; +alter table wcowrtest attach partition wcowrtest2 for values in (2); +create table sometable (a int, b text); +insert into sometable values (1, 'a'), (2, 'b'); +create view wcowrtest_v2 as + select * + from wcowrtest r + where r in (select s from sometable s where r.a = s.a) +with check option; +-- WITH CHECK qual will be processed with wcowrtest2's +-- rowtype after tuple-routing +insert into wcowrtest_v2 values (2, 'no such row in sometable'); +ERROR: new row violates check option for view "wcowrtest_v2" +DETAIL: Failing row contains (2, no such row in sometable). +drop view wcowrtest_v, wcowrtest_v2; +drop table wcowrtest, sometable; diff --git a/src/test/regress/sql/insert.sql b/src/test/regress/sql/insert.sql index 6adf25da40..6f17872087 100644 --- a/src/test/regress/sql/insert.sql +++ b/src/test/regress/sql/insert.sql @@ -399,3 +399,16 @@ insert into mcrparted values ('aaa', 0), ('b', 0), ('bz', 10), ('c', -10), ('commons', 0), ('d', -10), ('e', 0); select tableoid::regclass, * from mcrparted order by a, b; drop table mcrparted; + +-- check that wholerow vars in the RETURNING list work with partitioned tables +create table returningwrtest (a int) partition by list (a); +create table returningwrtest1 partition of returningwrtest for values in (1); +insert into returningwrtest values (1) returning returningwrtest; + +-- check also that the wholerow vars in RETURNING list are converted as needed +alter table returningwrtest add b text; +create table returningwrtest2 (b text, c int, a int); +alter table returningwrtest2 drop c; +alter table returningwrtest attach partition returningwrtest2 for values in (2); +insert into returningwrtest values (2, 'foo') returning returningwrtest; +drop table returningwrtest; diff --git a/src/test/regress/sql/updatable_views.sql b/src/test/regress/sql/updatable_views.sql index 2ede44c02b..a6ba5aad9e 100644 --- a/src/test/regress/sql/updatable_views.sql +++ b/src/test/regress/sql/updatable_views.sql @@ -1141,3 +1141,30 @@ create view ptv_wco as select * from pt where a = 0 with check option; insert into ptv_wco values (1, 2); drop view ptv, ptv_wco; drop table pt, pt1, pt11; + +-- check that wholerow vars appearing in WITH CHECK OPTION constraint expressions +-- work fine with partitioned tables +create table wcowrtest (a int) partition by list (a); +create table wcowrtest1 partition of wcowrtest for values in (1); +create view wcowrtest_v as select * from wcowrtest where wcowrtest = '(2)'::wcowrtest with check option; +insert into wcowrtest_v values (1); + +alter table wcowrtest add b text; +create table wcowrtest2 (b text, c int, a int); +alter table wcowrtest2 drop c; +alter table wcowrtest attach partition wcowrtest2 for values in (2); + +create table sometable (a int, b text); +insert into sometable values (1, 'a'), (2, 'b'); +create view wcowrtest_v2 as + select * + from wcowrtest r + where r in (select s from sometable s where r.a = s.a) +with check option; + +-- WITH CHECK qual will be processed with wcowrtest2's +-- rowtype after tuple-routing +insert into wcowrtest_v2 values (2, 'no such row in sometable'); + +drop view wcowrtest_v, wcowrtest_v2; +drop table wcowrtest, sometable; -- cgit v1.2.3 From 12a34f59bf8bc5babf375c95f5192d208dca1739 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Thu, 3 Aug 2017 12:47:00 -0400 Subject: Improve ExecModifyTable comments. Some of these comments wrongly implied that only an AFTER ROW trigger will cause a 'wholerow' attribute to be present for a foreign table, but a BEFORE ROW trigger can have the same effect. Others implied that it would always be present for a foreign table, but that's not true either. Etsuro Fujita and Robert Haas Discussion: http://postgr.es/m/10026bc7-1403-ef85-9e43-c6100c1cc0e3@lab.ntt.co.jp --- src/backend/executor/nodeModifyTable.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/backend/executor/nodeModifyTable.c') diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 435aed3b8b..30add8e3c7 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -1696,7 +1696,7 @@ ExecModifyTable(PlanState *pstate) * the old relation tuple. * * Foreign table updates have a wholerow attribute when the - * relation has an AFTER ROW trigger. Note that the wholerow + * relation has a row-level trigger. Note that the wholerow * attribute does not carry system columns. Foreign table * triggers miss seeing those, except that we know enough here * to set t_tableOid. Quite separately from this, the FDW may @@ -2182,8 +2182,11 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) /* * Initialize the junk filter(s) if needed. INSERT queries need a filter * if there are any junk attrs in the tlist. UPDATE and DELETE always - * need a filter, since there's always a junk 'ctid' or 'wholerow' - * attribute present --- no need to look first. + * need a filter, since there's always at least one junk attribute present + * --- no need to look first. Typically, this will be a 'ctid' or + * 'wholerow' attribute, but in the case of a foreign data wrapper it + * might be a set of junk attributes sufficient to identify the remote + * row. * * If there are multiple result relations, each one needs its own junk * filter. Note multiple rels are only possible for UPDATE/DELETE, so we @@ -2251,7 +2254,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) else if (relkind == RELKIND_FOREIGN_TABLE) { /* - * When there is an AFTER trigger, there should be a + * When there is a row-level trigger, there should be a * wholerow attribute. */ j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow"); -- cgit v1.2.3 From 21d304dfedb4f26d0d6587d9ac39b1b5c499bb55 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 14 Aug 2017 17:29:33 -0400 Subject: Final pgindent + perltidy run for v10. --- src/backend/access/hash/hashpage.c | 8 +- src/backend/access/transam/slru.c | 2 +- src/backend/catalog/namespace.c | 14 +- src/backend/catalog/partition.c | 6 +- src/backend/commands/copy.c | 3 +- src/backend/commands/subscriptioncmds.c | 3 +- src/backend/commands/tablecmds.c | 4 +- src/backend/commands/trigger.c | 14 +- src/backend/commands/vacuumlazy.c | 10 +- src/backend/executor/execProcnode.c | 6 +- src/backend/executor/nodeModifyTable.c | 8 +- src/backend/libpq/be-secure-openssl.c | 5 +- src/backend/optimizer/geqo/geqo_cx.c | 2 +- src/backend/optimizer/geqo/geqo_ox1.c | 2 +- src/backend/optimizer/geqo/geqo_ox2.c | 2 +- src/backend/optimizer/geqo/geqo_px.c | 2 +- src/backend/optimizer/geqo/geqo_recombination.c | 2 +- src/backend/parser/parse_utilcmd.c | 4 +- src/backend/replication/logical/launcher.c | 11 +- src/backend/replication/logical/origin.c | 6 +- src/backend/replication/logical/snapbuild.c | 6 +- src/backend/replication/slot.c | 6 +- src/backend/replication/syncrep.c | 8 +- src/backend/storage/ipc/procarray.c | 4 +- src/backend/utils/adt/ruleutils.c | 4 +- src/bin/pg_ctl/t/001_start_stop.pl | 6 +- src/bin/pg_dump/compress_io.c | 2 +- src/bin/pg_dump/pg_backup_tar.c | 2 +- src/bin/pg_dump/pg_dump.c | 8 +- src/bin/pg_dump/t/002_pg_dump.pl | 201 ++++++++++----------- src/bin/pg_rewind/libpq_fetch.c | 8 +- src/include/commands/trigger.h | 9 +- src/include/nodes/execnodes.h | 4 +- src/include/optimizer/geqo_recombination.h | 14 +- src/test/perl/PostgresNode.pm | 5 +- src/test/perl/TestLib.pm | 1 + src/test/recovery/t/001_stream_rep.pl | 54 +++--- src/test/recovery/t/006_logical_decoding.pl | 6 +- src/test/recovery/t/007_sync_rep.pl | 2 +- src/test/recovery/t/009_twophase.pl | 23 +-- .../recovery/t/010_logical_decoding_timelines.pl | 3 +- src/test/subscription/t/001_rep_changes.pl | 27 +-- src/tools/msvc/Mkvcbuild.pm | 6 +- src/tools/msvc/vcregress.pl | 4 +- src/tools/pgindent/pgindent | 11 +- src/tools/pgindent/typedefs.list | 8 +- 46 files changed, 273 insertions(+), 273 deletions(-) (limited to 'src/backend/executor/nodeModifyTable.c') diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c index 08eaf1d7bf..7b2906b0ca 100644 --- a/src/backend/access/hash/hashpage.c +++ b/src/backend/access/hash/hashpage.c @@ -1320,10 +1320,10 @@ _hash_splitbucket(Relation rel, /* * If possible, clean up the old bucket. We might not be able to do this * if someone else has a pin on it, but if not then we can go ahead. This - * isn't absolutely necessary, but it reduces bloat; if we don't do it now, - * VACUUM will do it eventually, but maybe not until new overflow pages - * have been allocated. Note that there's no need to clean up the new - * bucket. + * isn't absolutely necessary, but it reduces bloat; if we don't do it + * now, VACUUM will do it eventually, but maybe not until new overflow + * pages have been allocated. Note that there's no need to clean up the + * new bucket. */ if (IsBufferCleanupOK(bucket_obuf)) { diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index d037c369a7..77edc51e1c 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -233,7 +233,7 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, } /* Should fit to estimated shmem size */ - Assert(ptr - (char *) shared <= SimpleLruShmemSize(nslots, nlsns)); + Assert(ptr - (char *) shared <= SimpleLruShmemSize(nslots, nlsns)); } else Assert(found); diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 6859a97363..5d71302ded 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -3802,14 +3802,14 @@ InitTempTableNamespace(void) get_database_name(MyDatabaseId)))); /* - * Do not allow a Hot Standby session to make temp tables. Aside - * from problems with modifying the system catalogs, there is a naming + * Do not allow a Hot Standby session to make temp tables. Aside from + * problems with modifying the system catalogs, there is a naming * conflict: pg_temp_N belongs to the session with BackendId N on the - * master, not to a hot standby session with the same BackendId. We should not - * be able to get here anyway due to XactReadOnly checks, but let's just - * make real sure. Note that this also backstops various operations that - * allow XactReadOnly transactions to modify temp tables; they'd need - * RecoveryInProgress checks if not for this. + * master, not to a hot standby session with the same BackendId. We + * should not be able to get here anyway due to XactReadOnly checks, but + * let's just make real sure. Note that this also backstops various + * operations that allow XactReadOnly transactions to modify temp tables; + * they'd need RecoveryInProgress checks if not for this. */ if (RecoveryInProgress()) ereport(ERROR, diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index 0e4b343ab2..71bc4b3d10 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -728,9 +728,9 @@ check_new_partition_bound(char *relname, Relation parent, errmsg("empty range bound specified for partition \"%s\"", relname), errdetail("Specified lower bound %s is greater than or equal to upper bound %s.", - get_range_partbound_string(spec->lowerdatums), - get_range_partbound_string(spec->upperdatums)), - parser_errposition(pstate, spec->location))); + get_range_partbound_string(spec->lowerdatums), + get_range_partbound_string(spec->upperdatums)), + parser_errposition(pstate, spec->location))); } if (partdesc->nparts > 0) diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 53e296559a..a258965c20 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -1454,7 +1454,7 @@ BeginCopy(ParseState *pstate, */ if (cstate->transition_capture != NULL) { - int i; + int i; cstate->transition_tupconv_maps = (TupleConversionMap **) palloc0(sizeof(TupleConversionMap *) * @@ -2651,6 +2651,7 @@ CopyFrom(CopyState cstate) cstate->transition_capture->tcs_map = NULL; } } + /* * We might need to convert from the parent rowtype to the * partition rowtype. diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index ae40f7164d..005e74201d 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -919,9 +919,10 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel) LWLockAcquire(LogicalRepWorkerLock, LW_SHARED); subworkers = logicalrep_workers_find(subid, false); LWLockRelease(LogicalRepWorkerLock); - foreach (lc, subworkers) + foreach(lc, subworkers) { LogicalRepWorker *w = (LogicalRepWorker *) lfirst(lc); + if (slotname) logicalrep_worker_stop(w->subid, w->relid); else diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 2afde0abd8..513a9ec485 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -13509,8 +13509,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) * having to construct this list again, so we request the strongest lock * on all partitions. We need the strongest lock, because we may decide * to scan them if we find out that the table being attached (or its leaf - * partitions) may contain rows that violate the partition constraint. - * If the table has a constraint that would prevent such rows, which by + * partitions) may contain rows that violate the partition constraint. If + * the table has a constraint that would prevent such rows, which by * definition is present in all the partitions, we need not scan the * table, nor its partitions. But we cannot risk a deadlock by taking a * weaker lock now and the stronger one only when needed. diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index b502941b08..da0850bfd6 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -2071,11 +2071,11 @@ FindTriggerIncompatibleWithInheritance(TriggerDesc *trigdesc) { if (trigdesc != NULL) { - int i; + int i; for (i = 0; i < trigdesc->numtriggers; ++i) { - Trigger *trigger = &trigdesc->triggers[i]; + Trigger *trigger = &trigdesc->triggers[i]; if (trigger->tgoldtable != NULL || trigger->tgnewtable != NULL) return trigger->tgname; @@ -5253,12 +5253,12 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, */ if (row_trigger && transition_capture != NULL) { - HeapTuple original_insert_tuple = transition_capture->tcs_original_insert_tuple; + HeapTuple original_insert_tuple = transition_capture->tcs_original_insert_tuple; TupleConversionMap *map = transition_capture->tcs_map; - bool delete_old_table = transition_capture->tcs_delete_old_table; - bool update_old_table = transition_capture->tcs_update_old_table; - bool update_new_table = transition_capture->tcs_update_new_table; - bool insert_new_table = transition_capture->tcs_insert_new_table;; + bool delete_old_table = transition_capture->tcs_delete_old_table; + bool update_old_table = transition_capture->tcs_update_old_table; + bool update_new_table = transition_capture->tcs_update_new_table; + bool insert_new_table = transition_capture->tcs_insert_new_table;; if ((event == TRIGGER_EVENT_DELETE && delete_old_table) || (event == TRIGGER_EVENT_UPDATE && update_old_table)) diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index fabb2f8d52..e9b4045fe5 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -529,11 +529,11 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats, * safely set for relfrozenxid or relminmxid. * * Before entering the main loop, establish the invariant that - * next_unskippable_block is the next block number >= blkno that we - * can't skip based on the visibility map, either all-visible for a - * regular scan or all-frozen for an aggressive scan. We set it to - * nblocks if there's no such block. We also set up the skipping_blocks - * flag correctly at this stage. + * next_unskippable_block is the next block number >= blkno that we can't + * skip based on the visibility map, either all-visible for a regular scan + * or all-frozen for an aggressive scan. We set it to nblocks if there's + * no such block. We also set up the skipping_blocks flag correctly at + * this stage. * * Note: The value returned by visibilitymap_get_status could be slightly * out-of-date, since we make this test before reading the corresponding diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 396920c0a2..36d2914249 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -411,9 +411,9 @@ ExecProcNodeFirst(PlanState *node) /* * Perform stack depth check during the first execution of the node. We * only do so the first time round because it turns out to not be cheap on - * some common architectures (eg. x86). This relies on the assumption that - * ExecProcNode calls for a given plan node will always be made at roughly - * the same stack depth. + * some common architectures (eg. x86). This relies on the assumption + * that ExecProcNode calls for a given plan node will always be made at + * roughly the same stack depth. */ check_stack_depth(); diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 30add8e3c7..36b2b43bc6 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -1469,7 +1469,7 @@ static void ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate) { ResultRelInfo *targetRelInfo = getASTriggerResultRelInfo(mtstate); - int i; + int i; /* Check for transition tables on the directly targeted relation. */ mtstate->mt_transition_capture = @@ -1483,7 +1483,7 @@ ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate) if (mtstate->mt_transition_capture != NULL) { ResultRelInfo *resultRelInfos; - int numResultRelInfos; + int numResultRelInfos; /* Find the set of partitions so that we can find their TupleDescs. */ if (mtstate->mt_partition_dispatch_info != NULL) @@ -2254,8 +2254,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) else if (relkind == RELKIND_FOREIGN_TABLE) { /* - * When there is a row-level trigger, there should be a - * wholerow attribute. + * When there is a row-level trigger, there should be + * a wholerow attribute. */ j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow"); } diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c index 00f17f7843..fe15227a77 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -730,9 +730,10 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor) n = -1; break; case SSL_ERROR_ZERO_RETURN: + /* - * the SSL connnection was closed, leave it to the caller - * to ereport it + * the SSL connnection was closed, leave it to the caller to + * ereport it */ errno = ECONNRESET; n = -1; diff --git a/src/backend/optimizer/geqo/geqo_cx.c b/src/backend/optimizer/geqo/geqo_cx.c index d05327d8ab..a54690884a 100644 --- a/src/backend/optimizer/geqo/geqo_cx.c +++ b/src/backend/optimizer/geqo/geqo_cx.c @@ -46,7 +46,7 @@ */ int cx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, - int num_gene, City *city_table) + int num_gene, City * city_table) { int i, start_pos, diff --git a/src/backend/optimizer/geqo/geqo_ox1.c b/src/backend/optimizer/geqo/geqo_ox1.c index 53dacb811f..10d2d0a33a 100644 --- a/src/backend/optimizer/geqo/geqo_ox1.c +++ b/src/backend/optimizer/geqo/geqo_ox1.c @@ -45,7 +45,7 @@ */ void ox1(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, - City *city_table) + City * city_table) { int left, right, diff --git a/src/backend/optimizer/geqo/geqo_ox2.c b/src/backend/optimizer/geqo/geqo_ox2.c index 8d5baa9826..72b9b0fb87 100644 --- a/src/backend/optimizer/geqo/geqo_ox2.c +++ b/src/backend/optimizer/geqo/geqo_ox2.c @@ -44,7 +44,7 @@ * position crossover */ void -ox2(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) +ox2(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City * city_table) { int k, j, diff --git a/src/backend/optimizer/geqo/geqo_px.c b/src/backend/optimizer/geqo/geqo_px.c index 2e7748c5aa..ad5ad3f1e5 100644 --- a/src/backend/optimizer/geqo/geqo_px.c +++ b/src/backend/optimizer/geqo/geqo_px.c @@ -45,7 +45,7 @@ */ void px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, - City *city_table) + City * city_table) { int num_positions; int i, diff --git a/src/backend/optimizer/geqo/geqo_recombination.c b/src/backend/optimizer/geqo/geqo_recombination.c index eb6ab42808..a5d3e47ad1 100644 --- a/src/backend/optimizer/geqo/geqo_recombination.c +++ b/src/backend/optimizer/geqo/geqo_recombination.c @@ -84,7 +84,7 @@ alloc_city_table(PlannerInfo *root, int num_gene) * deallocate memory of city table */ void -free_city_table(PlannerInfo *root, City *city_table) +free_city_table(PlannerInfo *root, City * city_table) { pfree(city_table); } diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 87cb4188a3..495ba3dffc 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -2131,8 +2131,8 @@ transformCheckConstraints(CreateStmtContext *cxt, bool skipValidation) /* * If creating a new table (but not a foreign table), we can safely skip - * validation of check constraints, and nonetheless mark them valid. - * (This will override any user-supplied NOT VALID flag.) + * validation of check constraints, and nonetheless mark them valid. (This + * will override any user-supplied NOT VALID flag.) */ if (skipValidation) { diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index 0f9e5755b9..4c6d4b2772 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -75,8 +75,8 @@ LogicalRepCtxStruct *LogicalRepCtx; typedef struct LogicalRepWorkerId { - Oid subid; - Oid relid; + Oid subid; + Oid relid; } LogicalRepWorkerId; static List *on_commit_stop_workers = NIL; @@ -552,7 +552,7 @@ void logicalrep_worker_stop_at_commit(Oid subid, Oid relid) { LogicalRepWorkerId *wid; - MemoryContext oldctx; + MemoryContext oldctx; /* Make sure we store the info in context that survives until commit. */ oldctx = MemoryContextSwitchTo(TopTransactionContext); @@ -824,11 +824,12 @@ AtEOXact_ApplyLauncher(bool isCommit) { if (isCommit) { - ListCell *lc; + ListCell *lc; - foreach (lc, on_commit_stop_workers) + foreach(lc, on_commit_stop_workers) { LogicalRepWorkerId *wid = lfirst(lc); + logicalrep_worker_stop(wid->subid, wid->relid); } diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 9e1b19bb35..14cb3d0bf2 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -353,7 +353,7 @@ restart: { if (state->acquired_by != 0) { - ConditionVariable *cv; + ConditionVariable *cv; if (nowait) ereport(ERROR, @@ -977,7 +977,7 @@ replorigin_get_progress(RepOriginId node, bool flush) static void ReplicationOriginExitCleanup(int code, Datum arg) { - ConditionVariable *cv = NULL; + ConditionVariable *cv = NULL; LWLockAcquire(ReplicationOriginLock, LW_EXCLUSIVE); @@ -1097,7 +1097,7 @@ replorigin_session_setup(RepOriginId node) void replorigin_session_reset(void) { - ConditionVariable *cv; + ConditionVariable *cv; Assert(max_replication_slots != 0); diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index 0ca4fa5d25..fba57a0470 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1117,9 +1117,9 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact * only ever look at those. * * NB: We only increase xmax when a catalog modifying transaction commits - * (see SnapBuildCommitTxn). Because of this, xmax can be lower than xmin, - * which looks odd but is correct and actually more efficient, since we hit - * fast paths in tqual.c. + * (see SnapBuildCommitTxn). Because of this, xmax can be lower than + * xmin, which looks odd but is correct and actually more efficient, since + * we hit fast paths in tqual.c. */ builder->xmin = running->oldestRunningXid; diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 63e1aaa910..a8a16f55e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -351,8 +351,8 @@ retry: if (s->in_use && strcmp(name, NameStr(s->data.name)) == 0) { /* - * This is the slot we want. We don't know yet if it's active, - * so get ready to sleep on it in case it is. (We may end up not + * This is the slot we want. We don't know yet if it's active, so + * get ready to sleep on it in case it is. (We may end up not * sleeping, but we don't want to do this while holding the * spinlock.) */ @@ -397,7 +397,7 @@ retry: goto retry; } else - ConditionVariableCancelSleep(); /* no sleep needed after all */ + ConditionVariableCancelSleep(); /* no sleep needed after all */ /* Let everybody know we've modified this slot */ ConditionVariableBroadcast(&slot->active_cv); diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index 77e80f1612..8677235411 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -293,8 +293,8 @@ SyncRepWaitForLSN(XLogRecPtr lsn, bool commit) * WalSender has checked our LSN and has removed us from queue. Clean up * state and leave. It's OK to reset these shared memory fields without * holding SyncRepLock, because any walsenders will ignore us anyway when - * we're not on the queue. We need a read barrier to make sure we see - * the changes to the queue link (this might be unnecessary without + * we're not on the queue. We need a read barrier to make sure we see the + * changes to the queue link (this might be unnecessary without * assertions, but better safe than sorry). */ pg_read_barrier(); @@ -715,7 +715,7 @@ SyncRepGetSyncStandbysQuorum(bool *am_sync) for (i = 0; i < max_wal_senders; i++) { XLogRecPtr flush; - WalSndState state; + WalSndState state; int pid; walsnd = &WalSndCtl->walsnds[i]; @@ -794,7 +794,7 @@ SyncRepGetSyncStandbysPriority(bool *am_sync) for (i = 0; i < max_wal_senders; i++) { XLogRecPtr flush; - WalSndState state; + WalSndState state; int pid; walsnd = &WalSndCtl->walsnds[i]; diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index eab218e316..ff96e2a86f 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -1408,8 +1408,8 @@ GetOldestXmin(Relation rel, int flags) * being careful not to generate a "permanent" XID. * * vacuum_defer_cleanup_age provides some additional "slop" for the - * benefit of hot standby queries on standby servers. This is quick and - * dirty, and perhaps not all that useful unless the master has a + * benefit of hot standby queries on standby servers. This is quick + * and dirty, and perhaps not all that useful unless the master has a * predictable transaction rate, but it offers some protection when * there's no walsender connection. Note that we are assuming * vacuum_defer_cleanup_age isn't large enough to cause wraparound --- diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 0faa0204ce..e9bd64b7a8 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -8723,8 +8723,8 @@ get_rule_expr(Node *node, deparse_context *context, list_length(spec->upperdatums)); appendStringInfo(buf, "FOR VALUES FROM %s TO %s", - get_range_partbound_string(spec->lowerdatums), - get_range_partbound_string(spec->upperdatums)); + get_range_partbound_string(spec->lowerdatums), + get_range_partbound_string(spec->upperdatums)); break; default: diff --git a/src/bin/pg_ctl/t/001_start_stop.pl b/src/bin/pg_ctl/t/001_start_stop.pl index 3acc80e204..5da4746cb4 100644 --- a/src/bin/pg_ctl/t/001_start_stop.pl +++ b/src/bin/pg_ctl/t/001_start_stop.pl @@ -32,14 +32,16 @@ else print $conf "listen_addresses = '127.0.0.1'\n"; } close $conf; -my $ctlcmd = [ 'pg_ctl', 'start', '-D', "$tempdir/data", - '-l', "$TestLib::log_path/001_start_stop_server.log" ]; +my $ctlcmd = [ + 'pg_ctl', 'start', '-D', "$tempdir/data", '-l', + "$TestLib::log_path/001_start_stop_server.log" ]; if ($Config{osname} ne 'msys') { command_like($ctlcmd, qr/done.*server started/s, 'pg_ctl start'); } else { + # use the version of command_like that doesn't hang on Msys here command_like_safe($ctlcmd, qr/done.*server started/s, 'pg_ctl start'); } diff --git a/src/bin/pg_dump/compress_io.c b/src/bin/pg_dump/compress_io.c index e94f7d3274..54003f7da6 100644 --- a/src/bin/pg_dump/compress_io.c +++ b/src/bin/pg_dump/compress_io.c @@ -593,7 +593,7 @@ cfread(void *ptr, int size, cfp *fp) ret = gzread(fp->compressedfp, ptr, size); if (ret != size && !gzeof(fp->compressedfp)) { - int errnum; + int errnum; const char *errmsg = gzerror(fp->compressedfp, &errnum); exit_horribly(modulename, diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c index 2339d659bc..ef9f7145b1 100644 --- a/src/bin/pg_dump/pg_backup_tar.c +++ b/src/bin/pg_dump/pg_backup_tar.c @@ -557,7 +557,7 @@ _tarReadRaw(ArchiveHandle *AH, void *buf, size_t len, TAR_MEMBER *th, FILE *fh) if (res != len && !GZEOF(th->zFH)) { #ifdef HAVE_LIBZ - int errnum; + int errnum; const char *errmsg = gzerror(th->zFH, &errnum); exit_horribly(modulename, diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 37cb7cd986..2d8bb32dc0 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -676,8 +676,8 @@ main(int argc, char **argv) dopt.no_security_labels = 1; /* - * On hot standbys, never try to dump unlogged table data, since it - * will just throw an error. + * On hot standbys, never try to dump unlogged table data, since it will + * just throw an error. */ if (fout->isStandby) dopt.no_unlogged_table_data = true; @@ -4141,8 +4141,8 @@ getNamespaces(Archive *fout, int *numNamespaces) */ if (dopt->outputClean) appendPQExpBuffer(query, " AND pip.objoid <> " - "coalesce((select oid from pg_namespace " - "where nspname = 'public'),0)"); + "coalesce((select oid from pg_namespace " + "where nspname = 'public'),0)"); appendPQExpBuffer(query, ") "); diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl index 4c6201be61..c492fbdc24 100644 --- a/src/bin/pg_dump/t/002_pg_dump.pl +++ b/src/bin/pg_dump/t/002_pg_dump.pl @@ -100,18 +100,12 @@ my %pgdump_runs = ( defaults_no_public => { database => 'regress_pg_dump_test', dump_cmd => [ - 'pg_dump', - '--no-sync', - '-f', - "$tempdir/defaults_no_public.sql", + 'pg_dump', '--no-sync', '-f', "$tempdir/defaults_no_public.sql", 'regress_pg_dump_test', ], }, defaults_no_public_clean => { database => 'regress_pg_dump_test', dump_cmd => [ - 'pg_dump', - '--no-sync', - '-c', - '-f', + 'pg_dump', '--no-sync', '-c', '-f', "$tempdir/defaults_no_public_clean.sql", 'regress_pg_dump_test', ], }, @@ -464,9 +458,8 @@ my %tests = ( with_oids => 1, }, }, 'ALTER COLLATION test0 OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', regexp => qr/^ALTER COLLATION test0 OWNER TO .*;/m, collation => 1, like => { @@ -491,11 +484,10 @@ my %tests = ( test_schema_plus_blobs => 1, }, }, 'ALTER FOREIGN DATA WRAPPER dummy OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', - regexp => qr/^ALTER FOREIGN DATA WRAPPER dummy OWNER TO .*;/m, - like => { + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', + regexp => qr/^ALTER FOREIGN DATA WRAPPER dummy OWNER TO .*;/m, + like => { binary_upgrade => 1, clean => 1, clean_if_exists => 1, @@ -518,11 +510,10 @@ my %tests = ( test_schema_plus_blobs => 1, }, }, 'ALTER SERVER s1 OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', - regexp => qr/^ALTER SERVER s1 OWNER TO .*;/m, - like => { + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', + regexp => qr/^ALTER SERVER s1 OWNER TO .*;/m, + like => { binary_upgrade => 1, clean => 1, clean_if_exists => 1, @@ -545,10 +536,9 @@ my %tests = ( test_schema_plus_blobs => 1, }, }, 'ALTER FUNCTION dump_test.pltestlang_call_handler() OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', - regexp => qr/^ + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', + regexp => qr/^ \QALTER FUNCTION dump_test.pltestlang_call_handler() \E \QOWNER TO \E .*;/xm, @@ -574,10 +564,9 @@ my %tests = ( role => 1, }, }, 'ALTER OPERATOR FAMILY dump_test.op_family OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', - regexp => qr/^ + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', + regexp => qr/^ \QALTER OPERATOR FAMILY dump_test.op_family USING btree \E \QOWNER TO \E .*;/xm, @@ -653,10 +642,9 @@ my %tests = ( role => 1, }, }, 'ALTER OPERATOR CLASS dump_test.op_class OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', - regexp => qr/^ + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', + regexp => qr/^ \QALTER OPERATOR CLASS dump_test.op_class USING btree \E \QOWNER TO \E .*;/xm, @@ -744,11 +732,10 @@ my %tests = ( section_post_data => 1, }, }, 'ALTER PROCEDURAL LANGUAGE pltestlang OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', - regexp => qr/^ALTER PROCEDURAL LANGUAGE pltestlang OWNER TO .*;/m, - like => { + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', + regexp => qr/^ALTER PROCEDURAL LANGUAGE pltestlang OWNER TO .*;/m, + like => { binary_upgrade => 1, clean => 1, clean_if_exists => 1, @@ -770,11 +757,10 @@ my %tests = ( test_schema_plus_blobs => 1, }, }, 'ALTER SCHEMA dump_test OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', - regexp => qr/^ALTER SCHEMA dump_test OWNER TO .*;/m, - like => { + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', + regexp => qr/^ALTER SCHEMA dump_test OWNER TO .*;/m, + like => { binary_upgrade => 1, clean => 1, clean_if_exists => 1, @@ -796,11 +782,10 @@ my %tests = ( role => 1, }, }, 'ALTER SCHEMA dump_test_second_schema OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', - regexp => qr/^ALTER SCHEMA dump_test_second_schema OWNER TO .*;/m, - like => { + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', + regexp => qr/^ALTER SCHEMA dump_test_second_schema OWNER TO .*;/m, + like => { binary_upgrade => 1, clean => 1, clean_if_exists => 1, @@ -1191,11 +1176,10 @@ my %tests = ( section_post_data => 1, }, }, 'ALTER TABLE test_table OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', - regexp => qr/^ALTER TABLE test_table OWNER TO .*;/m, - like => { + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', + regexp => qr/^ALTER TABLE test_table OWNER TO .*;/m, + like => { binary_upgrade => 1, clean => 1, clean_if_exists => 1, @@ -1249,11 +1233,10 @@ my %tests = ( role => 1, }, }, 'ALTER TABLE test_second_table OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', - regexp => qr/^ALTER TABLE test_second_table OWNER TO .*;/m, - like => { + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', + regexp => qr/^ALTER TABLE test_second_table OWNER TO .*;/m, + like => { binary_upgrade => 1, clean => 1, clean_if_exists => 1, @@ -1276,11 +1259,10 @@ my %tests = ( role => 1, }, }, 'ALTER TABLE test_third_table OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', - regexp => qr/^ALTER TABLE test_third_table OWNER TO .*;/m, - like => { + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', + regexp => qr/^ALTER TABLE test_third_table OWNER TO .*;/m, + like => { binary_upgrade => 1, clean => 1, clean_if_exists => 1, @@ -1303,11 +1285,10 @@ my %tests = ( test_schema_plus_blobs => 1, }, }, 'ALTER TABLE measurement OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', - regexp => qr/^ALTER TABLE measurement OWNER TO .*;/m, - like => { + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', + regexp => qr/^ALTER TABLE measurement OWNER TO .*;/m, + like => { binary_upgrade => 1, clean => 1, clean_if_exists => 1, @@ -1330,11 +1311,10 @@ my %tests = ( role => 1, }, }, 'ALTER TABLE measurement_y2006m2 OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', - regexp => qr/^ALTER TABLE measurement_y2006m2 OWNER TO .*;/m, - like => { + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', + regexp => qr/^ALTER TABLE measurement_y2006m2 OWNER TO .*;/m, + like => { binary_upgrade => 1, clean => 1, clean_if_exists => 1, @@ -1357,11 +1337,10 @@ my %tests = ( test_schema_plus_blobs => 1, }, }, 'ALTER FOREIGN TABLE foreign_table OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', - regexp => qr/^ALTER FOREIGN TABLE foreign_table OWNER TO .*;/m, - like => { + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', + regexp => qr/^ALTER FOREIGN TABLE foreign_table OWNER TO .*;/m, + like => { binary_upgrade => 1, clean => 1, clean_if_exists => 1, @@ -1384,9 +1363,8 @@ my %tests = ( role => 1, }, }, 'ALTER TEXT SEARCH CONFIGURATION alt_ts_conf1 OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', regexp => qr/^ALTER TEXT SEARCH CONFIGURATION alt_ts_conf1 OWNER TO .*;/m, like => { @@ -1412,9 +1390,8 @@ my %tests = ( role => 1, }, }, 'ALTER TEXT SEARCH DICTIONARY alt_ts_dict1 OWNER TO' => { - all_runs => 1, - catch_all => - 'ALTER ... OWNER commands (except post-data objects)', + all_runs => 1, + catch_all => 'ALTER ... OWNER commands (except post-data objects)', regexp => qr/^ALTER TEXT SEARCH DICTIONARY alt_ts_dict1 OWNER TO .*;/m, like => { @@ -4542,12 +4519,12 @@ qr/CREATE TRANSFORM FOR integer LANGUAGE sql \(FROM SQL WITH FUNCTION pg_catalog test_schema_plus_blobs => 1, }, }, 'CREATE SCHEMA public' => { - all_runs => 1, - catch_all => 'CREATE ... commands', - regexp => qr/^CREATE SCHEMA public;/m, - like => { - clean => 1, - clean_if_exists => 1, }, + all_runs => 1, + catch_all => 'CREATE ... commands', + regexp => qr/^CREATE SCHEMA public;/m, + like => { + clean => 1, + clean_if_exists => 1, }, unlike => { binary_upgrade => 1, createdb => 1, @@ -5266,31 +5243,32 @@ qr/CREATE TRANSFORM FOR integer LANGUAGE sql \(FROM SQL WITH FUNCTION pg_catalog section_data => 1, }, }, 'DROP SCHEMA public (for testing without public schema)' => { - all_runs => 1, - database => 'regress_pg_dump_test', + all_runs => 1, + database => 'regress_pg_dump_test', create_order => 100, - create_sql => 'DROP SCHEMA public;', - regexp => qr/^DROP SCHEMA public;/m, - like => { }, - unlike => { defaults_no_public => 1, - defaults_no_public_clean => 1, } }, + create_sql => 'DROP SCHEMA public;', + regexp => qr/^DROP SCHEMA public;/m, + like => {}, + unlike => { + defaults_no_public => 1, + defaults_no_public_clean => 1, } }, 'DROP SCHEMA public' => { all_runs => 1, catch_all => 'DROP ... commands', regexp => qr/^DROP SCHEMA public;/m, - like => { clean => 1 }, - unlike => { - clean_if_exists => 1, + like => { clean => 1 }, + unlike => { + clean_if_exists => 1, pg_dumpall_globals_clean => 1, }, }, 'DROP SCHEMA IF EXISTS public' => { all_runs => 1, catch_all => 'DROP ... commands', regexp => qr/^DROP SCHEMA IF EXISTS public;/m, - like => { clean_if_exists => 1 }, - unlike => { - clean => 1, + like => { clean_if_exists => 1 }, + unlike => { + clean => 1, pg_dumpall_globals_clean => 1, }, }, 'DROP EXTENSION plpgsql' => { @@ -6508,7 +6486,7 @@ if ($collation_check_stderr !~ /ERROR: /) } # Create a second database for certain tests to work against -$node->psql('postgres','create database regress_pg_dump_test;'); +$node->psql('postgres', 'create database regress_pg_dump_test;'); # Start with number of command_fails_like()*2 tests below (each # command_fails_like is actually 2 tests) @@ -6517,9 +6495,10 @@ my $num_tests = 12; foreach my $run (sort keys %pgdump_runs) { my $test_key = $run; - my $run_db = 'postgres'; + my $run_db = 'postgres'; - if (defined($pgdump_runs{$run}->{database})) { + if (defined($pgdump_runs{$run}->{database})) + { $run_db = $pgdump_runs{$run}->{database}; } @@ -6540,17 +6519,20 @@ foreach my $run (sort keys %pgdump_runs) # Then count all the tests run against each run foreach my $test (sort keys %tests) { + # postgres is the default database, if it isn't overridden my $test_db = 'postgres'; # Specific tests can override the database to use - if (defined($tests{$test}->{database})) { + if (defined($tests{$test}->{database})) + { $test_db = $tests{$test}->{database}; } # The database to test against needs to match the database the run is # for, so skip combinations where they don't match up. - if ($run_db ne $test_db) { + if ($run_db ne $test_db) + { next; } @@ -6626,7 +6608,8 @@ foreach my $test ( { my $test_db = 'postgres'; - if (defined($tests{$test}->{database})) { + if (defined($tests{$test}->{database})) + { $test_db = $tests{$test}->{database}; } diff --git a/src/bin/pg_rewind/libpq_fetch.c b/src/bin/pg_rewind/libpq_fetch.c index 6b4c8dd04e..a6ff4e3817 100644 --- a/src/bin/pg_rewind/libpq_fetch.c +++ b/src/bin/pg_rewind/libpq_fetch.c @@ -228,10 +228,10 @@ pg_recvint64(int64 value) { union { - int64 i64; - uint32 i32[2]; - } swap; - int64 result; + int64 i64; + uint32 i32[2]; + } swap; + int64 result; swap.i64 = value; diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h index 36c1134b64..aeb363f13e 100644 --- a/src/include/commands/trigger.h +++ b/src/include/commands/trigger.h @@ -75,13 +75,14 @@ typedef struct TransitionCaptureState /* * The tuplestores backing the transition tables. We use separate - * tuplestores for INSERT and UPDATE, because INSERT ... ON CONFLICT - * ... DO UPDATE causes INSERT and UPDATE triggers to fire and needs a way - * to keep track of the new tuple images resulting from the two cases + * tuplestores for INSERT and UPDATE, because INSERT ... ON CONFLICT ... + * DO UPDATE causes INSERT and UPDATE triggers to fire and needs a way to + * keep track of the new tuple images resulting from the two cases * separately. We only need a single old image tuplestore, because there * is no statement that can both update and delete at the same time. */ - Tuplestorestate *tcs_old_tuplestore; /* for DELETE and UPDATE old images */ + Tuplestorestate *tcs_old_tuplestore; /* for DELETE and UPDATE old + * images */ Tuplestorestate *tcs_insert_tuplestore; /* for INSERT new images */ Tuplestorestate *tcs_update_tuplestore; /* for UPDATE new images */ } TransitionCaptureState; diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 35c28a6143..577499465d 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -980,9 +980,9 @@ typedef struct ModifyTableState /* Per partition tuple conversion map */ TupleTableSlot *mt_partition_tuple_slot; struct TransitionCaptureState *mt_transition_capture; - /* controls transition table population */ + /* controls transition table population */ TupleConversionMap **mt_transition_tupconv_maps; - /* Per plan/partition tuple conversion */ + /* Per plan/partition tuple conversion */ } ModifyTableState; /* ---------------- diff --git a/src/include/optimizer/geqo_recombination.h b/src/include/optimizer/geqo_recombination.h index 8a436b9ec2..60286c6c27 100644 --- a/src/include/optimizer/geqo_recombination.h +++ b/src/include/optimizer/geqo_recombination.h @@ -65,25 +65,25 @@ typedef struct City int tour1_position; int used; int select_list; -} City; +} City; -extern City *alloc_city_table(PlannerInfo *root, int num_gene); -extern void free_city_table(PlannerInfo *root, City *city_table); +extern City * alloc_city_table(PlannerInfo *root, int num_gene); +extern void free_city_table(PlannerInfo *root, City * city_table); /* cycle crossover [CX] */ extern int cx(PlannerInfo *root, Gene *tour1, Gene *tour2, - Gene *offspring, int num_gene, City *city_table); + Gene *offspring, int num_gene, City * city_table); /* position crossover [PX] */ extern void px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, - int num_gene, City *city_table); + int num_gene, City * city_table); /* order crossover [OX1] according to Davis */ extern void ox1(PlannerInfo *root, Gene *mom, Gene *dad, Gene *offspring, - int num_gene, City *city_table); + int num_gene, City * city_table); /* order crossover [OX2] according to Syswerda */ extern void ox2(PlannerInfo *root, Gene *mom, Gene *dad, Gene *offspring, - int num_gene, City *city_table); + int num_gene, City * city_table); #endif /* GEQO_RECOMBINATION_H */ diff --git a/src/test/perl/PostgresNode.pm b/src/test/perl/PostgresNode.pm index bf982101a5..d9aeb277d9 100644 --- a/src/test/perl/PostgresNode.pm +++ b/src/test/perl/PostgresNode.pm @@ -1232,10 +1232,9 @@ sub poll_query_until { my ($self, $dbname, $query, $expected) = @_; - $expected = 't' unless defined($expected); # default value + $expected = 't' unless defined($expected); # default value - my $cmd = - [ 'psql', '-XAt', '-c', $query, '-d', $self->connstr($dbname) ]; + my $cmd = [ 'psql', '-XAt', '-c', $query, '-d', $self->connstr($dbname) ]; my ($stdout, $stderr); my $max_attempts = 180 * 10; my $attempts = 0; diff --git a/src/test/perl/TestLib.pm b/src/test/perl/TestLib.pm index bff6b3aed2..6dba21c073 100644 --- a/src/test/perl/TestLib.pm +++ b/src/test/perl/TestLib.pm @@ -303,6 +303,7 @@ sub command_like sub command_like_safe { + # Doesn't rely on detecting end of file on the file descriptors, # which can fail, causing the process to hang, notably on Msys # when used with 'pg_ctl start' diff --git a/src/test/recovery/t/001_stream_rep.pl b/src/test/recovery/t/001_stream_rep.pl index 23a19c67bf..fb27925069 100644 --- a/src/test/recovery/t/001_stream_rep.pl +++ b/src/test/recovery/t/001_stream_rep.pl @@ -152,12 +152,12 @@ sub get_slot_xmins { my ($node, $slotname, $check_expr) = @_; - $node->poll_query_until('postgres', qq[ + $node->poll_query_until( + 'postgres', qq[ SELECT $check_expr FROM pg_catalog.pg_replication_slots WHERE slot_name = '$slotname'; - ]) - or die "Timed out waiting for slot xmins to advance"; + ]) or die "Timed out waiting for slot xmins to advance"; my $slotinfo = $node->slot($slotname); return ($slotinfo->{'xmin'}, $slotinfo->{'catalog_xmin'}); @@ -166,14 +166,16 @@ sub get_slot_xmins # There's no hot standby feedback and there are no logical slots on either peer # so xmin and catalog_xmin should be null on both slots. my ($xmin, $catalog_xmin) = get_slot_xmins($node_master, $slotname_1, - "xmin IS NULL AND catalog_xmin IS NULL"); -is($xmin, '', 'xmin of non-cascaded slot null with no hs_feedback'); -is($catalog_xmin, '', 'catalog xmin of non-cascaded slot null with no hs_feedback'); + "xmin IS NULL AND catalog_xmin IS NULL"); +is($xmin, '', 'xmin of non-cascaded slot null with no hs_feedback'); +is($catalog_xmin, '', + 'catalog xmin of non-cascaded slot null with no hs_feedback'); ($xmin, $catalog_xmin) = get_slot_xmins($node_standby_1, $slotname_2, - "xmin IS NULL AND catalog_xmin IS NULL"); -is($xmin, '', 'xmin of cascaded slot null with no hs_feedback'); -is($catalog_xmin, '', 'catalog xmin of cascaded slot null with no hs_feedback'); + "xmin IS NULL AND catalog_xmin IS NULL"); +is($xmin, '', 'xmin of cascaded slot null with no hs_feedback'); +is($catalog_xmin, '', + 'catalog xmin of cascaded slot null with no hs_feedback'); # Replication still works? $node_master->safe_psql('postgres', 'CREATE TABLE replayed(val integer);'); @@ -210,19 +212,20 @@ $node_standby_2->reload; replay_check(); ($xmin, $catalog_xmin) = get_slot_xmins($node_master, $slotname_1, - "xmin IS NOT NULL AND catalog_xmin IS NULL"); + "xmin IS NOT NULL AND catalog_xmin IS NULL"); isnt($xmin, '', 'xmin of non-cascaded slot non-null with hs feedback'); is($catalog_xmin, '', 'catalog xmin of non-cascaded slot still null with hs_feedback'); my ($xmin1, $catalog_xmin1) = get_slot_xmins($node_standby_1, $slotname_2, - "xmin IS NOT NULL AND catalog_xmin IS NULL"); + "xmin IS NOT NULL AND catalog_xmin IS NULL"); isnt($xmin1, '', 'xmin of cascaded slot non-null with hs feedback'); is($catalog_xmin1, '', 'catalog xmin of cascaded slot still null with hs_feedback'); note "doing some work to advance xmin"; -$node_master->safe_psql('postgres', q{ +$node_master->safe_psql( + 'postgres', q{ do $$ begin for i in 10000..11000 loop @@ -239,15 +242,16 @@ end$$; $node_master->safe_psql('postgres', 'VACUUM;'); $node_master->safe_psql('postgres', 'CHECKPOINT;'); -my ($xmin2, $catalog_xmin2) = get_slot_xmins($node_master, $slotname_1, - "xmin <> '$xmin'"); +my ($xmin2, $catalog_xmin2) = + get_slot_xmins($node_master, $slotname_1, "xmin <> '$xmin'"); note "master slot's new xmin $xmin2, old xmin $xmin"; isnt($xmin2, $xmin, 'xmin of non-cascaded slot with hs feedback has changed'); is($catalog_xmin2, '', - 'catalog xmin of non-cascaded slot still null with hs_feedback unchanged'); + 'catalog xmin of non-cascaded slot still null with hs_feedback unchanged' +); -($xmin2, $catalog_xmin2) = get_slot_xmins($node_standby_1, $slotname_2, - "xmin <> '$xmin1'"); +($xmin2, $catalog_xmin2) = + get_slot_xmins($node_standby_1, $slotname_2, "xmin <> '$xmin1'"); note "standby_1 slot's new xmin $xmin2, old xmin $xmin1"; isnt($xmin2, $xmin1, 'xmin of cascaded slot with hs feedback has changed'); is($catalog_xmin2, '', @@ -265,14 +269,14 @@ $node_standby_2->reload; replay_check(); ($xmin, $catalog_xmin) = get_slot_xmins($node_master, $slotname_1, - "xmin IS NULL AND catalog_xmin IS NULL"); + "xmin IS NULL AND catalog_xmin IS NULL"); is($xmin, '', 'xmin of non-cascaded slot null with hs feedback reset'); is($catalog_xmin, '', - 'catalog xmin of non-cascaded slot still null with hs_feedback reset'); + 'catalog xmin of non-cascaded slot still null with hs_feedback reset'); ($xmin, $catalog_xmin) = get_slot_xmins($node_standby_1, $slotname_2, - "xmin IS NULL AND catalog_xmin IS NULL"); -is($xmin, '', 'xmin of cascaded slot null with hs feedback reset'); + "xmin IS NULL AND catalog_xmin IS NULL"); +is($xmin, '', 'xmin of cascaded slot null with hs feedback reset'); is($catalog_xmin, '', 'catalog xmin of cascaded slot still null with hs_feedback reset'); @@ -288,14 +292,14 @@ $node_standby_2->safe_psql('postgres', 'ALTER SYSTEM SET hot_standby_feedback = off;'); $node_standby_2->stop; -($xmin, $catalog_xmin) = get_slot_xmins($node_standby_1, $slotname_2, - "xmin IS NOT NULL"); +($xmin, $catalog_xmin) = + get_slot_xmins($node_standby_1, $slotname_2, "xmin IS NOT NULL"); isnt($xmin, '', 'xmin of cascaded slot non-null with postgres shut down'); # Xmin from a previous run should be cleared on startup. $node_standby_2->start; -($xmin, $catalog_xmin) = get_slot_xmins($node_standby_1, $slotname_2, - "xmin IS NULL"); +($xmin, $catalog_xmin) = + get_slot_xmins($node_standby_1, $slotname_2, "xmin IS NULL"); is($xmin, '', 'xmin of cascaded slot reset after startup with hs feedback reset'); diff --git a/src/test/recovery/t/006_logical_decoding.pl b/src/test/recovery/t/006_logical_decoding.pl index ea389ba463..4a90e9ac7e 100644 --- a/src/test/recovery/t/006_logical_decoding.pl +++ b/src/test/recovery/t/006_logical_decoding.pl @@ -111,8 +111,7 @@ SKIP: '-S', 'otherdb_slot', '-f', '-', '--start' ]); $node_master->poll_query_until('otherdb', "SELECT EXISTS (SELECT 1 FROM pg_replication_slots WHERE slot_name = 'otherdb_slot' AND active_pid IS NOT NULL)" - ) - or die "slot never became active"; + ) or die "slot never became active"; is($node_master->psql('postgres', 'DROP DATABASE otherdb'), 3, 'dropping a DB with active logical slots fails'); $pg_recvlogical->kill_kill; @@ -122,8 +121,7 @@ SKIP: $node_master->poll_query_until('otherdb', "SELECT EXISTS (SELECT 1 FROM pg_replication_slots WHERE slot_name = 'otherdb_slot' AND active_pid IS NULL)" -) - or die "slot never became inactive"; +) or die "slot never became inactive"; is($node_master->psql('postgres', 'DROP DATABASE otherdb'), 0, 'dropping a DB with inactive logical slots succeeds'); diff --git a/src/test/recovery/t/007_sync_rep.pl b/src/test/recovery/t/007_sync_rep.pl index 0f999f0535..e21d1a5274 100644 --- a/src/test/recovery/t/007_sync_rep.pl +++ b/src/test/recovery/t/007_sync_rep.pl @@ -23,7 +23,7 @@ sub test_sync_state $self->reload; } - ok( $self->poll_query_until('postgres', $check_sql, $expected), $msg); + ok($self->poll_query_until('postgres', $check_sql, $expected), $msg); } # Initialize master node diff --git a/src/test/recovery/t/009_twophase.pl b/src/test/recovery/t/009_twophase.pl index 1d1dae66f2..6c50139572 100644 --- a/src/test/recovery/t/009_twophase.pl +++ b/src/test/recovery/t/009_twophase.pl @@ -18,8 +18,7 @@ sub configure_and_reload 'postgresql.conf', qq( $parameter )); - $node->psql('postgres', "SELECT pg_reload_conf()", - stdout => \$psql_out); + $node->psql('postgres', "SELECT pg_reload_conf()", stdout => \$psql_out); is($psql_out, 't', "reload node $name with $parameter"); } @@ -44,7 +43,7 @@ $node_paris->start; # Switch to synchronous replication in both directions configure_and_reload($node_london, "synchronous_standby_names = 'paris'"); -configure_and_reload($node_paris, "synchronous_standby_names = 'london'"); +configure_and_reload($node_paris, "synchronous_standby_names = 'london'"); # Set up nonce names for current master and standby nodes note "Initially, london is master and paris is standby"; @@ -352,7 +351,7 @@ $cur_master->psql( 'postgres', "SELECT * FROM t_009_tbl ORDER BY id", stdout => \$psql_out); -is($psql_out, qq{1|issued to london +is( $psql_out, qq{1|issued to london 2|issued to london 5|issued to london 6|issued to london @@ -374,14 +373,15 @@ is($psql_out, qq{1|issued to london 24|issued to paris 25|issued to london 26|issued to london}, - "Check expected t_009_tbl data on master"); + "Check expected t_009_tbl data on master"); $cur_master->psql( 'postgres', "SELECT * FROM t_009_tbl2", stdout => \$psql_out); -is($psql_out, qq{27|issued to paris}, - "Check expected t_009_tbl2 data on master"); +is( $psql_out, + qq{27|issued to paris}, + "Check expected t_009_tbl2 data on master"); $cur_standby->psql( 'postgres', @@ -393,7 +393,7 @@ $cur_standby->psql( 'postgres', "SELECT * FROM t_009_tbl ORDER BY id", stdout => \$psql_out); -is($psql_out, qq{1|issued to london +is( $psql_out, qq{1|issued to london 2|issued to london 5|issued to london 6|issued to london @@ -415,11 +415,12 @@ is($psql_out, qq{1|issued to london 24|issued to paris 25|issued to london 26|issued to london}, - "Check expected t_009_tbl data on standby"); + "Check expected t_009_tbl data on standby"); $cur_standby->psql( 'postgres', "SELECT * FROM t_009_tbl2", stdout => \$psql_out); -is($psql_out, qq{27|issued to paris}, - "Check expected t_009_tbl2 data on standby"); +is( $psql_out, + qq{27|issued to paris}, + "Check expected t_009_tbl2 data on standby"); diff --git a/src/test/recovery/t/010_logical_decoding_timelines.pl b/src/test/recovery/t/010_logical_decoding_timelines.pl index d4259808dd..edc0219c9c 100644 --- a/src/test/recovery/t/010_logical_decoding_timelines.pl +++ b/src/test/recovery/t/010_logical_decoding_timelines.pl @@ -117,8 +117,7 @@ $node_master->poll_query_until( SELECT catalog_xmin IS NOT NULL FROM pg_replication_slots WHERE slot_name = 'phys_slot' - ]) - or die "slot's catalog_xmin never became set"; + ]) or die "slot's catalog_xmin never became set"; my $phys_slot = $node_master->slot('phys_slot'); isnt($phys_slot->{'xmin'}, '', 'xmin assigned on physical slot of master'); diff --git a/src/test/subscription/t/001_rep_changes.pl b/src/test/subscription/t/001_rep_changes.pl index 268808da7d..0136c79d4b 100644 --- a/src/test/subscription/t/001_rep_changes.pl +++ b/src/test/subscription/t/001_rep_changes.pl @@ -22,16 +22,15 @@ $node_publisher->safe_psql('postgres', "CREATE TABLE tab_ins AS SELECT generate_series(1,1002) AS a"); $node_publisher->safe_psql('postgres', "CREATE TABLE tab_full AS SELECT generate_series(1,10) AS a"); -$node_publisher->safe_psql('postgres', - "CREATE TABLE tab_full2 (x text)"); +$node_publisher->safe_psql('postgres', "CREATE TABLE tab_full2 (x text)"); $node_publisher->safe_psql('postgres', "INSERT INTO tab_full2 VALUES ('a'), ('b'), ('b')"); $node_publisher->safe_psql('postgres', "CREATE TABLE tab_rep (a int primary key)"); $node_publisher->safe_psql('postgres', - "CREATE TABLE tab_mixed (a int primary key, b text)"); + "CREATE TABLE tab_mixed (a int primary key, b text)"); $node_publisher->safe_psql('postgres', - "INSERT INTO tab_mixed (a, b) VALUES (1, 'foo')"); + "INSERT INTO tab_mixed (a, b) VALUES (1, 'foo')"); # Setup structure on subscriber $node_subscriber->safe_psql('postgres', "CREATE TABLE tab_notrep (a int)"); @@ -40,9 +39,10 @@ $node_subscriber->safe_psql('postgres', "CREATE TABLE tab_full (a int)"); $node_subscriber->safe_psql('postgres', "CREATE TABLE tab_full2 (x text)"); $node_subscriber->safe_psql('postgres', "CREATE TABLE tab_rep (a int primary key)"); + # different column count and order than on publisher $node_subscriber->safe_psql('postgres', - "CREATE TABLE tab_mixed (c text, b text, a int primary key)"); + "CREATE TABLE tab_mixed (c text, b text, a int primary key)"); # Setup logical replication my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres'; @@ -50,7 +50,8 @@ $node_publisher->safe_psql('postgres', "CREATE PUBLICATION tap_pub"); $node_publisher->safe_psql('postgres', "CREATE PUBLICATION tap_pub_ins_only WITH (publish = insert)"); $node_publisher->safe_psql('postgres', - "ALTER PUBLICATION tap_pub ADD TABLE tab_rep, tab_full, tab_full2, tab_mixed"); +"ALTER PUBLICATION tap_pub ADD TABLE tab_rep, tab_full, tab_full2, tab_mixed" +); $node_publisher->safe_psql('postgres', "ALTER PUBLICATION tap_pub_ins_only ADD TABLE tab_ins"); @@ -89,7 +90,8 @@ $node_publisher->safe_psql('postgres', $node_publisher->safe_psql('postgres', "DELETE FROM tab_rep WHERE a > 20"); $node_publisher->safe_psql('postgres', "UPDATE tab_rep SET a = -a"); -$node_publisher->safe_psql('postgres', "INSERT INTO tab_mixed VALUES (2, 'bar')"); +$node_publisher->safe_psql('postgres', + "INSERT INTO tab_mixed VALUES (2, 'bar')"); $node_publisher->poll_query_until('postgres', $caughtup_query) or die "Timed out while waiting for subscriber to catch up"; @@ -102,9 +104,9 @@ $result = $node_subscriber->safe_psql('postgres', "SELECT count(*), min(a), max(a) FROM tab_rep"); is($result, qq(20|-20|-1), 'check replicated changes on subscriber'); -$result = $node_subscriber->safe_psql('postgres', - "SELECT c, b, a FROM tab_mixed"); -is($result, qq(|foo|1 +$result = + $node_subscriber->safe_psql('postgres', "SELECT c, b, a FROM tab_mixed"); +is( $result, qq(|foo|1 |bar|2), 'check replicated changes with different column order'); # insert some duplicate rows @@ -127,7 +129,8 @@ $node_subscriber->safe_psql('postgres', # and do the updates $node_publisher->safe_psql('postgres', "UPDATE tab_full SET a = a * a"); -$node_publisher->safe_psql('postgres', "UPDATE tab_full2 SET x = 'bb' WHERE x = 'b'"); +$node_publisher->safe_psql('postgres', + "UPDATE tab_full2 SET x = 'bb' WHERE x = 'b'"); # Wait for subscription to catch up $node_publisher->poll_query_until('postgres', $caughtup_query) @@ -140,7 +143,7 @@ is($result, qq(20|1|100), $result = $node_subscriber->safe_psql('postgres', "SELECT x FROM tab_full2 ORDER BY 1"); -is($result, qq(a +is( $result, qq(a bb bb), 'update works with REPLICA IDENTITY FULL and text datums'); diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index c2e7f25097..159e79ee7d 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -520,10 +520,10 @@ sub mkvcbuild # Add defines from Perl's ccflags; see PGAC_CHECK_PERL_EMBED_CCFLAGS my @perl_embed_ccflags; - foreach my $f (split(" ",$Config{ccflags})) + foreach my $f (split(" ", $Config{ccflags})) { - if ($f =~ /^-D[^_]/ || - $f =~ /^-D_USE_32BIT_TIME_T/) + if ( $f =~ /^-D[^_]/ + || $f =~ /^-D_USE_32BIT_TIME_T/) { $f =~ s/\-D//; push(@perl_embed_ccflags, $f); diff --git a/src/tools/msvc/vcregress.pl b/src/tools/msvc/vcregress.pl index 5ccd5b36e1..2904679114 100644 --- a/src/tools/msvc/vcregress.pl +++ b/src/tools/msvc/vcregress.pl @@ -183,7 +183,7 @@ sub tap_check { next unless $_[$arg] =~ /^PROVE_FLAGS=(.*)/; @flags = split(/\s+/, $1); - splice(@_,$arg,1); + splice(@_, $arg, 1); last; } @@ -237,7 +237,7 @@ sub taptest die "no tests found!" unless -d "$topdir/$dir/t"; - push(@args,"$topdir/$dir"); + push(@args, "$topdir/$dir"); InstallTemp(); my $status = tap_check(@args); diff --git a/src/tools/pgindent/pgindent b/src/tools/pgindent/pgindent index 104f4c253b..a32aaa64f3 100755 --- a/src/tools/pgindent/pgindent +++ b/src/tools/pgindent/pgindent @@ -13,11 +13,12 @@ use Getopt::Long; # Update for pg_bsd_indent version my $INDENT_VERSION = "2.0"; + # Our standard indent settings my $indent_opts = - "-bad -bap -bbb -bc -bl -cli1 -cp33 -cdb -nce -d0 -di12 -nfc1 -i4 -l79 -lp -lpl -nip -npro -sac -tpg -ts4"; +"-bad -bap -bbb -bc -bl -cli1 -cp33 -cdb -nce -d0 -di12 -nfc1 -i4 -l79 -lp -lpl -nip -npro -sac -tpg -ts4"; -my $devnull = File::Spec->devnull; +my $devnull = File::Spec->devnull; my ($typedefs_file, $typedef_str, $code_base, $excludes, $indent, $build); @@ -75,7 +76,7 @@ sub check_indent if ($? == 0) { print STDERR - "You appear to have GNU indent rather than BSD indent.\n"; + "You appear to have GNU indent rather than BSD indent.\n"; exit 1; } } @@ -254,8 +255,7 @@ sub run_indent my $source = shift; my $error_message = shift; - my $cmd = - "$indent $indent_opts -U" . $filtered_typedefs_fh->filename; + my $cmd = "$indent $indent_opts -U" . $filtered_typedefs_fh->filename; my $tmp_fh = new File::Temp(TEMPLATE => "pgsrcXXXXX"); my $filename = $tmp_fh->filename; @@ -394,6 +394,7 @@ push(@files, @ARGV); foreach my $source_filename (@files) { + # Automatically ignore .c and .h files that correspond to a .y or .l # file. indent tends to get badly confused by Bison/flex output, # and there's no value in indenting derived files anyway. diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 951d80a7fb..8166d86ca1 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -307,7 +307,6 @@ CheckpointStatsData CheckpointerRequest CheckpointerShmemStruct Chromosome -City CkptSortItem CkptTsStatus ClientAuthentication_hook_type @@ -327,6 +326,7 @@ CoerceViaIO CoercionContext CoercionForm CoercionPathType +CollAliasData CollInfo CollateClause CollateExpr @@ -569,6 +569,7 @@ ExecForeignUpdate_function ExecParallelEstimateContext ExecParallelInitializeDSMContext ExecPhraseData +ExecProcNodeMtd ExecRowMark ExecScanAccessMtd ExecScanRecheckMtd @@ -1180,6 +1181,7 @@ LogicalRepRelation LogicalRepTupleData LogicalRepTyp LogicalRepWorker +LogicalRepWorkerId LogicalRewriteMappingData LogicalTape LogicalTapeSet @@ -1770,7 +1772,6 @@ RWConflictPoolHeader Range RangeBound RangeBox -RangeDatumContent RangeFunction RangeIOData RangeQueryClause @@ -1880,6 +1881,7 @@ ResourceReleaseCallback ResourceReleaseCallbackItem ResourceReleasePhase RestoreOptions +RestorePass RestrictInfo Result ResultPath @@ -2251,6 +2253,7 @@ TransactionStmt TransactionStmtKind TransformInfo TransformJsonStringValuesState +TransitionCaptureState TrgmArc TrgmArcInfo TrgmColor @@ -2388,6 +2391,7 @@ WaitEventIO WaitEventIPC WaitEventSet WaitEventTimeout +WaitPMResult WalCloseMethod WalLevel WalRcvData -- cgit v1.2.3