Improve correlation names in sanity tests

Some of the queries in the "sanity" tests in the regression test suite
(opr_sanity, type_sanity) are very confusing.  One main stumbling
block is that for some probably ancient reason many of the older
queries are written with correlation names p1, p2, etc. independent of
the name of the catalog. This one is a good example:

SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2          <-- HERE
WHERE p1.oprcode = p2.oid AND
    p1.oprkind = 'l' AND
    (p2.pronargs != 1
     OR NOT binary_coercible(p2.prorettype, p1.oprresult)
     OR NOT binary_coercible(p1.oprright, p2.proargtypes[0])
     OR p1.oprleft != 0);

This is better written as

SELECT o1.oid, o1.oprname, p1.oid, p1.proname
FROM pg_operator AS o1, pg_proc AS p1
WHERE o1.oprcode = p1.oid AND
    o1.oprkind = 'l' AND
    (p1.pronargs != 1
     OR NOT binary_coercible(p1.prorettype, o1.oprresult)
     OR NOT binary_coercible(o1.oprright, p1.proargtypes[0])
     OR o1.oprleft != 0);

This patch cleans up all the queries in this manner.

(As in the above case, I kept the digits like o1 and p1 even in cases
where only one of each letter is used in a query.  This is mainly to
keep the style consistent.)

Discussion: https://www.postgresql.org/message-id/flat/c538308b-319c-8784-e250-1284d12d5411%40enterprisedb.com
This commit is contained in:
Peter Eisentraut 2022-02-13 21:07:25 +01:00
parent cba5b994c9
commit 9898c5e03c
4 changed files with 840 additions and 840 deletions

View File

@ -991,9 +991,9 @@ WHERE c.castmethod = 'b' AND
-- **************** pg_conversion ****************
-- Look for illegal values in pg_conversion fields.
SELECT p1.oid, p1.conname
FROM pg_conversion as p1
WHERE p1.conproc = 0 OR
SELECT c.oid, c.conname
FROM pg_conversion as c
WHERE c.conproc = 0 OR
pg_encoding_to_char(conforencoding) = '' OR
pg_encoding_to_char(contoencoding) = '';
oid | conname
@ -1025,8 +1025,8 @@ WHERE p.oid = c.conproc AND
-- them directly from SQL. But there are no non-default built-in
-- conversions anyway.
-- (Similarly, this doesn't cope with any search path issues.)
SELECT p1.oid, p1.conname
FROM pg_conversion as p1
SELECT c.oid, c.conname
FROM pg_conversion as c
WHERE condefault AND
convert('ABC'::bytea, pg_encoding_to_char(conforencoding),
pg_encoding_to_char(contoencoding)) != 'ABC';
@ -1036,32 +1036,32 @@ WHERE condefault AND
-- **************** pg_operator ****************
-- Look for illegal values in pg_operator fields.
SELECT p1.oid, p1.oprname
FROM pg_operator as p1
WHERE (p1.oprkind != 'b' AND p1.oprkind != 'l') OR
p1.oprresult = 0 OR p1.oprcode = 0;
SELECT o1.oid, o1.oprname
FROM pg_operator as o1
WHERE (o1.oprkind != 'b' AND o1.oprkind != 'l') OR
o1.oprresult = 0 OR o1.oprcode = 0;
oid | oprname
-----+---------
(0 rows)
-- Look for missing or unwanted operand types
SELECT p1.oid, p1.oprname
FROM pg_operator as p1
WHERE (p1.oprleft = 0 and p1.oprkind != 'l') OR
(p1.oprleft != 0 and p1.oprkind = 'l') OR
p1.oprright = 0;
SELECT o1.oid, o1.oprname
FROM pg_operator as o1
WHERE (o1.oprleft = 0 and o1.oprkind != 'l') OR
(o1.oprleft != 0 and o1.oprkind = 'l') OR
o1.oprright = 0;
oid | oprname
-----+---------
(0 rows)
-- Look for conflicting operator definitions (same names and input datatypes).
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oid != p2.oid AND
p1.oprname = p2.oprname AND
p1.oprkind = p2.oprkind AND
p1.oprleft = p2.oprleft AND
p1.oprright = p2.oprright;
SELECT o1.oid, o1.oprcode, o2.oid, o2.oprcode
FROM pg_operator AS o1, pg_operator AS o2
WHERE o1.oid != o2.oid AND
o1.oprname = o2.oprname AND
o1.oprkind = o2.oprkind AND
o1.oprleft = o2.oprleft AND
o1.oprright = o2.oprright;
oid | oprcode | oid | oprcode
-----+---------+-----+---------
(0 rows)
@ -1070,14 +1070,14 @@ WHERE p1.oid != p2.oid AND
-- DEFINITIONAL NOTE: If A.oprcom = B, then x A y has the same result as y B x.
-- We expect that B will always say that B.oprcom = A as well; that's not
-- inherently essential, but it would be inefficient not to mark it so.
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprcom = p2.oid AND
(p1.oprkind != 'b' OR
p1.oprleft != p2.oprright OR
p1.oprright != p2.oprleft OR
p1.oprresult != p2.oprresult OR
p1.oid != p2.oprcom);
SELECT o1.oid, o1.oprcode, o2.oid, o2.oprcode
FROM pg_operator AS o1, pg_operator AS o2
WHERE o1.oprcom = o2.oid AND
(o1.oprkind != 'b' OR
o1.oprleft != o2.oprright OR
o1.oprright != o2.oprleft OR
o1.oprresult != o2.oprresult OR
o1.oid != o2.oprcom);
oid | oprcode | oid | oprcode
-----+---------+-----+---------
(0 rows)
@ -1089,16 +1089,16 @@ WHERE p1.oprcom = p2.oid AND
-- We expect that B will always say that B.oprnegate = A as well; that's not
-- inherently essential, but it would be inefficient not to mark it so.
-- Also, A and B had better not be the same operator.
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprnegate = p2.oid AND
(p1.oprkind != p2.oprkind OR
p1.oprleft != p2.oprleft OR
p1.oprright != p2.oprright OR
p1.oprresult != 'bool'::regtype OR
p2.oprresult != 'bool'::regtype OR
p1.oid != p2.oprnegate OR
p1.oid = p2.oid);
SELECT o1.oid, o1.oprcode, o2.oid, o2.oprcode
FROM pg_operator AS o1, pg_operator AS o2
WHERE o1.oprnegate = o2.oid AND
(o1.oprkind != o2.oprkind OR
o1.oprleft != o2.oprleft OR
o1.oprright != o2.oprright OR
o1.oprresult != 'bool'::regtype OR
o2.oprresult != 'bool'::regtype OR
o1.oid != o2.oprnegate OR
o1.oid = o2.oid);
oid | oprcode | oid | oprcode
-----+---------+-----+---------
(0 rows)
@ -1168,100 +1168,100 @@ ORDER BY 1, 2;
-- A mergejoinable or hashjoinable operator must be binary, must return
-- boolean, and must have a commutator (itself, unless it's a cross-type
-- operator).
SELECT p1.oid, p1.oprname FROM pg_operator AS p1
WHERE (p1.oprcanmerge OR p1.oprcanhash) AND NOT
(p1.oprkind = 'b' AND p1.oprresult = 'bool'::regtype AND p1.oprcom != 0);
SELECT o1.oid, o1.oprname FROM pg_operator AS o1
WHERE (o1.oprcanmerge OR o1.oprcanhash) AND NOT
(o1.oprkind = 'b' AND o1.oprresult = 'bool'::regtype AND o1.oprcom != 0);
oid | oprname
-----+---------
(0 rows)
-- What's more, the commutator had better be mergejoinable/hashjoinable too.
SELECT p1.oid, p1.oprname, p2.oid, p2.oprname
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprcom = p2.oid AND
(p1.oprcanmerge != p2.oprcanmerge OR
p1.oprcanhash != p2.oprcanhash);
SELECT o1.oid, o1.oprname, o2.oid, o2.oprname
FROM pg_operator AS o1, pg_operator AS o2
WHERE o1.oprcom = o2.oid AND
(o1.oprcanmerge != o2.oprcanmerge OR
o1.oprcanhash != o2.oprcanhash);
oid | oprname | oid | oprname
-----+---------+-----+---------
(0 rows)
-- Mergejoinable operators should appear as equality members of btree index
-- opfamilies.
SELECT p1.oid, p1.oprname
FROM pg_operator AS p1
WHERE p1.oprcanmerge AND NOT EXISTS
SELECT o1.oid, o1.oprname
FROM pg_operator AS o1
WHERE o1.oprcanmerge AND NOT EXISTS
(SELECT 1 FROM pg_amop
WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
amopopr = p1.oid AND amopstrategy = 3);
amopopr = o1.oid AND amopstrategy = 3);
oid | oprname
-----+---------
(0 rows)
-- And the converse.
SELECT p1.oid, p1.oprname, p.amopfamily
FROM pg_operator AS p1, pg_amop p
WHERE amopopr = p1.oid
SELECT o1.oid, o1.oprname, p.amopfamily
FROM pg_operator AS o1, pg_amop p
WHERE amopopr = o1.oid
AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
AND amopstrategy = 3
AND NOT p1.oprcanmerge;
AND NOT o1.oprcanmerge;
oid | oprname | amopfamily
-----+---------+------------
(0 rows)
-- Hashable operators should appear as members of hash index opfamilies.
SELECT p1.oid, p1.oprname
FROM pg_operator AS p1
WHERE p1.oprcanhash AND NOT EXISTS
SELECT o1.oid, o1.oprname
FROM pg_operator AS o1
WHERE o1.oprcanhash AND NOT EXISTS
(SELECT 1 FROM pg_amop
WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash') AND
amopopr = p1.oid AND amopstrategy = 1);
amopopr = o1.oid AND amopstrategy = 1);
oid | oprname
-----+---------
(0 rows)
-- And the converse.
SELECT p1.oid, p1.oprname, p.amopfamily
FROM pg_operator AS p1, pg_amop p
WHERE amopopr = p1.oid
SELECT o1.oid, o1.oprname, p.amopfamily
FROM pg_operator AS o1, pg_amop p
WHERE amopopr = o1.oid
AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash')
AND NOT p1.oprcanhash;
AND NOT o1.oprcanhash;
oid | oprname | amopfamily
-----+---------+------------
(0 rows)
-- Check that each operator defined in pg_operator matches its oprcode entry
-- in pg_proc. Easiest to do this separately for each oprkind.
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprcode = p2.oid AND
p1.oprkind = 'b' AND
(p2.pronargs != 2
OR NOT binary_coercible(p2.prorettype, p1.oprresult)
OR NOT binary_coercible(p1.oprleft, p2.proargtypes[0])
OR NOT binary_coercible(p1.oprright, p2.proargtypes[1]));
SELECT o1.oid, o1.oprname, p1.oid, p1.proname
FROM pg_operator AS o1, pg_proc AS p1
WHERE o1.oprcode = p1.oid AND
o1.oprkind = 'b' AND
(p1.pronargs != 2
OR NOT binary_coercible(p1.prorettype, o1.oprresult)
OR NOT binary_coercible(o1.oprleft, p1.proargtypes[0])
OR NOT binary_coercible(o1.oprright, p1.proargtypes[1]));
oid | oprname | oid | proname
-----+---------+-----+---------
(0 rows)
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprcode = p2.oid AND
p1.oprkind = 'l' AND
(p2.pronargs != 1
OR NOT binary_coercible(p2.prorettype, p1.oprresult)
OR NOT binary_coercible(p1.oprright, p2.proargtypes[0])
OR p1.oprleft != 0);
SELECT o1.oid, o1.oprname, p1.oid, p1.proname
FROM pg_operator AS o1, pg_proc AS p1
WHERE o1.oprcode = p1.oid AND
o1.oprkind = 'l' AND
(p1.pronargs != 1
OR NOT binary_coercible(p1.prorettype, o1.oprresult)
OR NOT binary_coercible(o1.oprright, p1.proargtypes[0])
OR o1.oprleft != 0);
oid | oprname | oid | proname
-----+---------+-----+---------
(0 rows)
-- If the operator is mergejoinable or hashjoinable, its underlying function
-- should not be volatile.
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprcode = p2.oid AND
(p1.oprcanmerge OR p1.oprcanhash) AND
p2.provolatile = 'v';
SELECT o1.oid, o1.oprname, p1.oid, p1.proname
FROM pg_operator AS o1, pg_proc AS p1
WHERE o1.oprcode = p1.oid AND
(o1.oprcanmerge OR o1.oprcanhash) AND
p1.provolatile = 'v';
oid | oprname | oid | proname
-----+---------+-----+---------
(0 rows)
@ -1270,10 +1270,10 @@ WHERE p1.oprcode = p2.oid AND
-- and it must link to a proc with the right signature
-- to be a restriction selectivity estimator.
-- The proc signature we want is: float8 proc(internal, oid, internal, int4)
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprrest = p2.oid AND
(p1.oprresult != 'bool'::regtype OR
SELECT o1.oid, o1.oprname, p2.oid, p2.proname
FROM pg_operator AS o1, pg_proc AS p2
WHERE o1.oprrest = p2.oid AND
(o1.oprresult != 'bool'::regtype OR
p2.prorettype != 'float8'::regtype OR p2.proretset OR
p2.pronargs != 4 OR
p2.proargtypes[0] != 'internal'::regtype OR
@ -1290,10 +1290,10 @@ WHERE p1.oprrest = p2.oid AND
-- The proc signature we want is: float8 proc(internal, oid, internal, int2, internal)
-- (Note: the old signature with only 4 args is still allowed, but no core
-- estimator should be using it.)
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprjoin = p2.oid AND
(p1.oprkind != 'b' OR p1.oprresult != 'bool'::regtype OR
SELECT o1.oid, o1.oprname, p2.oid, p2.proname
FROM pg_operator AS o1, pg_proc AS p2
WHERE o1.oprjoin = p2.oid AND
(o1.oprkind != 'b' OR o1.oprresult != 'bool'::regtype OR
p2.prorettype != 'float8'::regtype OR p2.proretset OR
p2.pronargs != 5 OR
p2.proargtypes[0] != 'internal'::regtype OR
@ -1306,10 +1306,10 @@ WHERE p1.oprjoin = p2.oid AND
(0 rows)
-- Insist that all built-in pg_operator entries have descriptions
SELECT p1.oid, p1.oprname
FROM pg_operator as p1 LEFT JOIN pg_description as d
ON p1.tableoid = d.classoid and p1.oid = d.objoid and d.objsubid = 0
WHERE d.classoid IS NULL AND p1.oid <= 9999;
SELECT o1.oid, o1.oprname
FROM pg_operator as o1 LEFT JOIN pg_description as d
ON o1.tableoid = d.classoid and o1.oid = d.objoid and d.objsubid = 0
WHERE d.classoid IS NULL AND o1.oid <= 9999;
oid | oprname
-----+---------
(0 rows)
@ -1417,7 +1417,7 @@ ORDER BY 1;
-- **************** pg_aggregate ****************
-- Look for illegal values in pg_aggregate fields.
SELECT ctid, aggfnoid::oid
FROM pg_aggregate as p1
FROM pg_aggregate as a
WHERE aggfnoid = 0 OR aggtransfn = 0 OR
aggkind NOT IN ('n', 'o', 'h') OR
aggnumdirectargs < 0 OR
@ -1518,7 +1518,7 @@ WHERE a.aggfnoid = p.oid AND
-- Check for inconsistent specifications of moving-aggregate columns.
SELECT ctid, aggfnoid::oid
FROM pg_aggregate as p1
FROM pg_aggregate as a
WHERE aggmtranstype != 0 AND
(aggmtransfn = 0 OR aggminvtransfn = 0);
ctid | aggfnoid
@ -1526,7 +1526,7 @@ WHERE aggmtranstype != 0 AND
(0 rows)
SELECT ctid, aggfnoid::oid
FROM pg_aggregate as p1
FROM pg_aggregate as a
WHERE aggmtranstype = 0 AND
(aggmtransfn != 0 OR aggminvtransfn != 0 OR aggmfinalfn != 0 OR
aggmtransspace != 0 OR aggminitval IS NOT NULL);
@ -1809,9 +1809,9 @@ WHERE prokind = 'a' AND provariadic != 0 AND a.aggkind = 'n';
-- **************** pg_opfamily ****************
-- Look for illegal values in pg_opfamily fields
SELECT p1.oid
FROM pg_opfamily as p1
WHERE p1.opfmethod = 0 OR p1.opfnamespace = 0;
SELECT f.oid
FROM pg_opfamily as f
WHERE f.opfmethod = 0 OR f.opfnamespace = 0;
oid
-----
(0 rows)
@ -1828,29 +1828,29 @@ WHERE NOT EXISTS (SELECT 1 FROM pg_opclass WHERE opcfamily = f.oid);
-- **************** pg_opclass ****************
-- Look for illegal values in pg_opclass fields
SELECT p1.oid
FROM pg_opclass AS p1
WHERE p1.opcmethod = 0 OR p1.opcnamespace = 0 OR p1.opcfamily = 0
OR p1.opcintype = 0;
SELECT c1.oid
FROM pg_opclass AS c1
WHERE c1.opcmethod = 0 OR c1.opcnamespace = 0 OR c1.opcfamily = 0
OR c1.opcintype = 0;
oid
-----
(0 rows)
-- opcmethod must match owning opfamily's opfmethod
SELECT p1.oid, p2.oid
FROM pg_opclass AS p1, pg_opfamily AS p2
WHERE p1.opcfamily = p2.oid AND p1.opcmethod != p2.opfmethod;
SELECT c1.oid, f1.oid
FROM pg_opclass AS c1, pg_opfamily AS f1
WHERE c1.opcfamily = f1.oid AND c1.opcmethod != f1.opfmethod;
oid | oid
-----+-----
(0 rows)
-- There should not be multiple entries in pg_opclass with opcdefault true
-- and the same opcmethod/opcintype combination.
SELECT p1.oid, p2.oid
FROM pg_opclass AS p1, pg_opclass AS p2
WHERE p1.oid != p2.oid AND
p1.opcmethod = p2.opcmethod AND p1.opcintype = p2.opcintype AND
p1.opcdefault AND p2.opcdefault;
SELECT c1.oid, c2.oid
FROM pg_opclass AS c1, pg_opclass AS c2
WHERE c1.oid != c2.oid AND
c1.opcmethod = c2.opcmethod AND c1.opcintype = c2.opcintype AND
c1.opcdefault AND c2.opcdefault;
oid | oid
-----+-----
(0 rows)
@ -1864,59 +1864,59 @@ SELECT oid, opcname FROM pg_opclass WHERE NOT amvalidate(oid);
-- **************** pg_am ****************
-- Look for illegal values in pg_am fields
SELECT p1.oid, p1.amname
FROM pg_am AS p1
WHERE p1.amhandler = 0;
SELECT a1.oid, a1.amname
FROM pg_am AS a1
WHERE a1.amhandler = 0;
oid | amname
-----+--------
(0 rows)
-- Check for index amhandler functions with the wrong signature
SELECT p1.oid, p1.amname, p2.oid, p2.proname
FROM pg_am AS p1, pg_proc AS p2
WHERE p2.oid = p1.amhandler AND p1.amtype = 'i' AND
(p2.prorettype != 'index_am_handler'::regtype
OR p2.proretset
OR p2.pronargs != 1
OR p2.proargtypes[0] != 'internal'::regtype);
SELECT a1.oid, a1.amname, p1.oid, p1.proname
FROM pg_am AS a1, pg_proc AS p1
WHERE p1.oid = a1.amhandler AND a1.amtype = 'i' AND
(p1.prorettype != 'index_am_handler'::regtype
OR p1.proretset
OR p1.pronargs != 1
OR p1.proargtypes[0] != 'internal'::regtype);
oid | amname | oid | proname
-----+--------+-----+---------
(0 rows)
-- Check for table amhandler functions with the wrong signature
SELECT p1.oid, p1.amname, p2.oid, p2.proname
FROM pg_am AS p1, pg_proc AS p2
WHERE p2.oid = p1.amhandler AND p1.amtype = 's' AND
(p2.prorettype != 'table_am_handler'::regtype
OR p2.proretset
OR p2.pronargs != 1
OR p2.proargtypes[0] != 'internal'::regtype);
SELECT a1.oid, a1.amname, p1.oid, p1.proname
FROM pg_am AS a1, pg_proc AS p1
WHERE p1.oid = a1.amhandler AND a1.amtype = 's' AND
(p1.prorettype != 'table_am_handler'::regtype
OR p1.proretset
OR p1.pronargs != 1
OR p1.proargtypes[0] != 'internal'::regtype);
oid | amname | oid | proname
-----+--------+-----+---------
(0 rows)
-- **************** pg_amop ****************
-- Look for illegal values in pg_amop fields
SELECT p1.amopfamily, p1.amopstrategy
FROM pg_amop as p1
WHERE p1.amopfamily = 0 OR p1.amoplefttype = 0 OR p1.amoprighttype = 0
OR p1.amopopr = 0 OR p1.amopmethod = 0 OR p1.amopstrategy < 1;
SELECT a1.amopfamily, a1.amopstrategy
FROM pg_amop as a1
WHERE a1.amopfamily = 0 OR a1.amoplefttype = 0 OR a1.amoprighttype = 0
OR a1.amopopr = 0 OR a1.amopmethod = 0 OR a1.amopstrategy < 1;
amopfamily | amopstrategy
------------+--------------
(0 rows)
SELECT p1.amopfamily, p1.amopstrategy
FROM pg_amop as p1
WHERE NOT ((p1.amoppurpose = 's' AND p1.amopsortfamily = 0) OR
(p1.amoppurpose = 'o' AND p1.amopsortfamily <> 0));
SELECT a1.amopfamily, a1.amopstrategy
FROM pg_amop as a1
WHERE NOT ((a1.amoppurpose = 's' AND a1.amopsortfamily = 0) OR
(a1.amoppurpose = 'o' AND a1.amopsortfamily <> 0));
amopfamily | amopstrategy
------------+--------------
(0 rows)
-- amopmethod must match owning opfamily's opfmethod
SELECT p1.oid, p2.oid
FROM pg_amop AS p1, pg_opfamily AS p2
WHERE p1.amopfamily = p2.oid AND p1.amopmethod != p2.opfmethod;
SELECT a1.oid, f1.oid
FROM pg_amop AS a1, pg_opfamily AS f1
WHERE a1.amopfamily = f1.oid AND a1.amopmethod != f1.opfmethod;
oid | oid
-----+-----
(0 rows)
@ -1926,7 +1926,7 @@ WHERE p1.amopfamily = p2.oid AND p1.amopmethod != p2.opfmethod;
-- in future releases, but it's an effective way of spotting mistakes such as
-- swapping two operators within a family.
SELECT DISTINCT amopmethod, amopstrategy, oprname
FROM pg_amop p1 LEFT JOIN pg_operator p2 ON amopopr = p2.oid
FROM pg_amop a1 LEFT JOIN pg_operator o1 ON amopopr = o1.oid
ORDER BY 1, 2, 3;
amopmethod | amopstrategy | oprname
------------+--------------+---------
@ -2059,21 +2059,21 @@ ORDER BY 1, 2, 3;
-- Check that all opclass search operators have selectivity estimators.
-- This is not absolutely required, but it seems a reasonable thing
-- to insist on for all standard datatypes.
SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
FROM pg_amop AS p1, pg_operator AS p2
WHERE p1.amopopr = p2.oid AND p1.amoppurpose = 's' AND
(p2.oprrest = 0 OR p2.oprjoin = 0);
SELECT a1.amopfamily, a1.amopopr, o1.oid, o1.oprname
FROM pg_amop AS a1, pg_operator AS o1
WHERE a1.amopopr = o1.oid AND a1.amoppurpose = 's' AND
(o1.oprrest = 0 OR o1.oprjoin = 0);
amopfamily | amopopr | oid | oprname
------------+---------+-----+---------
(0 rows)
-- Check that each opclass in an opfamily has associated operators, that is
-- ones whose oprleft matches opcintype (possibly by coercion).
SELECT p1.opcname, p1.opcfamily
FROM pg_opclass AS p1
WHERE NOT EXISTS(SELECT 1 FROM pg_amop AS p2
WHERE p2.amopfamily = p1.opcfamily
AND binary_coercible(p1.opcintype, p2.amoplefttype));
SELECT c1.opcname, c1.opcfamily
FROM pg_opclass AS c1
WHERE NOT EXISTS(SELECT 1 FROM pg_amop AS a1
WHERE a1.amopfamily = c1.opcfamily
AND binary_coercible(c1.opcintype, a1.amoplefttype));
opcname | opcfamily
---------+-----------
(0 rows)
@ -2084,11 +2084,11 @@ WHERE NOT EXISTS(SELECT 1 FROM pg_amop AS p2
-- (In principle it could be useful to list such operators in multiple-datatype
-- btree opfamilies, but in practice you'd expect there to be an opclass for
-- every datatype the family knows about.)
SELECT p1.amopfamily, p1.amopstrategy, p1.amopopr
FROM pg_amop AS p1
WHERE NOT EXISTS(SELECT 1 FROM pg_opclass AS p2
WHERE p2.opcfamily = p1.amopfamily
AND binary_coercible(p2.opcintype, p1.amoplefttype));
SELECT a1.amopfamily, a1.amopstrategy, a1.amopopr
FROM pg_amop AS a1
WHERE NOT EXISTS(SELECT 1 FROM pg_opclass AS c1
WHERE c1.opcfamily = a1.amopfamily
AND binary_coercible(c1.opcintype, a1.amoplefttype));
amopfamily | amopstrategy | amopopr
------------+--------------+---------
(0 rows)
@ -2097,30 +2097,30 @@ WHERE NOT EXISTS(SELECT 1 FROM pg_opclass AS p2
-- it suggests that the index ordering isn't fixed). Operators that are
-- cross-type members need only be stable, since they are just shorthands
-- for index probe queries.
SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
p1.amoplefttype = p1.amoprighttype AND
p3.provolatile != 'i';
SELECT a1.amopfamily, a1.amopopr, o1.oprname, p1.prosrc
FROM pg_amop AS a1, pg_operator AS o1, pg_proc AS p1
WHERE a1.amopopr = o1.oid AND o1.oprcode = p1.oid AND
a1.amoplefttype = a1.amoprighttype AND
p1.provolatile != 'i';
amopfamily | amopopr | oprname | prosrc
------------+---------+---------+--------
(0 rows)
SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
p1.amoplefttype != p1.amoprighttype AND
p3.provolatile = 'v';
SELECT a1.amopfamily, a1.amopopr, o1.oprname, p1.prosrc
FROM pg_amop AS a1, pg_operator AS o1, pg_proc AS p1
WHERE a1.amopopr = o1.oid AND o1.oprcode = p1.oid AND
a1.amoplefttype != a1.amoprighttype AND
p1.provolatile = 'v';
amopfamily | amopopr | oprname | prosrc
------------+---------+---------+--------
(0 rows)
-- **************** pg_amproc ****************
-- Look for illegal values in pg_amproc fields
SELECT p1.amprocfamily, p1.amprocnum
FROM pg_amproc as p1
WHERE p1.amprocfamily = 0 OR p1.amproclefttype = 0 OR p1.amprocrighttype = 0
OR p1.amprocnum < 0 OR p1.amproc = 0;
SELECT a1.amprocfamily, a1.amprocnum
FROM pg_amproc as a1
WHERE a1.amprocfamily = 0 OR a1.amproclefttype = 0 OR a1.amprocrighttype = 0
OR a1.amprocnum < 0 OR a1.amproc = 0;
amprocfamily | amprocnum
--------------+-----------
(0 rows)
@ -2129,20 +2129,20 @@ WHERE p1.amprocfamily = 0 OR p1.amproclefttype = 0 OR p1.amprocrighttype = 0
-- (else it suggests that the index ordering isn't fixed). But cross-type
-- members need only be stable, since they are just shorthands
-- for index probe queries.
SELECT p1.amprocfamily, p1.amproc, p2.prosrc
FROM pg_amproc AS p1, pg_proc AS p2
WHERE p1.amproc = p2.oid AND
p1.amproclefttype = p1.amprocrighttype AND
p2.provolatile != 'i';
SELECT a1.amprocfamily, a1.amproc, p1.prosrc
FROM pg_amproc AS a1, pg_proc AS p1
WHERE a1.amproc = p1.oid AND
a1.amproclefttype = a1.amprocrighttype AND
p1.provolatile != 'i';
amprocfamily | amproc | prosrc
--------------+--------+--------
(0 rows)
SELECT p1.amprocfamily, p1.amproc, p2.prosrc
FROM pg_amproc AS p1, pg_proc AS p2
WHERE p1.amproc = p2.oid AND
p1.amproclefttype != p1.amprocrighttype AND
p2.provolatile = 'v';
SELECT a1.amprocfamily, a1.amproc, p1.prosrc
FROM pg_amproc AS a1, pg_proc AS p1
WHERE a1.amproc = p1.oid AND
a1.amproclefttype != a1.amprocrighttype AND
p1.provolatile = 'v';
amprocfamily | amproc | prosrc
--------------+--------+--------
(0 rows)
@ -2186,17 +2186,17 @@ ORDER BY 1, 2, 3;
-- **************** pg_index ****************
-- Look for illegal values in pg_index fields.
SELECT p1.indexrelid, p1.indrelid
FROM pg_index as p1
WHERE p1.indexrelid = 0 OR p1.indrelid = 0 OR
p1.indnatts <= 0 OR p1.indnatts > 32;
SELECT indexrelid, indrelid
FROM pg_index
WHERE indexrelid = 0 OR indrelid = 0 OR
indnatts <= 0 OR indnatts > 32;
indexrelid | indrelid
------------+----------
(0 rows)
-- oidvector and int2vector fields should be of length indnatts.
SELECT p1.indexrelid, p1.indrelid
FROM pg_index as p1
SELECT indexrelid, indrelid
FROM pg_index
WHERE array_lower(indkey, 1) != 0 OR array_upper(indkey, 1) != indnatts-1 OR
array_lower(indclass, 1) != 0 OR array_upper(indclass, 1) != indnatts-1 OR
array_lower(indcollation, 1) != 0 OR array_upper(indcollation, 1) != indnatts-1 OR

View File

@ -13,45 +13,45 @@
-- field can't be 0, we have to check it here.
-- **************** pg_type ****************
-- Look for illegal values in pg_type fields.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typnamespace = 0 OR
(p1.typlen <= 0 AND p1.typlen != -1 AND p1.typlen != -2) OR
(p1.typtype not in ('b', 'c', 'd', 'e', 'p', 'r', 'm')) OR
NOT p1.typisdefined OR
(p1.typalign not in ('c', 's', 'i', 'd')) OR
(p1.typstorage not in ('p', 'x', 'e', 'm'));
SELECT t1.oid, t1.typname
FROM pg_type as t1
WHERE t1.typnamespace = 0 OR
(t1.typlen <= 0 AND t1.typlen != -1 AND t1.typlen != -2) OR
(t1.typtype not in ('b', 'c', 'd', 'e', 'p', 'r', 'm')) OR
NOT t1.typisdefined OR
(t1.typalign not in ('c', 's', 'i', 'd')) OR
(t1.typstorage not in ('p', 'x', 'e', 'm'));
oid | typname
-----+---------
(0 rows)
-- Look for "pass by value" types that can't be passed by value.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typbyval AND
(p1.typlen != 1 OR p1.typalign != 'c') AND
(p1.typlen != 2 OR p1.typalign != 's') AND
(p1.typlen != 4 OR p1.typalign != 'i') AND
(p1.typlen != 8 OR p1.typalign != 'd');
SELECT t1.oid, t1.typname
FROM pg_type as t1
WHERE t1.typbyval AND
(t1.typlen != 1 OR t1.typalign != 'c') AND
(t1.typlen != 2 OR t1.typalign != 's') AND
(t1.typlen != 4 OR t1.typalign != 'i') AND
(t1.typlen != 8 OR t1.typalign != 'd');
oid | typname
-----+---------
(0 rows)
-- Look for "toastable" types that aren't varlena.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typstorage != 'p' AND
(p1.typbyval OR p1.typlen != -1);
SELECT t1.oid, t1.typname
FROM pg_type as t1
WHERE t1.typstorage != 'p' AND
(t1.typbyval OR t1.typlen != -1);
oid | typname
-----+---------
(0 rows)
-- Look for complex types that do not have a typrelid entry,
-- or basic types that do.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
(p1.typtype != 'c' AND p1.typrelid != 0);
SELECT t1.oid, t1.typname
FROM pg_type as t1
WHERE (t1.typtype = 'c' AND t1.typrelid = 0) OR
(t1.typtype != 'c' AND t1.typrelid != 0);
oid | typname
-----+---------
(0 rows)
@ -59,14 +59,14 @@ WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
-- Look for types that should have an array type but don't.
-- Generally anything that's not a pseudotype should have an array type.
-- However, we do have a small number of exceptions.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typtype not in ('p') AND p1.typname NOT LIKE E'\\_%'
SELECT t1.oid, t1.typname
FROM pg_type as t1
WHERE t1.typtype not in ('p') AND t1.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)
ORDER BY p1.oid;
(SELECT 1 FROM pg_type as t2
WHERE t2.typname = ('_' || t1.typname)::name AND
t2.typelem = t1.oid and t1.typarray = t2.oid)
ORDER BY t1.oid;
oid | typname
------+------------------------------
194 | pg_node_tree
@ -78,56 +78,56 @@ ORDER BY p1.oid;
(6 rows)
-- Make sure typarray points to a "true" array type of our own base
SELECT p1.oid, p1.typname as basetype, p2.typname as arraytype,
p2.typsubscript
FROM pg_type p1 LEFT JOIN pg_type p2 ON (p1.typarray = p2.oid)
WHERE p1.typarray <> 0 AND
(p2.oid IS NULL OR
p2.typsubscript <> 'array_subscript_handler'::regproc);
SELECT t1.oid, t1.typname as basetype, t2.typname as arraytype,
t2.typsubscript
FROM pg_type t1 LEFT JOIN pg_type t2 ON (t1.typarray = t2.oid)
WHERE t1.typarray <> 0 AND
(t2.oid IS NULL OR
t2.typsubscript <> 'array_subscript_handler'::regproc);
oid | basetype | arraytype | typsubscript
-----+----------+-----------+--------------
(0 rows)
-- Look for range types that do not have a pg_range entry
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typtype = 'r' AND
NOT EXISTS(SELECT 1 FROM pg_range r WHERE rngtypid = p1.oid);
SELECT t1.oid, t1.typname
FROM pg_type as t1
WHERE t1.typtype = 'r' AND
NOT EXISTS(SELECT 1 FROM pg_range r WHERE rngtypid = t1.oid);
oid | typname
-----+---------
(0 rows)
-- Look for range types whose typalign isn't sufficient
SELECT p1.oid, p1.typname, p1.typalign, p2.typname, p2.typalign
FROM pg_type as p1
LEFT JOIN pg_range as r ON rngtypid = p1.oid
LEFT JOIN pg_type as p2 ON rngsubtype = p2.oid
WHERE p1.typtype = 'r' AND
(p1.typalign != (CASE WHEN p2.typalign = 'd' THEN 'd'::"char"
SELECT t1.oid, t1.typname, t1.typalign, t2.typname, t2.typalign
FROM pg_type as t1
LEFT JOIN pg_range as r ON rngtypid = t1.oid
LEFT JOIN pg_type as t2 ON rngsubtype = t2.oid
WHERE t1.typtype = 'r' AND
(t1.typalign != (CASE WHEN t2.typalign = 'd' THEN 'd'::"char"
ELSE 'i'::"char" END)
OR p2.oid IS NULL);
OR t2.oid IS NULL);
oid | typname | typalign | typname | typalign
-----+---------+----------+---------+----------
(0 rows)
-- Text conversion routines must be provided.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE (p1.typinput = 0 OR p1.typoutput = 0);
SELECT t1.oid, t1.typname
FROM pg_type as t1
WHERE (t1.typinput = 0 OR t1.typoutput = 0);
oid | typname
-----+---------
(0 rows)
-- Check for bogus typinput routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typinput = p2.oid AND NOT
((p2.pronargs = 1 AND p2.proargtypes[0] = 'cstring'::regtype) OR
(p2.pronargs = 2 AND p2.proargtypes[0] = 'cstring'::regtype AND
p2.proargtypes[1] = 'oid'::regtype) OR
(p2.pronargs = 3 AND p2.proargtypes[0] = 'cstring'::regtype AND
p2.proargtypes[1] = 'oid'::regtype AND
p2.proargtypes[2] = 'int4'::regtype));
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typinput = p1.oid AND NOT
((p1.pronargs = 1 AND p1.proargtypes[0] = 'cstring'::regtype) OR
(p1.pronargs = 2 AND p1.proargtypes[0] = 'cstring'::regtype AND
p1.proargtypes[1] = 'oid'::regtype) OR
(p1.pronargs = 3 AND p1.proargtypes[0] = 'cstring'::regtype AND
p1.proargtypes[1] = 'oid'::regtype AND
p1.proargtypes[2] = 'int4'::regtype));
oid | typname | oid | proname
-----+---------+-----+---------
(0 rows)
@ -165,11 +165,11 @@ WHERE (proargmodes IS NOT NULL AND 'v' = any(proargmodes))
-- As of 8.0, this check finds refcursor, which is borrowing
-- other types' I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
(p2.prorettype = p1.oid AND NOT p2.proretset)
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typinput = p1.oid AND t1.typtype in ('b', 'p') AND NOT
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
(p1.prorettype = t1.oid AND NOT p1.proretset)
ORDER BY 1;
oid | typname | oid | proname
------+-----------+-----+---------
@ -178,11 +178,11 @@ ORDER BY 1;
-- Varlena array types will point to array_in
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typinput = p2.oid AND
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
(p2.oid = 'array_in'::regproc)
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typinput = p1.oid AND
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
(p1.oid = 'array_in'::regproc)
ORDER BY 1;
oid | typname | oid | proname
-----+------------+-----+--------------
@ -191,17 +191,17 @@ ORDER BY 1;
(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');
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typinput = p1.oid AND p1.provolatile NOT IN ('i', 's');
oid | typname | oid | proname
-----+---------+-----+---------
(0 rows)
-- Composites, domains, enums, multiranges, ranges should all use the same input routines
SELECT DISTINCT typtype, typinput
FROM pg_type AS p1
WHERE p1.typtype not in ('b', 'p')
FROM pg_type AS t1
WHERE t1.typtype not in ('b', 'p')
ORDER BY 1;
typtype | typinput
---------+---------------
@ -215,39 +215,39 @@ ORDER BY 1;
-- Check for bogus typoutput routines
-- As of 8.0, this check finds refcursor, which is borrowing
-- other types' I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
(p2.pronargs = 1 AND
(p2.proargtypes[0] = p1.oid OR
(p2.oid = 'array_out'::regproc AND
p1.typelem != 0 AND p1.typlen = -1)))
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typoutput = p1.oid AND t1.typtype in ('b', 'p') AND NOT
(p1.pronargs = 1 AND
(p1.proargtypes[0] = t1.oid OR
(p1.oid = 'array_out'::regproc AND
t1.typelem != 0 AND t1.typlen = -1)))
ORDER BY 1;
oid | typname | oid | proname
------+-----------+-----+---------
1790 | refcursor | 47 | textout
(1 row)
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typoutput = p2.oid AND NOT
(p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typoutput = p1.oid AND NOT
(p1.prorettype = 'cstring'::regtype AND NOT p1.proretset);
oid | typname | oid | proname
-----+---------+-----+---------
(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');
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typoutput = p1.oid AND p1.provolatile NOT IN ('i', 's');
oid | typname | oid | proname
-----+---------+-----+---------
(0 rows)
-- Composites, enums, multiranges, 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')
FROM pg_type AS t1
WHERE t1.typtype not in ('b', 'd', 'p')
ORDER BY 1;
typtype | typoutput
---------+----------------
@ -258,34 +258,34 @@ ORDER BY 1;
(4 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;
SELECT t1.oid, t1.typname, t2.oid, t2.typname
FROM pg_type AS t1 LEFT JOIN pg_type AS t2 ON t1.typbasetype = t2.oid
WHERE t1.typtype = 'd' AND t1.typoutput IS DISTINCT FROM t2.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
WHERE p1.typreceive = p2.oid AND NOT
((p2.pronargs = 1 AND p2.proargtypes[0] = 'internal'::regtype) OR
(p2.pronargs = 2 AND p2.proargtypes[0] = 'internal'::regtype AND
p2.proargtypes[1] = 'oid'::regtype) OR
(p2.pronargs = 3 AND p2.proargtypes[0] = 'internal'::regtype AND
p2.proargtypes[1] = 'oid'::regtype AND
p2.proargtypes[2] = 'int4'::regtype));
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typreceive = p1.oid AND NOT
((p1.pronargs = 1 AND p1.proargtypes[0] = 'internal'::regtype) OR
(p1.pronargs = 2 AND p1.proargtypes[0] = 'internal'::regtype AND
p1.proargtypes[1] = 'oid'::regtype) OR
(p1.pronargs = 3 AND p1.proargtypes[0] = 'internal'::regtype AND
p1.proargtypes[1] = 'oid'::regtype AND
p1.proargtypes[2] = 'int4'::regtype));
oid | typname | oid | proname
-----+---------+-----+---------
(0 rows)
-- As of 7.4, this check finds refcursor, which is borrowing
-- other types' I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND NOT
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
(p2.prorettype = p1.oid AND NOT p2.proretset)
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typreceive = p1.oid AND t1.typtype in ('b', 'p') AND NOT
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
(p1.prorettype = t1.oid AND NOT p1.proretset)
ORDER BY 1;
oid | typname | oid | proname
------+-----------+------+----------
@ -294,11 +294,11 @@ ORDER BY 1;
-- Varlena array types will point to array_recv
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typreceive = p2.oid AND
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
(p2.oid = 'array_recv'::regproc)
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typreceive = p1.oid AND
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
(p1.oid = 'array_recv'::regproc)
ORDER BY 1;
oid | typname | oid | proname
-----+------------+------+----------------
@ -307,26 +307,26 @@ ORDER BY 1;
(2 rows)
-- Suspicious if typreceive doesn't take same number of args as typinput
SELECT p1.oid, p1.typname, p2.oid, p2.proname, p3.oid, p3.proname
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;
SELECT t1.oid, t1.typname, p1.oid, p1.proname, p2.oid, p2.proname
FROM pg_type AS t1, pg_proc AS p1, pg_proc AS p2
WHERE t1.typinput = p1.oid AND t1.typreceive = p2.oid AND
p1.pronargs != p2.pronargs;
oid | typname | oid | proname | oid | proname
-----+---------+-----+---------+-----+---------
(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');
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typreceive = p1.oid AND p1.provolatile NOT IN ('i', 's');
oid | typname | oid | proname
-----+---------+-----+---------
(0 rows)
-- Composites, domains, enums, multiranges, ranges should all use the same receive routines
SELECT DISTINCT typtype, typreceive
FROM pg_type AS p1
WHERE p1.typtype not in ('b', 'p')
FROM pg_type AS t1
WHERE t1.typtype not in ('b', 'p')
ORDER BY 1;
typtype | typreceive
---------+-----------------
@ -340,39 +340,39 @@ ORDER BY 1;
-- Check for bogus typsend routines
-- As of 7.4, this check finds refcursor, which is borrowing
-- other types' I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
(p2.pronargs = 1 AND
(p2.proargtypes[0] = p1.oid OR
(p2.oid = 'array_send'::regproc AND
p1.typelem != 0 AND p1.typlen = -1)))
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typsend = p1.oid AND t1.typtype in ('b', 'p') AND NOT
(p1.pronargs = 1 AND
(p1.proargtypes[0] = t1.oid OR
(p1.oid = 'array_send'::regproc AND
t1.typelem != 0 AND t1.typlen = -1)))
ORDER BY 1;
oid | typname | oid | proname
------+-----------+------+----------
1790 | refcursor | 2415 | textsend
(1 row)
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typsend = p2.oid AND NOT
(p2.prorettype = 'bytea'::regtype AND NOT p2.proretset);
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typsend = p1.oid AND NOT
(p1.prorettype = 'bytea'::regtype AND NOT p1.proretset);
oid | typname | oid | proname
-----+---------+-----+---------
(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');
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typsend = p1.oid AND p1.provolatile NOT IN ('i', 's');
oid | typname | oid | proname
-----+---------+-----+---------
(0 rows)
-- Composites, enums, multiranges, 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')
FROM pg_type AS t1
WHERE t1.typtype not in ('b', 'd', 'p')
ORDER BY 1;
typtype | typsend
---------+-----------------
@ -383,112 +383,112 @@ ORDER BY 1;
(4 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;
SELECT t1.oid, t1.typname, t2.oid, t2.typname
FROM pg_type AS t1 LEFT JOIN pg_type AS t2 ON t1.typbasetype = t2.oid
WHERE t1.typtype = 'd' AND t1.typsend IS DISTINCT FROM t2.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 NOT
(p2.pronargs = 1 AND
p2.proargtypes[0] = 'cstring[]'::regtype AND
p2.prorettype = 'int4'::regtype AND NOT p2.proretset);
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typmodin = p1.oid AND NOT
(p1.pronargs = 1 AND
p1.proargtypes[0] = 'cstring[]'::regtype AND
p1.prorettype = 'int4'::regtype AND NOT p1.proretset);
oid | typname | oid | proname
-----+---------+-----+---------
(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');
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typmodin = p1.oid AND p1.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
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);
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typmodout = p1.oid AND NOT
(p1.pronargs = 1 AND
p1.proargtypes[0] = 'int4'::regtype AND
p1.prorettype = 'cstring'::regtype AND NOT p1.proretset);
oid | typname | oid | proname
-----+---------+-----+---------
(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');
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typmodout = p1.oid AND p1.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
WHERE p1.typelem = p2.oid AND NOT
(p1.typmodin = p2.typmodin AND p1.typmodout = p2.typmodout);
SELECT t1.oid, t1.typname, t2.oid, t2.typname
FROM pg_type AS t1, pg_type AS t2
WHERE t1.typelem = t2.oid AND NOT
(t1.typmodin = t2.typmodin AND t1.typmodout = t2.typmodout);
oid | typname | oid | typname
-----+---------+-----+---------
(0 rows)
-- Array types should have same typdelim as their element types
SELECT p1.oid, p1.typname, p2.oid, p2.typname
FROM pg_type AS p1, pg_type AS p2
WHERE p1.typarray = p2.oid AND NOT (p1.typdelim = p2.typdelim);
SELECT t1.oid, t1.typname, t2.oid, t2.typname
FROM pg_type AS t1, pg_type AS t2
WHERE t1.typarray = t2.oid AND NOT (t1.typdelim = t2.typdelim);
oid | typname | oid | typname
-----+---------+-----+---------
(0 rows)
-- Look for array types whose typalign isn't sufficient
SELECT p1.oid, p1.typname, p1.typalign, p2.typname, p2.typalign
FROM pg_type AS p1, pg_type AS p2
WHERE p1.typarray = p2.oid AND
p2.typalign != (CASE WHEN p1.typalign = 'd' THEN 'd'::"char"
SELECT t1.oid, t1.typname, t1.typalign, t2.typname, t2.typalign
FROM pg_type AS t1, pg_type AS t2
WHERE t1.typarray = t2.oid AND
t2.typalign != (CASE WHEN t1.typalign = 'd' THEN 'd'::"char"
ELSE 'i'::"char" END);
oid | typname | typalign | typname | typalign
-----+---------+----------+---------+----------
(0 rows)
-- Check for typelem set without a handler
SELECT p1.oid, p1.typname, p1.typelem
FROM pg_type AS p1
WHERE p1.typelem != 0 AND p1.typsubscript = 0;
SELECT t1.oid, t1.typname, t1.typelem
FROM pg_type AS t1
WHERE t1.typelem != 0 AND t1.typsubscript = 0;
oid | typname | typelem
-----+---------+---------
(0 rows)
-- Check for misuse of standard subscript handlers
SELECT p1.oid, p1.typname,
p1.typelem, p1.typlen, p1.typbyval
FROM pg_type AS p1
WHERE p1.typsubscript = 'array_subscript_handler'::regproc AND NOT
(p1.typelem != 0 AND p1.typlen = -1 AND NOT p1.typbyval);
SELECT t1.oid, t1.typname,
t1.typelem, t1.typlen, t1.typbyval
FROM pg_type AS t1
WHERE t1.typsubscript = 'array_subscript_handler'::regproc AND NOT
(t1.typelem != 0 AND t1.typlen = -1 AND NOT t1.typbyval);
oid | typname | typelem | typlen | typbyval
-----+---------+---------+--------+----------
(0 rows)
SELECT p1.oid, p1.typname,
p1.typelem, p1.typlen, p1.typbyval
FROM pg_type AS p1
WHERE p1.typsubscript = 'raw_array_subscript_handler'::regproc AND NOT
(p1.typelem != 0 AND p1.typlen > 0 AND NOT p1.typbyval);
SELECT t1.oid, t1.typname,
t1.typelem, t1.typlen, t1.typbyval
FROM pg_type AS t1
WHERE t1.typsubscript = 'raw_array_subscript_handler'::regproc AND NOT
(t1.typelem != 0 AND t1.typlen > 0 AND NOT t1.typbyval);
oid | typname | typelem | typlen | typbyval
-----+---------+---------+--------+----------
(0 rows)
-- 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 NOT
(p2.pronargs = 1 AND
p2.proargtypes[0] = 'internal'::regtype AND
p2.prorettype = 'bool'::regtype AND NOT p2.proretset);
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typanalyze = p1.oid AND NOT
(p1.pronargs = 1 AND
p1.proargtypes[0] = 'internal'::regtype AND
p1.prorettype = 'bool'::regtype AND NOT p1.proretset);
oid | typname | oid | proname
-----+---------+-----+---------
(0 rows)
@ -529,8 +529,8 @@ ORDER BY 1;
-- **************** pg_class ****************
-- Look for illegal values in pg_class fields
SELECT p1.oid, p1.relname
FROM pg_class as p1
SELECT c1.oid, c1.relname
FROM pg_class as c1
WHERE relkind NOT IN ('r', 'i', 'S', 't', 'v', 'm', 'c', 'f', 'p') OR
relpersistence NOT IN ('p', 'u', 't') OR
relreplident NOT IN ('d', 'n', 'f', 'i');
@ -539,19 +539,19 @@ WHERE relkind NOT IN ('r', 'i', 'S', 't', 'v', 'm', 'c', 'f', 'p') OR
(0 rows)
-- All tables and indexes should have an access method.
SELECT p1.oid, p1.relname
FROM pg_class as p1
WHERE p1.relkind NOT IN ('S', 'v', 'f', 'c') and
p1.relam = 0;
SELECT c1.oid, c1.relname
FROM pg_class as c1
WHERE c1.relkind NOT IN ('S', 'v', 'f', 'c') and
c1.relam = 0;
oid | relname
-----+---------
(0 rows)
-- Conversely, sequences, views, types shouldn't have them
SELECT p1.oid, p1.relname
FROM pg_class as p1
WHERE p1.relkind IN ('S', 'v', 'f', 'c') and
p1.relam != 0;
SELECT c1.oid, c1.relname
FROM pg_class as c1
WHERE c1.relkind IN ('S', 'v', 'f', 'c') and
c1.relam != 0;
oid | relname
-----+---------
(0 rows)
@ -576,29 +576,29 @@ WHERE pc.relkind IN ('r', 't', 'm') and
-- **************** pg_attribute ****************
-- Look for illegal values in pg_attribute fields
SELECT p1.attrelid, p1.attname
FROM pg_attribute as p1
WHERE p1.attrelid = 0 OR p1.atttypid = 0 OR p1.attnum = 0 OR
p1.attcacheoff != -1 OR p1.attinhcount < 0 OR
(p1.attinhcount = 0 AND NOT p1.attislocal);
SELECT a1.attrelid, a1.attname
FROM pg_attribute as a1
WHERE a1.attrelid = 0 OR a1.atttypid = 0 OR a1.attnum = 0 OR
a1.attcacheoff != -1 OR a1.attinhcount < 0 OR
(a1.attinhcount = 0 AND NOT a1.attislocal);
attrelid | attname
----------+---------
(0 rows)
-- Cross-check attnum against parent relation
SELECT p1.attrelid, p1.attname, p2.oid, p2.relname
FROM pg_attribute AS p1, pg_class AS p2
WHERE p1.attrelid = p2.oid AND p1.attnum > p2.relnatts;
SELECT a1.attrelid, a1.attname, c1.oid, c1.relname
FROM pg_attribute AS a1, pg_class AS c1
WHERE a1.attrelid = c1.oid AND a1.attnum > c1.relnatts;
attrelid | attname | oid | relname
----------+---------+-----+---------
(0 rows)
-- Detect missing pg_attribute entries: should have as many non-system
-- attributes as parent relation expects
SELECT p1.oid, p1.relname
FROM pg_class AS p1
WHERE p1.relnatts != (SELECT count(*) FROM pg_attribute AS p2
WHERE p2.attrelid = p1.oid AND p2.attnum > 0);
SELECT c1.oid, c1.relname
FROM pg_class AS c1
WHERE c1.relnatts != (SELECT count(*) FROM pg_attribute AS a1
WHERE a1.attrelid = c1.oid AND a1.attnum > 0);
oid | relname
-----+---------
(0 rows)
@ -606,29 +606,29 @@ WHERE p1.relnatts != (SELECT count(*) FROM pg_attribute AS p2
-- Cross-check against pg_type entry
-- NOTE: we allow attstorage to be 'plain' even when typstorage is not;
-- this is mainly for toast tables.
SELECT p1.attrelid, p1.attname, p2.oid, p2.typname
FROM pg_attribute AS p1, pg_type AS p2
WHERE p1.atttypid = p2.oid AND
(p1.attlen != p2.typlen OR
p1.attalign != p2.typalign OR
p1.attbyval != p2.typbyval OR
(p1.attstorage != p2.typstorage AND p1.attstorage != 'p'));
SELECT a1.attrelid, a1.attname, t1.oid, t1.typname
FROM pg_attribute AS a1, pg_type AS t1
WHERE a1.atttypid = t1.oid AND
(a1.attlen != t1.typlen OR
a1.attalign != t1.typalign OR
a1.attbyval != t1.typbyval OR
(a1.attstorage != t1.typstorage AND a1.attstorage != 'p'));
attrelid | attname | oid | typname
----------+---------+-----+---------
(0 rows)
-- **************** pg_range ****************
-- Look for illegal values in pg_range fields.
SELECT p1.rngtypid, p1.rngsubtype
FROM pg_range as p1
WHERE p1.rngtypid = 0 OR p1.rngsubtype = 0 OR p1.rngsubopc = 0;
SELECT r.rngtypid, r.rngsubtype
FROM pg_range as r
WHERE r.rngtypid = 0 OR r.rngsubtype = 0 OR r.rngsubopc = 0;
rngtypid | rngsubtype
----------+------------
(0 rows)
-- rngcollation should be specified iff subtype is collatable
SELECT p1.rngtypid, p1.rngsubtype, p1.rngcollation, t.typcollation
FROM pg_range p1 JOIN pg_type t ON t.oid = p1.rngsubtype
SELECT r.rngtypid, r.rngsubtype, r.rngcollation, t.typcollation
FROM pg_range r JOIN pg_type t ON t.oid = r.rngsubtype
WHERE (rngcollation = 0) != (typcollation = 0);
rngtypid | rngsubtype | rngcollation | typcollation
----------+------------+--------------+--------------
@ -636,29 +636,29 @@ WHERE (rngcollation = 0) != (typcollation = 0);
-- opclass had better be a btree opclass accepting the subtype.
-- We must allow anyarray matches, cf IsBinaryCoercible()
SELECT p1.rngtypid, p1.rngsubtype, o.opcmethod, o.opcname
FROM pg_range p1 JOIN pg_opclass o ON o.oid = p1.rngsubopc
SELECT r.rngtypid, r.rngsubtype, o.opcmethod, o.opcname
FROM pg_range r JOIN pg_opclass o ON o.oid = r.rngsubopc
WHERE o.opcmethod != 403 OR
((o.opcintype != p1.rngsubtype) AND NOT
((o.opcintype != r.rngsubtype) AND NOT
(o.opcintype = 'pg_catalog.anyarray'::regtype AND
EXISTS(select 1 from pg_catalog.pg_type where
oid = p1.rngsubtype and typelem != 0 and
oid = r.rngsubtype and typelem != 0 and
typsubscript = 'array_subscript_handler'::regproc)));
rngtypid | rngsubtype | opcmethod | opcname
----------+------------+-----------+---------
(0 rows)
-- canonical function, if any, had better match the range type
SELECT p1.rngtypid, p1.rngsubtype, p.proname
FROM pg_range p1 JOIN pg_proc p ON p.oid = p1.rngcanonical
SELECT r.rngtypid, r.rngsubtype, p.proname
FROM pg_range r JOIN pg_proc p ON p.oid = r.rngcanonical
WHERE pronargs != 1 OR proargtypes[0] != rngtypid OR prorettype != rngtypid;
rngtypid | rngsubtype | proname
----------+------------+---------
(0 rows)
-- subdiff function, if any, had better match the subtype
SELECT p1.rngtypid, p1.rngsubtype, p.proname
FROM pg_range p1 JOIN pg_proc p ON p.oid = p1.rngsubdiff
SELECT r.rngtypid, r.rngsubtype, p.proname
FROM pg_range r JOIN pg_proc p ON p.oid = r.rngsubdiff
WHERE pronargs != 2
OR proargtypes[0] != rngsubtype OR proargtypes[1] != rngsubtype
OR prorettype != 'pg_catalog.float8'::regtype;
@ -667,9 +667,9 @@ WHERE pronargs != 2
(0 rows)
-- every range should have a valid multirange
SELECT p1.rngtypid, p1.rngsubtype, p1.rngmultitypid
FROM pg_range p1
WHERE p1.rngmultitypid IS NULL OR p1.rngmultitypid = 0;
SELECT r.rngtypid, r.rngsubtype, r.rngmultitypid
FROM pg_range r
WHERE r.rngmultitypid IS NULL OR r.rngmultitypid = 0;
rngtypid | rngsubtype | rngmultitypid
----------+------------+---------------
(0 rows)

View File

@ -489,9 +489,9 @@ WHERE c.castmethod = 'b' AND
-- Look for illegal values in pg_conversion fields.
SELECT p1.oid, p1.conname
FROM pg_conversion as p1
WHERE p1.conproc = 0 OR
SELECT c.oid, c.conname
FROM pg_conversion as c
WHERE c.conproc = 0 OR
pg_encoding_to_char(conforencoding) = '' OR
pg_encoding_to_char(contoencoding) = '';
@ -519,8 +519,8 @@ WHERE p.oid = c.conproc AND
-- conversions anyway.
-- (Similarly, this doesn't cope with any search path issues.)
SELECT p1.oid, p1.conname
FROM pg_conversion as p1
SELECT c.oid, c.conname
FROM pg_conversion as c
WHERE condefault AND
convert('ABC'::bytea, pg_encoding_to_char(conforencoding),
pg_encoding_to_char(contoencoding)) != 'ABC';
@ -530,42 +530,42 @@ WHERE condefault AND
-- Look for illegal values in pg_operator fields.
SELECT p1.oid, p1.oprname
FROM pg_operator as p1
WHERE (p1.oprkind != 'b' AND p1.oprkind != 'l') OR
p1.oprresult = 0 OR p1.oprcode = 0;
SELECT o1.oid, o1.oprname
FROM pg_operator as o1
WHERE (o1.oprkind != 'b' AND o1.oprkind != 'l') OR
o1.oprresult = 0 OR o1.oprcode = 0;
-- Look for missing or unwanted operand types
SELECT p1.oid, p1.oprname
FROM pg_operator as p1
WHERE (p1.oprleft = 0 and p1.oprkind != 'l') OR
(p1.oprleft != 0 and p1.oprkind = 'l') OR
p1.oprright = 0;
SELECT o1.oid, o1.oprname
FROM pg_operator as o1
WHERE (o1.oprleft = 0 and o1.oprkind != 'l') OR
(o1.oprleft != 0 and o1.oprkind = 'l') OR
o1.oprright = 0;
-- Look for conflicting operator definitions (same names and input datatypes).
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oid != p2.oid AND
p1.oprname = p2.oprname AND
p1.oprkind = p2.oprkind AND
p1.oprleft = p2.oprleft AND
p1.oprright = p2.oprright;
SELECT o1.oid, o1.oprcode, o2.oid, o2.oprcode
FROM pg_operator AS o1, pg_operator AS o2
WHERE o1.oid != o2.oid AND
o1.oprname = o2.oprname AND
o1.oprkind = o2.oprkind AND
o1.oprleft = o2.oprleft AND
o1.oprright = o2.oprright;
-- Look for commutative operators that don't commute.
-- DEFINITIONAL NOTE: If A.oprcom = B, then x A y has the same result as y B x.
-- We expect that B will always say that B.oprcom = A as well; that's not
-- inherently essential, but it would be inefficient not to mark it so.
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprcom = p2.oid AND
(p1.oprkind != 'b' OR
p1.oprleft != p2.oprright OR
p1.oprright != p2.oprleft OR
p1.oprresult != p2.oprresult OR
p1.oid != p2.oprcom);
SELECT o1.oid, o1.oprcode, o2.oid, o2.oprcode
FROM pg_operator AS o1, pg_operator AS o2
WHERE o1.oprcom = o2.oid AND
(o1.oprkind != 'b' OR
o1.oprleft != o2.oprright OR
o1.oprright != o2.oprleft OR
o1.oprresult != o2.oprresult OR
o1.oid != o2.oprcom);
-- Look for negatory operators that don't agree.
-- DEFINITIONAL NOTE: If A.oprnegate = B, then both A and B must yield
@ -575,16 +575,16 @@ WHERE p1.oprcom = p2.oid AND
-- inherently essential, but it would be inefficient not to mark it so.
-- Also, A and B had better not be the same operator.
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprnegate = p2.oid AND
(p1.oprkind != p2.oprkind OR
p1.oprleft != p2.oprleft OR
p1.oprright != p2.oprright OR
p1.oprresult != 'bool'::regtype OR
p2.oprresult != 'bool'::regtype OR
p1.oid != p2.oprnegate OR
p1.oid = p2.oid);
SELECT o1.oid, o1.oprcode, o2.oid, o2.oprcode
FROM pg_operator AS o1, pg_operator AS o2
WHERE o1.oprnegate = o2.oid AND
(o1.oprkind != o2.oprkind OR
o1.oprleft != o2.oprleft OR
o1.oprright != o2.oprright OR
o1.oprresult != 'bool'::regtype OR
o2.oprresult != 'bool'::regtype OR
o1.oid != o2.oprnegate OR
o1.oid = o2.oid);
-- Make a list of the names of operators that are claimed to be commutator
-- pairs. This list will grow over time, but before accepting a new entry
@ -606,93 +606,93 @@ ORDER BY 1, 2;
-- boolean, and must have a commutator (itself, unless it's a cross-type
-- operator).
SELECT p1.oid, p1.oprname FROM pg_operator AS p1
WHERE (p1.oprcanmerge OR p1.oprcanhash) AND NOT
(p1.oprkind = 'b' AND p1.oprresult = 'bool'::regtype AND p1.oprcom != 0);
SELECT o1.oid, o1.oprname FROM pg_operator AS o1
WHERE (o1.oprcanmerge OR o1.oprcanhash) AND NOT
(o1.oprkind = 'b' AND o1.oprresult = 'bool'::regtype AND o1.oprcom != 0);
-- What's more, the commutator had better be mergejoinable/hashjoinable too.
SELECT p1.oid, p1.oprname, p2.oid, p2.oprname
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprcom = p2.oid AND
(p1.oprcanmerge != p2.oprcanmerge OR
p1.oprcanhash != p2.oprcanhash);
SELECT o1.oid, o1.oprname, o2.oid, o2.oprname
FROM pg_operator AS o1, pg_operator AS o2
WHERE o1.oprcom = o2.oid AND
(o1.oprcanmerge != o2.oprcanmerge OR
o1.oprcanhash != o2.oprcanhash);
-- Mergejoinable operators should appear as equality members of btree index
-- opfamilies.
SELECT p1.oid, p1.oprname
FROM pg_operator AS p1
WHERE p1.oprcanmerge AND NOT EXISTS
SELECT o1.oid, o1.oprname
FROM pg_operator AS o1
WHERE o1.oprcanmerge AND NOT EXISTS
(SELECT 1 FROM pg_amop
WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
amopopr = p1.oid AND amopstrategy = 3);
amopopr = o1.oid AND amopstrategy = 3);
-- And the converse.
SELECT p1.oid, p1.oprname, p.amopfamily
FROM pg_operator AS p1, pg_amop p
WHERE amopopr = p1.oid
SELECT o1.oid, o1.oprname, p.amopfamily
FROM pg_operator AS o1, pg_amop p
WHERE amopopr = o1.oid
AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
AND amopstrategy = 3
AND NOT p1.oprcanmerge;
AND NOT o1.oprcanmerge;
-- Hashable operators should appear as members of hash index opfamilies.
SELECT p1.oid, p1.oprname
FROM pg_operator AS p1
WHERE p1.oprcanhash AND NOT EXISTS
SELECT o1.oid, o1.oprname
FROM pg_operator AS o1
WHERE o1.oprcanhash AND NOT EXISTS
(SELECT 1 FROM pg_amop
WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash') AND
amopopr = p1.oid AND amopstrategy = 1);
amopopr = o1.oid AND amopstrategy = 1);
-- And the converse.
SELECT p1.oid, p1.oprname, p.amopfamily
FROM pg_operator AS p1, pg_amop p
WHERE amopopr = p1.oid
SELECT o1.oid, o1.oprname, p.amopfamily
FROM pg_operator AS o1, pg_amop p
WHERE amopopr = o1.oid
AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash')
AND NOT p1.oprcanhash;
AND NOT o1.oprcanhash;
-- Check that each operator defined in pg_operator matches its oprcode entry
-- in pg_proc. Easiest to do this separately for each oprkind.
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprcode = p2.oid AND
p1.oprkind = 'b' AND
(p2.pronargs != 2
OR NOT binary_coercible(p2.prorettype, p1.oprresult)
OR NOT binary_coercible(p1.oprleft, p2.proargtypes[0])
OR NOT binary_coercible(p1.oprright, p2.proargtypes[1]));
SELECT o1.oid, o1.oprname, p1.oid, p1.proname
FROM pg_operator AS o1, pg_proc AS p1
WHERE o1.oprcode = p1.oid AND
o1.oprkind = 'b' AND
(p1.pronargs != 2
OR NOT binary_coercible(p1.prorettype, o1.oprresult)
OR NOT binary_coercible(o1.oprleft, p1.proargtypes[0])
OR NOT binary_coercible(o1.oprright, p1.proargtypes[1]));
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprcode = p2.oid AND
p1.oprkind = 'l' AND
(p2.pronargs != 1
OR NOT binary_coercible(p2.prorettype, p1.oprresult)
OR NOT binary_coercible(p1.oprright, p2.proargtypes[0])
OR p1.oprleft != 0);
SELECT o1.oid, o1.oprname, p1.oid, p1.proname
FROM pg_operator AS o1, pg_proc AS p1
WHERE o1.oprcode = p1.oid AND
o1.oprkind = 'l' AND
(p1.pronargs != 1
OR NOT binary_coercible(p1.prorettype, o1.oprresult)
OR NOT binary_coercible(o1.oprright, p1.proargtypes[0])
OR o1.oprleft != 0);
-- If the operator is mergejoinable or hashjoinable, its underlying function
-- should not be volatile.
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprcode = p2.oid AND
(p1.oprcanmerge OR p1.oprcanhash) AND
p2.provolatile = 'v';
SELECT o1.oid, o1.oprname, p1.oid, p1.proname
FROM pg_operator AS o1, pg_proc AS p1
WHERE o1.oprcode = p1.oid AND
(o1.oprcanmerge OR o1.oprcanhash) AND
p1.provolatile = 'v';
-- If oprrest is set, the operator must return boolean,
-- and it must link to a proc with the right signature
-- to be a restriction selectivity estimator.
-- The proc signature we want is: float8 proc(internal, oid, internal, int4)
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprrest = p2.oid AND
(p1.oprresult != 'bool'::regtype OR
SELECT o1.oid, o1.oprname, p2.oid, p2.proname
FROM pg_operator AS o1, pg_proc AS p2
WHERE o1.oprrest = p2.oid AND
(o1.oprresult != 'bool'::regtype OR
p2.prorettype != 'float8'::regtype OR p2.proretset OR
p2.pronargs != 4 OR
p2.proargtypes[0] != 'internal'::regtype OR
@ -707,10 +707,10 @@ WHERE p1.oprrest = p2.oid AND
-- (Note: the old signature with only 4 args is still allowed, but no core
-- estimator should be using it.)
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprjoin = p2.oid AND
(p1.oprkind != 'b' OR p1.oprresult != 'bool'::regtype OR
SELECT o1.oid, o1.oprname, p2.oid, p2.proname
FROM pg_operator AS o1, pg_proc AS p2
WHERE o1.oprjoin = p2.oid AND
(o1.oprkind != 'b' OR o1.oprresult != 'bool'::regtype OR
p2.prorettype != 'float8'::regtype OR p2.proretset OR
p2.pronargs != 5 OR
p2.proargtypes[0] != 'internal'::regtype OR
@ -720,10 +720,10 @@ WHERE p1.oprjoin = p2.oid AND
p2.proargtypes[4] != 'internal'::regtype);
-- Insist that all built-in pg_operator entries have descriptions
SELECT p1.oid, p1.oprname
FROM pg_operator as p1 LEFT JOIN pg_description as d
ON p1.tableoid = d.classoid and p1.oid = d.objoid and d.objsubid = 0
WHERE d.classoid IS NULL AND p1.oid <= 9999;
SELECT o1.oid, o1.oprname
FROM pg_operator as o1 LEFT JOIN pg_description as d
ON o1.tableoid = d.classoid and o1.oid = d.objoid and d.objsubid = 0
WHERE d.classoid IS NULL AND o1.oid <= 9999;
-- Check that operators' underlying functions have suitable comments,
-- namely 'implementation of XXX operator'. (Note: it's not necessary to
@ -807,7 +807,7 @@ ORDER BY 1;
-- Look for illegal values in pg_aggregate fields.
SELECT ctid, aggfnoid::oid
FROM pg_aggregate as p1
FROM pg_aggregate as a
WHERE aggfnoid = 0 OR aggtransfn = 0 OR
aggkind NOT IN ('n', 'o', 'h') OR
aggnumdirectargs < 0 OR
@ -893,12 +893,12 @@ WHERE a.aggfnoid = p.oid AND
-- Check for inconsistent specifications of moving-aggregate columns.
SELECT ctid, aggfnoid::oid
FROM pg_aggregate as p1
FROM pg_aggregate as a
WHERE aggmtranstype != 0 AND
(aggmtransfn = 0 OR aggminvtransfn = 0);
SELECT ctid, aggfnoid::oid
FROM pg_aggregate as p1
FROM pg_aggregate as a
WHERE aggmtranstype = 0 AND
(aggmtransfn != 0 OR aggminvtransfn != 0 OR aggmfinalfn != 0 OR
aggmtransspace != 0 OR aggminitval IS NOT NULL);
@ -1130,9 +1130,9 @@ WHERE prokind = 'a' AND provariadic != 0 AND a.aggkind = 'n';
-- Look for illegal values in pg_opfamily fields
SELECT p1.oid
FROM pg_opfamily as p1
WHERE p1.opfmethod = 0 OR p1.opfnamespace = 0;
SELECT f.oid
FROM pg_opfamily as f
WHERE f.opfmethod = 0 OR f.opfnamespace = 0;
-- Look for opfamilies having no opclasses. While most validation of
-- opfamilies is now handled by AM-specific amvalidate functions, that's
@ -1147,25 +1147,25 @@ WHERE NOT EXISTS (SELECT 1 FROM pg_opclass WHERE opcfamily = f.oid);
-- Look for illegal values in pg_opclass fields
SELECT p1.oid
FROM pg_opclass AS p1
WHERE p1.opcmethod = 0 OR p1.opcnamespace = 0 OR p1.opcfamily = 0
OR p1.opcintype = 0;
SELECT c1.oid
FROM pg_opclass AS c1
WHERE c1.opcmethod = 0 OR c1.opcnamespace = 0 OR c1.opcfamily = 0
OR c1.opcintype = 0;
-- opcmethod must match owning opfamily's opfmethod
SELECT p1.oid, p2.oid
FROM pg_opclass AS p1, pg_opfamily AS p2
WHERE p1.opcfamily = p2.oid AND p1.opcmethod != p2.opfmethod;
SELECT c1.oid, f1.oid
FROM pg_opclass AS c1, pg_opfamily AS f1
WHERE c1.opcfamily = f1.oid AND c1.opcmethod != f1.opfmethod;
-- There should not be multiple entries in pg_opclass with opcdefault true
-- and the same opcmethod/opcintype combination.
SELECT p1.oid, p2.oid
FROM pg_opclass AS p1, pg_opclass AS p2
WHERE p1.oid != p2.oid AND
p1.opcmethod = p2.opcmethod AND p1.opcintype = p2.opcintype AND
p1.opcdefault AND p2.opcdefault;
SELECT c1.oid, c2.oid
FROM pg_opclass AS c1, pg_opclass AS c2
WHERE c1.oid != c2.oid AND
c1.opcmethod = c2.opcmethod AND c1.opcintype = c2.opcintype AND
c1.opcdefault AND c2.opcdefault;
-- Ask access methods to validate opclasses
-- (this replaces a lot of SQL-level checks that used to be done in this file)
@ -1177,49 +1177,49 @@ SELECT oid, opcname FROM pg_opclass WHERE NOT amvalidate(oid);
-- Look for illegal values in pg_am fields
SELECT p1.oid, p1.amname
FROM pg_am AS p1
WHERE p1.amhandler = 0;
SELECT a1.oid, a1.amname
FROM pg_am AS a1
WHERE a1.amhandler = 0;
-- Check for index amhandler functions with the wrong signature
SELECT p1.oid, p1.amname, p2.oid, p2.proname
FROM pg_am AS p1, pg_proc AS p2
WHERE p2.oid = p1.amhandler AND p1.amtype = 'i' AND
(p2.prorettype != 'index_am_handler'::regtype
OR p2.proretset
OR p2.pronargs != 1
OR p2.proargtypes[0] != 'internal'::regtype);
SELECT a1.oid, a1.amname, p1.oid, p1.proname
FROM pg_am AS a1, pg_proc AS p1
WHERE p1.oid = a1.amhandler AND a1.amtype = 'i' AND
(p1.prorettype != 'index_am_handler'::regtype
OR p1.proretset
OR p1.pronargs != 1
OR p1.proargtypes[0] != 'internal'::regtype);
-- Check for table amhandler functions with the wrong signature
SELECT p1.oid, p1.amname, p2.oid, p2.proname
FROM pg_am AS p1, pg_proc AS p2
WHERE p2.oid = p1.amhandler AND p1.amtype = 's' AND
(p2.prorettype != 'table_am_handler'::regtype
OR p2.proretset
OR p2.pronargs != 1
OR p2.proargtypes[0] != 'internal'::regtype);
SELECT a1.oid, a1.amname, p1.oid, p1.proname
FROM pg_am AS a1, pg_proc AS p1
WHERE p1.oid = a1.amhandler AND a1.amtype = 's' AND
(p1.prorettype != 'table_am_handler'::regtype
OR p1.proretset
OR p1.pronargs != 1
OR p1.proargtypes[0] != 'internal'::regtype);
-- **************** pg_amop ****************
-- Look for illegal values in pg_amop fields
SELECT p1.amopfamily, p1.amopstrategy
FROM pg_amop as p1
WHERE p1.amopfamily = 0 OR p1.amoplefttype = 0 OR p1.amoprighttype = 0
OR p1.amopopr = 0 OR p1.amopmethod = 0 OR p1.amopstrategy < 1;
SELECT a1.amopfamily, a1.amopstrategy
FROM pg_amop as a1
WHERE a1.amopfamily = 0 OR a1.amoplefttype = 0 OR a1.amoprighttype = 0
OR a1.amopopr = 0 OR a1.amopmethod = 0 OR a1.amopstrategy < 1;
SELECT p1.amopfamily, p1.amopstrategy
FROM pg_amop as p1
WHERE NOT ((p1.amoppurpose = 's' AND p1.amopsortfamily = 0) OR
(p1.amoppurpose = 'o' AND p1.amopsortfamily <> 0));
SELECT a1.amopfamily, a1.amopstrategy
FROM pg_amop as a1
WHERE NOT ((a1.amoppurpose = 's' AND a1.amopsortfamily = 0) OR
(a1.amoppurpose = 'o' AND a1.amopsortfamily <> 0));
-- amopmethod must match owning opfamily's opfmethod
SELECT p1.oid, p2.oid
FROM pg_amop AS p1, pg_opfamily AS p2
WHERE p1.amopfamily = p2.oid AND p1.amopmethod != p2.opfmethod;
SELECT a1.oid, f1.oid
FROM pg_amop AS a1, pg_opfamily AS f1
WHERE a1.amopfamily = f1.oid AND a1.amopmethod != f1.opfmethod;
-- Make a list of all the distinct operator names being used in particular
-- strategy slots. This is a bit hokey, since the list might need to change
@ -1227,26 +1227,26 @@ WHERE p1.amopfamily = p2.oid AND p1.amopmethod != p2.opfmethod;
-- swapping two operators within a family.
SELECT DISTINCT amopmethod, amopstrategy, oprname
FROM pg_amop p1 LEFT JOIN pg_operator p2 ON amopopr = p2.oid
FROM pg_amop a1 LEFT JOIN pg_operator o1 ON amopopr = o1.oid
ORDER BY 1, 2, 3;
-- Check that all opclass search operators have selectivity estimators.
-- This is not absolutely required, but it seems a reasonable thing
-- to insist on for all standard datatypes.
SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
FROM pg_amop AS p1, pg_operator AS p2
WHERE p1.amopopr = p2.oid AND p1.amoppurpose = 's' AND
(p2.oprrest = 0 OR p2.oprjoin = 0);
SELECT a1.amopfamily, a1.amopopr, o1.oid, o1.oprname
FROM pg_amop AS a1, pg_operator AS o1
WHERE a1.amopopr = o1.oid AND a1.amoppurpose = 's' AND
(o1.oprrest = 0 OR o1.oprjoin = 0);
-- Check that each opclass in an opfamily has associated operators, that is
-- ones whose oprleft matches opcintype (possibly by coercion).
SELECT p1.opcname, p1.opcfamily
FROM pg_opclass AS p1
WHERE NOT EXISTS(SELECT 1 FROM pg_amop AS p2
WHERE p2.amopfamily = p1.opcfamily
AND binary_coercible(p1.opcintype, p2.amoplefttype));
SELECT c1.opcname, c1.opcfamily
FROM pg_opclass AS c1
WHERE NOT EXISTS(SELECT 1 FROM pg_amop AS a1
WHERE a1.amopfamily = c1.opcfamily
AND binary_coercible(c1.opcintype, a1.amoplefttype));
-- Check that each operator listed in pg_amop has an associated opclass,
-- that is one whose opcintype matches oprleft (possibly by coercion).
@ -1255,55 +1255,55 @@ WHERE NOT EXISTS(SELECT 1 FROM pg_amop AS p2
-- btree opfamilies, but in practice you'd expect there to be an opclass for
-- every datatype the family knows about.)
SELECT p1.amopfamily, p1.amopstrategy, p1.amopopr
FROM pg_amop AS p1
WHERE NOT EXISTS(SELECT 1 FROM pg_opclass AS p2
WHERE p2.opcfamily = p1.amopfamily
AND binary_coercible(p2.opcintype, p1.amoplefttype));
SELECT a1.amopfamily, a1.amopstrategy, a1.amopopr
FROM pg_amop AS a1
WHERE NOT EXISTS(SELECT 1 FROM pg_opclass AS c1
WHERE c1.opcfamily = a1.amopfamily
AND binary_coercible(c1.opcintype, a1.amoplefttype));
-- Operators that are primary members of opclasses must be immutable (else
-- it suggests that the index ordering isn't fixed). Operators that are
-- cross-type members need only be stable, since they are just shorthands
-- for index probe queries.
SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
p1.amoplefttype = p1.amoprighttype AND
p3.provolatile != 'i';
SELECT a1.amopfamily, a1.amopopr, o1.oprname, p1.prosrc
FROM pg_amop AS a1, pg_operator AS o1, pg_proc AS p1
WHERE a1.amopopr = o1.oid AND o1.oprcode = p1.oid AND
a1.amoplefttype = a1.amoprighttype AND
p1.provolatile != 'i';
SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
p1.amoplefttype != p1.amoprighttype AND
p3.provolatile = 'v';
SELECT a1.amopfamily, a1.amopopr, o1.oprname, p1.prosrc
FROM pg_amop AS a1, pg_operator AS o1, pg_proc AS p1
WHERE a1.amopopr = o1.oid AND o1.oprcode = p1.oid AND
a1.amoplefttype != a1.amoprighttype AND
p1.provolatile = 'v';
-- **************** pg_amproc ****************
-- Look for illegal values in pg_amproc fields
SELECT p1.amprocfamily, p1.amprocnum
FROM pg_amproc as p1
WHERE p1.amprocfamily = 0 OR p1.amproclefttype = 0 OR p1.amprocrighttype = 0
OR p1.amprocnum < 0 OR p1.amproc = 0;
SELECT a1.amprocfamily, a1.amprocnum
FROM pg_amproc as a1
WHERE a1.amprocfamily = 0 OR a1.amproclefttype = 0 OR a1.amprocrighttype = 0
OR a1.amprocnum < 0 OR a1.amproc = 0;
-- Support routines that are primary members of opfamilies must be immutable
-- (else it suggests that the index ordering isn't fixed). But cross-type
-- members need only be stable, since they are just shorthands
-- for index probe queries.
SELECT p1.amprocfamily, p1.amproc, p2.prosrc
FROM pg_amproc AS p1, pg_proc AS p2
WHERE p1.amproc = p2.oid AND
p1.amproclefttype = p1.amprocrighttype AND
p2.provolatile != 'i';
SELECT a1.amprocfamily, a1.amproc, p1.prosrc
FROM pg_amproc AS a1, pg_proc AS p1
WHERE a1.amproc = p1.oid AND
a1.amproclefttype = a1.amprocrighttype AND
p1.provolatile != 'i';
SELECT p1.amprocfamily, p1.amproc, p2.prosrc
FROM pg_amproc AS p1, pg_proc AS p2
WHERE p1.amproc = p2.oid AND
p1.amproclefttype != p1.amprocrighttype AND
p2.provolatile = 'v';
SELECT a1.amprocfamily, a1.amproc, p1.prosrc
FROM pg_amproc AS a1, pg_proc AS p1
WHERE a1.amproc = p1.oid AND
a1.amproclefttype != a1.amprocrighttype AND
p1.provolatile = 'v';
-- Almost all of the core distribution's Btree opclasses can use one of the
-- two generic "equalimage" functions as their support function 4. Look for
@ -1328,15 +1328,15 @@ ORDER BY 1, 2, 3;
-- Look for illegal values in pg_index fields.
SELECT p1.indexrelid, p1.indrelid
FROM pg_index as p1
WHERE p1.indexrelid = 0 OR p1.indrelid = 0 OR
p1.indnatts <= 0 OR p1.indnatts > 32;
SELECT indexrelid, indrelid
FROM pg_index
WHERE indexrelid = 0 OR indrelid = 0 OR
indnatts <= 0 OR indnatts > 32;
-- oidvector and int2vector fields should be of length indnatts.
SELECT p1.indexrelid, p1.indrelid
FROM pg_index as p1
SELECT indexrelid, indrelid
FROM pg_index
WHERE array_lower(indkey, 1) != 0 OR array_upper(indkey, 1) != indnatts-1 OR
array_lower(indclass, 1) != 0 OR array_upper(indclass, 1) != indnatts-1 OR
array_lower(indcollation, 1) != 0 OR array_upper(indcollation, 1) != indnatts-1 OR

View File

@ -16,94 +16,94 @@
-- Look for illegal values in pg_type fields.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typnamespace = 0 OR
(p1.typlen <= 0 AND p1.typlen != -1 AND p1.typlen != -2) OR
(p1.typtype not in ('b', 'c', 'd', 'e', 'p', 'r', 'm')) OR
NOT p1.typisdefined OR
(p1.typalign not in ('c', 's', 'i', 'd')) OR
(p1.typstorage not in ('p', 'x', 'e', 'm'));
SELECT t1.oid, t1.typname
FROM pg_type as t1
WHERE t1.typnamespace = 0 OR
(t1.typlen <= 0 AND t1.typlen != -1 AND t1.typlen != -2) OR
(t1.typtype not in ('b', 'c', 'd', 'e', 'p', 'r', 'm')) OR
NOT t1.typisdefined OR
(t1.typalign not in ('c', 's', 'i', 'd')) OR
(t1.typstorage not in ('p', 'x', 'e', 'm'));
-- Look for "pass by value" types that can't be passed by value.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typbyval AND
(p1.typlen != 1 OR p1.typalign != 'c') AND
(p1.typlen != 2 OR p1.typalign != 's') AND
(p1.typlen != 4 OR p1.typalign != 'i') AND
(p1.typlen != 8 OR p1.typalign != 'd');
SELECT t1.oid, t1.typname
FROM pg_type as t1
WHERE t1.typbyval AND
(t1.typlen != 1 OR t1.typalign != 'c') AND
(t1.typlen != 2 OR t1.typalign != 's') AND
(t1.typlen != 4 OR t1.typalign != 'i') AND
(t1.typlen != 8 OR t1.typalign != 'd');
-- Look for "toastable" types that aren't varlena.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typstorage != 'p' AND
(p1.typbyval OR p1.typlen != -1);
SELECT t1.oid, t1.typname
FROM pg_type as t1
WHERE t1.typstorage != 'p' AND
(t1.typbyval OR t1.typlen != -1);
-- Look for complex types that do not have a typrelid entry,
-- or basic types that do.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
(p1.typtype != 'c' AND p1.typrelid != 0);
SELECT t1.oid, t1.typname
FROM pg_type as t1
WHERE (t1.typtype = 'c' AND t1.typrelid = 0) OR
(t1.typtype != 'c' AND t1.typrelid != 0);
-- Look for types that should have an array type but don't.
-- Generally anything that's not a pseudotype should have an array type.
-- However, we do have a small number of exceptions.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typtype not in ('p') AND p1.typname NOT LIKE E'\\_%'
SELECT t1.oid, t1.typname
FROM pg_type as t1
WHERE t1.typtype not in ('p') AND t1.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)
ORDER BY p1.oid;
(SELECT 1 FROM pg_type as t2
WHERE t2.typname = ('_' || t1.typname)::name AND
t2.typelem = t1.oid and t1.typarray = t2.oid)
ORDER BY t1.oid;
-- Make sure typarray points to a "true" array type of our own base
SELECT p1.oid, p1.typname as basetype, p2.typname as arraytype,
p2.typsubscript
FROM pg_type p1 LEFT JOIN pg_type p2 ON (p1.typarray = p2.oid)
WHERE p1.typarray <> 0 AND
(p2.oid IS NULL OR
p2.typsubscript <> 'array_subscript_handler'::regproc);
SELECT t1.oid, t1.typname as basetype, t2.typname as arraytype,
t2.typsubscript
FROM pg_type t1 LEFT JOIN pg_type t2 ON (t1.typarray = t2.oid)
WHERE t1.typarray <> 0 AND
(t2.oid IS NULL OR
t2.typsubscript <> 'array_subscript_handler'::regproc);
-- Look for range types that do not have a pg_range entry
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typtype = 'r' AND
NOT EXISTS(SELECT 1 FROM pg_range r WHERE rngtypid = p1.oid);
SELECT t1.oid, t1.typname
FROM pg_type as t1
WHERE t1.typtype = 'r' AND
NOT EXISTS(SELECT 1 FROM pg_range r WHERE rngtypid = t1.oid);
-- Look for range types whose typalign isn't sufficient
SELECT p1.oid, p1.typname, p1.typalign, p2.typname, p2.typalign
FROM pg_type as p1
LEFT JOIN pg_range as r ON rngtypid = p1.oid
LEFT JOIN pg_type as p2 ON rngsubtype = p2.oid
WHERE p1.typtype = 'r' AND
(p1.typalign != (CASE WHEN p2.typalign = 'd' THEN 'd'::"char"
SELECT t1.oid, t1.typname, t1.typalign, t2.typname, t2.typalign
FROM pg_type as t1
LEFT JOIN pg_range as r ON rngtypid = t1.oid
LEFT JOIN pg_type as t2 ON rngsubtype = t2.oid
WHERE t1.typtype = 'r' AND
(t1.typalign != (CASE WHEN t2.typalign = 'd' THEN 'd'::"char"
ELSE 'i'::"char" END)
OR p2.oid IS NULL);
OR t2.oid IS NULL);
-- Text conversion routines must be provided.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE (p1.typinput = 0 OR p1.typoutput = 0);
SELECT t1.oid, t1.typname
FROM pg_type as t1
WHERE (t1.typinput = 0 OR t1.typoutput = 0);
-- Check for bogus typinput routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typinput = p2.oid AND NOT
((p2.pronargs = 1 AND p2.proargtypes[0] = 'cstring'::regtype) OR
(p2.pronargs = 2 AND p2.proargtypes[0] = 'cstring'::regtype AND
p2.proargtypes[1] = 'oid'::regtype) OR
(p2.pronargs = 3 AND p2.proargtypes[0] = 'cstring'::regtype AND
p2.proargtypes[1] = 'oid'::regtype AND
p2.proargtypes[2] = 'int4'::regtype));
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typinput = p1.oid AND NOT
((p1.pronargs = 1 AND p1.proargtypes[0] = 'cstring'::regtype) OR
(p1.pronargs = 2 AND p1.proargtypes[0] = 'cstring'::regtype AND
p1.proargtypes[1] = 'oid'::regtype) OR
(p1.pronargs = 3 AND p1.proargtypes[0] = 'cstring'::regtype AND
p1.proargtypes[1] = 'oid'::regtype AND
p1.proargtypes[2] = 'int4'::regtype));
-- Check for type of the variadic array parameter's elements.
-- provariadic should be ANYOID if the type of the last element is ANYOID,
@ -133,225 +133,225 @@ WHERE (proargmodes IS NOT NULL AND 'v' = any(proargmodes))
-- As of 8.0, this check finds refcursor, which is borrowing
-- other types' I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
(p2.prorettype = p1.oid AND NOT p2.proretset)
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typinput = p1.oid AND t1.typtype in ('b', 'p') AND NOT
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
(p1.prorettype = t1.oid AND NOT p1.proretset)
ORDER BY 1;
-- Varlena array types will point to array_in
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typinput = p2.oid AND
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
(p2.oid = 'array_in'::regproc)
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typinput = p1.oid AND
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
(p1.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');
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typinput = p1.oid AND p1.provolatile NOT IN ('i', 's');
-- Composites, domains, enums, multiranges, ranges should all use the same input routines
SELECT DISTINCT typtype, typinput
FROM pg_type AS p1
WHERE p1.typtype not in ('b', 'p')
FROM pg_type AS t1
WHERE t1.typtype not in ('b', 'p')
ORDER BY 1;
-- Check for bogus typoutput routines
-- As of 8.0, this check finds refcursor, which is borrowing
-- other types' I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
(p2.pronargs = 1 AND
(p2.proargtypes[0] = p1.oid OR
(p2.oid = 'array_out'::regproc AND
p1.typelem != 0 AND p1.typlen = -1)))
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typoutput = p1.oid AND t1.typtype in ('b', 'p') AND NOT
(p1.pronargs = 1 AND
(p1.proargtypes[0] = t1.oid OR
(p1.oid = 'array_out'::regproc AND
t1.typelem != 0 AND t1.typlen = -1)))
ORDER BY 1;
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typoutput = p2.oid AND NOT
(p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typoutput = p1.oid AND NOT
(p1.prorettype = 'cstring'::regtype AND NOT p1.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');
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typoutput = p1.oid AND p1.provolatile NOT IN ('i', 's');
-- Composites, enums, multiranges, 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')
FROM pg_type AS t1
WHERE t1.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;
SELECT t1.oid, t1.typname, t2.oid, t2.typname
FROM pg_type AS t1 LEFT JOIN pg_type AS t2 ON t1.typbasetype = t2.oid
WHERE t1.typtype = 'd' AND t1.typoutput IS DISTINCT FROM t2.typoutput;
-- Check for bogus typreceive routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typreceive = p2.oid AND NOT
((p2.pronargs = 1 AND p2.proargtypes[0] = 'internal'::regtype) OR
(p2.pronargs = 2 AND p2.proargtypes[0] = 'internal'::regtype AND
p2.proargtypes[1] = 'oid'::regtype) OR
(p2.pronargs = 3 AND p2.proargtypes[0] = 'internal'::regtype AND
p2.proargtypes[1] = 'oid'::regtype AND
p2.proargtypes[2] = 'int4'::regtype));
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typreceive = p1.oid AND NOT
((p1.pronargs = 1 AND p1.proargtypes[0] = 'internal'::regtype) OR
(p1.pronargs = 2 AND p1.proargtypes[0] = 'internal'::regtype AND
p1.proargtypes[1] = 'oid'::regtype) OR
(p1.pronargs = 3 AND p1.proargtypes[0] = 'internal'::regtype AND
p1.proargtypes[1] = 'oid'::regtype AND
p1.proargtypes[2] = 'int4'::regtype));
-- As of 7.4, this check finds refcursor, which is borrowing
-- other types' I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND NOT
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
(p2.prorettype = p1.oid AND NOT p2.proretset)
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typreceive = p1.oid AND t1.typtype in ('b', 'p') AND NOT
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
(p1.prorettype = t1.oid AND NOT p1.proretset)
ORDER BY 1;
-- Varlena array types will point to array_recv
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typreceive = p2.oid AND
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
(p2.oid = 'array_recv'::regproc)
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typreceive = p1.oid AND
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
(p1.oid = 'array_recv'::regproc)
ORDER BY 1;
-- Suspicious if typreceive doesn't take same number of args as typinput
SELECT p1.oid, p1.typname, p2.oid, p2.proname, p3.oid, p3.proname
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;
SELECT t1.oid, t1.typname, p1.oid, p1.proname, p2.oid, p2.proname
FROM pg_type AS t1, pg_proc AS p1, pg_proc AS p2
WHERE t1.typinput = p1.oid AND t1.typreceive = p2.oid AND
p1.pronargs != p2.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');
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typreceive = p1.oid AND p1.provolatile NOT IN ('i', 's');
-- Composites, domains, enums, multiranges, ranges should all use the same receive routines
SELECT DISTINCT typtype, typreceive
FROM pg_type AS p1
WHERE p1.typtype not in ('b', 'p')
FROM pg_type AS t1
WHERE t1.typtype not in ('b', 'p')
ORDER BY 1;
-- Check for bogus typsend routines
-- As of 7.4, this check finds refcursor, which is borrowing
-- other types' I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
(p2.pronargs = 1 AND
(p2.proargtypes[0] = p1.oid OR
(p2.oid = 'array_send'::regproc AND
p1.typelem != 0 AND p1.typlen = -1)))
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typsend = p1.oid AND t1.typtype in ('b', 'p') AND NOT
(p1.pronargs = 1 AND
(p1.proargtypes[0] = t1.oid OR
(p1.oid = 'array_send'::regproc AND
t1.typelem != 0 AND t1.typlen = -1)))
ORDER BY 1;
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typsend = p2.oid AND NOT
(p2.prorettype = 'bytea'::regtype AND NOT p2.proretset);
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typsend = p1.oid AND NOT
(p1.prorettype = 'bytea'::regtype AND NOT p1.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');
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typsend = p1.oid AND p1.provolatile NOT IN ('i', 's');
-- Composites, enums, multiranges, 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')
FROM pg_type AS t1
WHERE t1.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;
SELECT t1.oid, t1.typname, t2.oid, t2.typname
FROM pg_type AS t1 LEFT JOIN pg_type AS t2 ON t1.typbasetype = t2.oid
WHERE t1.typtype = 'd' AND t1.typsend IS DISTINCT FROM t2.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 NOT
(p2.pronargs = 1 AND
p2.proargtypes[0] = 'cstring[]'::regtype AND
p2.prorettype = 'int4'::regtype AND NOT p2.proretset);
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typmodin = p1.oid AND NOT
(p1.pronargs = 1 AND
p1.proargtypes[0] = 'cstring[]'::regtype AND
p1.prorettype = 'int4'::regtype AND NOT p1.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');
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typmodin = p1.oid AND p1.provolatile NOT IN ('i', 's');
-- 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 NOT
(p2.pronargs = 1 AND
p2.proargtypes[0] = 'int4'::regtype AND
p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typmodout = p1.oid AND NOT
(p1.pronargs = 1 AND
p1.proargtypes[0] = 'int4'::regtype AND
p1.prorettype = 'cstring'::regtype AND NOT p1.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');
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typmodout = p1.oid AND p1.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
FROM pg_type AS p1, pg_type AS p2
WHERE p1.typelem = p2.oid AND NOT
(p1.typmodin = p2.typmodin AND p1.typmodout = p2.typmodout);
SELECT t1.oid, t1.typname, t2.oid, t2.typname
FROM pg_type AS t1, pg_type AS t2
WHERE t1.typelem = t2.oid AND NOT
(t1.typmodin = t2.typmodin AND t1.typmodout = t2.typmodout);
-- Array types should have same typdelim as their element types
SELECT p1.oid, p1.typname, p2.oid, p2.typname
FROM pg_type AS p1, pg_type AS p2
WHERE p1.typarray = p2.oid AND NOT (p1.typdelim = p2.typdelim);
SELECT t1.oid, t1.typname, t2.oid, t2.typname
FROM pg_type AS t1, pg_type AS t2
WHERE t1.typarray = t2.oid AND NOT (t1.typdelim = t2.typdelim);
-- Look for array types whose typalign isn't sufficient
SELECT p1.oid, p1.typname, p1.typalign, p2.typname, p2.typalign
FROM pg_type AS p1, pg_type AS p2
WHERE p1.typarray = p2.oid AND
p2.typalign != (CASE WHEN p1.typalign = 'd' THEN 'd'::"char"
SELECT t1.oid, t1.typname, t1.typalign, t2.typname, t2.typalign
FROM pg_type AS t1, pg_type AS t2
WHERE t1.typarray = t2.oid AND
t2.typalign != (CASE WHEN t1.typalign = 'd' THEN 'd'::"char"
ELSE 'i'::"char" END);
-- Check for typelem set without a handler
SELECT p1.oid, p1.typname, p1.typelem
FROM pg_type AS p1
WHERE p1.typelem != 0 AND p1.typsubscript = 0;
SELECT t1.oid, t1.typname, t1.typelem
FROM pg_type AS t1
WHERE t1.typelem != 0 AND t1.typsubscript = 0;
-- Check for misuse of standard subscript handlers
SELECT p1.oid, p1.typname,
p1.typelem, p1.typlen, p1.typbyval
FROM pg_type AS p1
WHERE p1.typsubscript = 'array_subscript_handler'::regproc AND NOT
(p1.typelem != 0 AND p1.typlen = -1 AND NOT p1.typbyval);
SELECT t1.oid, t1.typname,
t1.typelem, t1.typlen, t1.typbyval
FROM pg_type AS t1
WHERE t1.typsubscript = 'array_subscript_handler'::regproc AND NOT
(t1.typelem != 0 AND t1.typlen = -1 AND NOT t1.typbyval);
SELECT p1.oid, p1.typname,
p1.typelem, p1.typlen, p1.typbyval
FROM pg_type AS p1
WHERE p1.typsubscript = 'raw_array_subscript_handler'::regproc AND NOT
(p1.typelem != 0 AND p1.typlen > 0 AND NOT p1.typbyval);
SELECT t1.oid, t1.typname,
t1.typelem, t1.typlen, t1.typbyval
FROM pg_type AS t1
WHERE t1.typsubscript = 'raw_array_subscript_handler'::regproc AND NOT
(t1.typelem != 0 AND t1.typlen > 0 AND NOT t1.typbyval);
-- 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 NOT
(p2.pronargs = 1 AND
p2.proargtypes[0] = 'internal'::regtype AND
p2.prorettype = 'bool'::regtype AND NOT p2.proretset);
SELECT t1.oid, t1.typname, p1.oid, p1.proname
FROM pg_type AS t1, pg_proc AS p1
WHERE t1.typanalyze = p1.oid AND NOT
(p1.pronargs = 1 AND
p1.proargtypes[0] = 'internal'::regtype AND
p1.prorettype = 'bool'::regtype AND NOT p1.proretset);
-- there does not seem to be a reason to care about volatility of typanalyze
@ -384,23 +384,23 @@ ORDER BY 1;
-- Look for illegal values in pg_class fields
SELECT p1.oid, p1.relname
FROM pg_class as p1
SELECT c1.oid, c1.relname
FROM pg_class as c1
WHERE relkind NOT IN ('r', 'i', 'S', 't', 'v', 'm', 'c', 'f', 'p') OR
relpersistence NOT IN ('p', 'u', 't') OR
relreplident NOT IN ('d', 'n', 'f', 'i');
-- All tables and indexes should have an access method.
SELECT p1.oid, p1.relname
FROM pg_class as p1
WHERE p1.relkind NOT IN ('S', 'v', 'f', 'c') and
p1.relam = 0;
SELECT c1.oid, c1.relname
FROM pg_class as c1
WHERE c1.relkind NOT IN ('S', 'v', 'f', 'c') and
c1.relam = 0;
-- Conversely, sequences, views, types shouldn't have them
SELECT p1.oid, p1.relname
FROM pg_class as p1
WHERE p1.relkind IN ('S', 'v', 'f', 'c') and
p1.relam != 0;
SELECT c1.oid, c1.relname
FROM pg_class as c1
WHERE c1.relkind IN ('S', 'v', 'f', 'c') and
c1.relam != 0;
-- Indexes should have AMs of type 'i'
SELECT pc.oid, pc.relname, pa.amname, pa.amtype
@ -418,83 +418,83 @@ WHERE pc.relkind IN ('r', 't', 'm') and
-- Look for illegal values in pg_attribute fields
SELECT p1.attrelid, p1.attname
FROM pg_attribute as p1
WHERE p1.attrelid = 0 OR p1.atttypid = 0 OR p1.attnum = 0 OR
p1.attcacheoff != -1 OR p1.attinhcount < 0 OR
(p1.attinhcount = 0 AND NOT p1.attislocal);
SELECT a1.attrelid, a1.attname
FROM pg_attribute as a1
WHERE a1.attrelid = 0 OR a1.atttypid = 0 OR a1.attnum = 0 OR
a1.attcacheoff != -1 OR a1.attinhcount < 0 OR
(a1.attinhcount = 0 AND NOT a1.attislocal);
-- Cross-check attnum against parent relation
SELECT p1.attrelid, p1.attname, p2.oid, p2.relname
FROM pg_attribute AS p1, pg_class AS p2
WHERE p1.attrelid = p2.oid AND p1.attnum > p2.relnatts;
SELECT a1.attrelid, a1.attname, c1.oid, c1.relname
FROM pg_attribute AS a1, pg_class AS c1
WHERE a1.attrelid = c1.oid AND a1.attnum > c1.relnatts;
-- Detect missing pg_attribute entries: should have as many non-system
-- attributes as parent relation expects
SELECT p1.oid, p1.relname
FROM pg_class AS p1
WHERE p1.relnatts != (SELECT count(*) FROM pg_attribute AS p2
WHERE p2.attrelid = p1.oid AND p2.attnum > 0);
SELECT c1.oid, c1.relname
FROM pg_class AS c1
WHERE c1.relnatts != (SELECT count(*) FROM pg_attribute AS a1
WHERE a1.attrelid = c1.oid AND a1.attnum > 0);
-- Cross-check against pg_type entry
-- NOTE: we allow attstorage to be 'plain' even when typstorage is not;
-- this is mainly for toast tables.
SELECT p1.attrelid, p1.attname, p2.oid, p2.typname
FROM pg_attribute AS p1, pg_type AS p2
WHERE p1.atttypid = p2.oid AND
(p1.attlen != p2.typlen OR
p1.attalign != p2.typalign OR
p1.attbyval != p2.typbyval OR
(p1.attstorage != p2.typstorage AND p1.attstorage != 'p'));
SELECT a1.attrelid, a1.attname, t1.oid, t1.typname
FROM pg_attribute AS a1, pg_type AS t1
WHERE a1.atttypid = t1.oid AND
(a1.attlen != t1.typlen OR
a1.attalign != t1.typalign OR
a1.attbyval != t1.typbyval OR
(a1.attstorage != t1.typstorage AND a1.attstorage != 'p'));
-- **************** pg_range ****************
-- Look for illegal values in pg_range fields.
SELECT p1.rngtypid, p1.rngsubtype
FROM pg_range as p1
WHERE p1.rngtypid = 0 OR p1.rngsubtype = 0 OR p1.rngsubopc = 0;
SELECT r.rngtypid, r.rngsubtype
FROM pg_range as r
WHERE r.rngtypid = 0 OR r.rngsubtype = 0 OR r.rngsubopc = 0;
-- rngcollation should be specified iff subtype is collatable
SELECT p1.rngtypid, p1.rngsubtype, p1.rngcollation, t.typcollation
FROM pg_range p1 JOIN pg_type t ON t.oid = p1.rngsubtype
SELECT r.rngtypid, r.rngsubtype, r.rngcollation, t.typcollation
FROM pg_range r JOIN pg_type t ON t.oid = r.rngsubtype
WHERE (rngcollation = 0) != (typcollation = 0);
-- opclass had better be a btree opclass accepting the subtype.
-- We must allow anyarray matches, cf IsBinaryCoercible()
SELECT p1.rngtypid, p1.rngsubtype, o.opcmethod, o.opcname
FROM pg_range p1 JOIN pg_opclass o ON o.oid = p1.rngsubopc
SELECT r.rngtypid, r.rngsubtype, o.opcmethod, o.opcname
FROM pg_range r JOIN pg_opclass o ON o.oid = r.rngsubopc
WHERE o.opcmethod != 403 OR
((o.opcintype != p1.rngsubtype) AND NOT
((o.opcintype != r.rngsubtype) AND NOT
(o.opcintype = 'pg_catalog.anyarray'::regtype AND
EXISTS(select 1 from pg_catalog.pg_type where
oid = p1.rngsubtype and typelem != 0 and
oid = r.rngsubtype and typelem != 0 and
typsubscript = 'array_subscript_handler'::regproc)));
-- canonical function, if any, had better match the range type
SELECT p1.rngtypid, p1.rngsubtype, p.proname
FROM pg_range p1 JOIN pg_proc p ON p.oid = p1.rngcanonical
SELECT r.rngtypid, r.rngsubtype, p.proname
FROM pg_range r JOIN pg_proc p ON p.oid = r.rngcanonical
WHERE pronargs != 1 OR proargtypes[0] != rngtypid OR prorettype != rngtypid;
-- subdiff function, if any, had better match the subtype
SELECT p1.rngtypid, p1.rngsubtype, p.proname
FROM pg_range p1 JOIN pg_proc p ON p.oid = p1.rngsubdiff
SELECT r.rngtypid, r.rngsubtype, p.proname
FROM pg_range r JOIN pg_proc p ON p.oid = r.rngsubdiff
WHERE pronargs != 2
OR proargtypes[0] != rngsubtype OR proargtypes[1] != rngsubtype
OR prorettype != 'pg_catalog.float8'::regtype;
-- every range should have a valid multirange
SELECT p1.rngtypid, p1.rngsubtype, p1.rngmultitypid
FROM pg_range p1
WHERE p1.rngmultitypid IS NULL OR p1.rngmultitypid = 0;
SELECT r.rngtypid, r.rngsubtype, r.rngmultitypid
FROM pg_range r
WHERE r.rngmultitypid IS NULL OR r.rngmultitypid = 0;
-- Create a table that holds all the known in-core data types and leave it
-- around so as pg_upgrade is able to test their binary compatibility.