Clean up/tighten up coercibility checks in opr_sanity regression test.
With the removal of the old abstime type, there are no longer any cases in this test where we need to use the weaker castcontext-ignoring form of binary coercibility check. (The other major source of such headaches, apparently-incompatible hash functions, is now hashvalidate()'s problem not this test script's problem.) Hence, just use binary_coercible() everywhere, and remove the comments explaining why we don't do so --- which were broken anyway by cda6a8d01. I left physically_coercible() in place but renamed it to better match what it's actually testing, and added some comments. Also, in test queries that have an assumption about the maximum number of function arguments they need to handle, add a clause to make them fail if someday there's a relevant function with more arguments. Otherwise we're likely not to notice that we need to extend the queries. Discussion: https://postgr.es/m/27637.1539388060@sss.pgh.pa.us
This commit is contained in:
parent
1df21ddb19
commit
e9f42d529f
@ -19,6 +19,8 @@
|
||||
-- Helper functions to deal with cases where binary-coercible matches are
|
||||
-- allowed.
|
||||
-- This should match IsBinaryCoercible() in parse_coerce.c.
|
||||
-- It doesn't currently know about some cases, notably domains, anyelement,
|
||||
-- anynonarray, anyenum, or record, but it doesn't need to (yet).
|
||||
create function binary_coercible(oid, oid) returns bool as $$
|
||||
begin
|
||||
if $1 = $2 then return true; end if;
|
||||
@ -39,9 +41,11 @@ begin
|
||||
return false;
|
||||
end
|
||||
$$ language plpgsql strict stable;
|
||||
-- This one ignores castcontext, so it considers only physical equivalence
|
||||
-- and not whether the coercion can be invoked implicitly.
|
||||
create function physically_coercible(oid, oid) returns bool as $$
|
||||
-- This one ignores castcontext, so it will allow cases where an explicit
|
||||
-- (but still binary) cast would be required to convert the input type.
|
||||
-- We don't currently use this for any tests in this file, but it is a
|
||||
-- reasonable alternative definition for some scenarios.
|
||||
create function explicitly_binary_coercible(oid, oid) returns bool as $$
|
||||
begin
|
||||
if $1 = $2 then return true; end if;
|
||||
if EXISTS(select 1 from pg_catalog.pg_cast where
|
||||
@ -1221,7 +1225,7 @@ WHERE d.classoid IS NULL AND p1.oid <= 9999;
|
||||
|
||||
-- Check that operators' underlying functions have suitable comments,
|
||||
-- namely 'implementation of XXX operator'. (Note: it's not necessary to
|
||||
-- put such comments into pg_proc.h; initdb will generate them as needed.)
|
||||
-- put such comments into pg_proc.dat; initdb will generate them as needed.)
|
||||
-- In some cases involving legacy names for operators, there are multiple
|
||||
-- operators referencing the same pg_proc entry, so ignore operators whose
|
||||
-- comments say they are deprecated.
|
||||
@ -1323,7 +1327,6 @@ WHERE a.aggfnoid = p.oid AND
|
||||
(0 rows)
|
||||
|
||||
-- Cross-check transfn against its entry in pg_proc.
|
||||
-- NOTE: use physically_coercible here, not binary_coercible, because
|
||||
SELECT a.aggfnoid::oid, p.proname, ptr.oid, ptr.proname
|
||||
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS ptr
|
||||
WHERE a.aggfnoid = p.oid AND
|
||||
@ -1332,15 +1335,16 @@ WHERE a.aggfnoid = p.oid AND
|
||||
OR NOT (ptr.pronargs =
|
||||
CASE WHEN a.aggkind = 'n' THEN p.pronargs + 1
|
||||
ELSE greatest(p.pronargs - a.aggnumdirectargs, 1) + 1 END)
|
||||
OR NOT physically_coercible(ptr.prorettype, a.aggtranstype)
|
||||
OR NOT physically_coercible(a.aggtranstype, ptr.proargtypes[0])
|
||||
OR NOT binary_coercible(ptr.prorettype, a.aggtranstype)
|
||||
OR NOT binary_coercible(a.aggtranstype, ptr.proargtypes[0])
|
||||
OR (p.pronargs > 0 AND
|
||||
NOT physically_coercible(p.proargtypes[0], ptr.proargtypes[1]))
|
||||
NOT binary_coercible(p.proargtypes[0], ptr.proargtypes[1]))
|
||||
OR (p.pronargs > 1 AND
|
||||
NOT physically_coercible(p.proargtypes[1], ptr.proargtypes[2]))
|
||||
NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
|
||||
OR (p.pronargs > 2 AND
|
||||
NOT physically_coercible(p.proargtypes[2], ptr.proargtypes[3]))
|
||||
NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
|
||||
-- we could carry the check further, but 3 args is enough for now
|
||||
OR (p.pronargs > 3)
|
||||
);
|
||||
aggfnoid | proname | oid | proname
|
||||
----------+---------+-----+---------
|
||||
@ -1362,7 +1366,8 @@ WHERE a.aggfnoid = p.oid AND
|
||||
NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
|
||||
OR (pfn.pronargs > 3 AND
|
||||
NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
|
||||
-- we could carry the check further, but 3 args is enough for now
|
||||
-- we could carry the check further, but 4 args is enough for now
|
||||
OR (pfn.pronargs > 4)
|
||||
);
|
||||
aggfnoid | proname | oid | proname
|
||||
----------+---------+-----+---------
|
||||
@ -1418,15 +1423,16 @@ WHERE a.aggfnoid = p.oid AND
|
||||
OR NOT (ptr.pronargs =
|
||||
CASE WHEN a.aggkind = 'n' THEN p.pronargs + 1
|
||||
ELSE greatest(p.pronargs - a.aggnumdirectargs, 1) + 1 END)
|
||||
OR NOT physically_coercible(ptr.prorettype, a.aggmtranstype)
|
||||
OR NOT physically_coercible(a.aggmtranstype, ptr.proargtypes[0])
|
||||
OR NOT binary_coercible(ptr.prorettype, a.aggmtranstype)
|
||||
OR NOT binary_coercible(a.aggmtranstype, ptr.proargtypes[0])
|
||||
OR (p.pronargs > 0 AND
|
||||
NOT physically_coercible(p.proargtypes[0], ptr.proargtypes[1]))
|
||||
NOT binary_coercible(p.proargtypes[0], ptr.proargtypes[1]))
|
||||
OR (p.pronargs > 1 AND
|
||||
NOT physically_coercible(p.proargtypes[1], ptr.proargtypes[2]))
|
||||
NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
|
||||
OR (p.pronargs > 2 AND
|
||||
NOT physically_coercible(p.proargtypes[2], ptr.proargtypes[3]))
|
||||
NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
|
||||
-- we could carry the check further, but 3 args is enough for now
|
||||
OR (p.pronargs > 3)
|
||||
);
|
||||
aggfnoid | proname | oid | proname
|
||||
----------+---------+-----+---------
|
||||
@ -1441,15 +1447,16 @@ WHERE a.aggfnoid = p.oid AND
|
||||
OR NOT (ptr.pronargs =
|
||||
CASE WHEN a.aggkind = 'n' THEN p.pronargs + 1
|
||||
ELSE greatest(p.pronargs - a.aggnumdirectargs, 1) + 1 END)
|
||||
OR NOT physically_coercible(ptr.prorettype, a.aggmtranstype)
|
||||
OR NOT physically_coercible(a.aggmtranstype, ptr.proargtypes[0])
|
||||
OR NOT binary_coercible(ptr.prorettype, a.aggmtranstype)
|
||||
OR NOT binary_coercible(a.aggmtranstype, ptr.proargtypes[0])
|
||||
OR (p.pronargs > 0 AND
|
||||
NOT physically_coercible(p.proargtypes[0], ptr.proargtypes[1]))
|
||||
NOT binary_coercible(p.proargtypes[0], ptr.proargtypes[1]))
|
||||
OR (p.pronargs > 1 AND
|
||||
NOT physically_coercible(p.proargtypes[1], ptr.proargtypes[2]))
|
||||
NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
|
||||
OR (p.pronargs > 2 AND
|
||||
NOT physically_coercible(p.proargtypes[2], ptr.proargtypes[3]))
|
||||
NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
|
||||
-- we could carry the check further, but 3 args is enough for now
|
||||
OR (p.pronargs > 3)
|
||||
);
|
||||
aggfnoid | proname | oid | proname
|
||||
----------+---------+-----+---------
|
||||
@ -1471,7 +1478,8 @@ WHERE a.aggfnoid = p.oid AND
|
||||
NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
|
||||
OR (pfn.pronargs > 3 AND
|
||||
NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
|
||||
-- we could carry the check further, but 3 args is enough for now
|
||||
-- we could carry the check further, but 4 args is enough for now
|
||||
OR (pfn.pronargs > 4)
|
||||
);
|
||||
aggfnoid | proname | oid | proname
|
||||
----------+---------+-----+---------
|
||||
@ -1503,14 +1511,13 @@ WHERE a.aggfnoid = p.oid AND
|
||||
|
||||
-- Check that all combine functions have signature
|
||||
-- combine(transtype, transtype) returns transtype
|
||||
-- NOTE: use physically_coercible here, not binary_coercible, because
|
||||
SELECT a.aggfnoid, p.proname
|
||||
FROM pg_aggregate as a, pg_proc as p
|
||||
WHERE a.aggcombinefn = p.oid AND
|
||||
(p.pronargs != 2 OR
|
||||
p.prorettype != p.proargtypes[0] OR
|
||||
p.prorettype != p.proargtypes[1] OR
|
||||
NOT physically_coercible(a.aggtranstype, p.proargtypes[0]));
|
||||
NOT binary_coercible(a.aggtranstype, p.proargtypes[0]));
|
||||
aggfnoid | proname
|
||||
----------+---------
|
||||
(0 rows)
|
||||
|
@ -22,6 +22,8 @@
|
||||
-- allowed.
|
||||
|
||||
-- This should match IsBinaryCoercible() in parse_coerce.c.
|
||||
-- It doesn't currently know about some cases, notably domains, anyelement,
|
||||
-- anynonarray, anyenum, or record, but it doesn't need to (yet).
|
||||
create function binary_coercible(oid, oid) returns bool as $$
|
||||
begin
|
||||
if $1 = $2 then return true; end if;
|
||||
@ -43,9 +45,11 @@ begin
|
||||
end
|
||||
$$ language plpgsql strict stable;
|
||||
|
||||
-- This one ignores castcontext, so it considers only physical equivalence
|
||||
-- and not whether the coercion can be invoked implicitly.
|
||||
create function physically_coercible(oid, oid) returns bool as $$
|
||||
-- This one ignores castcontext, so it will allow cases where an explicit
|
||||
-- (but still binary) cast would be required to convert the input type.
|
||||
-- We don't currently use this for any tests in this file, but it is a
|
||||
-- reasonable alternative definition for some scenarios.
|
||||
create function explicitly_binary_coercible(oid, oid) returns bool as $$
|
||||
begin
|
||||
if $1 = $2 then return true; end if;
|
||||
if EXISTS(select 1 from pg_catalog.pg_cast where
|
||||
@ -741,7 +745,7 @@ WHERE d.classoid IS NULL AND p1.oid <= 9999;
|
||||
|
||||
-- Check that operators' underlying functions have suitable comments,
|
||||
-- namely 'implementation of XXX operator'. (Note: it's not necessary to
|
||||
-- put such comments into pg_proc.h; initdb will generate them as needed.)
|
||||
-- put such comments into pg_proc.dat; initdb will generate them as needed.)
|
||||
-- In some cases involving legacy names for operators, there are multiple
|
||||
-- operators referencing the same pg_proc entry, so ignore operators whose
|
||||
-- comments say they are deprecated.
|
||||
@ -822,7 +826,6 @@ WHERE a.aggfnoid = p.oid AND
|
||||
a.aggfinalfn = 0 AND p.prorettype != a.aggtranstype;
|
||||
|
||||
-- Cross-check transfn against its entry in pg_proc.
|
||||
-- NOTE: use physically_coercible here, not binary_coercible, because
|
||||
SELECT a.aggfnoid::oid, p.proname, ptr.oid, ptr.proname
|
||||
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS ptr
|
||||
WHERE a.aggfnoid = p.oid AND
|
||||
@ -831,15 +834,16 @@ WHERE a.aggfnoid = p.oid AND
|
||||
OR NOT (ptr.pronargs =
|
||||
CASE WHEN a.aggkind = 'n' THEN p.pronargs + 1
|
||||
ELSE greatest(p.pronargs - a.aggnumdirectargs, 1) + 1 END)
|
||||
OR NOT physically_coercible(ptr.prorettype, a.aggtranstype)
|
||||
OR NOT physically_coercible(a.aggtranstype, ptr.proargtypes[0])
|
||||
OR NOT binary_coercible(ptr.prorettype, a.aggtranstype)
|
||||
OR NOT binary_coercible(a.aggtranstype, ptr.proargtypes[0])
|
||||
OR (p.pronargs > 0 AND
|
||||
NOT physically_coercible(p.proargtypes[0], ptr.proargtypes[1]))
|
||||
NOT binary_coercible(p.proargtypes[0], ptr.proargtypes[1]))
|
||||
OR (p.pronargs > 1 AND
|
||||
NOT physically_coercible(p.proargtypes[1], ptr.proargtypes[2]))
|
||||
NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
|
||||
OR (p.pronargs > 2 AND
|
||||
NOT physically_coercible(p.proargtypes[2], ptr.proargtypes[3]))
|
||||
NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
|
||||
-- we could carry the check further, but 3 args is enough for now
|
||||
OR (p.pronargs > 3)
|
||||
);
|
||||
|
||||
-- Cross-check finalfn (if present) against its entry in pg_proc.
|
||||
@ -859,7 +863,8 @@ WHERE a.aggfnoid = p.oid AND
|
||||
NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
|
||||
OR (pfn.pronargs > 3 AND
|
||||
NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
|
||||
-- we could carry the check further, but 3 args is enough for now
|
||||
-- we could carry the check further, but 4 args is enough for now
|
||||
OR (pfn.pronargs > 4)
|
||||
);
|
||||
|
||||
-- If transfn is strict then either initval should be non-NULL, or
|
||||
@ -903,15 +908,16 @@ WHERE a.aggfnoid = p.oid AND
|
||||
OR NOT (ptr.pronargs =
|
||||
CASE WHEN a.aggkind = 'n' THEN p.pronargs + 1
|
||||
ELSE greatest(p.pronargs - a.aggnumdirectargs, 1) + 1 END)
|
||||
OR NOT physically_coercible(ptr.prorettype, a.aggmtranstype)
|
||||
OR NOT physically_coercible(a.aggmtranstype, ptr.proargtypes[0])
|
||||
OR NOT binary_coercible(ptr.prorettype, a.aggmtranstype)
|
||||
OR NOT binary_coercible(a.aggmtranstype, ptr.proargtypes[0])
|
||||
OR (p.pronargs > 0 AND
|
||||
NOT physically_coercible(p.proargtypes[0], ptr.proargtypes[1]))
|
||||
NOT binary_coercible(p.proargtypes[0], ptr.proargtypes[1]))
|
||||
OR (p.pronargs > 1 AND
|
||||
NOT physically_coercible(p.proargtypes[1], ptr.proargtypes[2]))
|
||||
NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
|
||||
OR (p.pronargs > 2 AND
|
||||
NOT physically_coercible(p.proargtypes[2], ptr.proargtypes[3]))
|
||||
NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
|
||||
-- we could carry the check further, but 3 args is enough for now
|
||||
OR (p.pronargs > 3)
|
||||
);
|
||||
|
||||
-- Cross-check minvtransfn (if present) against its entry in pg_proc.
|
||||
@ -923,15 +929,16 @@ WHERE a.aggfnoid = p.oid AND
|
||||
OR NOT (ptr.pronargs =
|
||||
CASE WHEN a.aggkind = 'n' THEN p.pronargs + 1
|
||||
ELSE greatest(p.pronargs - a.aggnumdirectargs, 1) + 1 END)
|
||||
OR NOT physically_coercible(ptr.prorettype, a.aggmtranstype)
|
||||
OR NOT physically_coercible(a.aggmtranstype, ptr.proargtypes[0])
|
||||
OR NOT binary_coercible(ptr.prorettype, a.aggmtranstype)
|
||||
OR NOT binary_coercible(a.aggmtranstype, ptr.proargtypes[0])
|
||||
OR (p.pronargs > 0 AND
|
||||
NOT physically_coercible(p.proargtypes[0], ptr.proargtypes[1]))
|
||||
NOT binary_coercible(p.proargtypes[0], ptr.proargtypes[1]))
|
||||
OR (p.pronargs > 1 AND
|
||||
NOT physically_coercible(p.proargtypes[1], ptr.proargtypes[2]))
|
||||
NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
|
||||
OR (p.pronargs > 2 AND
|
||||
NOT physically_coercible(p.proargtypes[2], ptr.proargtypes[3]))
|
||||
NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
|
||||
-- we could carry the check further, but 3 args is enough for now
|
||||
OR (p.pronargs > 3)
|
||||
);
|
||||
|
||||
-- Cross-check mfinalfn (if present) against its entry in pg_proc.
|
||||
@ -951,7 +958,8 @@ WHERE a.aggfnoid = p.oid AND
|
||||
NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
|
||||
OR (pfn.pronargs > 3 AND
|
||||
NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
|
||||
-- we could carry the check further, but 3 args is enough for now
|
||||
-- we could carry the check further, but 4 args is enough for now
|
||||
OR (pfn.pronargs > 4)
|
||||
);
|
||||
|
||||
-- If mtransfn is strict then either minitval should be non-NULL, or
|
||||
@ -976,7 +984,6 @@ WHERE a.aggfnoid = p.oid AND
|
||||
|
||||
-- Check that all combine functions have signature
|
||||
-- combine(transtype, transtype) returns transtype
|
||||
-- NOTE: use physically_coercible here, not binary_coercible, because
|
||||
|
||||
SELECT a.aggfnoid, p.proname
|
||||
FROM pg_aggregate as a, pg_proc as p
|
||||
@ -984,7 +991,7 @@ WHERE a.aggcombinefn = p.oid AND
|
||||
(p.pronargs != 2 OR
|
||||
p.prorettype != p.proargtypes[0] OR
|
||||
p.prorettype != p.proargtypes[1] OR
|
||||
NOT physically_coercible(a.aggtranstype, p.proargtypes[0]));
|
||||
NOT binary_coercible(a.aggtranstype, p.proargtypes[0]));
|
||||
|
||||
-- Check that no combine function for an INTERNAL transtype is strict.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user