Add hash functions for the record type as well as a hash operator
family and operator class for the record type. This enables all the
hash functionality for the record type such as hash-based plans for
UNION/INTERSECT/EXCEPT DISTINCT, recursive queries using UNION
DISTINCT, hash joins, and hash partitioning.
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://www.postgresql.org/message-id/flat/38eccd35-4e2d-6767-1b3c-dada1eac3124%402ndquadrant.com
select x from (values (row(1, 2)), (row(1, 3))) _(x) except select x from (values (row(1, 2)), (row(1, 4))) _(x);
x
@ -708,8 +702,26 @@ select x from (values (row(1, 2)), (row(1, 3))) _(x) except select x from (value
(1 row)
-- non-hashable type
-- With an anonymous row type, the typcache reports that the type is
-- hashable, but then it will fail at run time.
explain (costs off)
select x from (values (row(100::money)), (row(200::money))) _(x) union select x from (values (row(100::money)), (row(300::money))) _(x);
QUERY PLAN
-----------------------------------------
HashAggregate
Group Key: "*VALUES*".column1
-> Append
-> Values Scan on "*VALUES*"
-> Values Scan on "*VALUES*_1"
(5 rows)
select x from (values (row(100::money)), (row(200::money))) _(x) union select x from (values (row(100::money)), (row(300::money))) _(x);
ERROR: could not identify a hash function for type money
-- With a defined row type, the typcache can inspect the type's fields
-- for hashability.
create type ct1 as (f1 money);
explain (costs off)
select x from (values (row(100::money)::ct1), (row(200::money)::ct1)) _(x) union select x from (values (row(100::money)::ct1), (row(300::money)::ct1)) _(x);
QUERY PLAN
-----------------------------------------------
Unique
@ -720,7 +732,7 @@ select x from (values (row(100::money)), (row(200::money))) _(x) union select x
-> Values Scan on "*VALUES*_1"
(6 rows)
select x from (values (row(100::money)), (row(200::money))) _(x) union select x from (values (row(100::money)), (row(300::money))) _(x);
select x from (values (row(100::money)::ct1), (row(200::money)::ct1)) _(x) union select x from (values (row(100::money)::ct1), (row(300::money)::ct1)) _(x);
x
-----------
($100.00)
@ -728,6 +740,7 @@ select x from (values (row(100::money)), (row(200::money))) _(x) union select x
($300.00)
(3 rows)
drop type ct1;
set enable_hashagg to off;
explain (costs off)
select x from (values (row(1, 2)), (row(1, 3))) _(x) union select x from (values (row(1, 2)), (row(1, 4))) _(x);