Commit a1a233af authored by Tom Lane's avatar Tom Lane

Further review of range-types patch.

Lots of documentation cleanup today, and still more type_sanity tests.
parent c1458cc4
...@@ -4607,7 +4607,9 @@ ...@@ -4607,7 +4607,9 @@
</indexterm> </indexterm>
<para> <para>
The catalog <structname>pg_range</structname> stores information about range types. The catalog <structname>pg_range</structname> stores information about
range types. This is in addition to the types' entries in
<link linkend="catalog-pg-type"><structname>pg_type</structname></link>.
</para> </para>
<table> <table>
...@@ -4628,47 +4630,57 @@ ...@@ -4628,47 +4630,57 @@
<entry><structfield>rngtypid</structfield></entry> <entry><structfield>rngtypid</structfield></entry>
<entry><type>oid</type></entry> <entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry> <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry>
<entry>The type that is a range type</entry> <entry>OID of the range type</entry>
</row> </row>
<row> <row>
<entry><structfield>rngsubtype</structfield></entry> <entry><structfield>rngsubtype</structfield></entry>
<entry><type>oid</type></entry> <entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry> <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry>
<entry>Subtype of this range type, e.g. <type>integer</type> is the subtype of <type>int4range</type></entry> <entry>OID of the element type (subtype) of this range type</entry>
</row> </row>
<row> <row>
<entry><structfield>rngcollation</structfield></entry> <entry><structfield>rngcollation</structfield></entry>
<entry><type>oid</type></entry> <entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-collation"><structname>pg_collation</structname></link>.oid</literal></entry> <entry><literal><link linkend="catalog-pg-collation"><structname>pg_collation</structname></link>.oid</literal></entry>
<entry>The collation used when comparing range boundaries</entry> <entry>OID of the collation used for range comparisons, or 0 if none</entry>
</row> </row>
<row> <row>
<entry><structfield>rngsubopc</structfield></entry> <entry><structfield>rngsubopc</structfield></entry>
<entry><type>oid</type></entry> <entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link>.oid</literal></entry> <entry><literal><link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link>.oid</literal></entry>
<entry>The operator class used when comparing range boundaries</entry> <entry>OID of the subtype's operator class used for range comparisons</entry>
</row> </row>
<row> <row>
<entry><structfield>rngcanonical</structfield></entry> <entry><structfield>rngcanonical</structfield></entry>
<entry><type>regproc</type></entry> <entry><type>regproc</type></entry>
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
<entry>A function to convert a range into its canonical form</entry> <entry>OID of the function to convert a range value into canonical form,
or 0 if none</entry>
</row> </row>
<row> <row>
<entry><structfield>rngsubdiff</structfield></entry> <entry><structfield>rngsubdiff</structfield></entry>
<entry><type>regproc</type></entry> <entry><type>regproc</type></entry>
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
<entry>A function to return the distance between two lower and upper bound, as a <type>double precision</type>. Used for GiST support</entry> <entry>OID of the function to return the difference between two element
values as <type>double precision</type>, or 0 if none</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
<para>
<structfield>rngsubopc</> (plus <structfield>rngcollation</>, if the
element type is collatable) determines the sort ordering used by the range
type. <structfield>rngcanonical</> is used when the element type is
discrete. <structfield>rngsubdiff</> is optional but should be supplied to
improve performance of GiST indexes on the range type.
</para>
</sect1> </sect1>
<sect1 id="catalog-pg-rewrite"> <sect1 id="catalog-pg-rewrite">
...@@ -6059,7 +6071,8 @@ ...@@ -6059,7 +6071,8 @@
<literal>c</literal> for a composite type (e.g., a table's row type), <literal>c</literal> for a composite type (e.g., a table's row type),
<literal>d</literal> for a domain, <literal>d</literal> for a domain,
<literal>e</literal> for an enum type, <literal>e</literal> for an enum type,
or <literal>p</literal> for a pseudo-type. <literal>p</literal> for a pseudo-type, or
<literal>r</literal> for a range type.
See also <structfield>typrelid</structfield> and See also <structfield>typrelid</structfield> and
<structfield>typbasetype</structfield>. <structfield>typbasetype</structfield>.
</entry> </entry>
...@@ -6429,6 +6442,10 @@ ...@@ -6429,6 +6442,10 @@
<entry><literal>P</literal></entry> <entry><literal>P</literal></entry>
<entry>Pseudo-types</entry> <entry>Pseudo-types</entry>
</row> </row>
<row>
<entry><literal>R</literal></entry>
<entry>Range types</entry>
</row>
<row> <row>
<entry><literal>S</literal></entry> <entry><literal>S</literal></entry>
<entry>String types</entry> <entry>String types</entry>
......
...@@ -200,13 +200,13 @@ ...@@ -200,13 +200,13 @@
<para> <para>
Five pseudo-types of special interest are <type>anyelement</>, Five pseudo-types of special interest are <type>anyelement</>,
<type>anyarray</>, <type>anynonarray</>, <type>anyenum</>, <type>anyarray</>, <type>anynonarray</>, <type>anyenum</>,
and <type>anyrange</>, which are collectively and <type>anyrange</>,
called <firstterm>polymorphic types</>. Any function declared which are collectively called <firstterm>polymorphic types</>.
using these types is said to be a <firstterm>polymorphic Any function declared using these types is said to be
function</>. A polymorphic function can operate on many a <firstterm>polymorphic function</>. A polymorphic function can
different data types, with the specific data type(s) being operate on many different data types, with the specific data type(s)
determined by the data types actually passed to it in a being determined by the data types actually passed to it in a particular
particular call. call.
</para> </para>
<para> <para>
...@@ -217,15 +217,16 @@ ...@@ -217,15 +217,16 @@
data type, but in any given call they must all be the data type, but in any given call they must all be the
<emphasis>same</emphasis> actual type. Each <emphasis>same</emphasis> actual type. Each
position declared as <type>anyarray</type> can have any array data type, position declared as <type>anyarray</type> can have any array data type,
but similarly they must all be the same type. If there are but similarly they must all be the same type. And similarly,
positions declared as <type>anyrange</type> must all be the same range
type. Furthermore, if there are
positions declared <type>anyarray</type> and others declared positions declared <type>anyarray</type> and others declared
<type>anyelement</type>, the actual array type in the <type>anyelement</type>, the actual array type in the
<type>anyarray</type> positions must be an array whose elements are <type>anyarray</type> positions must be an array whose elements are
the same type appearing in the <type>anyelement</type> positions. the same type appearing in the <type>anyelement</type> positions.
Similarly, if there are positions declared <type>anyrange</type> Similarly, if there are positions declared <type>anyrange</type>
and others declared and others declared <type>anyelement</type>, the actual range type in
<type>anyelement</type>, the actual range type in the the <type>anyrange</type> positions must be a range whose subtype is
<type>anyrange</type> positions must be a range whose subtype is
the same type appearing in the <type>anyelement</type> positions. the same type appearing in the <type>anyelement</type> positions.
<type>anynonarray</> is treated exactly the same as <type>anyelement</>, <type>anynonarray</> is treated exactly the same as <type>anyelement</>,
but adds the additional constraint that the actual type must not be but adds the additional constraint that the actual type must not be
......
...@@ -10525,18 +10525,32 @@ SELECT NULLIF(value, '(none)') ... ...@@ -10525,18 +10525,32 @@ SELECT NULLIF(value, '(none)') ...
<row> <row>
<entry> <literal>@&gt;</literal> </entry> <entry> <literal>@&gt;</literal> </entry>
<entry>contains</entry> <entry>contains range</entry>
<entry><literal>int4range(2,4) @&gt; int4range(2,3)</literal></entry>
<entry><literal>t</literal></entry>
</row>
<row>
<entry> <literal>@&gt;</literal> </entry>
<entry>contains element</entry>
<entry><literal>'[2011-01-01,2011-03-01)'::tsrange @&gt; '2011-01-10'::timestamp</literal></entry> <entry><literal>'[2011-01-01,2011-03-01)'::tsrange @&gt; '2011-01-10'::timestamp</literal></entry>
<entry><literal>t</literal></entry> <entry><literal>t</literal></entry>
</row> </row>
<row> <row>
<entry> <literal>&lt;@</literal> </entry> <entry> <literal>&lt;@</literal> </entry>
<entry>is contained by</entry> <entry>range is contained by</entry>
<entry><literal>int4range(2,4) &lt;@ int4range(1,7)</literal></entry> <entry><literal>int4range(2,4) &lt;@ int4range(1,7)</literal></entry>
<entry><literal>t</literal></entry> <entry><literal>t</literal></entry>
</row> </row>
<row>
<entry> <literal>&lt;@</literal> </entry>
<entry>element is contained by</entry>
<entry><literal>42 &lt;@ int4range(1,7)</literal></entry>
<entry><literal>f</literal></entry>
</row>
<row> <row>
<entry> <literal>&amp;&amp;</literal> </entry> <entry> <literal>&amp;&amp;</literal> </entry>
<entry>overlap (have points in common)</entry> <entry>overlap (have points in common)</entry>
......
This diff is collapsed.
This diff is collapsed.
...@@ -243,7 +243,7 @@ INSERT INTO mytab (complex_col.r, complex_col.i) VALUES(1.1, 2.2); ...@@ -243,7 +243,7 @@ INSERT INTO mytab (complex_col.r, complex_col.i) VALUES(1.1, 2.2);
</para> </para>
</sect2> </sect2>
<sect2> <sect2 id="rowtypes-io-syntax">
<title>Composite Type Input and Output Syntax</title> <title>Composite Type Input and Output Syntax</title>
<para> <para>
......
...@@ -2986,7 +2986,8 @@ getTypes(int *numTypes) ...@@ -2986,7 +2986,8 @@ getTypes(int *numTypes)
/* /*
* If it's a base type, make a DumpableObject representing a shell * 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 * 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 * 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 * should copy the base type's catId, but then it might capture the
...@@ -3006,8 +3007,8 @@ getTypes(int *numTypes) ...@@ -3006,8 +3007,8 @@ getTypes(int *numTypes)
/* /*
* Initially mark the shell type as not to be dumped. We'll only * 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 * dump it if the I/O or canonicalize functions need to be dumped;
* care of while sorting dependencies. * this is taken care of while sorting dependencies.
*/ */
stinfo->dobj.dump = false; stinfo->dobj.dump = false;
...@@ -7340,6 +7341,9 @@ dumpType(Archive *fout, TypeInfo *tyinfo) ...@@ -7340,6 +7341,9 @@ dumpType(Archive *fout, TypeInfo *tyinfo)
dumpEnumType(fout, tyinfo); dumpEnumType(fout, tyinfo);
else if (tyinfo->typtype == TYPTYPE_RANGE) else if (tyinfo->typtype == TYPTYPE_RANGE)
dumpRangeType(fout, tyinfo); dumpRangeType(fout, tyinfo);
else
write_msg(NULL, "WARNING: typtype of data type \"%s\" appears to be invalid\n",
tyinfo->dobj.name);
} }
/* /*
......
...@@ -636,7 +636,8 @@ findLoop(DumpableObject *obj, ...@@ -636,7 +636,8 @@ findLoop(DumpableObject *obj,
/* /*
* A user-defined datatype will have a dependency loop with each of its * 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). * 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. * shell type, instead.
*/ */
static void static void
...@@ -651,7 +652,7 @@ repairTypeFuncLoop(DumpableObject *typeobj, DumpableObject *funcobj) ...@@ -651,7 +652,7 @@ repairTypeFuncLoop(DumpableObject *typeobj, DumpableObject *funcobj)
if (typeInfo->shellType) if (typeInfo->shellType)
{ {
addObjectDependency(funcobj, typeInfo->shellType->dobj.dumpId); 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) if (funcobj->dump)
typeInfo->shellType->dobj.dump = true; typeInfo->shellType->dobj.dump = true;
} }
...@@ -789,7 +790,7 @@ repairDependencyLoop(DumpableObject **loop, ...@@ -789,7 +790,7 @@ repairDependencyLoop(DumpableObject **loop,
int i, int i,
j; j;
/* Datatype and one of its I/O functions */ /* Datatype and one of its I/O or canonicalize functions */
if (nLoop == 2 && if (nLoop == 2 &&
loop[0]->objType == DO_TYPE && loop[0]->objType == DO_TYPE &&
loop[1]->objType == DO_FUNC) loop[1]->objType == DO_FUNC)
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
CATALOG(pg_range,3541) BKI_WITHOUT_OIDS CATALOG(pg_range,3541) BKI_WITHOUT_OIDS
{ {
Oid rngtypid; /* OID of owning range type */ 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 rngcollation; /* collation for this range type, or 0 */
Oid rngsubopc; /* subtype's btree opclass */ Oid rngsubopc; /* subtype's btree opclass */
regproc rngcanonical; /* canonicalize range, or 0 */ regproc rngcanonical; /* canonicalize range, or 0 */
......
...@@ -61,8 +61,9 @@ CATALOG(pg_type,1247) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71) BKI_SCHEMA_MACRO ...@@ -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 * 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' * table's rowtype), 'd' for a domain, 'e' for an enum type,
* for a pseudo-type. (Use the TYPTYPE macros below.) * '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. * If typtype is 'c', typrelid is the OID of the class' entry in pg_class.
*/ */
......
...@@ -56,11 +56,14 @@ WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR ...@@ -56,11 +56,14 @@ WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
-----+--------- -----+---------
(0 rows) (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. -- NOTE: as of 9.1, this check finds pg_node_tree, smgr, and unknown.
SELECT p1.oid, p1.typname SELECT p1.oid, p1.typname
FROM pg_type as p1 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 (SELECT 1 FROM pg_type as p2
WHERE p2.typname = ('_' || p1.typname)::name AND WHERE p2.typname = ('_' || p1.typname)::name AND
p2.typelem = p1.oid and p1.typarray = p2.oid); p2.typelem = p1.oid and p1.typarray = p2.oid);
...@@ -150,6 +153,19 @@ ORDER BY 1; ...@@ -150,6 +153,19 @@ ORDER BY 1;
30 | oidvector | 54 | oidvectorin 30 | oidvector | 54 | oidvectorin
(2 rows) (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 -- Check for bogus typoutput routines
-- As of 8.0, this check finds refcursor, which is borrowing -- As of 8.0, this check finds refcursor, which is borrowing
-- other types' I/O routines -- other types' I/O routines
...@@ -174,6 +190,26 @@ WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT ...@@ -174,6 +190,26 @@ WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
-----+---------+-----+--------- -----+---------+-----+---------
(0 rows) (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 -- Check for bogus typreceive routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2 FROM pg_type AS p1, pg_proc AS p2
...@@ -222,6 +258,19 @@ WHERE p1.typinput = p2.oid AND p1.typreceive = p3.oid AND ...@@ -222,6 +258,19 @@ WHERE p1.typinput = p2.oid AND p1.typreceive = p3.oid AND
-----+---------+-----+---------+-----+--------- -----+---------+-----+---------+-----+---------
(0 rows) (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 -- Check for bogus typsend routines
-- As of 7.4, this check finds refcursor, which is borrowing -- As of 7.4, this check finds refcursor, which is borrowing
-- other types' I/O routines -- other types' I/O routines
...@@ -246,10 +295,30 @@ WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT ...@@ -246,10 +295,30 @@ WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
-----+---------+-----+--------- -----+---------+-----+---------
(0 rows) (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 -- Check for bogus typmodin routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2 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.pronargs = 1 AND
p2.proargtypes[0] = 'cstring[]'::regtype AND p2.proargtypes[0] = 'cstring[]'::regtype AND
p2.prorettype = 'int4'::regtype AND NOT p2.proretset); 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 ...@@ -260,7 +329,7 @@ WHERE p1.typmodin = p2.oid AND p1.typtype in ('b', 'p') AND NOT
-- Check for bogus typmodout routines -- Check for bogus typmodout routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2 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.pronargs = 1 AND
p2.proargtypes[0] = 'int4'::regtype AND p2.proargtypes[0] = 'int4'::regtype AND
p2.prorettype = 'cstring'::regtype AND NOT p2.proretset); p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
...@@ -298,7 +367,7 @@ WHERE p1.typarray = p2.oid AND ...@@ -298,7 +367,7 @@ WHERE p1.typarray = p2.oid AND
-- Check for bogus typanalyze routines -- Check for bogus typanalyze routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2 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.pronargs = 1 AND
p2.proargtypes[0] = 'internal'::regtype AND p2.proargtypes[0] = 'internal'::regtype AND
p2.prorettype = 'bool'::regtype AND NOT p2.proretset); p2.prorettype = 'bool'::regtype AND NOT p2.proretset);
......
...@@ -50,12 +50,15 @@ FROM pg_type as p1 ...@@ -50,12 +50,15 @@ FROM pg_type as p1
WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
(p1.typtype != 'c' AND p1.typrelid != 0); (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. -- NOTE: as of 9.1, this check finds pg_node_tree, smgr, and unknown.
SELECT p1.oid, p1.typname SELECT p1.oid, p1.typname
FROM pg_type as p1 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 (SELECT 1 FROM pg_type as p2
WHERE p2.typname = ('_' || p1.typname)::name AND WHERE p2.typname = ('_' || p1.typname)::name AND
p2.typelem = p1.oid and p1.typarray = p2.oid); 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 ...@@ -117,6 +120,12 @@ WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND
(p2.oid = 'array_in'::regproc) (p2.oid = 'array_in'::regproc)
ORDER BY 1; 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 -- Check for bogus typoutput routines
-- As of 8.0, this check finds refcursor, which is borrowing -- As of 8.0, this check finds refcursor, which is borrowing
...@@ -135,6 +144,17 @@ FROM pg_type AS p1, pg_proc AS p2 ...@@ -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 WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
(p2.prorettype = 'cstring'::regtype AND NOT p2.proretset); (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 -- Check for bogus typreceive routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname 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 ...@@ -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 WHERE p1.typinput = p2.oid AND p1.typreceive = p3.oid AND
p2.pronargs != p3.pronargs; 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 -- Check for bogus typsend routines
-- As of 7.4, this check finds refcursor, which is borrowing -- As of 7.4, this check finds refcursor, which is borrowing
...@@ -187,11 +213,22 @@ FROM pg_type AS p1, pg_proc AS p2 ...@@ -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 WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
(p2.prorettype = 'bytea'::regtype AND NOT p2.proretset); (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 -- Check for bogus typmodin routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2 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.pronargs = 1 AND
p2.proargtypes[0] = 'cstring[]'::regtype AND p2.proargtypes[0] = 'cstring[]'::regtype AND
p2.prorettype = 'int4'::regtype AND NOT p2.proretset); 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 ...@@ -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 SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2 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.pronargs = 1 AND
p2.proargtypes[0] = 'int4'::regtype AND p2.proargtypes[0] = 'int4'::regtype AND
p2.prorettype = 'cstring'::regtype AND NOT p2.proretset); p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
...@@ -230,7 +267,7 @@ WHERE p1.typarray = p2.oid AND ...@@ -230,7 +267,7 @@ WHERE p1.typarray = p2.oid AND
SELECT p1.oid, p1.typname, p2.oid, p2.proname SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2 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.pronargs = 1 AND
p2.proargtypes[0] = 'internal'::regtype AND p2.proargtypes[0] = 'internal'::regtype AND
p2.prorettype = 'bool'::regtype AND NOT p2.proretset); p2.prorettype = 'bool'::regtype AND NOT p2.proretset);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment