]> granicus.if.org Git - postgresql/blob - src/test/regress/sql/opr_sanity.sql
Divide functions into three volatility classes (immutable, stable, and
[postgresql] / src / test / regress / sql / opr_sanity.sql
1 --
2 -- OPR_SANITY
3 -- Sanity checks for common errors in making operator/procedure system tables:
4 -- pg_operator, pg_proc, pg_aggregate, pg_am, pg_amop, pg_amproc, pg_opclass.
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 -- NB: run this test earlier than the create_operator test, because
16 -- that test creates some bogus operators...
17 --
18 -- NOTE hardwired assumptions about standard types:
19 --                type bool has OID 16
20 --                type float8 has OID 701
21 --
22
23 -- **************** pg_proc ****************
24
25 -- Look for illegal values in pg_proc fields.
26 -- NOTE: currently there are a few pg_proc entries that have prorettype = 0.
27 -- Someday that ought to be cleaned up.
28
29 SELECT p1.oid, p1.proname
30 FROM pg_proc as p1
31 WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR
32     p1.pronargs < 0 OR p1.pronargs > 9)
33         AND p1.proname !~ '^pl[^_]+_call_handler$'
34         AND p1.proname !~ '^RI_FKey_'
35         AND p1.proname !~ 'costestimate$'
36         AND p1.proname != 'update_pg_pwd_and_pg_group';
37
38 -- Look for conflicting proc definitions (same names and input datatypes).
39 -- (This test should be dead code now that we have the unique index
40 -- pg_proc_proname_narg_type_index, but I'll leave it in anyway.)
41
42 SELECT p1.oid, p1.proname, p2.oid, p2.proname
43 FROM pg_proc AS p1, pg_proc AS p2
44 WHERE p1.oid != p2.oid AND
45     p1.proname = p2.proname AND
46     p1.pronargs = p2.pronargs AND
47     p1.proargtypes = p2.proargtypes;
48
49 -- Considering only built-in procs (prolang = 11/12), look for multiple uses
50 -- of the same internal function (ie, matching prosrc fields).  It's OK to
51 -- have several entries with different pronames for the same internal function,
52 -- but conflicts in the number of arguments and other critical items should
53 -- be complained of.
54
55 SELECT p1.oid, p1.proname, p2.oid, p2.proname
56 FROM pg_proc AS p1, pg_proc AS p2
57 WHERE p1.oid != p2.oid AND
58     p1.prosrc = p2.prosrc AND
59     (p1.prolang = 11 OR p1.prolang = 12) AND
60     (p2.prolang = 11 OR p2.prolang = 12) AND
61     (p1.prolang != p2.prolang OR
62      p1.proisinh != p2.proisinh OR
63      p1.proistrusted != p2.proistrusted OR
64      p1.provolatile != p2.provolatile OR
65      p1.pronargs != p2.pronargs OR
66      p1.proretset != p2.proretset);
67
68 -- Look for uses of different type OIDs in the argument/result type fields
69 -- for different aliases of the same built-in function.
70 -- This indicates that the types are being presumed to be binary-equivalent.
71 -- That's not wrong, necessarily, but we make lists of all the types being
72 -- so treated.  Note that the expected output of this part of the test will
73 -- need to be modified whenever new pairs of types are made binary-equivalent!
74
75 SELECT DISTINCT p1.prorettype, p2.prorettype
76 FROM pg_proc AS p1, pg_proc AS p2
77 WHERE p1.oid != p2.oid AND
78     p1.prosrc = p2.prosrc AND
79     (p1.prolang = 11 OR p1.prolang = 12) AND
80     (p2.prolang = 11 OR p2.prolang = 12) AND
81     (p1.prorettype < p2.prorettype);
82
83 SELECT DISTINCT p1.proargtypes[0], p2.proargtypes[0]
84 FROM pg_proc AS p1, pg_proc AS p2
85 WHERE p1.oid != p2.oid AND
86     p1.prosrc = p2.prosrc AND
87     (p1.prolang = 11 OR p1.prolang = 12) AND
88     (p2.prolang = 11 OR p2.prolang = 12) AND
89     (p1.proargtypes[0] < p2.proargtypes[0]);
90
91 SELECT DISTINCT p1.proargtypes[1], p2.proargtypes[1]
92 FROM pg_proc AS p1, pg_proc AS p2
93 WHERE p1.oid != p2.oid AND
94     p1.prosrc = p2.prosrc AND
95     (p1.prolang = 11 OR p1.prolang = 12) AND
96     (p2.prolang = 11 OR p2.prolang = 12) AND
97     (p1.proargtypes[1] < p2.proargtypes[1]);
98
99 SELECT DISTINCT p1.proargtypes[2], p2.proargtypes[2]
100 FROM pg_proc AS p1, pg_proc AS p2
101 WHERE p1.oid != p2.oid AND
102     p1.prosrc = p2.prosrc AND
103     (p1.prolang = 11 OR p1.prolang = 12) AND
104     (p2.prolang = 11 OR p2.prolang = 12) AND
105     (p1.proargtypes[2] < p2.proargtypes[2]);
106
107 SELECT DISTINCT p1.proargtypes[3], p2.proargtypes[3]
108 FROM pg_proc AS p1, pg_proc AS p2
109 WHERE p1.oid != p2.oid AND
110     p1.prosrc = p2.prosrc AND
111     (p1.prolang = 11 OR p1.prolang = 12) AND
112     (p2.prolang = 11 OR p2.prolang = 12) AND
113     (p1.proargtypes[3] < p2.proargtypes[3]);
114
115 SELECT DISTINCT p1.proargtypes[4], p2.proargtypes[4]
116 FROM pg_proc AS p1, pg_proc AS p2
117 WHERE p1.oid != p2.oid AND
118     p1.prosrc = p2.prosrc AND
119     (p1.prolang = 11 OR p1.prolang = 12) AND
120     (p2.prolang = 11 OR p2.prolang = 12) AND
121     (p1.proargtypes[4] < p2.proargtypes[4]);
122
123 SELECT DISTINCT p1.proargtypes[5], p2.proargtypes[5]
124 FROM pg_proc AS p1, pg_proc AS p2
125 WHERE p1.oid != p2.oid AND
126     p1.prosrc = p2.prosrc AND
127     (p1.prolang = 11 OR p1.prolang = 12) AND
128     (p2.prolang = 11 OR p2.prolang = 12) AND
129     (p1.proargtypes[5] < p2.proargtypes[5]);
130
131 SELECT DISTINCT p1.proargtypes[6], p2.proargtypes[6]
132 FROM pg_proc AS p1, pg_proc AS p2
133 WHERE p1.oid != p2.oid AND
134     p1.prosrc = p2.prosrc AND
135     (p1.prolang = 11 OR p1.prolang = 12) AND
136     (p2.prolang = 11 OR p2.prolang = 12) AND
137     (p1.proargtypes[6] < p2.proargtypes[6]);
138
139 SELECT DISTINCT p1.proargtypes[7], p2.proargtypes[7]
140 FROM pg_proc AS p1, pg_proc AS p2
141 WHERE p1.oid != p2.oid AND
142     p1.prosrc = p2.prosrc AND
143     (p1.prolang = 11 OR p1.prolang = 12) AND
144     (p2.prolang = 11 OR p2.prolang = 12) AND
145     (p1.proargtypes[7] < p2.proargtypes[7]);
146
147 -- **************** pg_operator ****************
148
149 -- Look for illegal values in pg_operator fields.
150
151 SELECT p1.oid, p1.oprname
152 FROM pg_operator as p1
153 WHERE (p1.oprkind != 'b' AND p1.oprkind != 'l' AND p1.oprkind != 'r') OR
154     p1.oprresult = 0 OR p1.oprcode = 0;
155
156 -- Look for missing or unwanted operand types
157
158 SELECT p1.oid, p1.oprname
159 FROM pg_operator as p1
160 WHERE (p1.oprleft = 0 and p1.oprkind != 'l') OR
161     (p1.oprleft != 0 and p1.oprkind = 'l') OR
162     (p1.oprright = 0 and p1.oprkind != 'r') OR
163     (p1.oprright != 0 and p1.oprkind = 'r');
164
165 -- Look for conflicting operator definitions (same names and input datatypes).
166
167 SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
168 FROM pg_operator AS p1, pg_operator AS p2
169 WHERE p1.oid != p2.oid AND
170     p1.oprname = p2.oprname AND
171     p1.oprkind = p2.oprkind AND
172     p1.oprleft = p2.oprleft AND
173     p1.oprright = p2.oprright;
174
175 -- Look for commutative operators that don't commute.
176 -- DEFINITIONAL NOTE: If A.oprcom = B, then x A y has the same result as y B x.
177 -- We expect that B will always say that B.oprcom = A as well; that's not
178 -- inherently essential, but it would be inefficient not to mark it so.
179
180 SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
181 FROM pg_operator AS p1, pg_operator AS p2
182 WHERE p1.oprcom = p2.oid AND
183     (p1.oprkind != 'b' OR
184      p1.oprleft != p2.oprright OR
185      p1.oprright != p2.oprleft OR
186      p1.oprresult != p2.oprresult OR
187      p1.oid != p2.oprcom);
188
189 -- Look for negatory operators that don't agree.
190 -- DEFINITIONAL NOTE: If A.oprnegate = B, then both A and B must yield
191 -- boolean results, and (x A y) == ! (x B y), or the equivalent for
192 -- single-operand operators.
193 -- We expect that B will always say that B.oprnegate = A as well; that's not
194 -- inherently essential, but it would be inefficient not to mark it so.
195
196 SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
197 FROM pg_operator AS p1, pg_operator AS p2
198 WHERE p1.oprnegate = p2.oid AND
199     (p1.oprkind != p2.oprkind OR
200      p1.oprleft != p2.oprleft OR
201      p1.oprright != p2.oprright OR
202      p1.oprresult != 16 OR
203      p2.oprresult != 16 OR
204      p1.oid != p2.oprnegate);
205
206 -- Look for mergejoin operators that don't match their links.
207 -- A mergejoin link leads from an '=' operator to the
208 -- sort operator ('<' operator) that's appropriate for
209 -- its left-side or right-side data type.
210
211 SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
212 FROM pg_operator AS p1, pg_operator AS p2
213 WHERE p1.oprlsortop = p2.oid AND
214     (p1.oprname != '=' OR p2.oprname != '<' OR
215      p1.oprkind != 'b' OR p2.oprkind != 'b' OR
216      p1.oprleft != p2.oprleft OR
217      p1.oprleft != p2.oprright OR
218      p1.oprresult != 16 OR
219      p2.oprresult != 16 OR
220      p1.oprrsortop = 0);
221
222 SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
223 FROM pg_operator AS p1, pg_operator AS p2
224 WHERE p1.oprrsortop = p2.oid AND
225     (p1.oprname != '=' OR p2.oprname != '<' OR
226      p1.oprkind != 'b' OR p2.oprkind != 'b' OR
227      p1.oprright != p2.oprleft OR
228      p1.oprright != p2.oprright OR
229      p1.oprresult != 16 OR
230      p2.oprresult != 16 OR
231      p1.oprlsortop = 0);
232
233 -- A mergejoinable = operator must have a commutator (usually itself)
234 -- as well as corresponding < and > operators.  Note that the "corresponding"
235 -- operators have the same L and R input datatypes as the = operator,
236 -- whereas the operators linked to by oprlsortop and oprrsortop have input
237 -- datatypes L,L and R,R respectively.
238
239 SELECT p1.oid, p1.oprname FROM pg_operator AS p1
240 WHERE p1.oprlsortop != 0 AND
241       p1.oprcom = 0;
242
243 SELECT p1.oid, p1.oprname FROM pg_operator AS p1
244 WHERE p1.oprlsortop != 0 AND NOT
245       EXISTS(SELECT * FROM pg_operator AS p2 WHERE
246         p2.oprname = '<' AND
247         p2.oprleft = p1.oprleft AND
248         p2.oprright = p1.oprright AND
249         p2.oprkind = 'b');
250
251 SELECT p1.oid, p1.oprname FROM pg_operator AS p1
252 WHERE p1.oprlsortop != 0 AND NOT
253       EXISTS(SELECT * FROM pg_operator AS p2 WHERE
254         p2.oprname = '>' AND
255         p2.oprleft = p1.oprleft AND
256         p2.oprright = p1.oprright AND
257         p2.oprkind = 'b');
258
259 -- Mergejoinable operators across datatypes must come in closed sets, that
260 -- is if you provide int2 = int4 and int4 = int8 then you must also provide
261 -- int2 = int8 (and commutators of all these).  This is necessary because
262 -- the planner tries to deduce additional qual clauses from transitivity
263 -- of mergejoinable operators.  If there are clauses int2var = int4var and
264 -- int4var = int8var, the planner will deduce int2var = int8var ... and it
265 -- had better have a way to represent it.
266
267 SELECT p1.oid, p2.oid FROM pg_operator AS p1, pg_operator AS p2
268 WHERE p1.oprlsortop != p1.oprrsortop AND
269       p1.oprrsortop = p2.oprlsortop AND
270       p2.oprlsortop != p2.oprrsortop AND
271       NOT EXISTS (SELECT 1 FROM pg_operator p3 WHERE
272       p3.oprlsortop = p1.oprlsortop AND p3.oprrsortop = p2.oprrsortop);
273
274
275 -- Hashing only works on simple equality operators "type = sametype",
276 -- since the hash itself depends on the bitwise representation of the type.
277 -- Check that allegedly hashable operators look like they might be "=".
278 -- NOTE: in 7.2, this search finds int4eqoid, oideqint4, and xideqint4.
279 -- Until we have some cleaner way of dealing with binary-equivalent types,
280 -- just leave those three tuples in the expected output.
281
282 SELECT p1.oid, p1.oprname
283 FROM pg_operator AS p1
284 WHERE p1.oprcanhash AND NOT
285     (p1.oprkind = 'b' AND p1.oprresult = 16 AND p1.oprleft = p1.oprright AND
286      p1.oprname = '=' AND p1.oprcom = p1.oid);
287
288 -- In 6.5 we accepted hashable array equality operators when the array element
289 -- type is hashable.  However, what we actually need to make hashjoin work on
290 -- an array is a hashable element type *and* no padding between elements in
291 -- the array storage (or, perhaps, guaranteed-zero padding).  Currently,
292 -- since the padding code in arrayfuncs.c is pretty bogus, it seems safest
293 -- to just forbid hashjoin on array equality ops.
294 -- This should be reconsidered someday.
295
296 -- -- Look for array equality operators that are hashable when the underlying
297 -- -- type is not, or vice versa.  This is presumably bogus.
298 -- 
299 -- SELECT p1.oid, p1.oprcanhash, p2.oid, p2.oprcanhash, t1.typname, t2.typname
300 -- FROM pg_operator AS p1, pg_operator AS p2, pg_type AS t1, pg_type AS t2
301 -- WHERE p1.oprname = '=' AND p1.oprleft = p1.oprright AND 
302 --     p2.oprname = '=' AND p2.oprleft = p2.oprright AND
303 --     p1.oprleft = t1.oid AND p2.oprleft = t2.oid AND t1.typelem = t2.oid AND
304 --     p1.oprcanhash != p2.oprcanhash;
305
306 -- Substitute check: forbid hashable array ops, period.
307 SELECT p1.oid, p1.oprname
308 FROM pg_operator AS p1, pg_proc AS p2
309 WHERE p1.oprcanhash AND p1.oprcode = p2.oid AND p2.proname = 'array_eq';
310
311 -- Check that each operator defined in pg_operator matches its oprcode entry
312 -- in pg_proc.  Easiest to do this separately for each oprkind.
313 -- FIXME: want to check that argument/result types match, but how to do that
314 -- in the face of binary-compatible types?
315
316 SELECT p1.oid, p1.oprname, p2.oid, p2.proname
317 FROM pg_operator AS p1, pg_proc AS p2
318 WHERE p1.oprcode = p2.oid AND
319     p1.oprkind = 'b' AND
320     (p2.pronargs != 2
321 -- diked out until we find a way of marking binary-compatible types
322 -- OR
323 --     p1.oprresult != p2.prorettype OR
324 --     (p1.oprleft != p2.proargtypes[0] AND p2.proargtypes[0] != 0) OR
325 --     (p1.oprright != p2.proargtypes[1] AND p2.proargtypes[1] != 0)
326 );
327
328 -- These two selects can be left as-is because there are no binary-compatible
329 -- cases that they trip over, at least in 6.5:
330
331 SELECT p1.oid, p1.oprname, p2.oid, p2.proname
332 FROM pg_operator AS p1, pg_proc AS p2
333 WHERE p1.oprcode = p2.oid AND
334     p1.oprkind = 'l' AND
335     (p2.pronargs != 1 OR
336      p1.oprresult != p2.prorettype OR
337      (p1.oprright != p2.proargtypes[0] AND p2.proargtypes[0] != 0) OR
338      p1.oprleft != 0);
339
340 SELECT p1.oid, p1.oprname, p2.oid, p2.proname
341 FROM pg_operator AS p1, pg_proc AS p2
342 WHERE p1.oprcode = p2.oid AND
343     p1.oprkind = 'r' AND
344     (p2.pronargs != 1 OR
345      p1.oprresult != p2.prorettype OR
346      (p1.oprleft != p2.proargtypes[0] AND p2.proargtypes[0] != 0) OR
347      p1.oprright != 0);
348
349 -- If oprrest is set, the operator must return boolean,
350 -- and it must link to a proc with the right signature
351 -- to be a restriction selectivity estimator.
352 -- The proc signature we want is: float8 proc(opaque, oid, opaque, int4)
353
354 SELECT p1.oid, p1.oprname, p2.oid, p2.proname
355 FROM pg_operator AS p1, pg_proc AS p2
356 WHERE p1.oprrest = p2.oid AND
357     (p1.oprresult != 16 OR
358      p2.prorettype != 701 OR p2.proretset OR
359      p2.pronargs != 4 OR
360      p2.proargtypes[0] != 0 OR p2.proargtypes[1] != 26 OR
361      p2.proargtypes[2] != 0 OR p2.proargtypes[3] != 23);
362
363 -- If oprjoin is set, the operator must be a binary boolean op,
364 -- and it must link to a proc with the right signature
365 -- to be a join selectivity estimator.
366 -- The proc signature we want is: float8 proc(opaque, oid, opaque)
367
368 SELECT p1.oid, p1.oprname, p2.oid, p2.proname
369 FROM pg_operator AS p1, pg_proc AS p2
370 WHERE p1.oprjoin = p2.oid AND
371     (p1.oprkind != 'b' OR p1.oprresult != 16 OR
372      p2.prorettype != 701 OR p2.proretset OR
373      p2.pronargs != 3 OR
374      p2.proargtypes[0] != 0 OR p2.proargtypes[1] != 26 OR
375      p2.proargtypes[2] != 0);
376
377 -- **************** pg_aggregate ****************
378
379 -- Look for illegal values in pg_aggregate fields.
380
381 SELECT p1.oid, p1.aggname
382 FROM pg_aggregate as p1
383 WHERE aggtransfn = 0 OR aggtranstype = 0 OR aggfinaltype = 0;
384
385 -- If there is no finalfn then the output type must be the transtype.
386
387 SELECT p1.oid, p1.aggname
388 FROM pg_aggregate as p1
389 WHERE p1.aggfinalfn = 0 AND p1.aggfinaltype != p1.aggtranstype;
390
391 -- Cross-check transfn against its entry in pg_proc.
392 -- FIXME: what about binary-compatible types?
393 -- NOTE: in 7.1, this search finds max and min on abstime, which are
394 -- implemented using int4larger/int4smaller.  Until we have
395 -- some cleaner way of dealing with binary-equivalent types, just leave
396 -- those two tuples in the expected output.
397 SELECT p1.oid, p1.aggname, p2.oid, p2.proname
398 FROM pg_aggregate AS p1, pg_proc AS p2
399 WHERE p1.aggtransfn = p2.oid AND
400     (p2.proretset OR
401      p1.aggtranstype != p2.prorettype OR
402      p1.aggtranstype != p2.proargtypes[0] OR
403      NOT ((p2.pronargs = 2 AND p1.aggbasetype = p2.proargtypes[1]) OR
404           (p2.pronargs = 1 AND p1.aggbasetype = 0)));
405
406 -- Cross-check finalfn (if present) against its entry in pg_proc.
407 -- FIXME: what about binary-compatible types?
408
409 SELECT p1.oid, p1.aggname, p2.oid, p2.proname
410 FROM pg_aggregate AS p1, pg_proc AS p2
411 WHERE p1.aggfinalfn = p2.oid AND
412     (p2.proretset OR p1.aggfinaltype != p2.prorettype OR
413      p2.pronargs != 1 OR
414      p1.aggtranstype != p2.proargtypes[0]);
415
416 -- If transfn is strict then either initval should be non-NULL, or
417 -- basetype should equal transtype so that the first non-null input
418 -- can be assigned as the state value.
419
420 SELECT p1.oid, p1.aggname, p2.oid, p2.proname
421 FROM pg_aggregate AS p1, pg_proc AS p2
422 WHERE p1.aggtransfn = p2.oid AND p2.proisstrict AND
423     p1.agginitval IS NULL AND p1.aggbasetype != p1.aggtranstype;
424
425 -- **************** pg_opclass ****************
426
427 -- Look for illegal values in pg_opclass fields
428
429 SELECT p1.oid
430 FROM pg_opclass as p1
431 WHERE p1.opcamid = 0 OR p1.opcintype = 0;
432
433 -- There should not be multiple entries in pg_opclass with opcdefault true
434 -- and the same opcamid/opcintype combination.
435
436 SELECT p1.oid, p2.oid
437 FROM pg_opclass AS p1, pg_opclass AS p2
438 WHERE p1.oid != p2.oid AND
439     p1.opcamid = p2.opcamid AND p1.opcintype = p2.opcintype AND
440     p1.opcdefault AND p2.opcdefault;
441
442 -- **************** pg_amop ****************
443
444 -- Look for illegal values in pg_amop fields
445
446 SELECT p1.amopclaid, p1.amopstrategy
447 FROM pg_amop as p1
448 WHERE p1.amopclaid = 0 OR p1.amopstrategy <= 0 OR p1.amopopr = 0;
449
450 -- Cross-check amopstrategy index against parent AM
451
452 SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.amname
453 FROM pg_amop AS p1, pg_am AS p2, pg_opclass AS p3
454 WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND
455     p1.amopstrategy > p2.amstrategies;
456
457 -- Detect missing pg_amop entries: should have as many strategy functions
458 -- as AM expects for each opclass for the AM
459
460 SELECT p1.oid, p1.amname, p2.oid, p2.opcname
461 FROM pg_am AS p1, pg_opclass AS p2
462 WHERE p2.opcamid = p1.oid AND
463     p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3
464                         WHERE p3.amopclaid = p2.oid);
465
466 -- Check that amopopr points at a reasonable-looking operator, ie a binary
467 -- operator yielding boolean.
468 -- NOTE: for 7.1, add restriction that operator inputs are of same type.
469 -- We used to have opclasses like "int24_ops" but these were broken.
470
471 SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname
472 FROM pg_amop AS p1, pg_operator AS p2
473 WHERE p1.amopopr = p2.oid AND
474     (p2.oprkind != 'b' OR p2.oprresult != 16 OR p2.oprleft != p2.oprright);
475
476 -- Check that operator input types match the opclass
477
478 SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname
479 FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3
480 WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND
481     (p3.opcintype != p2.oprleft OR p3.opcintype != p2.oprright);
482
483 -- **************** pg_amproc ****************
484
485 -- Look for illegal values in pg_amproc fields
486
487 SELECT p1.amopclaid, p1.amprocnum
488 FROM pg_amproc as p1
489 WHERE p1.amopclaid = 0 OR p1.amprocnum <= 0 OR p1.amproc = 0;
490
491 -- Cross-check amprocnum index against parent AM
492
493 SELECT p1.amopclaid, p1.amprocnum, p2.oid, p2.amname
494 FROM pg_amproc AS p1, pg_am AS p2, pg_opclass AS p3
495 WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND
496     p1.amprocnum > p2.amsupport;
497
498 -- Detect missing pg_amproc entries: should have as many support functions
499 -- as AM expects for each opclass for the AM
500
501 SELECT p1.oid, p1.amname, p2.oid, p2.opcname
502 FROM pg_am AS p1, pg_opclass AS p2
503 WHERE p2.opcamid = p1.oid AND
504     p1.amsupport != (SELECT count(*) FROM pg_amproc AS p3
505                      WHERE p3.amopclaid = p2.oid);
506
507 -- Unfortunately, we can't check the amproc link very well because the
508 -- signature of the function may be different for different support routines
509 -- or different base data types.
510 -- We can check that all the referenced instances of the same support
511 -- routine number take the same number of parameters, but that's about it...
512
513 SELECT p1.amopclaid, p1.amprocnum,
514         p2.oid, p2.proname,
515         p3.opcname,
516         p4.amopclaid, p4.amprocnum,
517         p5.oid, p5.proname,
518         p6.opcname
519 FROM pg_amproc AS p1, pg_proc AS p2, pg_opclass AS p3,
520      pg_amproc AS p4, pg_proc AS p5, pg_opclass AS p6
521 WHERE p1.amopclaid = p3.oid AND p4.amopclaid = p6.oid AND
522     p3.opcamid = p6.opcamid AND p1.amprocnum = p4.amprocnum AND
523     p1.amproc = p2.oid AND p4.amproc = p5.oid AND
524     (p2.proretset OR p5.proretset OR p2.pronargs != p5.pronargs);