From e9f42d529f990f94e1b7bdcec4a1111465c85326 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 14 Oct 2018 12:11:16 -0400 Subject: [PATCH] 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 --- src/test/regress/expected/opr_sanity.out | 55 +++++++++++++----------- src/test/regress/sql/opr_sanity.sql | 55 +++++++++++++----------- 2 files changed, 62 insertions(+), 48 deletions(-) diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index 11e6cd85714..69ea821a0cf 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -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) diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql index 5bb365e9da5..b155d90b11b 100644 --- a/src/test/regress/sql/opr_sanity.sql +++ b/src/test/regress/sql/opr_sanity.sql @@ -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.