From 6478896675660402171c97d6307e6e1519250025 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 16 Jan 2022 16:39:26 -0500 Subject: [PATCH] Teach hash_ok_operator() that record_eq is only sometimes hashable. The need for this was foreseen long ago, but when record_eq actually became hashable (in commit 01e658fa7), we missed updating this spot. Per bug #17363 from Elvis Pranskevichus. Back-patch to v14 where the faulty commit came in. Discussion: https://postgr.es/m/17363-f6d42fd0d726be02@postgresql.org --- src/backend/optimizer/plan/subselect.c | 6 +++--- src/test/regress/expected/subselect.out | 23 +++++++++++++++++++++++ src/test/regress/sql/subselect.sql | 10 ++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 8c9408d372..41bd1ae7d4 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -848,10 +848,10 @@ hash_ok_operator(OpExpr *expr) /* quick out if not a binary operator */ if (list_length(expr->args) != 2) return false; - if (opid == ARRAY_EQ_OP) + if (opid == ARRAY_EQ_OP || + opid == RECORD_EQ_OP) { - /* array_eq is strict, but must check input type to ensure hashable */ - /* XXX record_eq will need same treatment when it becomes hashable */ + /* these are strict, but must check input type to ensure hashable */ Node *leftarg = linitial(expr->args); return op_hashjoinable(opid, exprType(leftarg)); diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out index 4e8ddc7061..45c75eecc5 100644 --- a/src/test/regress/expected/subselect.out +++ b/src/test/regress/expected/subselect.out @@ -789,6 +789,29 @@ select 'foo'::text in (select 'bar'::name union all select 'bar'::name); f (1 row) +-- +-- Test that we don't try to hash nested records (bug #17363) +-- (Hashing could be supported, but for now we don't) +-- +explain (verbose, costs off) +select row(row(row(1))) = any (select row(row(1))); + QUERY PLAN +------------------------------------------- + Result + Output: (SubPlan 1) + SubPlan 1 + -> Materialize + Output: '("(1)")'::record + -> Result + Output: '("(1)")'::record +(7 rows) + +select row(row(row(1))) = any (select row(row(1))); + ?column? +---------- + t +(1 row) + -- -- Test case for premature memory release during hashing of subplan output -- diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql index e879999708..94ba91f5bb 100644 --- a/src/test/regress/sql/subselect.sql +++ b/src/test/regress/sql/subselect.sql @@ -463,6 +463,16 @@ select 'foo'::text in (select 'bar'::name union all select 'bar'::name); select 'foo'::text in (select 'bar'::name union all select 'bar'::name); +-- +-- Test that we don't try to hash nested records (bug #17363) +-- (Hashing could be supported, but for now we don't) +-- + +explain (verbose, costs off) +select row(row(row(1))) = any (select row(row(1))); + +select row(row(row(1))) = any (select row(row(1))); + -- -- Test case for premature memory release during hashing of subplan output --