diff options
-rw-r--r-- | src/backend/executor/nodeSubplan.c | 17 | ||||
-rw-r--r-- | src/test/regress/expected/subselect.out | 17 | ||||
-rw-r--r-- | src/test/regress/sql/subselect.sql | 15 |
3 files changed, 43 insertions, 6 deletions
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index d615b78373d..b501fc4f037 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -46,7 +46,8 @@ static Datum ExecScanSubPlan(SubPlanState *node, ExprContext *econtext, bool *isNull); static void buildSubPlanHash(SubPlanState *node, ExprContext *econtext); -static bool findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot); +static bool findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot, + FmgrInfo *eqfunctions); static bool slotAllNulls(TupleTableSlot *slot); static bool slotNoNulls(TupleTableSlot *slot); @@ -153,7 +154,7 @@ ExecHashSubPlan(SubPlanState *node, return BoolGetDatum(true); } if (node->havenullrows && - findPartialMatch(node->hashnulls, slot)) + findPartialMatch(node->hashnulls, slot, node->cur_eq_funcs)) { ExecClearTuple(slot); *isNull = true; @@ -186,14 +187,14 @@ ExecHashSubPlan(SubPlanState *node, } /* Scan partly-null table first, since more likely to get a match */ if (node->havenullrows && - findPartialMatch(node->hashnulls, slot)) + findPartialMatch(node->hashnulls, slot, node->cur_eq_funcs)) { ExecClearTuple(slot); *isNull = true; return BoolGetDatum(false); } if (node->havehashrows && - findPartialMatch(node->hashtable, slot)) + findPartialMatch(node->hashtable, slot, node->cur_eq_funcs)) { ExecClearTuple(slot); *isNull = true; @@ -573,9 +574,13 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext) * We have to scan the whole hashtable; we can't usefully use hashkeys * to guide probing, since we might get partial matches on tuples with * hashkeys quite unrelated to what we'd get from the given tuple. + * + * Caller must provide the equality functions to use, since in cross-type + * cases these are different from the hashtable's internal functions. */ static bool -findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot) +findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot, + FmgrInfo *eqfunctions) { int numCols = hashtable->numCols; AttrNumber *keyColIdx = hashtable->keyColIdx; @@ -588,7 +593,7 @@ findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot) ExecStoreMinimalTuple(entry->firstTuple, hashtable->tableslot, false); if (!execTuplesUnequal(slot, hashtable->tableslot, numCols, keyColIdx, - hashtable->cur_eq_funcs, + eqfunctions, hashtable->tempcxt)) { TermTupleHashIterator(&hashiter); diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out index 30cff04cb70..6a81df95386 100644 --- a/src/test/regress/expected/subselect.out +++ b/src/test/regress/expected/subselect.out @@ -544,6 +544,23 @@ from (0 rows) -- +-- Test case for cross-type partial matching in hashed subplan (bug #7597) +-- +create temp table outer_7597 (f1 int4, f2 int4); +insert into outer_7597 values (0, 0); +insert into outer_7597 values (1, 0); +insert into outer_7597 values (0, null); +insert into outer_7597 values (1, null); +create temp table inner_7597(c1 int8, c2 int8); +insert into inner_7597 values(0, null); +select * from outer_7597 where (f1, f2) not in (select * from inner_7597); + f1 | f2 +----+---- + 1 | 0 + 1 | +(2 rows) + +-- -- Test case for premature memory release during hashing of subplan output -- select '1'::text in (select '1'::name union all select '1'::name); diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql index e07a30ed03b..cba449a203d 100644 --- a/src/test/regress/sql/subselect.sql +++ b/src/test/regress/sql/subselect.sql @@ -346,6 +346,21 @@ from int4_tbl i4 on dummy = i4.f1; -- +-- Test case for cross-type partial matching in hashed subplan (bug #7597) +-- + +create temp table outer_7597 (f1 int4, f2 int4); +insert into outer_7597 values (0, 0); +insert into outer_7597 values (1, 0); +insert into outer_7597 values (0, null); +insert into outer_7597 values (1, null); + +create temp table inner_7597(c1 int8, c2 int8); +insert into inner_7597 values(0, null); + +select * from outer_7597 where (f1, f2) not in (select * from inner_7597); + +-- -- Test case for premature memory release during hashing of subplan output -- |