diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index 7ba1db7d7e..fa65d4efbe 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -352,9 +352,7 @@ BitmapHeapNext(BitmapHeapScanState *node) if (tbmres->recheck) { econtext->ecxt_scantuple = slot; - ResetExprContext(econtext); - - if (!ExecQual(node->bitmapqualorig, econtext)) + if (!ExecQualAndReset(node->bitmapqualorig, econtext)) { /* Fails recheck, so drop it and loop back for another */ InstrCountFiltered2(node, 1); @@ -717,10 +715,7 @@ BitmapHeapRecheck(BitmapHeapScanState *node, TupleTableSlot *slot) /* Does the tuple meet the original qual conditions? */ econtext->ecxt_scantuple = slot; - - ResetExprContext(econtext); - - return ExecQual(node->bitmapqualorig, econtext); + return ExecQualAndReset(node->bitmapqualorig, econtext); } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c index a9149ef81c..c26b8ea44e 100644 --- a/src/backend/executor/nodeHash.c +++ b/src/backend/executor/nodeHash.c @@ -1942,10 +1942,7 @@ ExecScanHashBucket(HashJoinState *hjstate, false); /* do not pfree */ econtext->ecxt_innertuple = inntuple; - /* reset temp memory each time to avoid leaks from qual expr */ - ResetExprContext(econtext); - - if (ExecQual(hjclauses, econtext)) + if (ExecQualAndReset(hjclauses, econtext)) { hjstate->hj_CurTuple = hashTuple; return true; @@ -2002,10 +1999,7 @@ ExecParallelScanHashBucket(HashJoinState *hjstate, false); /* do not pfree */ econtext->ecxt_innertuple = inntuple; - /* reset temp memory each time to avoid leaks from qual expr */ - ResetExprContext(econtext); - - if (ExecQual(hjclauses, econtext)) + if (ExecQualAndReset(hjclauses, econtext)) { hjstate->hj_CurTuple = hashTuple; return true; diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index f61b3abf32..8ffcc52bea 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -214,8 +214,7 @@ IndexOnlyNext(IndexOnlyScanState *node) if (scandesc->xs_recheck) { econtext->ecxt_scantuple = slot; - ResetExprContext(econtext); - if (!ExecQual(node->indexqual, econtext)) + if (!ExecQualAndReset(node->indexqual, econtext)) { /* Fails recheck, so drop it and loop back for another */ InstrCountFiltered2(node, 1); diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index eed69a0c66..b8b961add4 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -152,8 +152,7 @@ IndexNext(IndexScanState *node) if (scandesc->xs_recheck) { econtext->ecxt_scantuple = slot; - ResetExprContext(econtext); - if (!ExecQual(node->indexqualorig, econtext)) + if (!ExecQualAndReset(node->indexqualorig, econtext)) { /* Fails recheck, so drop it and loop back for another */ InstrCountFiltered2(node, 1); @@ -300,8 +299,7 @@ next_indextuple: if (scandesc->xs_recheck) { econtext->ecxt_scantuple = slot; - ResetExprContext(econtext); - if (!ExecQual(node->indexqualorig, econtext)) + if (!ExecQualAndReset(node->indexqualorig, econtext)) { /* Fails recheck, so drop it and loop back for another */ InstrCountFiltered2(node, 1); @@ -420,10 +418,7 @@ IndexRecheck(IndexScanState *node, TupleTableSlot *slot) /* Does the tuple meet the indexqual condition? */ econtext->ecxt_scantuple = slot; - - ResetExprContext(econtext); - - return ExecQual(node->indexqualorig, econtext); + return ExecQualAndReset(node->indexqualorig, econtext); } diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 6545a80222..1d824eff36 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -17,6 +17,7 @@ #include "catalog/partition.h" #include "executor/execdesc.h" #include "nodes/parsenodes.h" +#include "utils/memutils.h" /* @@ -381,6 +382,22 @@ ExecQual(ExprState *state, ExprContext *econtext) } #endif +/* + * ExecQualAndReset() - evaluate qual with ExecQual() and reset expression + * context. + */ +#ifndef FRONTEND +static inline bool +ExecQualAndReset(ExprState *state, ExprContext *econtext) +{ + bool ret = ExecQual(state, econtext); + + /* inline ResetExprContext, to avoid ordering issue in this file */ + MemoryContextReset(econtext->ecxt_per_tuple_memory); + return ret; +} +#endif + extern bool ExecCheck(ExprState *state, ExprContext *context); /*