]> granicus.if.org Git - postgresql/blob - src/test/regress/sql/type_sanity.sql
Basic foreign table support.
[postgresql] / src / test / regress / sql / type_sanity.sql
1 --
2 -- TYPE_SANITY
3 -- Sanity checks for common errors in making type-related system tables:
4 -- pg_type, pg_class, pg_attribute.
5 --
6 -- None of the SELECTs here should ever find any matching entries,
7 -- so the expected output is easy to maintain ;-).
8 -- A test failure indicates someone messed up an entry in the system tables.
9 --
10 -- NB: we assume the oidjoins test will have caught any dangling links,
11 -- that is OID or REGPROC fields that are not zero and do not match some
12 -- row in the linked-to table.  However, if we want to enforce that a link
13 -- field can't be 0, we have to check it here.
14
15 -- **************** pg_type ****************
16
17 -- Look for illegal values in pg_type fields.
18
19 SELECT p1.oid, p1.typname
20 FROM pg_type as p1
21 WHERE p1.typnamespace = 0 OR
22     (p1.typlen <= 0 AND p1.typlen != -1 AND p1.typlen != -2) OR
23     (p1.typtype not in ('b', 'c', 'd', 'e', 'p')) OR
24     NOT p1.typisdefined OR
25     (p1.typalign not in ('c', 's', 'i', 'd')) OR
26     (p1.typstorage not in ('p', 'x', 'e', 'm'));
27
28 -- Look for "pass by value" types that can't be passed by value.
29
30 SELECT p1.oid, p1.typname
31 FROM pg_type as p1
32 WHERE p1.typbyval AND
33     (p1.typlen != 1 OR p1.typalign != 'c') AND
34     (p1.typlen != 2 OR p1.typalign != 's') AND
35     (p1.typlen != 4 OR p1.typalign != 'i') AND
36     (p1.typlen != 8 OR p1.typalign != 'd');
37
38 -- Look for "toastable" types that aren't varlena.
39
40 SELECT p1.oid, p1.typname
41 FROM pg_type as p1
42 WHERE p1.typstorage != 'p' AND
43     (p1.typbyval OR p1.typlen != -1);
44
45 -- Look for complex types that do not have a typrelid entry,
46 -- or basic types that do.
47
48 SELECT p1.oid, p1.typname
49 FROM pg_type as p1
50 WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
51     (p1.typtype != 'c' AND p1.typrelid != 0);
52
53 -- Look for basic or enum types that don't have an array type.
54 -- NOTE: as of 9.1, this check finds pg_node_tree, smgr, and unknown.
55
56 SELECT p1.oid, p1.typname
57 FROM pg_type as p1
58 WHERE p1.typtype in ('b','e') AND p1.typname NOT LIKE E'\\_%' AND NOT EXISTS
59     (SELECT 1 FROM pg_type as p2
60      WHERE p2.typname = ('_' || p1.typname)::name AND
61            p2.typelem = p1.oid and p1.typarray = p2.oid);
62
63 -- Make sure typarray points to a varlena array type of our own base
64 SELECT p1.oid, p1.typname as basetype, p2.typname as arraytype,
65        p2.typelem, p2.typlen
66 FROM   pg_type p1 LEFT JOIN pg_type p2 ON (p1.typarray = p2.oid)
67 WHERE  p1.typarray <> 0 AND
68        (p2.oid IS NULL OR p2.typelem <> p1.oid OR p2.typlen <> -1);
69
70 -- Text conversion routines must be provided.
71
72 SELECT p1.oid, p1.typname
73 FROM pg_type as p1
74 WHERE (p1.typinput = 0 OR p1.typoutput = 0);
75
76 -- Check for bogus typinput routines
77
78 SELECT p1.oid, p1.typname, p2.oid, p2.proname
79 FROM pg_type AS p1, pg_proc AS p2
80 WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
81     ((p2.pronargs = 1 AND p2.proargtypes[0] = 'cstring'::regtype) OR
82      (p2.pronargs = 3 AND p2.proargtypes[0] = 'cstring'::regtype AND
83       p2.proargtypes[1] = 'oid'::regtype AND
84       p2.proargtypes[2] = 'int4'::regtype));
85
86 -- As of 8.0, this check finds refcursor, which is borrowing
87 -- other types' I/O routines
88 SELECT p1.oid, p1.typname, p2.oid, p2.proname
89 FROM pg_type AS p1, pg_proc AS p2
90 WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
91     (p1.typelem != 0 AND p1.typlen < 0) AND NOT
92     (p2.prorettype = p1.oid AND NOT p2.proretset)
93 ORDER BY 1;
94
95 -- Varlena array types will point to array_in
96 -- Exception as of 8.1: int2vector and oidvector have their own I/O routines
97 SELECT p1.oid, p1.typname, p2.oid, p2.proname
98 FROM pg_type AS p1, pg_proc AS p2
99 WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND
100     (p1.typelem != 0 AND p1.typlen < 0) AND NOT
101     (p2.oid = 'array_in'::regproc)
102 ORDER BY 1;
103
104 -- Check for bogus typoutput routines
105
106 -- As of 8.0, this check finds refcursor, which is borrowing
107 -- other types' I/O routines
108 SELECT p1.oid, p1.typname, p2.oid, p2.proname
109 FROM pg_type AS p1, pg_proc AS p2
110 WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
111     (p2.pronargs = 1 AND
112      (p2.proargtypes[0] = p1.oid OR
113       (p2.oid = 'array_out'::regproc AND
114        p1.typelem != 0 AND p1.typlen = -1)))
115 ORDER BY 1;
116
117 SELECT p1.oid, p1.typname, p2.oid, p2.proname
118 FROM pg_type AS p1, pg_proc AS p2
119 WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
120     (p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
121
122 -- Check for bogus typreceive routines
123
124 SELECT p1.oid, p1.typname, p2.oid, p2.proname
125 FROM pg_type AS p1, pg_proc AS p2
126 WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND NOT
127     ((p2.pronargs = 1 AND p2.proargtypes[0] = 'internal'::regtype) OR
128      (p2.pronargs = 3 AND p2.proargtypes[0] = 'internal'::regtype AND
129       p2.proargtypes[1] = 'oid'::regtype AND
130       p2.proargtypes[2] = 'int4'::regtype));
131
132 -- As of 7.4, this check finds refcursor, which is borrowing
133 -- other types' I/O routines
134 SELECT p1.oid, p1.typname, p2.oid, p2.proname
135 FROM pg_type AS p1, pg_proc AS p2
136 WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND NOT
137     (p1.typelem != 0 AND p1.typlen < 0) AND NOT
138     (p2.prorettype = p1.oid AND NOT p2.proretset)
139 ORDER BY 1;
140
141 -- Varlena array types will point to array_recv
142 -- Exception as of 8.1: int2vector and oidvector have their own I/O routines
143 SELECT p1.oid, p1.typname, p2.oid, p2.proname
144 FROM pg_type AS p1, pg_proc AS p2
145 WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND
146     (p1.typelem != 0 AND p1.typlen < 0) AND NOT
147     (p2.oid = 'array_recv'::regproc)
148 ORDER BY 1;
149
150 -- Suspicious if typreceive doesn't take same number of args as typinput
151 SELECT p1.oid, p1.typname, p2.oid, p2.proname, p3.oid, p3.proname
152 FROM pg_type AS p1, pg_proc AS p2, pg_proc AS p3
153 WHERE p1.typinput = p2.oid AND p1.typreceive = p3.oid AND
154     p2.pronargs != p3.pronargs;
155
156 -- Check for bogus typsend routines
157
158 -- As of 7.4, this check finds refcursor, which is borrowing
159 -- other types' I/O routines
160 SELECT p1.oid, p1.typname, p2.oid, p2.proname
161 FROM pg_type AS p1, pg_proc AS p2
162 WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
163     (p2.pronargs = 1 AND
164      (p2.proargtypes[0] = p1.oid OR
165       (p2.oid = 'array_send'::regproc AND
166        p1.typelem != 0 AND p1.typlen = -1)))
167 ORDER BY 1;
168
169 SELECT p1.oid, p1.typname, p2.oid, p2.proname
170 FROM pg_type AS p1, pg_proc AS p2
171 WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
172     (p2.prorettype = 'bytea'::regtype AND NOT p2.proretset);
173
174 -- Check for bogus typmodin routines
175
176 SELECT p1.oid, p1.typname, p2.oid, p2.proname
177 FROM pg_type AS p1, pg_proc AS p2
178 WHERE p1.typmodin = p2.oid AND p1.typtype in ('b', 'p') AND NOT
179     (p2.pronargs = 1 AND
180      p2.proargtypes[0] = 'cstring[]'::regtype AND
181      p2.prorettype = 'int4'::regtype AND NOT p2.proretset);
182
183 -- Check for bogus typmodout routines
184
185 SELECT p1.oid, p1.typname, p2.oid, p2.proname
186 FROM pg_type AS p1, pg_proc AS p2
187 WHERE p1.typmodout = p2.oid AND p1.typtype in ('b', 'p') AND NOT
188     (p2.pronargs = 1 AND
189      p2.proargtypes[0] = 'int4'::regtype AND
190      p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
191
192 -- Array types should have same typmodin/out as their element types
193
194 SELECT p1.oid, p1.typname, p2.oid, p2.typname
195 FROM pg_type AS p1, pg_type AS p2
196 WHERE p1.typelem = p2.oid AND NOT
197     (p1.typmodin = p2.typmodin AND p1.typmodout = p2.typmodout);
198
199 -- Array types should have same typdelim as their element types
200
201 SELECT p1.oid, p1.typname, p2.oid, p2.typname
202 FROM pg_type AS p1, pg_type AS p2
203 WHERE p1.typarray = p2.oid AND NOT (p1.typdelim = p2.typdelim);
204
205 -- Check for bogus typanalyze routines
206
207 SELECT p1.oid, p1.typname, p2.oid, p2.proname
208 FROM pg_type AS p1, pg_proc AS p2
209 WHERE p1.typanalyze = p2.oid AND p1.typtype in ('b', 'p') AND NOT
210     (p2.pronargs = 1 AND
211      p2.proargtypes[0] = 'internal'::regtype AND
212      p2.prorettype = 'bool'::regtype AND NOT p2.proretset);
213
214 -- **************** pg_class ****************
215
216 -- Look for illegal values in pg_class fields
217
218 SELECT p1.oid, p1.relname
219 FROM pg_class as p1
220 WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 'c', 't', 'v', 'f');
221
222 -- Indexes should have an access method, others not.
223
224 SELECT p1.oid, p1.relname
225 FROM pg_class as p1
226 WHERE (p1.relkind = 'i' AND p1.relam = 0) OR
227     (p1.relkind != 'i' AND p1.relam != 0);
228
229 -- **************** pg_attribute ****************
230
231 -- Look for illegal values in pg_attribute fields
232
233 SELECT p1.attrelid, p1.attname
234 FROM pg_attribute as p1
235 WHERE p1.attrelid = 0 OR p1.atttypid = 0 OR p1.attnum = 0 OR
236     p1.attcacheoff != -1 OR p1.attinhcount < 0 OR
237     (p1.attinhcount = 0 AND NOT p1.attislocal);
238
239 -- Cross-check attnum against parent relation
240
241 SELECT p1.attrelid, p1.attname, p2.oid, p2.relname
242 FROM pg_attribute AS p1, pg_class AS p2
243 WHERE p1.attrelid = p2.oid AND p1.attnum > p2.relnatts;
244
245 -- Detect missing pg_attribute entries: should have as many non-system
246 -- attributes as parent relation expects
247
248 SELECT p1.oid, p1.relname
249 FROM pg_class AS p1
250 WHERE p1.relnatts != (SELECT count(*) FROM pg_attribute AS p2
251                       WHERE p2.attrelid = p1.oid AND p2.attnum > 0);
252
253 -- Cross-check against pg_type entry
254 -- NOTE: we allow attstorage to be 'plain' even when typstorage is not;
255 -- this is mainly for toast tables.
256
257 SELECT p1.attrelid, p1.attname, p2.oid, p2.typname
258 FROM pg_attribute AS p1, pg_type AS p2
259 WHERE p1.atttypid = p2.oid AND
260     (p1.attlen != p2.typlen OR
261      p1.attalign != p2.typalign OR
262      p1.attbyval != p2.typbyval OR
263      (p1.attstorage != p2.typstorage AND p1.attstorage != 'p'));