aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/executor/nodeSubplan.c17
-rw-r--r--src/test/regress/expected/subselect.out17
-rw-r--r--src/test/regress/sql/subselect.sql15
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
--