summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-11-18 18:23:55 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2011-11-18 18:24:32 -0500
commita1a233af66ed14d225ac2d5e7948a5cc8ed2cde6 (patch)
treef6f2fff65bc789c998deea0cbb515f556ba587fe /src
parentc1458cc495ff800cd176a1c2e56d8b62680d9b71 (diff)
Further review of range-types patch.
Lots of documentation cleanup today, and still more type_sanity tests.
Diffstat (limited to 'src')
-rw-r--r--src/bin/pg_dump/pg_dump.c10
-rw-r--r--src/bin/pg_dump/pg_dump_sort.c7
-rw-r--r--src/include/catalog/pg_range.h2
-rw-r--r--src/include/catalog/pg_type.h5
-rw-r--r--src/test/regress/expected/type_sanity.out79
-rw-r--r--src/test/regress/sql/type_sanity.sql47
6 files changed, 131 insertions, 19 deletions
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 973f0b335d7..d2005c1e809 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -2986,7 +2986,8 @@ getTypes(int *numTypes)
/*
* If it's a base type, make a DumpableObject representing a shell
* definition of the type. We will need to dump that ahead of the I/O
- * functions for the type.
+ * functions for the type. Similarly, range types need a shell
+ * definition in case they have a canonicalize function.
*
* Note: the shell type doesn't have a catId. You might think it
* should copy the base type's catId, but then it might capture the
@@ -3006,8 +3007,8 @@ getTypes(int *numTypes)
/*
* Initially mark the shell type as not to be dumped. We'll only
- * dump it if the I/O functions need to be dumped; this is taken
- * care of while sorting dependencies.
+ * dump it if the I/O or canonicalize functions need to be dumped;
+ * this is taken care of while sorting dependencies.
*/
stinfo->dobj.dump = false;
@@ -7340,6 +7341,9 @@ dumpType(Archive *fout, TypeInfo *tyinfo)
dumpEnumType(fout, tyinfo);
else if (tyinfo->typtype == TYPTYPE_RANGE)
dumpRangeType(fout, tyinfo);
+ else
+ write_msg(NULL, "WARNING: typtype of data type \"%s\" appears to be invalid\n",
+ tyinfo->dobj.name);
}
/*
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
index efde0d0026b..6b6c073eb6a 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -636,7 +636,8 @@ findLoop(DumpableObject *obj,
/*
* A user-defined datatype will have a dependency loop with each of its
* I/O functions (since those have the datatype as input or output).
- * Break the loop and make the I/O function depend on the associated
+ * Similarly, a range type will have a loop with its canonicalize function,
+ * if any. Break the loop by making the function depend on the associated
* shell type, instead.
*/
static void
@@ -651,7 +652,7 @@ repairTypeFuncLoop(DumpableObject *typeobj, DumpableObject *funcobj)
if (typeInfo->shellType)
{
addObjectDependency(funcobj, typeInfo->shellType->dobj.dumpId);
- /* Mark shell type as to be dumped if any I/O function is */
+ /* Mark shell type as to be dumped if any such function is */
if (funcobj->dump)
typeInfo->shellType->dobj.dump = true;
}
@@ -789,7 +790,7 @@ repairDependencyLoop(DumpableObject **loop,
int i,
j;
- /* Datatype and one of its I/O functions */
+ /* Datatype and one of its I/O or canonicalize functions */
if (nLoop == 2 &&
loop[0]->objType == DO_TYPE &&
loop[1]->objType == DO_FUNC)
diff --git a/src/include/catalog/pg_range.h b/src/include/catalog/pg_range.h
index cc9ba293c14..4fbde166b39 100644
--- a/src/include/catalog/pg_range.h
+++ b/src/include/catalog/pg_range.h
@@ -34,7 +34,7 @@
CATALOG(pg_range,3541) BKI_WITHOUT_OIDS
{
Oid rngtypid; /* OID of owning range type */
- Oid rngsubtype; /* OID of range's subtype */
+ Oid rngsubtype; /* OID of range's element type (subtype) */
Oid rngcollation; /* collation for this range type, or 0 */
Oid rngsubopc; /* subtype's btree opclass */
regproc rngcanonical; /* canonicalize range, or 0 */
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 1806985b69a..f2a32507908 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -61,8 +61,9 @@ CATALOG(pg_type,1247) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71) BKI_SCHEMA_MACRO
/*
* typtype is 'b' for a base type, 'c' for a composite type (e.g., a
- * table's rowtype), 'd' for a domain type, 'e' for an enum type, or 'p'
- * for a pseudo-type. (Use the TYPTYPE macros below.)
+ * table's rowtype), 'd' for a domain, 'e' for an enum type,
+ * 'p' for a pseudo-type, or 'r' for a range type.
+ * (Use the TYPTYPE macros below.)
*
* If typtype is 'c', typrelid is the OID of the class' entry in pg_class.
*/
diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out
index 19d437ade50..0e1dfd84861 100644
--- a/src/test/regress/expected/type_sanity.out
+++ b/src/test/regress/expected/type_sanity.out
@@ -56,11 +56,14 @@ WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
-----+---------
(0 rows)
--- Look for basic or enum types that don't have an array type.
+-- Look for types that should have an array type according to their typtype,
+-- but don't. We exclude composites here because we have not bothered to
+-- make array types corresponding to the system catalogs' rowtypes.
-- NOTE: as of 9.1, this check finds pg_node_tree, smgr, and unknown.
SELECT p1.oid, p1.typname
FROM pg_type as p1
-WHERE p1.typtype in ('b','e') AND p1.typname NOT LIKE E'\\_%' AND NOT EXISTS
+WHERE p1.typtype not in ('c','d','p') AND p1.typname NOT LIKE E'\\_%'
+ AND NOT EXISTS
(SELECT 1 FROM pg_type as p2
WHERE p2.typname = ('_' || p1.typname)::name AND
p2.typelem = p1.oid and p1.typarray = p2.oid);
@@ -150,6 +153,19 @@ ORDER BY 1;
30 | oidvector | 54 | oidvectorin
(2 rows)
+-- Composites, domains, enums, ranges should all use the same input routines
+SELECT DISTINCT typtype, typinput
+FROM pg_type AS p1
+WHERE p1.typtype not in ('b', 'p')
+ORDER BY 1;
+ typtype | typinput
+---------+-----------
+ c | record_in
+ d | domain_in
+ e | enum_in
+ r | range_in
+(4 rows)
+
-- Check for bogus typoutput routines
-- As of 8.0, this check finds refcursor, which is borrowing
-- other types' I/O routines
@@ -174,6 +190,26 @@ WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
-----+---------+-----+---------
(0 rows)
+-- Composites, enums, ranges should all use the same output routines
+SELECT DISTINCT typtype, typoutput
+FROM pg_type AS p1
+WHERE p1.typtype not in ('b', 'd', 'p')
+ORDER BY 1;
+ typtype | typoutput
+---------+------------
+ c | record_out
+ e | enum_out
+ r | range_out
+(3 rows)
+
+-- Domains should have same typoutput as their base types
+SELECT p1.oid, p1.typname, p2.oid, p2.typname
+FROM pg_type AS p1 LEFT JOIN pg_type AS p2 ON p1.typbasetype = p2.oid
+WHERE p1.typtype = 'd' AND p1.typoutput IS DISTINCT FROM p2.typoutput;
+ oid | typname | oid | typname
+-----+---------+-----+---------
+(0 rows)
+
-- Check for bogus typreceive routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
@@ -222,6 +258,19 @@ WHERE p1.typinput = p2.oid AND p1.typreceive = p3.oid AND
-----+---------+-----+---------+-----+---------
(0 rows)
+-- Composites, domains, enums, ranges should all use the same receive routines
+SELECT DISTINCT typtype, typreceive
+FROM pg_type AS p1
+WHERE p1.typtype not in ('b', 'p')
+ORDER BY 1;
+ typtype | typreceive
+---------+-------------
+ c | record_recv
+ d | domain_recv
+ e | enum_recv
+ r | range_recv
+(4 rows)
+
-- Check for bogus typsend routines
-- As of 7.4, this check finds refcursor, which is borrowing
-- other types' I/O routines
@@ -246,10 +295,30 @@ WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
-----+---------+-----+---------
(0 rows)
+-- Composites, enums, ranges should all use the same send routines
+SELECT DISTINCT typtype, typsend
+FROM pg_type AS p1
+WHERE p1.typtype not in ('b', 'd', 'p')
+ORDER BY 1;
+ typtype | typsend
+---------+-------------
+ c | record_send
+ e | enum_send
+ r | range_send
+(3 rows)
+
+-- Domains should have same typsend as their base types
+SELECT p1.oid, p1.typname, p2.oid, p2.typname
+FROM pg_type AS p1 LEFT JOIN pg_type AS p2 ON p1.typbasetype = p2.oid
+WHERE p1.typtype = 'd' AND p1.typsend IS DISTINCT FROM p2.typsend;
+ oid | typname | oid | typname
+-----+---------+-----+---------
+(0 rows)
+
-- Check for bogus typmodin routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
-WHERE p1.typmodin = p2.oid AND p1.typtype in ('b', 'p') AND NOT
+WHERE p1.typmodin = p2.oid AND NOT
(p2.pronargs = 1 AND
p2.proargtypes[0] = 'cstring[]'::regtype AND
p2.prorettype = 'int4'::regtype AND NOT p2.proretset);
@@ -260,7 +329,7 @@ WHERE p1.typmodin = p2.oid AND p1.typtype in ('b', 'p') AND NOT
-- Check for bogus typmodout routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
-WHERE p1.typmodout = p2.oid AND p1.typtype in ('b', 'p') AND NOT
+WHERE p1.typmodout = p2.oid AND NOT
(p2.pronargs = 1 AND
p2.proargtypes[0] = 'int4'::regtype AND
p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
@@ -298,7 +367,7 @@ WHERE p1.typarray = p2.oid AND
-- Check for bogus typanalyze routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
-WHERE p1.typanalyze = p2.oid AND p1.typtype in ('b', 'p') AND NOT
+WHERE p1.typanalyze = p2.oid AND NOT
(p2.pronargs = 1 AND
p2.proargtypes[0] = 'internal'::regtype AND
p2.prorettype = 'bool'::regtype AND NOT p2.proretset);
diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/type_sanity.sql
index d7d9cea5dc5..c6a70ad14c5 100644
--- a/src/test/regress/sql/type_sanity.sql
+++ b/src/test/regress/sql/type_sanity.sql
@@ -50,12 +50,15 @@ FROM pg_type as p1
WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
(p1.typtype != 'c' AND p1.typrelid != 0);
--- Look for basic or enum types that don't have an array type.
+-- Look for types that should have an array type according to their typtype,
+-- but don't. We exclude composites here because we have not bothered to
+-- make array types corresponding to the system catalogs' rowtypes.
-- NOTE: as of 9.1, this check finds pg_node_tree, smgr, and unknown.
SELECT p1.oid, p1.typname
FROM pg_type as p1
-WHERE p1.typtype in ('b','e') AND p1.typname NOT LIKE E'\\_%' AND NOT EXISTS
+WHERE p1.typtype not in ('c','d','p') AND p1.typname NOT LIKE E'\\_%'
+ AND NOT EXISTS
(SELECT 1 FROM pg_type as p2
WHERE p2.typname = ('_' || p1.typname)::name AND
p2.typelem = p1.oid and p1.typarray = p2.oid);
@@ -117,6 +120,12 @@ WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND
(p2.oid = 'array_in'::regproc)
ORDER BY 1;
+-- Composites, domains, enums, ranges should all use the same input routines
+SELECT DISTINCT typtype, typinput
+FROM pg_type AS p1
+WHERE p1.typtype not in ('b', 'p')
+ORDER BY 1;
+
-- Check for bogus typoutput routines
-- As of 8.0, this check finds refcursor, which is borrowing
@@ -135,6 +144,17 @@ FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
(p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
+-- Composites, enums, ranges should all use the same output routines
+SELECT DISTINCT typtype, typoutput
+FROM pg_type AS p1
+WHERE p1.typtype not in ('b', 'd', 'p')
+ORDER BY 1;
+
+-- Domains should have same typoutput as their base types
+SELECT p1.oid, p1.typname, p2.oid, p2.typname
+FROM pg_type AS p1 LEFT JOIN pg_type AS p2 ON p1.typbasetype = p2.oid
+WHERE p1.typtype = 'd' AND p1.typoutput IS DISTINCT FROM p2.typoutput;
+
-- Check for bogus typreceive routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
@@ -169,6 +189,12 @@ 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;
+-- Composites, domains, enums, ranges should all use the same receive routines
+SELECT DISTINCT typtype, typreceive
+FROM pg_type AS p1
+WHERE p1.typtype not in ('b', 'p')
+ORDER BY 1;
+
-- Check for bogus typsend routines
-- As of 7.4, this check finds refcursor, which is borrowing
@@ -187,11 +213,22 @@ FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
(p2.prorettype = 'bytea'::regtype AND NOT p2.proretset);
+-- Composites, enums, ranges should all use the same send routines
+SELECT DISTINCT typtype, typsend
+FROM pg_type AS p1
+WHERE p1.typtype not in ('b', 'd', 'p')
+ORDER BY 1;
+
+-- Domains should have same typsend as their base types
+SELECT p1.oid, p1.typname, p2.oid, p2.typname
+FROM pg_type AS p1 LEFT JOIN pg_type AS p2 ON p1.typbasetype = p2.oid
+WHERE p1.typtype = 'd' AND p1.typsend IS DISTINCT FROM p2.typsend;
+
-- Check for bogus typmodin routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
-WHERE p1.typmodin = p2.oid AND p1.typtype in ('b', 'p') AND NOT
+WHERE p1.typmodin = p2.oid AND NOT
(p2.pronargs = 1 AND
p2.proargtypes[0] = 'cstring[]'::regtype AND
p2.prorettype = 'int4'::regtype AND NOT p2.proretset);
@@ -200,7 +237,7 @@ WHERE p1.typmodin = p2.oid AND p1.typtype in ('b', 'p') AND NOT
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
-WHERE p1.typmodout = p2.oid AND p1.typtype in ('b', 'p') AND NOT
+WHERE p1.typmodout = p2.oid AND NOT
(p2.pronargs = 1 AND
p2.proargtypes[0] = 'int4'::regtype AND
p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
@@ -230,7 +267,7 @@ WHERE p1.typarray = p2.oid AND
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
-WHERE p1.typanalyze = p2.oid AND p1.typtype in ('b', 'p') AND NOT
+WHERE p1.typanalyze = p2.oid AND NOT
(p2.pronargs = 1 AND
p2.proargtypes[0] = 'internal'::regtype AND
p2.prorettype = 'bool'::regtype AND NOT p2.proretset);