agora inbox for [email protected]
help / color / mirror / Atom feed[PATCH 1/2] Move interrupt checking from ExecProcNode() to executor nodes.
4+ messages / 3 participants
[nested] [flat]
* [PATCH 1/2] Move interrupt checking from ExecProcNode() to executor nodes.
@ 2017-07-26 00:37 Andres Freund <[email protected]>
0 siblings, 0 replies; 4+ messages in thread
From: Andres Freund @ 2017-07-26 00:37 UTC (permalink / raw)
In a followup commit ExecProcNode(), and especially the large switch
it contains, will 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
missing interrupt checks, add these too.
Author: Andres Freund
Reviewed-By: Tom Lane
Discussion:
https://postgr.es/m/[email protected]
---
src/backend/executor/execProcnode.c | 2 --
src/backend/executor/execScan.c | 1 +
src/backend/executor/nodeAgg.c | 5 +++++
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 | 9 ++-------
src/backend/executor/nodeIndexonlyscan.c | 3 +++
src/backend/executor/nodeIndexscan.c | 6 ++++++
src/backend/executor/nodeLimit.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, 92 insertions(+), 10 deletions(-)
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/execScan.c b/src/backend/executor/execScan.c
index 4f131b3ee0..dc40f6b699 100644
--- a/src/backend/executor/execScan.c
+++ b/src/backend/executor/execScan.c
@@ -139,6 +139,7 @@ ExecScan(ScanState *node,
*/
if (!qual && !projInfo)
{
+ CHECK_FOR_INTERRUPTS();
ResetExprContext(econtext);
return ExecScanFetch(node, accessMtd, recheckMtd);
}
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index de9a18e71c..c1096ed8b0 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -677,6 +677,7 @@ fetch_input_tuple(AggState *aggstate)
if (aggstate->sort_in)
{
+ CHECK_FOR_INTERRUPTS();
if (!tuplesort_gettupleslot(aggstate->sort_in, true, false,
aggstate->sort_slot, NULL))
return NULL;
@@ -1414,6 +1415,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
@@ -2563,6 +2566,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..e28e41df59 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"
@@ -105,6 +106,8 @@ TupleTableSlot *
ExecCustomScan(CustomScanState *node)
{
Assert(node->methods->ExecCustomScan != NULL);
+ CHECK_FOR_INTERRUPTS();
+
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..917c3b6cef 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -92,6 +92,8 @@ ExecHashJoin(HashJoinState *node)
*/
for (;;)
{
+ CHECK_FOR_INTERRUPTS();
+
switch (node->hj_JoinState)
{
case HJ_BUILD_HASHTABLE:
@@ -246,13 +248,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..581a2092be 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,7 @@ next_indextuple:
{
/* Fails recheck, so drop it and loop back for another */
InstrCountFiltered2(node, 1);
+ 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/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..657af4692f 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"
@@ -634,6 +635,8 @@ ExecMergeJoin(MergeJoinState *node)
{
MJ_dump(node);
+ CHECK_FOR_INTERRUPTS();
+
/*
* get the current state of the join and do things accordingly.
*/
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..ec8862653e 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"
@@ -95,6 +96,8 @@ ExecNestLoop(NestLoopState *node)
for (;;)
{
+ CHECK_FOR_INTERRUPTS();
+
/*
* If we don't have an outer tuple, get the next one and reset the
* inner scan.
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;
--
2.13.1.392.g8d1b10321b.dirty
--qd4kdyuvxjcfqsa2
Content-Type: text/plain
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
MIME-Version: 1.0
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
--qd4kdyuvxjcfqsa2--
^ permalink raw reply [nested|flat] 4+ messages in thread
* [PATCH 1/2] Move interrupt checking from ExecProcNode() to callers.
@ 2017-07-26 00:37 Andres Freund <[email protected]>
0 siblings, 0 replies; 4+ messages in thread
From: Andres Freund @ 2017-07-26 00:37 UTC (permalink / raw)
---
contrib/postgres_fdw/postgres_fdw.c | 2 ++
src/backend/executor/execMain.c | 2 ++
src/backend/executor/execProcnode.c | 2 --
src/backend/executor/nodeAgg.c | 2 ++
src/backend/executor/nodeAppend.c | 3 +++
src/backend/executor/nodeCtescan.c | 2 ++
src/backend/executor/nodeCustom.c | 3 +++
src/backend/executor/nodeForeignscan.c | 3 +++
src/backend/executor/nodeGather.c | 2 ++
src/backend/executor/nodeGatherMerge.c | 2 ++
src/backend/executor/nodeGroup.c | 6 +++++
src/backend/executor/nodeHash.c | 4 +++
src/backend/executor/nodeHashjoin.c | 21 +++++----------
src/backend/executor/nodeLimit.c | 4 +++
src/backend/executor/nodeLockRows.c | 2 ++
src/backend/executor/nodeMaterial.c | 2 ++
src/backend/executor/nodeMergeAppend.c | 6 ++++-
src/backend/executor/nodeMergejoin.c | 3 +++
src/backend/executor/nodeModifyTable.c | 2 ++
src/backend/executor/nodeNestloop.c | 3 +++
src/backend/executor/nodeProjectSet.c | 5 ++++
src/backend/executor/nodeRecursiveunion.c | 2 ++
src/backend/executor/nodeResult.c | 3 +++
src/backend/executor/nodeSetOp.c | 9 +++++++
src/backend/executor/nodeSort.c | 4 +++
src/backend/executor/nodeSubplan.c | 44 +++++++++++++++++++++++--------
src/backend/executor/nodeSubqueryscan.c | 3 +++
src/backend/executor/nodeUnique.c | 3 +++
src/backend/executor/nodeWindowAgg.c | 8 +++++-
29 files changed, 128 insertions(+), 29 deletions(-)
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index d77c2a70e4..0b2093f34b 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -2079,6 +2079,8 @@ postgresRecheckForeignScan(ForeignScanState *node, TupleTableSlot *slot)
Assert(outerPlan != NULL);
+ CHECK_FOR_INTERRUPTS();
+
/* Execute a local join execution plan */
result = ExecProcNode(outerPlan);
if (TupIsNull(result))
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 78cbcd1a32..a58a70e3f5 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1542,6 +1542,8 @@ ExecPostprocessPlan(EState *estate)
{
TupleTableSlot *slot;
+ CHECK_FOR_INTERRUPTS();
+
/* Reset the per-output-tuple exprcontext each time */
ResetPerTupleExprContext(estate);
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..f9073e79aa 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -675,6 +675,8 @@ fetch_input_tuple(AggState *aggstate)
{
TupleTableSlot *slot;
+ CHECK_FOR_INTERRUPTS();
+
if (aggstate->sort_in)
{
if (!tuplesort_gettupleslot(aggstate->sort_in, true, false,
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/nodeCtescan.c b/src/backend/executor/nodeCtescan.c
index bed7949c5a..e7d3c69c4b 100644
--- a/src/backend/executor/nodeCtescan.c
+++ b/src/backend/executor/nodeCtescan.c
@@ -37,6 +37,8 @@ CteScanNext(CteScanState *node)
bool eof_tuplestore;
TupleTableSlot *slot;
+ CHECK_FOR_INTERRUPTS();
+
/*
* get state info from node
*/
diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c
index 69e27047f1..e28e41df59 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"
@@ -105,6 +106,8 @@ TupleTableSlot *
ExecCustomScan(CustomScanState *node)
{
Assert(node->methods->ExecCustomScan != NULL);
+ CHECK_FOR_INTERRUPTS();
+
return node->methods->ExecCustomScan(node);
}
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index 9cde112554..2873f24e36 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -25,6 +25,7 @@
#include "executor/executor.h"
#include "executor/nodeForeignscan.h"
#include "foreign/fdwapi.h"
+#include "miscadmin.h"
#include "utils/memutils.h"
#include "utils/rel.h"
@@ -46,6 +47,8 @@ ForeignNext(ForeignScanState *node)
ExprContext *econtext = node->ss.ps.ps_ExprContext;
MemoryContext oldcontext;
+ CHECK_FOR_INTERRUPTS();
+
/* Call the Iterate function in short-lived context */
oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
if (plan->operation != CMD_SELECT)
diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c
index f83cd584d7..7f12b526ba 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -247,6 +247,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..a7065b4519 100644
--- a/src/backend/executor/nodeGatherMerge.c
+++ b/src/backend/executor/nodeGatherMerge.c
@@ -533,6 +533,8 @@ gather_merge_readnext(GatherMergeState *gm_state, int reader, bool nowait)
GMReaderTupleBuffer *tuple_buffer;
HeapTuple tup = NULL;
+ CHECK_FOR_INTERRUPTS();
+
/*
* If we're being asked to generate a tuple from the leader, then we just
* call ExecProcNode as normal to produce one.
diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c
index af9ba4905e..a83d88efd8 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"
/*
@@ -45,6 +46,9 @@ ExecGroup(GroupState *node)
*/
if (node->grp_done)
return NULL;
+
+ CHECK_FOR_INTERRUPTS();
+
econtext = node->ss.ps.ps_ExprContext;
numCols = ((Group *) node->ss.ps.plan)->numCols;
grpColIdx = ((Group *) node->ss.ps.plan)->grpColIdx;
@@ -108,6 +112,8 @@ ExecGroup(GroupState *node)
*/
for (;;)
{
+ CHECK_FOR_INTERRUPTS();
+
outerslot = ExecProcNode(outerPlanState(node));
if (TupIsNull(outerslot))
{
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index 075f4ed11c..1ba4366d75 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -101,6 +101,8 @@ MultiExecHash(HashState *node)
*/
for (;;)
{
+ CHECK_FOR_INTERRUPTS();
+
slot = ExecProcNode(outerNode);
if (TupIsNull(slot))
break;
@@ -1145,6 +1147,8 @@ ExecScanHashTableForUnmatched(HashJoinState *hjstate, ExprContext *econtext)
for (;;)
{
+ CHECK_FOR_INTERRUPTS();
+
/*
* hj_CurTuple is the address of the tuple last returned from the
* current bucket, or NULL if it's time to start scanning a new
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index 668ed871e1..0a9595948c 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -92,6 +92,8 @@ ExecHashJoin(HashJoinState *node)
*/
for (;;)
{
+ CHECK_FOR_INTERRUPTS();
+
switch (node->hj_JoinState)
{
case HJ_BUILD_HASHTABLE:
@@ -246,13 +248,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
*/
@@ -596,6 +591,8 @@ ExecHashJoinOuterGetTuple(PlanState *outerNode,
int curbatch = hashtable->curbatch;
TupleTableSlot *slot;
+ CHECK_FOR_INTERRUPTS();
+
if (curbatch == 0) /* if it is the first pass */
{
/*
@@ -632,6 +629,7 @@ ExecHashJoinOuterGetTuple(PlanState *outerNode,
* That tuple couldn't match because of a NULL, so discard it and
* continue with the next one.
*/
+ CHECK_FOR_INTERRUPTS();
slot = ExecProcNode(outerNode);
}
}
@@ -771,6 +769,8 @@ ExecHashJoinNewBatch(HashJoinState *hjstate)
&hashvalue,
hjstate->hj_HashTupleSlot)))
{
+ CHECK_FOR_INTERRUPTS();
+
/*
* NOTE: some tuples may be sent to future batches. Also, it is
* possible for hashtable->nbatch to be increased here!
@@ -855,13 +855,6 @@ ExecHashJoinGetSavedTuple(HashJoinState *hjstate,
size_t nread;
MinimalTuple tuple;
- /*
- * We check for interrupts here because this is typically taken as an
- * alternative code path to an ExecProcNode() call, which would include
- * such a check.
- */
- CHECK_FOR_INTERRUPTS();
-
/*
* Since both the hash value and the MinimalTuple length word are uint32,
* we can read them both in one BufFileRead() call without any type
diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c
index abd060d75f..c6aaa5bdd4 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
*/
@@ -88,6 +91,7 @@ ExecLimit(LimitState *node)
*/
for (;;)
{
+ CHECK_FOR_INTERRUPTS();
slot = ExecProcNode(outerPlan);
if (TupIsNull(slot))
{
diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c
index f519794cf3..424fd0593d 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"
@@ -54,6 +55,7 @@ ExecLockRows(LockRowsState *node)
* Get next tuple from subplan, if any.
*/
lnext:
+ CHECK_FOR_INTERRUPTS();
slot = ExecProcNode(outerPlan);
if (TupIsNull(slot))
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..8e0ce1ef3f 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
@@ -183,6 +183,8 @@ ExecMergeAppend(MergeAppendState *node)
*/
for (i = 0; i < node->ms_nplans; i++)
{
+ CHECK_FOR_INTERRUPTS();
+
node->ms_slots[i] = ExecProcNode(node->mergeplans[i]);
if (!TupIsNull(node->ms_slots[i]))
binaryheap_add_unordered(node->ms_heap, Int32GetDatum(i));
@@ -192,6 +194,8 @@ ExecMergeAppend(MergeAppendState *node)
}
else
{
+ CHECK_FOR_INTERRUPTS();
+
/*
* Otherwise, pull the next tuple from whichever subplan we returned
* from last time, and reinsert the subplan index into the heap,
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index 6a145ee33a..657af4692f 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"
@@ -634,6 +635,8 @@ ExecMergeJoin(MergeJoinState *node)
{
MJ_dump(node);
+ CHECK_FOR_INTERRUPTS();
+
/*
* get the current state of the join and do things accordingly.
*/
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 77ba15dd90..11cb207b34 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -1603,6 +1603,8 @@ ExecModifyTable(ModifyTableState *node)
*/
for (;;)
{
+ CHECK_FOR_INTERRUPTS();
+
/*
* Reset the per-output-tuple exprcontext. This is needed because
* triggers expect to use that context as workspace. It's a bit ugly
diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c
index 0065fe601e..ec8862653e 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"
@@ -95,6 +96,8 @@ ExecNestLoop(NestLoopState *node)
for (;;)
{
+ CHECK_FOR_INTERRUPTS();
+
/*
* If we don't have an outer tuple, get the next one and reset the
* inner scan.
diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c
index 01048cc826..fbce3e09c5 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"
@@ -55,6 +56,8 @@ ExecProjectSet(ProjectSetState *node)
*/
if (node->pending_srf_tuples)
{
+ CHECK_FOR_INTERRUPTS();
+
resultSlot = ExecProjectSRF(node, true);
if (resultSlot != NULL)
@@ -76,6 +79,8 @@ ExecProjectSet(ProjectSetState *node)
/*
* Retrieve tuples from the outer plan until there are no more.
*/
+ CHECK_FOR_INTERRUPTS();
+
outerPlan = outerPlanState(node);
outerTupleSlot = ExecProcNode(outerPlan);
diff --git a/src/backend/executor/nodeRecursiveunion.c b/src/backend/executor/nodeRecursiveunion.c
index fc1c00d68f..7b5f5a972c 100644
--- a/src/backend/executor/nodeRecursiveunion.c
+++ b/src/backend/executor/nodeRecursiveunion.c
@@ -80,6 +80,7 @@ ExecRecursiveUnion(RecursiveUnionState *node)
{
for (;;)
{
+ CHECK_FOR_INTERRUPTS();
slot = ExecProcNode(outerPlan);
if (TupIsNull(slot))
break;
@@ -104,6 +105,7 @@ ExecRecursiveUnion(RecursiveUnionState *node)
/* 2. Execute recursive term */
for (;;)
{
+ CHECK_FOR_INTERRUPTS();
slot = ExecProcNode(innerPlan);
if (TupIsNull(slot))
{
diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c
index a753a53419..eec3048245 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"
@@ -101,6 +102,8 @@ ExecResult(ResultState *node)
*/
while (!node->rs_done)
{
+ CHECK_FOR_INTERRUPTS();
+
outerPlan = outerPlanState(node);
if (outerPlan != NULL)
diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c
index 9c7812e519..0e8f1b2a72 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"
@@ -234,6 +235,8 @@ setop_retrieve_direct(SetOpState *setopstate)
*/
while (!setopstate->setop_done)
{
+ CHECK_FOR_INTERRUPTS();
+
/*
* If we don't already have the first tuple of the new group, fetch it
* from the outer plan.
@@ -277,6 +280,8 @@ setop_retrieve_direct(SetOpState *setopstate)
*/
for (;;)
{
+ CHECK_FOR_INTERRUPTS();
+
outerslot = ExecProcNode(outerPlan);
if (TupIsNull(outerslot))
{
@@ -358,6 +363,8 @@ setop_fill_hash_table(SetOpState *setopstate)
TupleHashEntryData *entry;
bool isnew;
+ CHECK_FOR_INTERRUPTS();
+
outerslot = ExecProcNode(outerPlan);
if (TupIsNull(outerslot))
break;
@@ -428,6 +435,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..e74fa48124 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
*/
@@ -100,6 +102,8 @@ ExecSort(SortState *node)
for (;;)
{
+ CHECK_FOR_INTERRUPTS();
+
slot = ExecProcNode(outerNode);
if (TupIsNull(slot))
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index e8fa4c8547..cbd790c9e4 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"
@@ -307,16 +308,23 @@ ExecScanSubPlan(SubPlanState *node,
result = BoolGetDatum(subLinkType == ALL_SUBLINK);
*isNull = false;
- for (slot = ExecProcNode(planstate);
- !TupIsNull(slot);
- slot = ExecProcNode(planstate))
+ for (;;)
{
- TupleDesc tdesc = slot->tts_tupleDescriptor;
+ TupleDesc tdesc;
Datum rowresult;
bool rownull;
int col;
ListCell *plst;
+ CHECK_FOR_INTERRUPTS();
+
+ slot = ExecProcNode(planstate);
+
+ if (TupIsNull(slot))
+ break;
+
+ tdesc = slot->tts_tupleDescriptor;
+
if (subLinkType == EXISTS_SUBLINK)
{
found = true;
@@ -537,14 +545,19 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
* Scan the subplan and load the hash table(s). Note that when there are
* duplicate rows coming out of the sub-select, only one copy is stored.
*/
- for (slot = ExecProcNode(planstate);
- !TupIsNull(slot);
- slot = ExecProcNode(planstate))
+ for (;;)
{
int col = 1;
ListCell *plst;
bool isnew;
+ CHECK_FOR_INTERRUPTS();
+
+ slot = ExecProcNode(planstate);
+
+ if (TupIsNull(slot))
+ break;
+
/*
* Load up the Params representing the raw sub-select outputs, then
* form the projection tuple to store in the hashtable.
@@ -618,6 +631,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,
@@ -960,13 +975,20 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
* Run the plan. (If it needs to be rescanned, the first ExecProcNode
* call will take care of that.)
*/
- for (slot = ExecProcNode(planstate);
- !TupIsNull(slot);
- slot = ExecProcNode(planstate))
+ for (;;)
{
- TupleDesc tdesc = slot->tts_tupleDescriptor;
+ TupleDesc tdesc;
int i = 1;
+ CHECK_FOR_INTERRUPTS();
+
+ slot = ExecProcNode(planstate);
+
+ if (TupIsNull(slot))
+ break;
+
+ tdesc = slot->tts_tupleDescriptor;
+
if (subLinkType == EXISTS_SUBLINK)
{
/* There can be only one setParam... */
diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c
index ae184700a6..83b1b2b085 100644
--- a/src/backend/executor/nodeSubqueryscan.c
+++ b/src/backend/executor/nodeSubqueryscan.c
@@ -29,6 +29,7 @@
#include "executor/execdebug.h"
#include "executor/nodeSubqueryscan.h"
+#include "miscadmin.h"
static TupleTableSlot *SubqueryNext(SubqueryScanState *node);
@@ -47,6 +48,8 @@ SubqueryNext(SubqueryScanState *node)
{
TupleTableSlot *slot;
+ CHECK_FOR_INTERRUPTS();
+
/*
* Get the next tuple from the sub-query.
*/
diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c
index 28cc1e90f8..9f101375ef 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"
@@ -63,6 +64,8 @@ ExecUnique(UniqueState *node)
*/
for (;;)
{
+ CHECK_FOR_INTERRUPTS();
+
/*
* fetch a tuple from the outer subplan
*/
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 8f13fe0c73..838d3458d5 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -1079,7 +1079,11 @@ begin_partition(WindowAggState *winstate)
*/
if (TupIsNull(winstate->first_part_slot))
{
- TupleTableSlot *outerslot = ExecProcNode(outerPlan);
+ TupleTableSlot *outerslot;
+
+ CHECK_FOR_INTERRUPTS();
+
+ outerslot = ExecProcNode(outerPlan);
if (!TupIsNull(outerslot))
ExecCopySlot(winstate->first_part_slot, outerslot);
@@ -1191,6 +1195,8 @@ spool_tuples(WindowAggState *winstate, int64 pos)
while (winstate->spooled_rows <= pos || pos == -1)
{
+ CHECK_FOR_INTERRUPTS();
+
outerslot = ExecProcNode(outerPlan);
if (TupIsNull(outerslot))
{
--
2.13.1.392.g8d1b10321b.dirty
--gc4vl4obf6kp2jah
Content-Type: text/x-patch; charset=us-ascii
Content-Disposition: attachment;
filename="0002-Move-ExecProcNode-from-dispatch-to-function-pointer-.patch"
^ permalink raw reply [nested|flat] 4+ messages in thread
* [PATCH v24 2/7] psql: Add HIDE_COMPRESSAM for regress testing
@ 2021-02-14 02:48 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 4+ messages in thread
From: Justin Pryzby @ 2021-02-14 02:48 UTC (permalink / raw)
This avoids churn in regression output, and allows testing with alternate
compression AMs.
---
doc/src/sgml/ref/psql-ref.sgml | 11 +++++++++++
src/bin/psql/describe.c | 1 +
src/bin/psql/help.c | 2 ++
src/bin/psql/settings.h | 1 +
src/bin/psql/startup.c | 9 +++++++++
src/test/regress/pg_regress_main.c | 4 ++--
6 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 13c1edfa4d..66dcb1b33b 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -3863,6 +3863,17 @@ bar
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>HIDE_COMPRESSAM</varname></term>
+ <listitem>
+ <para>
+ If this variable is set to <literal>true</literal>, column's
+ compression access method details are not displayed. This is mainly
+ useful for regression tests.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>HIDE_TABLEAM</varname></term>
<listitem>
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index ba464d463e..b835b0cf76 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -1897,6 +1897,7 @@ describeOneTableDetails(const char *schemaname,
/* compresssion info */
if (pset.sversion >= 140000 &&
+ !pset.hide_compressam &&
(tableinfo.relkind == RELKIND_RELATION ||
tableinfo.relkind == RELKIND_PARTITIONED_TABLE ||
tableinfo.relkind == RELKIND_MATVIEW))
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index e44120bf76..a818ee5503 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -375,6 +375,8 @@ helpVariables(unsigned short int pager)
" true if last query failed, else false\n"));
fprintf(output, _(" FETCH_COUNT\n"
" the number of result rows to fetch and display at a time (0 = unlimited)\n"));
+ fprintf(output, _(" HIDE_COMPRESSAM\n"
+ " if set, compression access methods are not displayed\n"));
fprintf(output, _(" HIDE_TABLEAM\n"
" if set, table access methods are not displayed\n"));
fprintf(output, _(" HISTCONTROL\n"
diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h
index d65990059d..9755e8eac6 100644
--- a/src/bin/psql/settings.h
+++ b/src/bin/psql/settings.h
@@ -134,6 +134,7 @@ typedef struct _psqlSettings
bool quiet;
bool singleline;
bool singlestep;
+ bool hide_compressam;
bool hide_tableam;
int fetch_count;
int histsize;
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index 780479c8d7..554b64367d 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -1159,6 +1159,12 @@ show_context_hook(const char *newval)
return true;
}
+static bool
+hide_compressam_hook(const char *newval)
+{
+ return ParseVariableBool(newval, "HIDE_COMPRESSAM", &pset.hide_compressam);
+}
+
static bool
hide_tableam_hook(const char *newval)
{
@@ -1227,6 +1233,9 @@ EstablishVariableSpace(void)
SetVariableHooks(pset.vars, "SHOW_CONTEXT",
show_context_substitute_hook,
show_context_hook);
+ SetVariableHooks(pset.vars, "HIDE_COMPRESSAM",
+ bool_substitute_hook,
+ hide_compressam_hook);
SetVariableHooks(pset.vars, "HIDE_TABLEAM",
bool_substitute_hook,
hide_tableam_hook);
diff --git a/src/test/regress/pg_regress_main.c b/src/test/regress/pg_regress_main.c
index 8dc4941c24..07fd3f6a4d 100644
--- a/src/test/regress/pg_regress_main.c
+++ b/src/test/regress/pg_regress_main.c
@@ -78,11 +78,11 @@ psql_start_test(const char *testname,
* against different AMs without unnecessary differences.
*/
offset += snprintf(psql_cmd + offset, sizeof(psql_cmd) - offset,
- "\"%s%spsql\" -X -a -q -d \"%s\" -v %s < \"%s\" > \"%s\" 2>&1",
+ "\"%s%spsql\" -X -a -q -d \"%s\" %s < \"%s\" > \"%s\" 2>&1",
bindir ? bindir : "",
bindir ? "/" : "",
dblist->str,
- "HIDE_TABLEAM=\"on\"",
+ "-v HIDE_TABLEAM=on -v HIDE_COMPRESSAM=on",
infile,
outfile);
if (offset >= sizeof(psql_cmd))
--
2.17.0
--YZ5djTAD1cGYuMQK
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v24-0003-Add-default_toast_compression-GUC.patch"
^ permalink raw reply [nested|flat] 4+ messages in thread
* Re: SQL:2011 application time
@ 2022-01-15 05:58 Julien Rouhaud <[email protected]>
0 siblings, 0 replies; 4+ messages in thread
From: Julien Rouhaud @ 2022-01-15 05:58 UTC (permalink / raw)
To: Paul A Jungwirth <[email protected]>; +Cc: Corey Huinker <[email protected]>; Jaime Casanova <[email protected]>; PostgreSQL Hackers <[email protected]>
Hi,
On Sat, Nov 20, 2021 at 05:51:16PM -0800, Paul A Jungwirth wrote:
>
> Here are updated patches. They are rebased and clean up some of my TODOs.
The cfbot reports that the patchset doesn't apply anymore:
http://cfbot.cputube.org/patch_36_2048.log
=== Applying patches on top of PostgreSQL commit ID 5513dc6a304d8bda114004a3b906cc6fde5d6274 ===
=== applying patch ./v10-0001-Add-PERIODs.patch
patching file src/backend/commands/tablecmds.c
Hunk #1 FAILED at 40.
[...]
1 out of 21 hunks FAILED -- saving rejects to file src/backend/commands/tablecmds.c.rej
patching file src/bin/pg_dump/pg_dump.c
Hunk #1 succeeded at 5906 with fuzz 2 (offset -454 lines).
Hunk #2 FAILED at 6425.
Hunk #3 succeeded at 6121 with fuzz 2 (offset -566 lines).
Hunk #4 succeeded at 6203 (offset -561 lines).
Hunk #5 succeeded at 8015 with fuzz 2 (offset -539 lines).
Hunk #6 FAILED at 8862.
Hunk #7 FAILED at 8875.
Hunk #8 FAILED at 8917.
[...]
4 out of 15 hunks FAILED -- saving rejects to file src/bin/pg_dump/pg_dump.c.rej
patching file src/bin/pg_dump/pg_dump.h
Hunk #2 FAILED at 284.
Hunk #3 FAILED at 329.
Hunk #4 succeeded at 484 (offset 15 lines).
2 out of 4 hunks FAILED -- saving rejects to file src/bin/pg_dump/pg_dump.h.rej
I also see that there were multiple reviews with unanswered comments, so I will
switch the cf entry to Waiting on Author.
^ permalink raw reply [nested|flat] 4+ messages in thread
end of thread, other threads:[~2022-01-15 05:58 UTC | newest]
Thread overview: 4+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2017-07-26 00:37 [PATCH 1/2] Move interrupt checking from ExecProcNode() to executor nodes. Andres Freund <[email protected]>
2017-07-26 00:37 [PATCH 1/2] Move interrupt checking from ExecProcNode() to callers. Andres Freund <[email protected]>
2021-02-14 02:48 [PATCH v24 2/7] psql: Add HIDE_COMPRESSAM for regress testing Justin Pryzby <[email protected]>
2022-01-15 05:58 Re: SQL:2011 application time Julien Rouhaud <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox