From 43ac12c6e6e397fd9142ed908447eba32d3785b2 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 23 Oct 2014 15:59:40 -0400 Subject: [PATCH] In type_sanity, check I/O functions of built-in types are not volatile. We have a project policy that I/O functions must not be volatile, as per commit aab353a60b95aadc00f81da0c6d99bde696c4b75, but we weren't doing anything to enforce that. In most usage the marking of the function doesn't matter as long as its behavior is sane --- but I/O casts can expose the marking as user-visible behavior, as per today's complaint from Joe Van Dyk about contrib/ltree. This test as such will only protect us against future errors in built-in data types. To catch the same error in contrib or third-party types, perhaps we should make CREATE TYPE complain? But that's a separate issue from enforcing the policy for built-in types. --- src/test/regress/expected/type_sanity.out | 49 +++++++++++++++++++++++ src/test/regress/sql/type_sanity.sql | 32 +++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out index 3616c8dbd0..e2a7a418a8 100644 --- a/src/test/regress/expected/type_sanity.out +++ b/src/test/regress/expected/type_sanity.out @@ -155,6 +155,14 @@ ORDER BY 1; 30 | oidvector | 54 | oidvectorin (2 rows) +-- typinput routines should not be volatile +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typinput = p2.oid AND p2.provolatile NOT IN ('i', 's'); + oid | typname | oid | proname +-----+---------+-----+--------- +(0 rows) + -- Composites, domains, enums, ranges should all use the same input routines SELECT DISTINCT typtype, typinput FROM pg_type AS p1 @@ -192,6 +200,14 @@ WHERE p1.typoutput = p2.oid AND NOT -----+---------+-----+--------- (0 rows) +-- typoutput routines should not be volatile +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typoutput = p2.oid AND p2.provolatile NOT IN ('i', 's'); + oid | typname | oid | proname +-----+---------+-----+--------- +(0 rows) + -- Composites, enums, ranges should all use the same output routines SELECT DISTINCT typtype, typoutput FROM pg_type AS p1 @@ -262,6 +278,14 @@ WHERE p1.typinput = p2.oid AND p1.typreceive = p3.oid AND -----+---------+-----+---------+-----+--------- (0 rows) +-- typreceive routines should not be volatile +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typreceive = p2.oid AND p2.provolatile NOT IN ('i', 's'); + oid | typname | oid | proname +-----+---------+-----+--------- +(0 rows) + -- Composites, domains, enums, ranges should all use the same receive routines SELECT DISTINCT typtype, typreceive FROM pg_type AS p1 @@ -299,6 +323,14 @@ WHERE p1.typsend = p2.oid AND NOT -----+---------+-----+--------- (0 rows) +-- typsend routines should not be volatile +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typsend = p2.oid AND p2.provolatile NOT IN ('i', 's'); + oid | typname | oid | proname +-----+---------+-----+--------- +(0 rows) + -- Composites, enums, ranges should all use the same send routines SELECT DISTINCT typtype, typsend FROM pg_type AS p1 @@ -330,6 +362,14 @@ WHERE p1.typmodin = p2.oid AND NOT -----+---------+-----+--------- (0 rows) +-- typmodin routines should not be volatile +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typmodin = p2.oid AND p2.provolatile NOT IN ('i', 's'); + oid | typname | oid | proname +-----+---------+-----+--------- +(0 rows) + -- Check for bogus typmodout routines SELECT p1.oid, p1.typname, p2.oid, p2.proname FROM pg_type AS p1, pg_proc AS p2 @@ -341,6 +381,14 @@ WHERE p1.typmodout = p2.oid AND NOT -----+---------+-----+--------- (0 rows) +-- typmodout routines should not be volatile +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typmodout = p2.oid AND p2.provolatile NOT IN ('i', 's'); + oid | typname | oid | proname +-----+---------+-----+--------- +(0 rows) + -- Array types should have same typmodin/out as their element types SELECT p1.oid, p1.typname, p2.oid, p2.typname FROM pg_type AS p1, pg_type AS p2 @@ -379,6 +427,7 @@ WHERE p1.typanalyze = p2.oid AND NOT -----+---------+-----+--------- (0 rows) +-- there does not seem to be a reason to care about volatility of typanalyze -- domains inherit their base type's typanalyze SELECT d.oid, d.typname, d.typanalyze, t.oid, t.typname, t.typanalyze FROM pg_type d JOIN pg_type t ON d.typbasetype = t.oid diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/type_sanity.sql index 14cb5408b7..574ef9c6e2 100644 --- a/src/test/regress/sql/type_sanity.sql +++ b/src/test/regress/sql/type_sanity.sql @@ -122,6 +122,11 @@ WHERE p1.typinput = p2.oid AND (p2.oid = 'array_in'::regproc) ORDER BY 1; +-- typinput routines should not be volatile +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typinput = p2.oid AND p2.provolatile NOT IN ('i', 's'); + -- Composites, domains, enums, ranges should all use the same input routines SELECT DISTINCT typtype, typinput FROM pg_type AS p1 @@ -146,6 +151,11 @@ FROM pg_type AS p1, pg_proc AS p2 WHERE p1.typoutput = p2.oid AND NOT (p2.prorettype = 'cstring'::regtype AND NOT p2.proretset); +-- typoutput routines should not be volatile +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typoutput = p2.oid AND p2.provolatile NOT IN ('i', 's'); + -- Composites, enums, ranges should all use the same output routines SELECT DISTINCT typtype, typoutput FROM pg_type AS p1 @@ -193,6 +203,11 @@ FROM pg_type AS p1, pg_proc AS p2, pg_proc AS p3 WHERE p1.typinput = p2.oid AND p1.typreceive = p3.oid AND p2.pronargs != p3.pronargs; +-- typreceive routines should not be volatile +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typreceive = p2.oid AND p2.provolatile NOT IN ('i', 's'); + -- Composites, domains, enums, ranges should all use the same receive routines SELECT DISTINCT typtype, typreceive FROM pg_type AS p1 @@ -217,6 +232,11 @@ FROM pg_type AS p1, pg_proc AS p2 WHERE p1.typsend = p2.oid AND NOT (p2.prorettype = 'bytea'::regtype AND NOT p2.proretset); +-- typsend routines should not be volatile +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typsend = p2.oid AND p2.provolatile NOT IN ('i', 's'); + -- Composites, enums, ranges should all use the same send routines SELECT DISTINCT typtype, typsend FROM pg_type AS p1 @@ -237,6 +257,11 @@ WHERE p1.typmodin = p2.oid AND NOT p2.proargtypes[0] = 'cstring[]'::regtype AND p2.prorettype = 'int4'::regtype AND NOT p2.proretset); +-- typmodin routines should not be volatile +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typmodin = p2.oid AND p2.provolatile NOT IN ('i', 's'); + -- Check for bogus typmodout routines SELECT p1.oid, p1.typname, p2.oid, p2.proname @@ -246,6 +271,11 @@ WHERE p1.typmodout = p2.oid AND NOT p2.proargtypes[0] = 'int4'::regtype AND p2.prorettype = 'cstring'::regtype AND NOT p2.proretset); +-- typmodout routines should not be volatile +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typmodout = p2.oid AND p2.provolatile NOT IN ('i', 's'); + -- Array types should have same typmodin/out as their element types SELECT p1.oid, p1.typname, p2.oid, p2.typname @@ -276,6 +306,8 @@ WHERE p1.typanalyze = p2.oid AND NOT p2.proargtypes[0] = 'internal'::regtype AND p2.prorettype = 'bool'::regtype AND NOT p2.proretset); +-- there does not seem to be a reason to care about volatility of typanalyze + -- domains inherit their base type's typanalyze SELECT d.oid, d.typname, d.typanalyze, t.oid, t.typname, t.typanalyze