mirror of
https://github.com/postgres/postgres.git
synced 2025-12-12 02:37:31 +03:00
Revise hash join and hash aggregation code to use the same datatype-
specific hash functions used by hash indexes, rather than the old not-datatype-aware ComputeHashFunc routine. This makes it safe to do hash joining on several datatypes that previously couldn't use hashing. The sets of datatypes that are hash indexable and hash joinable are now exactly the same, whereas before each had some that weren't in the other.
This commit is contained in:
@@ -436,9 +436,6 @@ WHERE p1.oprlsortop != p1.oprrsortop AND
|
||||
-- Hashing only works on simple equality operators "type = sametype",
|
||||
-- since the hash itself depends on the bitwise representation of the type.
|
||||
-- Check that allegedly hashable operators look like they might be "=".
|
||||
-- NOTE: as of 7.3, this search finds xideqint4. Since we do not mark
|
||||
-- xid and int4 as binary-equivalent in pg_cast, there's no easy way to
|
||||
-- recognize that case as OK; just leave that tuple in the expected output.
|
||||
SELECT p1.oid, p1.oprname
|
||||
FROM pg_operator AS p1
|
||||
WHERE p1.oprcanhash AND NOT
|
||||
@@ -447,8 +444,7 @@ WHERE p1.oprcanhash AND NOT
|
||||
p1.oprcom = p1.oid);
|
||||
oid | oprname
|
||||
-----+---------
|
||||
353 | =
|
||||
(1 row)
|
||||
(0 rows)
|
||||
|
||||
-- In 6.5 we accepted hashable array equality operators when the array element
|
||||
-- type is hashable. However, what we actually need to make hashjoin work on
|
||||
@@ -474,6 +470,17 @@ WHERE p1.oprcanhash AND p1.oprcode = p2.oid AND p2.proname = 'array_eq';
|
||||
-----+---------
|
||||
(0 rows)
|
||||
|
||||
-- Hashable operators should appear as members of hash index opclasses.
|
||||
SELECT p1.oid, p1.oprname
|
||||
FROM pg_operator AS p1
|
||||
WHERE p1.oprcanhash AND NOT EXISTS
|
||||
(SELECT 1 FROM pg_opclass op JOIN pg_amop p ON op.oid = amopclaid
|
||||
WHERE opcamid = (SELECT oid FROM pg_am WHERE amname = 'hash') AND
|
||||
amopopr = p1.oid);
|
||||
oid | oprname
|
||||
-----+---------
|
||||
(0 rows)
|
||||
|
||||
-- Check that each operator defined in pg_operator matches its oprcode entry
|
||||
-- in pg_proc. Easiest to do this separately for each oprkind.
|
||||
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
||||
@@ -793,3 +800,24 @@ WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree')
|
||||
-----------+-----------+-----+---------+---------
|
||||
(0 rows)
|
||||
|
||||
-- For hash we can also do a little better: the support routines must be
|
||||
-- of the form hash(something) returns int4. Ideally we'd check that the
|
||||
-- opcintype is binary-coercible to the function's input, but there are
|
||||
-- enough cases where that fails that I'll just leave out the check for now.
|
||||
SELECT p1.amopclaid, p1.amprocnum,
|
||||
p2.oid, p2.proname,
|
||||
p3.opcname
|
||||
FROM pg_amproc AS p1, pg_proc AS p2, pg_opclass AS p3
|
||||
WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'hash')
|
||||
AND p1.amopclaid = p3.oid AND p1.amproc = p2.oid AND
|
||||
(opckeytype != 0
|
||||
OR amprocnum != 1
|
||||
OR proretset
|
||||
OR prorettype != 23
|
||||
OR pronargs != 1
|
||||
-- OR NOT physically_coercible(opcintype, proargtypes[0])
|
||||
);
|
||||
amopclaid | amprocnum | oid | proname | opcname
|
||||
-----------+-----------+-----+---------+---------
|
||||
(0 rows)
|
||||
|
||||
|
||||
@@ -364,10 +364,6 @@ WHERE p1.oprlsortop != p1.oprrsortop AND
|
||||
-- since the hash itself depends on the bitwise representation of the type.
|
||||
-- Check that allegedly hashable operators look like they might be "=".
|
||||
|
||||
-- NOTE: as of 7.3, this search finds xideqint4. Since we do not mark
|
||||
-- xid and int4 as binary-equivalent in pg_cast, there's no easy way to
|
||||
-- recognize that case as OK; just leave that tuple in the expected output.
|
||||
|
||||
SELECT p1.oid, p1.oprname
|
||||
FROM pg_operator AS p1
|
||||
WHERE p1.oprcanhash AND NOT
|
||||
@@ -398,6 +394,16 @@ SELECT p1.oid, p1.oprname
|
||||
FROM pg_operator AS p1, pg_proc AS p2
|
||||
WHERE p1.oprcanhash AND p1.oprcode = p2.oid AND p2.proname = 'array_eq';
|
||||
|
||||
-- Hashable operators should appear as members of hash index opclasses.
|
||||
|
||||
SELECT p1.oid, p1.oprname
|
||||
FROM pg_operator AS p1
|
||||
WHERE p1.oprcanhash AND NOT EXISTS
|
||||
(SELECT 1 FROM pg_opclass op JOIN pg_amop p ON op.oid = amopclaid
|
||||
WHERE opcamid = (SELECT oid FROM pg_am WHERE amname = 'hash') AND
|
||||
amopopr = p1.oid);
|
||||
|
||||
|
||||
-- Check that each operator defined in pg_operator matches its oprcode entry
|
||||
-- in pg_proc. Easiest to do this separately for each oprkind.
|
||||
|
||||
@@ -665,3 +671,22 @@ WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree')
|
||||
OR pronargs != 2
|
||||
OR NOT binary_coercible(opcintype, proargtypes[0])
|
||||
OR proargtypes[0] != proargtypes[1]);
|
||||
|
||||
-- For hash we can also do a little better: the support routines must be
|
||||
-- of the form hash(something) returns int4. Ideally we'd check that the
|
||||
-- opcintype is binary-coercible to the function's input, but there are
|
||||
-- enough cases where that fails that I'll just leave out the check for now.
|
||||
|
||||
SELECT p1.amopclaid, p1.amprocnum,
|
||||
p2.oid, p2.proname,
|
||||
p3.opcname
|
||||
FROM pg_amproc AS p1, pg_proc AS p2, pg_opclass AS p3
|
||||
WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'hash')
|
||||
AND p1.amopclaid = p3.oid AND p1.amproc = p2.oid AND
|
||||
(opckeytype != 0
|
||||
OR amprocnum != 1
|
||||
OR proretset
|
||||
OR prorettype != 23
|
||||
OR pronargs != 1
|
||||
-- OR NOT physically_coercible(opcintype, proargtypes[0])
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user