mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
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:
parent
cba5b994c9
commit
9898c5e03c
@ -991,9 +991,9 @@ WHERE c.castmethod = 'b' AND
|
|||||||
|
|
||||||
-- **************** pg_conversion ****************
|
-- **************** pg_conversion ****************
|
||||||
-- Look for illegal values in pg_conversion fields.
|
-- Look for illegal values in pg_conversion fields.
|
||||||
SELECT p1.oid, p1.conname
|
SELECT c.oid, c.conname
|
||||||
FROM pg_conversion as p1
|
FROM pg_conversion as c
|
||||||
WHERE p1.conproc = 0 OR
|
WHERE c.conproc = 0 OR
|
||||||
pg_encoding_to_char(conforencoding) = '' OR
|
pg_encoding_to_char(conforencoding) = '' OR
|
||||||
pg_encoding_to_char(contoencoding) = '';
|
pg_encoding_to_char(contoencoding) = '';
|
||||||
oid | conname
|
oid | conname
|
||||||
@ -1025,8 +1025,8 @@ WHERE p.oid = c.conproc AND
|
|||||||
-- them directly from SQL. But there are no non-default built-in
|
-- them directly from SQL. But there are no non-default built-in
|
||||||
-- conversions anyway.
|
-- conversions anyway.
|
||||||
-- (Similarly, this doesn't cope with any search path issues.)
|
-- (Similarly, this doesn't cope with any search path issues.)
|
||||||
SELECT p1.oid, p1.conname
|
SELECT c.oid, c.conname
|
||||||
FROM pg_conversion as p1
|
FROM pg_conversion as c
|
||||||
WHERE condefault AND
|
WHERE condefault AND
|
||||||
convert('ABC'::bytea, pg_encoding_to_char(conforencoding),
|
convert('ABC'::bytea, pg_encoding_to_char(conforencoding),
|
||||||
pg_encoding_to_char(contoencoding)) != 'ABC';
|
pg_encoding_to_char(contoencoding)) != 'ABC';
|
||||||
@ -1036,32 +1036,32 @@ WHERE condefault AND
|
|||||||
|
|
||||||
-- **************** pg_operator ****************
|
-- **************** pg_operator ****************
|
||||||
-- Look for illegal values in pg_operator fields.
|
-- Look for illegal values in pg_operator fields.
|
||||||
SELECT p1.oid, p1.oprname
|
SELECT o1.oid, o1.oprname
|
||||||
FROM pg_operator as p1
|
FROM pg_operator as o1
|
||||||
WHERE (p1.oprkind != 'b' AND p1.oprkind != 'l') OR
|
WHERE (o1.oprkind != 'b' AND o1.oprkind != 'l') OR
|
||||||
p1.oprresult = 0 OR p1.oprcode = 0;
|
o1.oprresult = 0 OR o1.oprcode = 0;
|
||||||
oid | oprname
|
oid | oprname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Look for missing or unwanted operand types
|
-- Look for missing or unwanted operand types
|
||||||
SELECT p1.oid, p1.oprname
|
SELECT o1.oid, o1.oprname
|
||||||
FROM pg_operator as p1
|
FROM pg_operator as o1
|
||||||
WHERE (p1.oprleft = 0 and p1.oprkind != 'l') OR
|
WHERE (o1.oprleft = 0 and o1.oprkind != 'l') OR
|
||||||
(p1.oprleft != 0 and p1.oprkind = 'l') OR
|
(o1.oprleft != 0 and o1.oprkind = 'l') OR
|
||||||
p1.oprright = 0;
|
o1.oprright = 0;
|
||||||
oid | oprname
|
oid | oprname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Look for conflicting operator definitions (same names and input datatypes).
|
-- Look for conflicting operator definitions (same names and input datatypes).
|
||||||
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
|
SELECT o1.oid, o1.oprcode, o2.oid, o2.oprcode
|
||||||
FROM pg_operator AS p1, pg_operator AS p2
|
FROM pg_operator AS o1, pg_operator AS o2
|
||||||
WHERE p1.oid != p2.oid AND
|
WHERE o1.oid != o2.oid AND
|
||||||
p1.oprname = p2.oprname AND
|
o1.oprname = o2.oprname AND
|
||||||
p1.oprkind = p2.oprkind AND
|
o1.oprkind = o2.oprkind AND
|
||||||
p1.oprleft = p2.oprleft AND
|
o1.oprleft = o2.oprleft AND
|
||||||
p1.oprright = p2.oprright;
|
o1.oprright = o2.oprright;
|
||||||
oid | oprcode | oid | oprcode
|
oid | oprcode | oid | oprcode
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(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.
|
-- 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
|
-- 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.
|
-- inherently essential, but it would be inefficient not to mark it so.
|
||||||
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
|
SELECT o1.oid, o1.oprcode, o2.oid, o2.oprcode
|
||||||
FROM pg_operator AS p1, pg_operator AS p2
|
FROM pg_operator AS o1, pg_operator AS o2
|
||||||
WHERE p1.oprcom = p2.oid AND
|
WHERE o1.oprcom = o2.oid AND
|
||||||
(p1.oprkind != 'b' OR
|
(o1.oprkind != 'b' OR
|
||||||
p1.oprleft != p2.oprright OR
|
o1.oprleft != o2.oprright OR
|
||||||
p1.oprright != p2.oprleft OR
|
o1.oprright != o2.oprleft OR
|
||||||
p1.oprresult != p2.oprresult OR
|
o1.oprresult != o2.oprresult OR
|
||||||
p1.oid != p2.oprcom);
|
o1.oid != o2.oprcom);
|
||||||
oid | oprcode | oid | oprcode
|
oid | oprcode | oid | oprcode
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(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
|
-- 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.
|
-- inherently essential, but it would be inefficient not to mark it so.
|
||||||
-- Also, A and B had better not be the same operator.
|
-- Also, A and B had better not be the same operator.
|
||||||
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
|
SELECT o1.oid, o1.oprcode, o2.oid, o2.oprcode
|
||||||
FROM pg_operator AS p1, pg_operator AS p2
|
FROM pg_operator AS o1, pg_operator AS o2
|
||||||
WHERE p1.oprnegate = p2.oid AND
|
WHERE o1.oprnegate = o2.oid AND
|
||||||
(p1.oprkind != p2.oprkind OR
|
(o1.oprkind != o2.oprkind OR
|
||||||
p1.oprleft != p2.oprleft OR
|
o1.oprleft != o2.oprleft OR
|
||||||
p1.oprright != p2.oprright OR
|
o1.oprright != o2.oprright OR
|
||||||
p1.oprresult != 'bool'::regtype OR
|
o1.oprresult != 'bool'::regtype OR
|
||||||
p2.oprresult != 'bool'::regtype OR
|
o2.oprresult != 'bool'::regtype OR
|
||||||
p1.oid != p2.oprnegate OR
|
o1.oid != o2.oprnegate OR
|
||||||
p1.oid = p2.oid);
|
o1.oid = o2.oid);
|
||||||
oid | oprcode | oid | oprcode
|
oid | oprcode | oid | oprcode
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
@ -1168,100 +1168,100 @@ ORDER BY 1, 2;
|
|||||||
-- A mergejoinable or hashjoinable operator must be binary, must return
|
-- A mergejoinable or hashjoinable operator must be binary, must return
|
||||||
-- boolean, and must have a commutator (itself, unless it's a cross-type
|
-- boolean, and must have a commutator (itself, unless it's a cross-type
|
||||||
-- operator).
|
-- operator).
|
||||||
SELECT p1.oid, p1.oprname FROM pg_operator AS p1
|
SELECT o1.oid, o1.oprname FROM pg_operator AS o1
|
||||||
WHERE (p1.oprcanmerge OR p1.oprcanhash) AND NOT
|
WHERE (o1.oprcanmerge OR o1.oprcanhash) AND NOT
|
||||||
(p1.oprkind = 'b' AND p1.oprresult = 'bool'::regtype AND p1.oprcom != 0);
|
(o1.oprkind = 'b' AND o1.oprresult = 'bool'::regtype AND o1.oprcom != 0);
|
||||||
oid | oprname
|
oid | oprname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- What's more, the commutator had better be mergejoinable/hashjoinable too.
|
-- What's more, the commutator had better be mergejoinable/hashjoinable too.
|
||||||
SELECT p1.oid, p1.oprname, p2.oid, p2.oprname
|
SELECT o1.oid, o1.oprname, o2.oid, o2.oprname
|
||||||
FROM pg_operator AS p1, pg_operator AS p2
|
FROM pg_operator AS o1, pg_operator AS o2
|
||||||
WHERE p1.oprcom = p2.oid AND
|
WHERE o1.oprcom = o2.oid AND
|
||||||
(p1.oprcanmerge != p2.oprcanmerge OR
|
(o1.oprcanmerge != o2.oprcanmerge OR
|
||||||
p1.oprcanhash != p2.oprcanhash);
|
o1.oprcanhash != o2.oprcanhash);
|
||||||
oid | oprname | oid | oprname
|
oid | oprname | oid | oprname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Mergejoinable operators should appear as equality members of btree index
|
-- Mergejoinable operators should appear as equality members of btree index
|
||||||
-- opfamilies.
|
-- opfamilies.
|
||||||
SELECT p1.oid, p1.oprname
|
SELECT o1.oid, o1.oprname
|
||||||
FROM pg_operator AS p1
|
FROM pg_operator AS o1
|
||||||
WHERE p1.oprcanmerge AND NOT EXISTS
|
WHERE o1.oprcanmerge AND NOT EXISTS
|
||||||
(SELECT 1 FROM pg_amop
|
(SELECT 1 FROM pg_amop
|
||||||
WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
|
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
|
oid | oprname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- And the converse.
|
-- And the converse.
|
||||||
SELECT p1.oid, p1.oprname, p.amopfamily
|
SELECT o1.oid, o1.oprname, p.amopfamily
|
||||||
FROM pg_operator AS p1, pg_amop p
|
FROM pg_operator AS o1, pg_amop p
|
||||||
WHERE amopopr = p1.oid
|
WHERE amopopr = o1.oid
|
||||||
AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
|
AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
|
||||||
AND amopstrategy = 3
|
AND amopstrategy = 3
|
||||||
AND NOT p1.oprcanmerge;
|
AND NOT o1.oprcanmerge;
|
||||||
oid | oprname | amopfamily
|
oid | oprname | amopfamily
|
||||||
-----+---------+------------
|
-----+---------+------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Hashable operators should appear as members of hash index opfamilies.
|
-- Hashable operators should appear as members of hash index opfamilies.
|
||||||
SELECT p1.oid, p1.oprname
|
SELECT o1.oid, o1.oprname
|
||||||
FROM pg_operator AS p1
|
FROM pg_operator AS o1
|
||||||
WHERE p1.oprcanhash AND NOT EXISTS
|
WHERE o1.oprcanhash AND NOT EXISTS
|
||||||
(SELECT 1 FROM pg_amop
|
(SELECT 1 FROM pg_amop
|
||||||
WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash') AND
|
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
|
oid | oprname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- And the converse.
|
-- And the converse.
|
||||||
SELECT p1.oid, p1.oprname, p.amopfamily
|
SELECT o1.oid, o1.oprname, p.amopfamily
|
||||||
FROM pg_operator AS p1, pg_amop p
|
FROM pg_operator AS o1, pg_amop p
|
||||||
WHERE amopopr = p1.oid
|
WHERE amopopr = o1.oid
|
||||||
AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash')
|
AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash')
|
||||||
AND NOT p1.oprcanhash;
|
AND NOT o1.oprcanhash;
|
||||||
oid | oprname | amopfamily
|
oid | oprname | amopfamily
|
||||||
-----+---------+------------
|
-----+---------+------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Check that each operator defined in pg_operator matches its oprcode entry
|
-- Check that each operator defined in pg_operator matches its oprcode entry
|
||||||
-- in pg_proc. Easiest to do this separately for each oprkind.
|
-- in pg_proc. Easiest to do this separately for each oprkind.
|
||||||
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
SELECT o1.oid, o1.oprname, p1.oid, p1.proname
|
||||||
FROM pg_operator AS p1, pg_proc AS p2
|
FROM pg_operator AS o1, pg_proc AS p1
|
||||||
WHERE p1.oprcode = p2.oid AND
|
WHERE o1.oprcode = p1.oid AND
|
||||||
p1.oprkind = 'b' AND
|
o1.oprkind = 'b' AND
|
||||||
(p2.pronargs != 2
|
(p1.pronargs != 2
|
||||||
OR NOT binary_coercible(p2.prorettype, p1.oprresult)
|
OR NOT binary_coercible(p1.prorettype, o1.oprresult)
|
||||||
OR NOT binary_coercible(p1.oprleft, p2.proargtypes[0])
|
OR NOT binary_coercible(o1.oprleft, p1.proargtypes[0])
|
||||||
OR NOT binary_coercible(p1.oprright, p2.proargtypes[1]));
|
OR NOT binary_coercible(o1.oprright, p1.proargtypes[1]));
|
||||||
oid | oprname | oid | proname
|
oid | oprname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
SELECT o1.oid, o1.oprname, p1.oid, p1.proname
|
||||||
FROM pg_operator AS p1, pg_proc AS p2
|
FROM pg_operator AS o1, pg_proc AS p1
|
||||||
WHERE p1.oprcode = p2.oid AND
|
WHERE o1.oprcode = p1.oid AND
|
||||||
p1.oprkind = 'l' AND
|
o1.oprkind = 'l' AND
|
||||||
(p2.pronargs != 1
|
(p1.pronargs != 1
|
||||||
OR NOT binary_coercible(p2.prorettype, p1.oprresult)
|
OR NOT binary_coercible(p1.prorettype, o1.oprresult)
|
||||||
OR NOT binary_coercible(p1.oprright, p2.proargtypes[0])
|
OR NOT binary_coercible(o1.oprright, p1.proargtypes[0])
|
||||||
OR p1.oprleft != 0);
|
OR o1.oprleft != 0);
|
||||||
oid | oprname | oid | proname
|
oid | oprname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- If the operator is mergejoinable or hashjoinable, its underlying function
|
-- If the operator is mergejoinable or hashjoinable, its underlying function
|
||||||
-- should not be volatile.
|
-- should not be volatile.
|
||||||
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
SELECT o1.oid, o1.oprname, p1.oid, p1.proname
|
||||||
FROM pg_operator AS p1, pg_proc AS p2
|
FROM pg_operator AS o1, pg_proc AS p1
|
||||||
WHERE p1.oprcode = p2.oid AND
|
WHERE o1.oprcode = p1.oid AND
|
||||||
(p1.oprcanmerge OR p1.oprcanhash) AND
|
(o1.oprcanmerge OR o1.oprcanhash) AND
|
||||||
p2.provolatile = 'v';
|
p1.provolatile = 'v';
|
||||||
oid | oprname | oid | proname
|
oid | oprname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
@ -1270,10 +1270,10 @@ WHERE p1.oprcode = p2.oid AND
|
|||||||
-- and it must link to a proc with the right signature
|
-- and it must link to a proc with the right signature
|
||||||
-- to be a restriction selectivity estimator.
|
-- to be a restriction selectivity estimator.
|
||||||
-- The proc signature we want is: float8 proc(internal, oid, internal, int4)
|
-- The proc signature we want is: float8 proc(internal, oid, internal, int4)
|
||||||
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
SELECT o1.oid, o1.oprname, p2.oid, p2.proname
|
||||||
FROM pg_operator AS p1, pg_proc AS p2
|
FROM pg_operator AS o1, pg_proc AS p2
|
||||||
WHERE p1.oprrest = p2.oid AND
|
WHERE o1.oprrest = p2.oid AND
|
||||||
(p1.oprresult != 'bool'::regtype OR
|
(o1.oprresult != 'bool'::regtype OR
|
||||||
p2.prorettype != 'float8'::regtype OR p2.proretset OR
|
p2.prorettype != 'float8'::regtype OR p2.proretset OR
|
||||||
p2.pronargs != 4 OR
|
p2.pronargs != 4 OR
|
||||||
p2.proargtypes[0] != 'internal'::regtype 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)
|
-- 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
|
-- (Note: the old signature with only 4 args is still allowed, but no core
|
||||||
-- estimator should be using it.)
|
-- estimator should be using it.)
|
||||||
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
SELECT o1.oid, o1.oprname, p2.oid, p2.proname
|
||||||
FROM pg_operator AS p1, pg_proc AS p2
|
FROM pg_operator AS o1, pg_proc AS p2
|
||||||
WHERE p1.oprjoin = p2.oid AND
|
WHERE o1.oprjoin = p2.oid AND
|
||||||
(p1.oprkind != 'b' OR p1.oprresult != 'bool'::regtype OR
|
(o1.oprkind != 'b' OR o1.oprresult != 'bool'::regtype OR
|
||||||
p2.prorettype != 'float8'::regtype OR p2.proretset OR
|
p2.prorettype != 'float8'::regtype OR p2.proretset OR
|
||||||
p2.pronargs != 5 OR
|
p2.pronargs != 5 OR
|
||||||
p2.proargtypes[0] != 'internal'::regtype OR
|
p2.proargtypes[0] != 'internal'::regtype OR
|
||||||
@ -1306,10 +1306,10 @@ WHERE p1.oprjoin = p2.oid AND
|
|||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Insist that all built-in pg_operator entries have descriptions
|
-- Insist that all built-in pg_operator entries have descriptions
|
||||||
SELECT p1.oid, p1.oprname
|
SELECT o1.oid, o1.oprname
|
||||||
FROM pg_operator as p1 LEFT JOIN pg_description as d
|
FROM pg_operator as o1 LEFT JOIN pg_description as d
|
||||||
ON p1.tableoid = d.classoid and p1.oid = d.objoid and d.objsubid = 0
|
ON o1.tableoid = d.classoid and o1.oid = d.objoid and d.objsubid = 0
|
||||||
WHERE d.classoid IS NULL AND p1.oid <= 9999;
|
WHERE d.classoid IS NULL AND o1.oid <= 9999;
|
||||||
oid | oprname
|
oid | oprname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
@ -1417,7 +1417,7 @@ ORDER BY 1;
|
|||||||
-- **************** pg_aggregate ****************
|
-- **************** pg_aggregate ****************
|
||||||
-- Look for illegal values in pg_aggregate fields.
|
-- Look for illegal values in pg_aggregate fields.
|
||||||
SELECT ctid, aggfnoid::oid
|
SELECT ctid, aggfnoid::oid
|
||||||
FROM pg_aggregate as p1
|
FROM pg_aggregate as a
|
||||||
WHERE aggfnoid = 0 OR aggtransfn = 0 OR
|
WHERE aggfnoid = 0 OR aggtransfn = 0 OR
|
||||||
aggkind NOT IN ('n', 'o', 'h') OR
|
aggkind NOT IN ('n', 'o', 'h') OR
|
||||||
aggnumdirectargs < 0 OR
|
aggnumdirectargs < 0 OR
|
||||||
@ -1518,7 +1518,7 @@ WHERE a.aggfnoid = p.oid AND
|
|||||||
|
|
||||||
-- Check for inconsistent specifications of moving-aggregate columns.
|
-- Check for inconsistent specifications of moving-aggregate columns.
|
||||||
SELECT ctid, aggfnoid::oid
|
SELECT ctid, aggfnoid::oid
|
||||||
FROM pg_aggregate as p1
|
FROM pg_aggregate as a
|
||||||
WHERE aggmtranstype != 0 AND
|
WHERE aggmtranstype != 0 AND
|
||||||
(aggmtransfn = 0 OR aggminvtransfn = 0);
|
(aggmtransfn = 0 OR aggminvtransfn = 0);
|
||||||
ctid | aggfnoid
|
ctid | aggfnoid
|
||||||
@ -1526,7 +1526,7 @@ WHERE aggmtranstype != 0 AND
|
|||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
SELECT ctid, aggfnoid::oid
|
SELECT ctid, aggfnoid::oid
|
||||||
FROM pg_aggregate as p1
|
FROM pg_aggregate as a
|
||||||
WHERE aggmtranstype = 0 AND
|
WHERE aggmtranstype = 0 AND
|
||||||
(aggmtransfn != 0 OR aggminvtransfn != 0 OR aggmfinalfn != 0 OR
|
(aggmtransfn != 0 OR aggminvtransfn != 0 OR aggmfinalfn != 0 OR
|
||||||
aggmtransspace != 0 OR aggminitval IS NOT NULL);
|
aggmtransspace != 0 OR aggminitval IS NOT NULL);
|
||||||
@ -1809,9 +1809,9 @@ WHERE prokind = 'a' AND provariadic != 0 AND a.aggkind = 'n';
|
|||||||
|
|
||||||
-- **************** pg_opfamily ****************
|
-- **************** pg_opfamily ****************
|
||||||
-- Look for illegal values in pg_opfamily fields
|
-- Look for illegal values in pg_opfamily fields
|
||||||
SELECT p1.oid
|
SELECT f.oid
|
||||||
FROM pg_opfamily as p1
|
FROM pg_opfamily as f
|
||||||
WHERE p1.opfmethod = 0 OR p1.opfnamespace = 0;
|
WHERE f.opfmethod = 0 OR f.opfnamespace = 0;
|
||||||
oid
|
oid
|
||||||
-----
|
-----
|
||||||
(0 rows)
|
(0 rows)
|
||||||
@ -1828,29 +1828,29 @@ WHERE NOT EXISTS (SELECT 1 FROM pg_opclass WHERE opcfamily = f.oid);
|
|||||||
|
|
||||||
-- **************** pg_opclass ****************
|
-- **************** pg_opclass ****************
|
||||||
-- Look for illegal values in pg_opclass fields
|
-- Look for illegal values in pg_opclass fields
|
||||||
SELECT p1.oid
|
SELECT c1.oid
|
||||||
FROM pg_opclass AS p1
|
FROM pg_opclass AS c1
|
||||||
WHERE p1.opcmethod = 0 OR p1.opcnamespace = 0 OR p1.opcfamily = 0
|
WHERE c1.opcmethod = 0 OR c1.opcnamespace = 0 OR c1.opcfamily = 0
|
||||||
OR p1.opcintype = 0;
|
OR c1.opcintype = 0;
|
||||||
oid
|
oid
|
||||||
-----
|
-----
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- opcmethod must match owning opfamily's opfmethod
|
-- opcmethod must match owning opfamily's opfmethod
|
||||||
SELECT p1.oid, p2.oid
|
SELECT c1.oid, f1.oid
|
||||||
FROM pg_opclass AS p1, pg_opfamily AS p2
|
FROM pg_opclass AS c1, pg_opfamily AS f1
|
||||||
WHERE p1.opcfamily = p2.oid AND p1.opcmethod != p2.opfmethod;
|
WHERE c1.opcfamily = f1.oid AND c1.opcmethod != f1.opfmethod;
|
||||||
oid | oid
|
oid | oid
|
||||||
-----+-----
|
-----+-----
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- There should not be multiple entries in pg_opclass with opcdefault true
|
-- There should not be multiple entries in pg_opclass with opcdefault true
|
||||||
-- and the same opcmethod/opcintype combination.
|
-- and the same opcmethod/opcintype combination.
|
||||||
SELECT p1.oid, p2.oid
|
SELECT c1.oid, c2.oid
|
||||||
FROM pg_opclass AS p1, pg_opclass AS p2
|
FROM pg_opclass AS c1, pg_opclass AS c2
|
||||||
WHERE p1.oid != p2.oid AND
|
WHERE c1.oid != c2.oid AND
|
||||||
p1.opcmethod = p2.opcmethod AND p1.opcintype = p2.opcintype AND
|
c1.opcmethod = c2.opcmethod AND c1.opcintype = c2.opcintype AND
|
||||||
p1.opcdefault AND p2.opcdefault;
|
c1.opcdefault AND c2.opcdefault;
|
||||||
oid | oid
|
oid | oid
|
||||||
-----+-----
|
-----+-----
|
||||||
(0 rows)
|
(0 rows)
|
||||||
@ -1864,59 +1864,59 @@ SELECT oid, opcname FROM pg_opclass WHERE NOT amvalidate(oid);
|
|||||||
|
|
||||||
-- **************** pg_am ****************
|
-- **************** pg_am ****************
|
||||||
-- Look for illegal values in pg_am fields
|
-- Look for illegal values in pg_am fields
|
||||||
SELECT p1.oid, p1.amname
|
SELECT a1.oid, a1.amname
|
||||||
FROM pg_am AS p1
|
FROM pg_am AS a1
|
||||||
WHERE p1.amhandler = 0;
|
WHERE a1.amhandler = 0;
|
||||||
oid | amname
|
oid | amname
|
||||||
-----+--------
|
-----+--------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Check for index amhandler functions with the wrong signature
|
-- Check for index amhandler functions with the wrong signature
|
||||||
SELECT p1.oid, p1.amname, p2.oid, p2.proname
|
SELECT a1.oid, a1.amname, p1.oid, p1.proname
|
||||||
FROM pg_am AS p1, pg_proc AS p2
|
FROM pg_am AS a1, pg_proc AS p1
|
||||||
WHERE p2.oid = p1.amhandler AND p1.amtype = 'i' AND
|
WHERE p1.oid = a1.amhandler AND a1.amtype = 'i' AND
|
||||||
(p2.prorettype != 'index_am_handler'::regtype
|
(p1.prorettype != 'index_am_handler'::regtype
|
||||||
OR p2.proretset
|
OR p1.proretset
|
||||||
OR p2.pronargs != 1
|
OR p1.pronargs != 1
|
||||||
OR p2.proargtypes[0] != 'internal'::regtype);
|
OR p1.proargtypes[0] != 'internal'::regtype);
|
||||||
oid | amname | oid | proname
|
oid | amname | oid | proname
|
||||||
-----+--------+-----+---------
|
-----+--------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Check for table amhandler functions with the wrong signature
|
-- Check for table amhandler functions with the wrong signature
|
||||||
SELECT p1.oid, p1.amname, p2.oid, p2.proname
|
SELECT a1.oid, a1.amname, p1.oid, p1.proname
|
||||||
FROM pg_am AS p1, pg_proc AS p2
|
FROM pg_am AS a1, pg_proc AS p1
|
||||||
WHERE p2.oid = p1.amhandler AND p1.amtype = 's' AND
|
WHERE p1.oid = a1.amhandler AND a1.amtype = 's' AND
|
||||||
(p2.prorettype != 'table_am_handler'::regtype
|
(p1.prorettype != 'table_am_handler'::regtype
|
||||||
OR p2.proretset
|
OR p1.proretset
|
||||||
OR p2.pronargs != 1
|
OR p1.pronargs != 1
|
||||||
OR p2.proargtypes[0] != 'internal'::regtype);
|
OR p1.proargtypes[0] != 'internal'::regtype);
|
||||||
oid | amname | oid | proname
|
oid | amname | oid | proname
|
||||||
-----+--------+-----+---------
|
-----+--------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- **************** pg_amop ****************
|
-- **************** pg_amop ****************
|
||||||
-- Look for illegal values in pg_amop fields
|
-- Look for illegal values in pg_amop fields
|
||||||
SELECT p1.amopfamily, p1.amopstrategy
|
SELECT a1.amopfamily, a1.amopstrategy
|
||||||
FROM pg_amop as p1
|
FROM pg_amop as a1
|
||||||
WHERE p1.amopfamily = 0 OR p1.amoplefttype = 0 OR p1.amoprighttype = 0
|
WHERE a1.amopfamily = 0 OR a1.amoplefttype = 0 OR a1.amoprighttype = 0
|
||||||
OR p1.amopopr = 0 OR p1.amopmethod = 0 OR p1.amopstrategy < 1;
|
OR a1.amopopr = 0 OR a1.amopmethod = 0 OR a1.amopstrategy < 1;
|
||||||
amopfamily | amopstrategy
|
amopfamily | amopstrategy
|
||||||
------------+--------------
|
------------+--------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
SELECT p1.amopfamily, p1.amopstrategy
|
SELECT a1.amopfamily, a1.amopstrategy
|
||||||
FROM pg_amop as p1
|
FROM pg_amop as a1
|
||||||
WHERE NOT ((p1.amoppurpose = 's' AND p1.amopsortfamily = 0) OR
|
WHERE NOT ((a1.amoppurpose = 's' AND a1.amopsortfamily = 0) OR
|
||||||
(p1.amoppurpose = 'o' AND p1.amopsortfamily <> 0));
|
(a1.amoppurpose = 'o' AND a1.amopsortfamily <> 0));
|
||||||
amopfamily | amopstrategy
|
amopfamily | amopstrategy
|
||||||
------------+--------------
|
------------+--------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- amopmethod must match owning opfamily's opfmethod
|
-- amopmethod must match owning opfamily's opfmethod
|
||||||
SELECT p1.oid, p2.oid
|
SELECT a1.oid, f1.oid
|
||||||
FROM pg_amop AS p1, pg_opfamily AS p2
|
FROM pg_amop AS a1, pg_opfamily AS f1
|
||||||
WHERE p1.amopfamily = p2.oid AND p1.amopmethod != p2.opfmethod;
|
WHERE a1.amopfamily = f1.oid AND a1.amopmethod != f1.opfmethod;
|
||||||
oid | oid
|
oid | oid
|
||||||
-----+-----
|
-----+-----
|
||||||
(0 rows)
|
(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
|
-- in future releases, but it's an effective way of spotting mistakes such as
|
||||||
-- swapping two operators within a family.
|
-- swapping two operators within a family.
|
||||||
SELECT DISTINCT amopmethod, amopstrategy, oprname
|
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;
|
ORDER BY 1, 2, 3;
|
||||||
amopmethod | amopstrategy | oprname
|
amopmethod | amopstrategy | oprname
|
||||||
------------+--------------+---------
|
------------+--------------+---------
|
||||||
@ -2059,21 +2059,21 @@ ORDER BY 1, 2, 3;
|
|||||||
-- Check that all opclass search operators have selectivity estimators.
|
-- Check that all opclass search operators have selectivity estimators.
|
||||||
-- This is not absolutely required, but it seems a reasonable thing
|
-- This is not absolutely required, but it seems a reasonable thing
|
||||||
-- to insist on for all standard datatypes.
|
-- to insist on for all standard datatypes.
|
||||||
SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
|
SELECT a1.amopfamily, a1.amopopr, o1.oid, o1.oprname
|
||||||
FROM pg_amop AS p1, pg_operator AS p2
|
FROM pg_amop AS a1, pg_operator AS o1
|
||||||
WHERE p1.amopopr = p2.oid AND p1.amoppurpose = 's' AND
|
WHERE a1.amopopr = o1.oid AND a1.amoppurpose = 's' AND
|
||||||
(p2.oprrest = 0 OR p2.oprjoin = 0);
|
(o1.oprrest = 0 OR o1.oprjoin = 0);
|
||||||
amopfamily | amopopr | oid | oprname
|
amopfamily | amopopr | oid | oprname
|
||||||
------------+---------+-----+---------
|
------------+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Check that each opclass in an opfamily has associated operators, that is
|
-- Check that each opclass in an opfamily has associated operators, that is
|
||||||
-- ones whose oprleft matches opcintype (possibly by coercion).
|
-- ones whose oprleft matches opcintype (possibly by coercion).
|
||||||
SELECT p1.opcname, p1.opcfamily
|
SELECT c1.opcname, c1.opcfamily
|
||||||
FROM pg_opclass AS p1
|
FROM pg_opclass AS c1
|
||||||
WHERE NOT EXISTS(SELECT 1 FROM pg_amop AS p2
|
WHERE NOT EXISTS(SELECT 1 FROM pg_amop AS a1
|
||||||
WHERE p2.amopfamily = p1.opcfamily
|
WHERE a1.amopfamily = c1.opcfamily
|
||||||
AND binary_coercible(p1.opcintype, p2.amoplefttype));
|
AND binary_coercible(c1.opcintype, a1.amoplefttype));
|
||||||
opcname | opcfamily
|
opcname | opcfamily
|
||||||
---------+-----------
|
---------+-----------
|
||||||
(0 rows)
|
(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
|
-- (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
|
-- btree opfamilies, but in practice you'd expect there to be an opclass for
|
||||||
-- every datatype the family knows about.)
|
-- every datatype the family knows about.)
|
||||||
SELECT p1.amopfamily, p1.amopstrategy, p1.amopopr
|
SELECT a1.amopfamily, a1.amopstrategy, a1.amopopr
|
||||||
FROM pg_amop AS p1
|
FROM pg_amop AS a1
|
||||||
WHERE NOT EXISTS(SELECT 1 FROM pg_opclass AS p2
|
WHERE NOT EXISTS(SELECT 1 FROM pg_opclass AS c1
|
||||||
WHERE p2.opcfamily = p1.amopfamily
|
WHERE c1.opcfamily = a1.amopfamily
|
||||||
AND binary_coercible(p2.opcintype, p1.amoplefttype));
|
AND binary_coercible(c1.opcintype, a1.amoplefttype));
|
||||||
amopfamily | amopstrategy | amopopr
|
amopfamily | amopstrategy | amopopr
|
||||||
------------+--------------+---------
|
------------+--------------+---------
|
||||||
(0 rows)
|
(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
|
-- it suggests that the index ordering isn't fixed). Operators that are
|
||||||
-- cross-type members need only be stable, since they are just shorthands
|
-- cross-type members need only be stable, since they are just shorthands
|
||||||
-- for index probe queries.
|
-- for index probe queries.
|
||||||
SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
|
SELECT a1.amopfamily, a1.amopopr, o1.oprname, p1.prosrc
|
||||||
FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
|
FROM pg_amop AS a1, pg_operator AS o1, pg_proc AS p1
|
||||||
WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
|
WHERE a1.amopopr = o1.oid AND o1.oprcode = p1.oid AND
|
||||||
p1.amoplefttype = p1.amoprighttype AND
|
a1.amoplefttype = a1.amoprighttype AND
|
||||||
p3.provolatile != 'i';
|
p1.provolatile != 'i';
|
||||||
amopfamily | amopopr | oprname | prosrc
|
amopfamily | amopopr | oprname | prosrc
|
||||||
------------+---------+---------+--------
|
------------+---------+---------+--------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
|
SELECT a1.amopfamily, a1.amopopr, o1.oprname, p1.prosrc
|
||||||
FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
|
FROM pg_amop AS a1, pg_operator AS o1, pg_proc AS p1
|
||||||
WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
|
WHERE a1.amopopr = o1.oid AND o1.oprcode = p1.oid AND
|
||||||
p1.amoplefttype != p1.amoprighttype AND
|
a1.amoplefttype != a1.amoprighttype AND
|
||||||
p3.provolatile = 'v';
|
p1.provolatile = 'v';
|
||||||
amopfamily | amopopr | oprname | prosrc
|
amopfamily | amopopr | oprname | prosrc
|
||||||
------------+---------+---------+--------
|
------------+---------+---------+--------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- **************** pg_amproc ****************
|
-- **************** pg_amproc ****************
|
||||||
-- Look for illegal values in pg_amproc fields
|
-- Look for illegal values in pg_amproc fields
|
||||||
SELECT p1.amprocfamily, p1.amprocnum
|
SELECT a1.amprocfamily, a1.amprocnum
|
||||||
FROM pg_amproc as p1
|
FROM pg_amproc as a1
|
||||||
WHERE p1.amprocfamily = 0 OR p1.amproclefttype = 0 OR p1.amprocrighttype = 0
|
WHERE a1.amprocfamily = 0 OR a1.amproclefttype = 0 OR a1.amprocrighttype = 0
|
||||||
OR p1.amprocnum < 0 OR p1.amproc = 0;
|
OR a1.amprocnum < 0 OR a1.amproc = 0;
|
||||||
amprocfamily | amprocnum
|
amprocfamily | amprocnum
|
||||||
--------------+-----------
|
--------------+-----------
|
||||||
(0 rows)
|
(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
|
-- (else it suggests that the index ordering isn't fixed). But cross-type
|
||||||
-- members need only be stable, since they are just shorthands
|
-- members need only be stable, since they are just shorthands
|
||||||
-- for index probe queries.
|
-- for index probe queries.
|
||||||
SELECT p1.amprocfamily, p1.amproc, p2.prosrc
|
SELECT a1.amprocfamily, a1.amproc, p1.prosrc
|
||||||
FROM pg_amproc AS p1, pg_proc AS p2
|
FROM pg_amproc AS a1, pg_proc AS p1
|
||||||
WHERE p1.amproc = p2.oid AND
|
WHERE a1.amproc = p1.oid AND
|
||||||
p1.amproclefttype = p1.amprocrighttype AND
|
a1.amproclefttype = a1.amprocrighttype AND
|
||||||
p2.provolatile != 'i';
|
p1.provolatile != 'i';
|
||||||
amprocfamily | amproc | prosrc
|
amprocfamily | amproc | prosrc
|
||||||
--------------+--------+--------
|
--------------+--------+--------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
SELECT p1.amprocfamily, p1.amproc, p2.prosrc
|
SELECT a1.amprocfamily, a1.amproc, p1.prosrc
|
||||||
FROM pg_amproc AS p1, pg_proc AS p2
|
FROM pg_amproc AS a1, pg_proc AS p1
|
||||||
WHERE p1.amproc = p2.oid AND
|
WHERE a1.amproc = p1.oid AND
|
||||||
p1.amproclefttype != p1.amprocrighttype AND
|
a1.amproclefttype != a1.amprocrighttype AND
|
||||||
p2.provolatile = 'v';
|
p1.provolatile = 'v';
|
||||||
amprocfamily | amproc | prosrc
|
amprocfamily | amproc | prosrc
|
||||||
--------------+--------+--------
|
--------------+--------+--------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
@ -2186,17 +2186,17 @@ ORDER BY 1, 2, 3;
|
|||||||
|
|
||||||
-- **************** pg_index ****************
|
-- **************** pg_index ****************
|
||||||
-- Look for illegal values in pg_index fields.
|
-- Look for illegal values in pg_index fields.
|
||||||
SELECT p1.indexrelid, p1.indrelid
|
SELECT indexrelid, indrelid
|
||||||
FROM pg_index as p1
|
FROM pg_index
|
||||||
WHERE p1.indexrelid = 0 OR p1.indrelid = 0 OR
|
WHERE indexrelid = 0 OR indrelid = 0 OR
|
||||||
p1.indnatts <= 0 OR p1.indnatts > 32;
|
indnatts <= 0 OR indnatts > 32;
|
||||||
indexrelid | indrelid
|
indexrelid | indrelid
|
||||||
------------+----------
|
------------+----------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- oidvector and int2vector fields should be of length indnatts.
|
-- oidvector and int2vector fields should be of length indnatts.
|
||||||
SELECT p1.indexrelid, p1.indrelid
|
SELECT indexrelid, indrelid
|
||||||
FROM pg_index as p1
|
FROM pg_index
|
||||||
WHERE array_lower(indkey, 1) != 0 OR array_upper(indkey, 1) != indnatts-1 OR
|
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(indclass, 1) != 0 OR array_upper(indclass, 1) != indnatts-1 OR
|
||||||
array_lower(indcollation, 1) != 0 OR array_upper(indcollation, 1) != indnatts-1 OR
|
array_lower(indcollation, 1) != 0 OR array_upper(indcollation, 1) != indnatts-1 OR
|
||||||
|
@ -13,45 +13,45 @@
|
|||||||
-- field can't be 0, we have to check it here.
|
-- field can't be 0, we have to check it here.
|
||||||
-- **************** pg_type ****************
|
-- **************** pg_type ****************
|
||||||
-- Look for illegal values in pg_type fields.
|
-- Look for illegal values in pg_type fields.
|
||||||
SELECT p1.oid, p1.typname
|
SELECT t1.oid, t1.typname
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
WHERE p1.typnamespace = 0 OR
|
WHERE t1.typnamespace = 0 OR
|
||||||
(p1.typlen <= 0 AND p1.typlen != -1 AND p1.typlen != -2) OR
|
(t1.typlen <= 0 AND t1.typlen != -1 AND t1.typlen != -2) OR
|
||||||
(p1.typtype not in ('b', 'c', 'd', 'e', 'p', 'r', 'm')) OR
|
(t1.typtype not in ('b', 'c', 'd', 'e', 'p', 'r', 'm')) OR
|
||||||
NOT p1.typisdefined OR
|
NOT t1.typisdefined OR
|
||||||
(p1.typalign not in ('c', 's', 'i', 'd')) OR
|
(t1.typalign not in ('c', 's', 'i', 'd')) OR
|
||||||
(p1.typstorage not in ('p', 'x', 'e', 'm'));
|
(t1.typstorage not in ('p', 'x', 'e', 'm'));
|
||||||
oid | typname
|
oid | typname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Look for "pass by value" types that can't be passed by value.
|
-- Look for "pass by value" types that can't be passed by value.
|
||||||
SELECT p1.oid, p1.typname
|
SELECT t1.oid, t1.typname
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
WHERE p1.typbyval AND
|
WHERE t1.typbyval AND
|
||||||
(p1.typlen != 1 OR p1.typalign != 'c') AND
|
(t1.typlen != 1 OR t1.typalign != 'c') AND
|
||||||
(p1.typlen != 2 OR p1.typalign != 's') AND
|
(t1.typlen != 2 OR t1.typalign != 's') AND
|
||||||
(p1.typlen != 4 OR p1.typalign != 'i') AND
|
(t1.typlen != 4 OR t1.typalign != 'i') AND
|
||||||
(p1.typlen != 8 OR p1.typalign != 'd');
|
(t1.typlen != 8 OR t1.typalign != 'd');
|
||||||
oid | typname
|
oid | typname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Look for "toastable" types that aren't varlena.
|
-- Look for "toastable" types that aren't varlena.
|
||||||
SELECT p1.oid, p1.typname
|
SELECT t1.oid, t1.typname
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
WHERE p1.typstorage != 'p' AND
|
WHERE t1.typstorage != 'p' AND
|
||||||
(p1.typbyval OR p1.typlen != -1);
|
(t1.typbyval OR t1.typlen != -1);
|
||||||
oid | typname
|
oid | typname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Look for complex types that do not have a typrelid entry,
|
-- Look for complex types that do not have a typrelid entry,
|
||||||
-- or basic types that do.
|
-- or basic types that do.
|
||||||
SELECT p1.oid, p1.typname
|
SELECT t1.oid, t1.typname
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
|
WHERE (t1.typtype = 'c' AND t1.typrelid = 0) OR
|
||||||
(p1.typtype != 'c' AND p1.typrelid != 0);
|
(t1.typtype != 'c' AND t1.typrelid != 0);
|
||||||
oid | typname
|
oid | typname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(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.
|
-- Look for types that should have an array type but don't.
|
||||||
-- Generally anything that's not a pseudotype should have an array type.
|
-- Generally anything that's not a pseudotype should have an array type.
|
||||||
-- However, we do have a small number of exceptions.
|
-- However, we do have a small number of exceptions.
|
||||||
SELECT p1.oid, p1.typname
|
SELECT t1.oid, t1.typname
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
WHERE p1.typtype not in ('p') AND p1.typname NOT LIKE E'\\_%'
|
WHERE t1.typtype not in ('p') AND t1.typname NOT LIKE E'\\_%'
|
||||||
AND NOT EXISTS
|
AND NOT EXISTS
|
||||||
(SELECT 1 FROM pg_type as p2
|
(SELECT 1 FROM pg_type as t2
|
||||||
WHERE p2.typname = ('_' || p1.typname)::name AND
|
WHERE t2.typname = ('_' || t1.typname)::name AND
|
||||||
p2.typelem = p1.oid and p1.typarray = p2.oid)
|
t2.typelem = t1.oid and t1.typarray = t2.oid)
|
||||||
ORDER BY p1.oid;
|
ORDER BY t1.oid;
|
||||||
oid | typname
|
oid | typname
|
||||||
------+------------------------------
|
------+------------------------------
|
||||||
194 | pg_node_tree
|
194 | pg_node_tree
|
||||||
@ -78,56 +78,56 @@ ORDER BY p1.oid;
|
|||||||
(6 rows)
|
(6 rows)
|
||||||
|
|
||||||
-- Make sure typarray points to a "true" array type of our own base
|
-- Make sure typarray points to a "true" array type of our own base
|
||||||
SELECT p1.oid, p1.typname as basetype, p2.typname as arraytype,
|
SELECT t1.oid, t1.typname as basetype, t2.typname as arraytype,
|
||||||
p2.typsubscript
|
t2.typsubscript
|
||||||
FROM pg_type p1 LEFT JOIN pg_type p2 ON (p1.typarray = p2.oid)
|
FROM pg_type t1 LEFT JOIN pg_type t2 ON (t1.typarray = t2.oid)
|
||||||
WHERE p1.typarray <> 0 AND
|
WHERE t1.typarray <> 0 AND
|
||||||
(p2.oid IS NULL OR
|
(t2.oid IS NULL OR
|
||||||
p2.typsubscript <> 'array_subscript_handler'::regproc);
|
t2.typsubscript <> 'array_subscript_handler'::regproc);
|
||||||
oid | basetype | arraytype | typsubscript
|
oid | basetype | arraytype | typsubscript
|
||||||
-----+----------+-----------+--------------
|
-----+----------+-----------+--------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Look for range types that do not have a pg_range entry
|
-- Look for range types that do not have a pg_range entry
|
||||||
SELECT p1.oid, p1.typname
|
SELECT t1.oid, t1.typname
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
WHERE p1.typtype = 'r' AND
|
WHERE t1.typtype = 'r' AND
|
||||||
NOT EXISTS(SELECT 1 FROM pg_range r WHERE rngtypid = p1.oid);
|
NOT EXISTS(SELECT 1 FROM pg_range r WHERE rngtypid = t1.oid);
|
||||||
oid | typname
|
oid | typname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Look for range types whose typalign isn't sufficient
|
-- Look for range types whose typalign isn't sufficient
|
||||||
SELECT p1.oid, p1.typname, p1.typalign, p2.typname, p2.typalign
|
SELECT t1.oid, t1.typname, t1.typalign, t2.typname, t2.typalign
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
LEFT JOIN pg_range as r ON rngtypid = p1.oid
|
LEFT JOIN pg_range as r ON rngtypid = t1.oid
|
||||||
LEFT JOIN pg_type as p2 ON rngsubtype = p2.oid
|
LEFT JOIN pg_type as t2 ON rngsubtype = t2.oid
|
||||||
WHERE p1.typtype = 'r' AND
|
WHERE t1.typtype = 'r' AND
|
||||||
(p1.typalign != (CASE WHEN p2.typalign = 'd' THEN 'd'::"char"
|
(t1.typalign != (CASE WHEN t2.typalign = 'd' THEN 'd'::"char"
|
||||||
ELSE 'i'::"char" END)
|
ELSE 'i'::"char" END)
|
||||||
OR p2.oid IS NULL);
|
OR t2.oid IS NULL);
|
||||||
oid | typname | typalign | typname | typalign
|
oid | typname | typalign | typname | typalign
|
||||||
-----+---------+----------+---------+----------
|
-----+---------+----------+---------+----------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Text conversion routines must be provided.
|
-- Text conversion routines must be provided.
|
||||||
SELECT p1.oid, p1.typname
|
SELECT t1.oid, t1.typname
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
WHERE (p1.typinput = 0 OR p1.typoutput = 0);
|
WHERE (t1.typinput = 0 OR t1.typoutput = 0);
|
||||||
oid | typname
|
oid | typname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Check for bogus typinput routines
|
-- Check for bogus typinput routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typinput = p2.oid AND NOT
|
WHERE t1.typinput = p1.oid AND NOT
|
||||||
((p2.pronargs = 1 AND p2.proargtypes[0] = 'cstring'::regtype) OR
|
((p1.pronargs = 1 AND p1.proargtypes[0] = 'cstring'::regtype) OR
|
||||||
(p2.pronargs = 2 AND p2.proargtypes[0] = 'cstring'::regtype AND
|
(p1.pronargs = 2 AND p1.proargtypes[0] = 'cstring'::regtype AND
|
||||||
p2.proargtypes[1] = 'oid'::regtype) OR
|
p1.proargtypes[1] = 'oid'::regtype) OR
|
||||||
(p2.pronargs = 3 AND p2.proargtypes[0] = 'cstring'::regtype AND
|
(p1.pronargs = 3 AND p1.proargtypes[0] = 'cstring'::regtype AND
|
||||||
p2.proargtypes[1] = 'oid'::regtype AND
|
p1.proargtypes[1] = 'oid'::regtype AND
|
||||||
p2.proargtypes[2] = 'int4'::regtype));
|
p1.proargtypes[2] = 'int4'::regtype));
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(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
|
-- As of 8.0, this check finds refcursor, which is borrowing
|
||||||
-- other types' I/O routines
|
-- other types' I/O routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
|
WHERE t1.typinput = p1.oid AND t1.typtype in ('b', 'p') AND NOT
|
||||||
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
|
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
|
||||||
(p2.prorettype = p1.oid AND NOT p2.proretset)
|
(p1.prorettype = t1.oid AND NOT p1.proretset)
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
------+-----------+-----+---------
|
------+-----------+-----+---------
|
||||||
@ -178,11 +178,11 @@ ORDER BY 1;
|
|||||||
|
|
||||||
-- Varlena array types will point to array_in
|
-- Varlena array types will point to array_in
|
||||||
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
|
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typinput = p2.oid AND
|
WHERE t1.typinput = p1.oid AND
|
||||||
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
|
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
|
||||||
(p2.oid = 'array_in'::regproc)
|
(p1.oid = 'array_in'::regproc)
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
-----+------------+-----+--------------
|
-----+------------+-----+--------------
|
||||||
@ -191,17 +191,17 @@ ORDER BY 1;
|
|||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
-- typinput routines should not be volatile
|
-- typinput routines should not be volatile
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typinput = p2.oid AND p2.provolatile NOT IN ('i', 's');
|
WHERE t1.typinput = p1.oid AND p1.provolatile NOT IN ('i', 's');
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Composites, domains, enums, multiranges, ranges should all use the same input routines
|
-- Composites, domains, enums, multiranges, ranges should all use the same input routines
|
||||||
SELECT DISTINCT typtype, typinput
|
SELECT DISTINCT typtype, typinput
|
||||||
FROM pg_type AS p1
|
FROM pg_type AS t1
|
||||||
WHERE p1.typtype not in ('b', 'p')
|
WHERE t1.typtype not in ('b', 'p')
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
typtype | typinput
|
typtype | typinput
|
||||||
---------+---------------
|
---------+---------------
|
||||||
@ -215,39 +215,39 @@ ORDER BY 1;
|
|||||||
-- Check for bogus typoutput routines
|
-- Check for bogus typoutput routines
|
||||||
-- As of 8.0, this check finds refcursor, which is borrowing
|
-- As of 8.0, this check finds refcursor, which is borrowing
|
||||||
-- other types' I/O routines
|
-- other types' I/O routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
|
WHERE t1.typoutput = p1.oid AND t1.typtype in ('b', 'p') AND NOT
|
||||||
(p2.pronargs = 1 AND
|
(p1.pronargs = 1 AND
|
||||||
(p2.proargtypes[0] = p1.oid OR
|
(p1.proargtypes[0] = t1.oid OR
|
||||||
(p2.oid = 'array_out'::regproc AND
|
(p1.oid = 'array_out'::regproc AND
|
||||||
p1.typelem != 0 AND p1.typlen = -1)))
|
t1.typelem != 0 AND t1.typlen = -1)))
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
------+-----------+-----+---------
|
------+-----------+-----+---------
|
||||||
1790 | refcursor | 47 | textout
|
1790 | refcursor | 47 | textout
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typoutput = p2.oid AND NOT
|
WHERE t1.typoutput = p1.oid AND NOT
|
||||||
(p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
|
(p1.prorettype = 'cstring'::regtype AND NOT p1.proretset);
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- typoutput routines should not be volatile
|
-- typoutput routines should not be volatile
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typoutput = p2.oid AND p2.provolatile NOT IN ('i', 's');
|
WHERE t1.typoutput = p1.oid AND p1.provolatile NOT IN ('i', 's');
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Composites, enums, multiranges, ranges should all use the same output routines
|
-- Composites, enums, multiranges, ranges should all use the same output routines
|
||||||
SELECT DISTINCT typtype, typoutput
|
SELECT DISTINCT typtype, typoutput
|
||||||
FROM pg_type AS p1
|
FROM pg_type AS t1
|
||||||
WHERE p1.typtype not in ('b', 'd', 'p')
|
WHERE t1.typtype not in ('b', 'd', 'p')
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
typtype | typoutput
|
typtype | typoutput
|
||||||
---------+----------------
|
---------+----------------
|
||||||
@ -258,34 +258,34 @@ ORDER BY 1;
|
|||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
-- Domains should have same typoutput as their base types
|
-- Domains should have same typoutput as their base types
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.typname
|
SELECT t1.oid, t1.typname, t2.oid, t2.typname
|
||||||
FROM pg_type AS p1 LEFT JOIN pg_type AS p2 ON p1.typbasetype = p2.oid
|
FROM pg_type AS t1 LEFT JOIN pg_type AS t2 ON t1.typbasetype = t2.oid
|
||||||
WHERE p1.typtype = 'd' AND p1.typoutput IS DISTINCT FROM p2.typoutput;
|
WHERE t1.typtype = 'd' AND t1.typoutput IS DISTINCT FROM t2.typoutput;
|
||||||
oid | typname | oid | typname
|
oid | typname | oid | typname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Check for bogus typreceive routines
|
-- Check for bogus typreceive routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typreceive = p2.oid AND NOT
|
WHERE t1.typreceive = p1.oid AND NOT
|
||||||
((p2.pronargs = 1 AND p2.proargtypes[0] = 'internal'::regtype) OR
|
((p1.pronargs = 1 AND p1.proargtypes[0] = 'internal'::regtype) OR
|
||||||
(p2.pronargs = 2 AND p2.proargtypes[0] = 'internal'::regtype AND
|
(p1.pronargs = 2 AND p1.proargtypes[0] = 'internal'::regtype AND
|
||||||
p2.proargtypes[1] = 'oid'::regtype) OR
|
p1.proargtypes[1] = 'oid'::regtype) OR
|
||||||
(p2.pronargs = 3 AND p2.proargtypes[0] = 'internal'::regtype AND
|
(p1.pronargs = 3 AND p1.proargtypes[0] = 'internal'::regtype AND
|
||||||
p2.proargtypes[1] = 'oid'::regtype AND
|
p1.proargtypes[1] = 'oid'::regtype AND
|
||||||
p2.proargtypes[2] = 'int4'::regtype));
|
p1.proargtypes[2] = 'int4'::regtype));
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- As of 7.4, this check finds refcursor, which is borrowing
|
-- As of 7.4, this check finds refcursor, which is borrowing
|
||||||
-- other types' I/O routines
|
-- other types' I/O routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND NOT
|
WHERE t1.typreceive = p1.oid AND t1.typtype in ('b', 'p') AND NOT
|
||||||
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
|
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
|
||||||
(p2.prorettype = p1.oid AND NOT p2.proretset)
|
(p1.prorettype = t1.oid AND NOT p1.proretset)
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
------+-----------+------+----------
|
------+-----------+------+----------
|
||||||
@ -294,11 +294,11 @@ ORDER BY 1;
|
|||||||
|
|
||||||
-- Varlena array types will point to array_recv
|
-- Varlena array types will point to array_recv
|
||||||
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
|
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typreceive = p2.oid AND
|
WHERE t1.typreceive = p1.oid AND
|
||||||
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
|
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
|
||||||
(p2.oid = 'array_recv'::regproc)
|
(p1.oid = 'array_recv'::regproc)
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
-----+------------+------+----------------
|
-----+------------+------+----------------
|
||||||
@ -307,26 +307,26 @@ ORDER BY 1;
|
|||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
-- Suspicious if typreceive doesn't take same number of args as typinput
|
-- 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
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname, p2.oid, p2.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2, pg_proc AS p3
|
FROM pg_type AS t1, pg_proc AS p1, pg_proc AS p2
|
||||||
WHERE p1.typinput = p2.oid AND p1.typreceive = p3.oid AND
|
WHERE t1.typinput = p1.oid AND t1.typreceive = p2.oid AND
|
||||||
p2.pronargs != p3.pronargs;
|
p1.pronargs != p2.pronargs;
|
||||||
oid | typname | oid | proname | oid | proname
|
oid | typname | oid | proname | oid | proname
|
||||||
-----+---------+-----+---------+-----+---------
|
-----+---------+-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- typreceive routines should not be volatile
|
-- typreceive routines should not be volatile
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typreceive = p2.oid AND p2.provolatile NOT IN ('i', 's');
|
WHERE t1.typreceive = p1.oid AND p1.provolatile NOT IN ('i', 's');
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Composites, domains, enums, multiranges, ranges should all use the same receive routines
|
-- Composites, domains, enums, multiranges, ranges should all use the same receive routines
|
||||||
SELECT DISTINCT typtype, typreceive
|
SELECT DISTINCT typtype, typreceive
|
||||||
FROM pg_type AS p1
|
FROM pg_type AS t1
|
||||||
WHERE p1.typtype not in ('b', 'p')
|
WHERE t1.typtype not in ('b', 'p')
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
typtype | typreceive
|
typtype | typreceive
|
||||||
---------+-----------------
|
---------+-----------------
|
||||||
@ -340,39 +340,39 @@ ORDER BY 1;
|
|||||||
-- Check for bogus typsend routines
|
-- Check for bogus typsend routines
|
||||||
-- As of 7.4, this check finds refcursor, which is borrowing
|
-- As of 7.4, this check finds refcursor, which is borrowing
|
||||||
-- other types' I/O routines
|
-- other types' I/O routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
|
WHERE t1.typsend = p1.oid AND t1.typtype in ('b', 'p') AND NOT
|
||||||
(p2.pronargs = 1 AND
|
(p1.pronargs = 1 AND
|
||||||
(p2.proargtypes[0] = p1.oid OR
|
(p1.proargtypes[0] = t1.oid OR
|
||||||
(p2.oid = 'array_send'::regproc AND
|
(p1.oid = 'array_send'::regproc AND
|
||||||
p1.typelem != 0 AND p1.typlen = -1)))
|
t1.typelem != 0 AND t1.typlen = -1)))
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
------+-----------+------+----------
|
------+-----------+------+----------
|
||||||
1790 | refcursor | 2415 | textsend
|
1790 | refcursor | 2415 | textsend
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typsend = p2.oid AND NOT
|
WHERE t1.typsend = p1.oid AND NOT
|
||||||
(p2.prorettype = 'bytea'::regtype AND NOT p2.proretset);
|
(p1.prorettype = 'bytea'::regtype AND NOT p1.proretset);
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- typsend routines should not be volatile
|
-- typsend routines should not be volatile
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typsend = p2.oid AND p2.provolatile NOT IN ('i', 's');
|
WHERE t1.typsend = p1.oid AND p1.provolatile NOT IN ('i', 's');
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Composites, enums, multiranges, ranges should all use the same send routines
|
-- Composites, enums, multiranges, ranges should all use the same send routines
|
||||||
SELECT DISTINCT typtype, typsend
|
SELECT DISTINCT typtype, typsend
|
||||||
FROM pg_type AS p1
|
FROM pg_type AS t1
|
||||||
WHERE p1.typtype not in ('b', 'd', 'p')
|
WHERE t1.typtype not in ('b', 'd', 'p')
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
typtype | typsend
|
typtype | typsend
|
||||||
---------+-----------------
|
---------+-----------------
|
||||||
@ -383,112 +383,112 @@ ORDER BY 1;
|
|||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
-- Domains should have same typsend as their base types
|
-- Domains should have same typsend as their base types
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.typname
|
SELECT t1.oid, t1.typname, t2.oid, t2.typname
|
||||||
FROM pg_type AS p1 LEFT JOIN pg_type AS p2 ON p1.typbasetype = p2.oid
|
FROM pg_type AS t1 LEFT JOIN pg_type AS t2 ON t1.typbasetype = t2.oid
|
||||||
WHERE p1.typtype = 'd' AND p1.typsend IS DISTINCT FROM p2.typsend;
|
WHERE t1.typtype = 'd' AND t1.typsend IS DISTINCT FROM t2.typsend;
|
||||||
oid | typname | oid | typname
|
oid | typname | oid | typname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Check for bogus typmodin routines
|
-- Check for bogus typmodin routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typmodin = p2.oid AND NOT
|
WHERE t1.typmodin = p1.oid AND NOT
|
||||||
(p2.pronargs = 1 AND
|
(p1.pronargs = 1 AND
|
||||||
p2.proargtypes[0] = 'cstring[]'::regtype AND
|
p1.proargtypes[0] = 'cstring[]'::regtype AND
|
||||||
p2.prorettype = 'int4'::regtype AND NOT p2.proretset);
|
p1.prorettype = 'int4'::regtype AND NOT p1.proretset);
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- typmodin routines should not be volatile
|
-- typmodin routines should not be volatile
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typmodin = p2.oid AND p2.provolatile NOT IN ('i', 's');
|
WHERE t1.typmodin = p1.oid AND p1.provolatile NOT IN ('i', 's');
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Check for bogus typmodout routines
|
-- Check for bogus typmodout routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typmodout = p2.oid AND NOT
|
WHERE t1.typmodout = p1.oid AND NOT
|
||||||
(p2.pronargs = 1 AND
|
(p1.pronargs = 1 AND
|
||||||
p2.proargtypes[0] = 'int4'::regtype AND
|
p1.proargtypes[0] = 'int4'::regtype AND
|
||||||
p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
|
p1.prorettype = 'cstring'::regtype AND NOT p1.proretset);
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- typmodout routines should not be volatile
|
-- typmodout routines should not be volatile
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typmodout = p2.oid AND p2.provolatile NOT IN ('i', 's');
|
WHERE t1.typmodout = p1.oid AND p1.provolatile NOT IN ('i', 's');
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Array types should have same typmodin/out as their element types
|
-- Array types should have same typmodin/out as their element types
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.typname
|
SELECT t1.oid, t1.typname, t2.oid, t2.typname
|
||||||
FROM pg_type AS p1, pg_type AS p2
|
FROM pg_type AS t1, pg_type AS t2
|
||||||
WHERE p1.typelem = p2.oid AND NOT
|
WHERE t1.typelem = t2.oid AND NOT
|
||||||
(p1.typmodin = p2.typmodin AND p1.typmodout = p2.typmodout);
|
(t1.typmodin = t2.typmodin AND t1.typmodout = t2.typmodout);
|
||||||
oid | typname | oid | typname
|
oid | typname | oid | typname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Array types should have same typdelim as their element types
|
-- Array types should have same typdelim as their element types
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.typname
|
SELECT t1.oid, t1.typname, t2.oid, t2.typname
|
||||||
FROM pg_type AS p1, pg_type AS p2
|
FROM pg_type AS t1, pg_type AS t2
|
||||||
WHERE p1.typarray = p2.oid AND NOT (p1.typdelim = p2.typdelim);
|
WHERE t1.typarray = t2.oid AND NOT (t1.typdelim = t2.typdelim);
|
||||||
oid | typname | oid | typname
|
oid | typname | oid | typname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Look for array types whose typalign isn't sufficient
|
-- Look for array types whose typalign isn't sufficient
|
||||||
SELECT p1.oid, p1.typname, p1.typalign, p2.typname, p2.typalign
|
SELECT t1.oid, t1.typname, t1.typalign, t2.typname, t2.typalign
|
||||||
FROM pg_type AS p1, pg_type AS p2
|
FROM pg_type AS t1, pg_type AS t2
|
||||||
WHERE p1.typarray = p2.oid AND
|
WHERE t1.typarray = t2.oid AND
|
||||||
p2.typalign != (CASE WHEN p1.typalign = 'd' THEN 'd'::"char"
|
t2.typalign != (CASE WHEN t1.typalign = 'd' THEN 'd'::"char"
|
||||||
ELSE 'i'::"char" END);
|
ELSE 'i'::"char" END);
|
||||||
oid | typname | typalign | typname | typalign
|
oid | typname | typalign | typname | typalign
|
||||||
-----+---------+----------+---------+----------
|
-----+---------+----------+---------+----------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Check for typelem set without a handler
|
-- Check for typelem set without a handler
|
||||||
SELECT p1.oid, p1.typname, p1.typelem
|
SELECT t1.oid, t1.typname, t1.typelem
|
||||||
FROM pg_type AS p1
|
FROM pg_type AS t1
|
||||||
WHERE p1.typelem != 0 AND p1.typsubscript = 0;
|
WHERE t1.typelem != 0 AND t1.typsubscript = 0;
|
||||||
oid | typname | typelem
|
oid | typname | typelem
|
||||||
-----+---------+---------
|
-----+---------+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Check for misuse of standard subscript handlers
|
-- Check for misuse of standard subscript handlers
|
||||||
SELECT p1.oid, p1.typname,
|
SELECT t1.oid, t1.typname,
|
||||||
p1.typelem, p1.typlen, p1.typbyval
|
t1.typelem, t1.typlen, t1.typbyval
|
||||||
FROM pg_type AS p1
|
FROM pg_type AS t1
|
||||||
WHERE p1.typsubscript = 'array_subscript_handler'::regproc AND NOT
|
WHERE t1.typsubscript = 'array_subscript_handler'::regproc AND NOT
|
||||||
(p1.typelem != 0 AND p1.typlen = -1 AND NOT p1.typbyval);
|
(t1.typelem != 0 AND t1.typlen = -1 AND NOT t1.typbyval);
|
||||||
oid | typname | typelem | typlen | typbyval
|
oid | typname | typelem | typlen | typbyval
|
||||||
-----+---------+---------+--------+----------
|
-----+---------+---------+--------+----------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname,
|
SELECT t1.oid, t1.typname,
|
||||||
p1.typelem, p1.typlen, p1.typbyval
|
t1.typelem, t1.typlen, t1.typbyval
|
||||||
FROM pg_type AS p1
|
FROM pg_type AS t1
|
||||||
WHERE p1.typsubscript = 'raw_array_subscript_handler'::regproc AND NOT
|
WHERE t1.typsubscript = 'raw_array_subscript_handler'::regproc AND NOT
|
||||||
(p1.typelem != 0 AND p1.typlen > 0 AND NOT p1.typbyval);
|
(t1.typelem != 0 AND t1.typlen > 0 AND NOT t1.typbyval);
|
||||||
oid | typname | typelem | typlen | typbyval
|
oid | typname | typelem | typlen | typbyval
|
||||||
-----+---------+---------+--------+----------
|
-----+---------+---------+--------+----------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Check for bogus typanalyze routines
|
-- Check for bogus typanalyze routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typanalyze = p2.oid AND NOT
|
WHERE t1.typanalyze = p1.oid AND NOT
|
||||||
(p2.pronargs = 1 AND
|
(p1.pronargs = 1 AND
|
||||||
p2.proargtypes[0] = 'internal'::regtype AND
|
p1.proargtypes[0] = 'internal'::regtype AND
|
||||||
p2.prorettype = 'bool'::regtype AND NOT p2.proretset);
|
p1.prorettype = 'bool'::regtype AND NOT p1.proretset);
|
||||||
oid | typname | oid | proname
|
oid | typname | oid | proname
|
||||||
-----+---------+-----+---------
|
-----+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
@ -529,8 +529,8 @@ ORDER BY 1;
|
|||||||
|
|
||||||
-- **************** pg_class ****************
|
-- **************** pg_class ****************
|
||||||
-- Look for illegal values in pg_class fields
|
-- Look for illegal values in pg_class fields
|
||||||
SELECT p1.oid, p1.relname
|
SELECT c1.oid, c1.relname
|
||||||
FROM pg_class as p1
|
FROM pg_class as c1
|
||||||
WHERE relkind NOT IN ('r', 'i', 'S', 't', 'v', 'm', 'c', 'f', 'p') OR
|
WHERE relkind NOT IN ('r', 'i', 'S', 't', 'v', 'm', 'c', 'f', 'p') OR
|
||||||
relpersistence NOT IN ('p', 'u', 't') OR
|
relpersistence NOT IN ('p', 'u', 't') OR
|
||||||
relreplident NOT IN ('d', 'n', 'f', 'i');
|
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)
|
(0 rows)
|
||||||
|
|
||||||
-- All tables and indexes should have an access method.
|
-- All tables and indexes should have an access method.
|
||||||
SELECT p1.oid, p1.relname
|
SELECT c1.oid, c1.relname
|
||||||
FROM pg_class as p1
|
FROM pg_class as c1
|
||||||
WHERE p1.relkind NOT IN ('S', 'v', 'f', 'c') and
|
WHERE c1.relkind NOT IN ('S', 'v', 'f', 'c') and
|
||||||
p1.relam = 0;
|
c1.relam = 0;
|
||||||
oid | relname
|
oid | relname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Conversely, sequences, views, types shouldn't have them
|
-- Conversely, sequences, views, types shouldn't have them
|
||||||
SELECT p1.oid, p1.relname
|
SELECT c1.oid, c1.relname
|
||||||
FROM pg_class as p1
|
FROM pg_class as c1
|
||||||
WHERE p1.relkind IN ('S', 'v', 'f', 'c') and
|
WHERE c1.relkind IN ('S', 'v', 'f', 'c') and
|
||||||
p1.relam != 0;
|
c1.relam != 0;
|
||||||
oid | relname
|
oid | relname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
@ -576,29 +576,29 @@ WHERE pc.relkind IN ('r', 't', 'm') and
|
|||||||
|
|
||||||
-- **************** pg_attribute ****************
|
-- **************** pg_attribute ****************
|
||||||
-- Look for illegal values in pg_attribute fields
|
-- Look for illegal values in pg_attribute fields
|
||||||
SELECT p1.attrelid, p1.attname
|
SELECT a1.attrelid, a1.attname
|
||||||
FROM pg_attribute as p1
|
FROM pg_attribute as a1
|
||||||
WHERE p1.attrelid = 0 OR p1.atttypid = 0 OR p1.attnum = 0 OR
|
WHERE a1.attrelid = 0 OR a1.atttypid = 0 OR a1.attnum = 0 OR
|
||||||
p1.attcacheoff != -1 OR p1.attinhcount < 0 OR
|
a1.attcacheoff != -1 OR a1.attinhcount < 0 OR
|
||||||
(p1.attinhcount = 0 AND NOT p1.attislocal);
|
(a1.attinhcount = 0 AND NOT a1.attislocal);
|
||||||
attrelid | attname
|
attrelid | attname
|
||||||
----------+---------
|
----------+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Cross-check attnum against parent relation
|
-- Cross-check attnum against parent relation
|
||||||
SELECT p1.attrelid, p1.attname, p2.oid, p2.relname
|
SELECT a1.attrelid, a1.attname, c1.oid, c1.relname
|
||||||
FROM pg_attribute AS p1, pg_class AS p2
|
FROM pg_attribute AS a1, pg_class AS c1
|
||||||
WHERE p1.attrelid = p2.oid AND p1.attnum > p2.relnatts;
|
WHERE a1.attrelid = c1.oid AND a1.attnum > c1.relnatts;
|
||||||
attrelid | attname | oid | relname
|
attrelid | attname | oid | relname
|
||||||
----------+---------+-----+---------
|
----------+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- Detect missing pg_attribute entries: should have as many non-system
|
-- Detect missing pg_attribute entries: should have as many non-system
|
||||||
-- attributes as parent relation expects
|
-- attributes as parent relation expects
|
||||||
SELECT p1.oid, p1.relname
|
SELECT c1.oid, c1.relname
|
||||||
FROM pg_class AS p1
|
FROM pg_class AS c1
|
||||||
WHERE p1.relnatts != (SELECT count(*) FROM pg_attribute AS p2
|
WHERE c1.relnatts != (SELECT count(*) FROM pg_attribute AS a1
|
||||||
WHERE p2.attrelid = p1.oid AND p2.attnum > 0);
|
WHERE a1.attrelid = c1.oid AND a1.attnum > 0);
|
||||||
oid | relname
|
oid | relname
|
||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
@ -606,29 +606,29 @@ WHERE p1.relnatts != (SELECT count(*) FROM pg_attribute AS p2
|
|||||||
-- Cross-check against pg_type entry
|
-- Cross-check against pg_type entry
|
||||||
-- NOTE: we allow attstorage to be 'plain' even when typstorage is not;
|
-- NOTE: we allow attstorage to be 'plain' even when typstorage is not;
|
||||||
-- this is mainly for toast tables.
|
-- this is mainly for toast tables.
|
||||||
SELECT p1.attrelid, p1.attname, p2.oid, p2.typname
|
SELECT a1.attrelid, a1.attname, t1.oid, t1.typname
|
||||||
FROM pg_attribute AS p1, pg_type AS p2
|
FROM pg_attribute AS a1, pg_type AS t1
|
||||||
WHERE p1.atttypid = p2.oid AND
|
WHERE a1.atttypid = t1.oid AND
|
||||||
(p1.attlen != p2.typlen OR
|
(a1.attlen != t1.typlen OR
|
||||||
p1.attalign != p2.typalign OR
|
a1.attalign != t1.typalign OR
|
||||||
p1.attbyval != p2.typbyval OR
|
a1.attbyval != t1.typbyval OR
|
||||||
(p1.attstorage != p2.typstorage AND p1.attstorage != 'p'));
|
(a1.attstorage != t1.typstorage AND a1.attstorage != 'p'));
|
||||||
attrelid | attname | oid | typname
|
attrelid | attname | oid | typname
|
||||||
----------+---------+-----+---------
|
----------+---------+-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- **************** pg_range ****************
|
-- **************** pg_range ****************
|
||||||
-- Look for illegal values in pg_range fields.
|
-- Look for illegal values in pg_range fields.
|
||||||
SELECT p1.rngtypid, p1.rngsubtype
|
SELECT r.rngtypid, r.rngsubtype
|
||||||
FROM pg_range as p1
|
FROM pg_range as r
|
||||||
WHERE p1.rngtypid = 0 OR p1.rngsubtype = 0 OR p1.rngsubopc = 0;
|
WHERE r.rngtypid = 0 OR r.rngsubtype = 0 OR r.rngsubopc = 0;
|
||||||
rngtypid | rngsubtype
|
rngtypid | rngsubtype
|
||||||
----------+------------
|
----------+------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- rngcollation should be specified iff subtype is collatable
|
-- rngcollation should be specified iff subtype is collatable
|
||||||
SELECT p1.rngtypid, p1.rngsubtype, p1.rngcollation, t.typcollation
|
SELECT r.rngtypid, r.rngsubtype, r.rngcollation, t.typcollation
|
||||||
FROM pg_range p1 JOIN pg_type t ON t.oid = p1.rngsubtype
|
FROM pg_range r JOIN pg_type t ON t.oid = r.rngsubtype
|
||||||
WHERE (rngcollation = 0) != (typcollation = 0);
|
WHERE (rngcollation = 0) != (typcollation = 0);
|
||||||
rngtypid | rngsubtype | rngcollation | typcollation
|
rngtypid | rngsubtype | rngcollation | typcollation
|
||||||
----------+------------+--------------+--------------
|
----------+------------+--------------+--------------
|
||||||
@ -636,29 +636,29 @@ WHERE (rngcollation = 0) != (typcollation = 0);
|
|||||||
|
|
||||||
-- opclass had better be a btree opclass accepting the subtype.
|
-- opclass had better be a btree opclass accepting the subtype.
|
||||||
-- We must allow anyarray matches, cf IsBinaryCoercible()
|
-- We must allow anyarray matches, cf IsBinaryCoercible()
|
||||||
SELECT p1.rngtypid, p1.rngsubtype, o.opcmethod, o.opcname
|
SELECT r.rngtypid, r.rngsubtype, o.opcmethod, o.opcname
|
||||||
FROM pg_range p1 JOIN pg_opclass o ON o.oid = p1.rngsubopc
|
FROM pg_range r JOIN pg_opclass o ON o.oid = r.rngsubopc
|
||||||
WHERE o.opcmethod != 403 OR
|
WHERE o.opcmethod != 403 OR
|
||||||
((o.opcintype != p1.rngsubtype) AND NOT
|
((o.opcintype != r.rngsubtype) AND NOT
|
||||||
(o.opcintype = 'pg_catalog.anyarray'::regtype AND
|
(o.opcintype = 'pg_catalog.anyarray'::regtype AND
|
||||||
EXISTS(select 1 from pg_catalog.pg_type where
|
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)));
|
typsubscript = 'array_subscript_handler'::regproc)));
|
||||||
rngtypid | rngsubtype | opcmethod | opcname
|
rngtypid | rngsubtype | opcmethod | opcname
|
||||||
----------+------------+-----------+---------
|
----------+------------+-----------+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- canonical function, if any, had better match the range type
|
-- canonical function, if any, had better match the range type
|
||||||
SELECT p1.rngtypid, p1.rngsubtype, p.proname
|
SELECT r.rngtypid, r.rngsubtype, p.proname
|
||||||
FROM pg_range p1 JOIN pg_proc p ON p.oid = p1.rngcanonical
|
FROM pg_range r JOIN pg_proc p ON p.oid = r.rngcanonical
|
||||||
WHERE pronargs != 1 OR proargtypes[0] != rngtypid OR prorettype != rngtypid;
|
WHERE pronargs != 1 OR proargtypes[0] != rngtypid OR prorettype != rngtypid;
|
||||||
rngtypid | rngsubtype | proname
|
rngtypid | rngsubtype | proname
|
||||||
----------+------------+---------
|
----------+------------+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- subdiff function, if any, had better match the subtype
|
-- subdiff function, if any, had better match the subtype
|
||||||
SELECT p1.rngtypid, p1.rngsubtype, p.proname
|
SELECT r.rngtypid, r.rngsubtype, p.proname
|
||||||
FROM pg_range p1 JOIN pg_proc p ON p.oid = p1.rngsubdiff
|
FROM pg_range r JOIN pg_proc p ON p.oid = r.rngsubdiff
|
||||||
WHERE pronargs != 2
|
WHERE pronargs != 2
|
||||||
OR proargtypes[0] != rngsubtype OR proargtypes[1] != rngsubtype
|
OR proargtypes[0] != rngsubtype OR proargtypes[1] != rngsubtype
|
||||||
OR prorettype != 'pg_catalog.float8'::regtype;
|
OR prorettype != 'pg_catalog.float8'::regtype;
|
||||||
@ -667,9 +667,9 @@ WHERE pronargs != 2
|
|||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- every range should have a valid multirange
|
-- every range should have a valid multirange
|
||||||
SELECT p1.rngtypid, p1.rngsubtype, p1.rngmultitypid
|
SELECT r.rngtypid, r.rngsubtype, r.rngmultitypid
|
||||||
FROM pg_range p1
|
FROM pg_range r
|
||||||
WHERE p1.rngmultitypid IS NULL OR p1.rngmultitypid = 0;
|
WHERE r.rngmultitypid IS NULL OR r.rngmultitypid = 0;
|
||||||
rngtypid | rngsubtype | rngmultitypid
|
rngtypid | rngsubtype | rngmultitypid
|
||||||
----------+------------+---------------
|
----------+------------+---------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
@ -489,9 +489,9 @@ WHERE c.castmethod = 'b' AND
|
|||||||
|
|
||||||
-- Look for illegal values in pg_conversion fields.
|
-- Look for illegal values in pg_conversion fields.
|
||||||
|
|
||||||
SELECT p1.oid, p1.conname
|
SELECT c.oid, c.conname
|
||||||
FROM pg_conversion as p1
|
FROM pg_conversion as c
|
||||||
WHERE p1.conproc = 0 OR
|
WHERE c.conproc = 0 OR
|
||||||
pg_encoding_to_char(conforencoding) = '' OR
|
pg_encoding_to_char(conforencoding) = '' OR
|
||||||
pg_encoding_to_char(contoencoding) = '';
|
pg_encoding_to_char(contoencoding) = '';
|
||||||
|
|
||||||
@ -519,8 +519,8 @@ WHERE p.oid = c.conproc AND
|
|||||||
-- conversions anyway.
|
-- conversions anyway.
|
||||||
-- (Similarly, this doesn't cope with any search path issues.)
|
-- (Similarly, this doesn't cope with any search path issues.)
|
||||||
|
|
||||||
SELECT p1.oid, p1.conname
|
SELECT c.oid, c.conname
|
||||||
FROM pg_conversion as p1
|
FROM pg_conversion as c
|
||||||
WHERE condefault AND
|
WHERE condefault AND
|
||||||
convert('ABC'::bytea, pg_encoding_to_char(conforencoding),
|
convert('ABC'::bytea, pg_encoding_to_char(conforencoding),
|
||||||
pg_encoding_to_char(contoencoding)) != 'ABC';
|
pg_encoding_to_char(contoencoding)) != 'ABC';
|
||||||
@ -530,42 +530,42 @@ WHERE condefault AND
|
|||||||
|
|
||||||
-- Look for illegal values in pg_operator fields.
|
-- Look for illegal values in pg_operator fields.
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprname
|
SELECT o1.oid, o1.oprname
|
||||||
FROM pg_operator as p1
|
FROM pg_operator as o1
|
||||||
WHERE (p1.oprkind != 'b' AND p1.oprkind != 'l') OR
|
WHERE (o1.oprkind != 'b' AND o1.oprkind != 'l') OR
|
||||||
p1.oprresult = 0 OR p1.oprcode = 0;
|
o1.oprresult = 0 OR o1.oprcode = 0;
|
||||||
|
|
||||||
-- Look for missing or unwanted operand types
|
-- Look for missing or unwanted operand types
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprname
|
SELECT o1.oid, o1.oprname
|
||||||
FROM pg_operator as p1
|
FROM pg_operator as o1
|
||||||
WHERE (p1.oprleft = 0 and p1.oprkind != 'l') OR
|
WHERE (o1.oprleft = 0 and o1.oprkind != 'l') OR
|
||||||
(p1.oprleft != 0 and p1.oprkind = 'l') OR
|
(o1.oprleft != 0 and o1.oprkind = 'l') OR
|
||||||
p1.oprright = 0;
|
o1.oprright = 0;
|
||||||
|
|
||||||
-- Look for conflicting operator definitions (same names and input datatypes).
|
-- Look for conflicting operator definitions (same names and input datatypes).
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
|
SELECT o1.oid, o1.oprcode, o2.oid, o2.oprcode
|
||||||
FROM pg_operator AS p1, pg_operator AS p2
|
FROM pg_operator AS o1, pg_operator AS o2
|
||||||
WHERE p1.oid != p2.oid AND
|
WHERE o1.oid != o2.oid AND
|
||||||
p1.oprname = p2.oprname AND
|
o1.oprname = o2.oprname AND
|
||||||
p1.oprkind = p2.oprkind AND
|
o1.oprkind = o2.oprkind AND
|
||||||
p1.oprleft = p2.oprleft AND
|
o1.oprleft = o2.oprleft AND
|
||||||
p1.oprright = p2.oprright;
|
o1.oprright = o2.oprright;
|
||||||
|
|
||||||
-- Look for commutative operators that don't commute.
|
-- 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.
|
-- 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
|
-- 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.
|
-- inherently essential, but it would be inefficient not to mark it so.
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
|
SELECT o1.oid, o1.oprcode, o2.oid, o2.oprcode
|
||||||
FROM pg_operator AS p1, pg_operator AS p2
|
FROM pg_operator AS o1, pg_operator AS o2
|
||||||
WHERE p1.oprcom = p2.oid AND
|
WHERE o1.oprcom = o2.oid AND
|
||||||
(p1.oprkind != 'b' OR
|
(o1.oprkind != 'b' OR
|
||||||
p1.oprleft != p2.oprright OR
|
o1.oprleft != o2.oprright OR
|
||||||
p1.oprright != p2.oprleft OR
|
o1.oprright != o2.oprleft OR
|
||||||
p1.oprresult != p2.oprresult OR
|
o1.oprresult != o2.oprresult OR
|
||||||
p1.oid != p2.oprcom);
|
o1.oid != o2.oprcom);
|
||||||
|
|
||||||
-- Look for negatory operators that don't agree.
|
-- Look for negatory operators that don't agree.
|
||||||
-- DEFINITIONAL NOTE: If A.oprnegate = B, then both A and B must yield
|
-- 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.
|
-- inherently essential, but it would be inefficient not to mark it so.
|
||||||
-- Also, A and B had better not be the same operator.
|
-- Also, A and B had better not be the same operator.
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
|
SELECT o1.oid, o1.oprcode, o2.oid, o2.oprcode
|
||||||
FROM pg_operator AS p1, pg_operator AS p2
|
FROM pg_operator AS o1, pg_operator AS o2
|
||||||
WHERE p1.oprnegate = p2.oid AND
|
WHERE o1.oprnegate = o2.oid AND
|
||||||
(p1.oprkind != p2.oprkind OR
|
(o1.oprkind != o2.oprkind OR
|
||||||
p1.oprleft != p2.oprleft OR
|
o1.oprleft != o2.oprleft OR
|
||||||
p1.oprright != p2.oprright OR
|
o1.oprright != o2.oprright OR
|
||||||
p1.oprresult != 'bool'::regtype OR
|
o1.oprresult != 'bool'::regtype OR
|
||||||
p2.oprresult != 'bool'::regtype OR
|
o2.oprresult != 'bool'::regtype OR
|
||||||
p1.oid != p2.oprnegate OR
|
o1.oid != o2.oprnegate OR
|
||||||
p1.oid = p2.oid);
|
o1.oid = o2.oid);
|
||||||
|
|
||||||
-- Make a list of the names of operators that are claimed to be commutator
|
-- 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
|
-- 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
|
-- boolean, and must have a commutator (itself, unless it's a cross-type
|
||||||
-- operator).
|
-- operator).
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprname FROM pg_operator AS p1
|
SELECT o1.oid, o1.oprname FROM pg_operator AS o1
|
||||||
WHERE (p1.oprcanmerge OR p1.oprcanhash) AND NOT
|
WHERE (o1.oprcanmerge OR o1.oprcanhash) AND NOT
|
||||||
(p1.oprkind = 'b' AND p1.oprresult = 'bool'::regtype AND p1.oprcom != 0);
|
(o1.oprkind = 'b' AND o1.oprresult = 'bool'::regtype AND o1.oprcom != 0);
|
||||||
|
|
||||||
-- What's more, the commutator had better be mergejoinable/hashjoinable too.
|
-- What's more, the commutator had better be mergejoinable/hashjoinable too.
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprname, p2.oid, p2.oprname
|
SELECT o1.oid, o1.oprname, o2.oid, o2.oprname
|
||||||
FROM pg_operator AS p1, pg_operator AS p2
|
FROM pg_operator AS o1, pg_operator AS o2
|
||||||
WHERE p1.oprcom = p2.oid AND
|
WHERE o1.oprcom = o2.oid AND
|
||||||
(p1.oprcanmerge != p2.oprcanmerge OR
|
(o1.oprcanmerge != o2.oprcanmerge OR
|
||||||
p1.oprcanhash != p2.oprcanhash);
|
o1.oprcanhash != o2.oprcanhash);
|
||||||
|
|
||||||
-- Mergejoinable operators should appear as equality members of btree index
|
-- Mergejoinable operators should appear as equality members of btree index
|
||||||
-- opfamilies.
|
-- opfamilies.
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprname
|
SELECT o1.oid, o1.oprname
|
||||||
FROM pg_operator AS p1
|
FROM pg_operator AS o1
|
||||||
WHERE p1.oprcanmerge AND NOT EXISTS
|
WHERE o1.oprcanmerge AND NOT EXISTS
|
||||||
(SELECT 1 FROM pg_amop
|
(SELECT 1 FROM pg_amop
|
||||||
WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
|
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.
|
-- And the converse.
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprname, p.amopfamily
|
SELECT o1.oid, o1.oprname, p.amopfamily
|
||||||
FROM pg_operator AS p1, pg_amop p
|
FROM pg_operator AS o1, pg_amop p
|
||||||
WHERE amopopr = p1.oid
|
WHERE amopopr = o1.oid
|
||||||
AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
|
AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
|
||||||
AND amopstrategy = 3
|
AND amopstrategy = 3
|
||||||
AND NOT p1.oprcanmerge;
|
AND NOT o1.oprcanmerge;
|
||||||
|
|
||||||
-- Hashable operators should appear as members of hash index opfamilies.
|
-- Hashable operators should appear as members of hash index opfamilies.
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprname
|
SELECT o1.oid, o1.oprname
|
||||||
FROM pg_operator AS p1
|
FROM pg_operator AS o1
|
||||||
WHERE p1.oprcanhash AND NOT EXISTS
|
WHERE o1.oprcanhash AND NOT EXISTS
|
||||||
(SELECT 1 FROM pg_amop
|
(SELECT 1 FROM pg_amop
|
||||||
WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash') AND
|
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.
|
-- And the converse.
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprname, p.amopfamily
|
SELECT o1.oid, o1.oprname, p.amopfamily
|
||||||
FROM pg_operator AS p1, pg_amop p
|
FROM pg_operator AS o1, pg_amop p
|
||||||
WHERE amopopr = p1.oid
|
WHERE amopopr = o1.oid
|
||||||
AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash')
|
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
|
-- Check that each operator defined in pg_operator matches its oprcode entry
|
||||||
-- in pg_proc. Easiest to do this separately for each oprkind.
|
-- in pg_proc. Easiest to do this separately for each oprkind.
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
SELECT o1.oid, o1.oprname, p1.oid, p1.proname
|
||||||
FROM pg_operator AS p1, pg_proc AS p2
|
FROM pg_operator AS o1, pg_proc AS p1
|
||||||
WHERE p1.oprcode = p2.oid AND
|
WHERE o1.oprcode = p1.oid AND
|
||||||
p1.oprkind = 'b' AND
|
o1.oprkind = 'b' AND
|
||||||
(p2.pronargs != 2
|
(p1.pronargs != 2
|
||||||
OR NOT binary_coercible(p2.prorettype, p1.oprresult)
|
OR NOT binary_coercible(p1.prorettype, o1.oprresult)
|
||||||
OR NOT binary_coercible(p1.oprleft, p2.proargtypes[0])
|
OR NOT binary_coercible(o1.oprleft, p1.proargtypes[0])
|
||||||
OR NOT binary_coercible(p1.oprright, p2.proargtypes[1]));
|
OR NOT binary_coercible(o1.oprright, p1.proargtypes[1]));
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
SELECT o1.oid, o1.oprname, p1.oid, p1.proname
|
||||||
FROM pg_operator AS p1, pg_proc AS p2
|
FROM pg_operator AS o1, pg_proc AS p1
|
||||||
WHERE p1.oprcode = p2.oid AND
|
WHERE o1.oprcode = p1.oid AND
|
||||||
p1.oprkind = 'l' AND
|
o1.oprkind = 'l' AND
|
||||||
(p2.pronargs != 1
|
(p1.pronargs != 1
|
||||||
OR NOT binary_coercible(p2.prorettype, p1.oprresult)
|
OR NOT binary_coercible(p1.prorettype, o1.oprresult)
|
||||||
OR NOT binary_coercible(p1.oprright, p2.proargtypes[0])
|
OR NOT binary_coercible(o1.oprright, p1.proargtypes[0])
|
||||||
OR p1.oprleft != 0);
|
OR o1.oprleft != 0);
|
||||||
|
|
||||||
-- If the operator is mergejoinable or hashjoinable, its underlying function
|
-- If the operator is mergejoinable or hashjoinable, its underlying function
|
||||||
-- should not be volatile.
|
-- should not be volatile.
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
SELECT o1.oid, o1.oprname, p1.oid, p1.proname
|
||||||
FROM pg_operator AS p1, pg_proc AS p2
|
FROM pg_operator AS o1, pg_proc AS p1
|
||||||
WHERE p1.oprcode = p2.oid AND
|
WHERE o1.oprcode = p1.oid AND
|
||||||
(p1.oprcanmerge OR p1.oprcanhash) AND
|
(o1.oprcanmerge OR o1.oprcanhash) AND
|
||||||
p2.provolatile = 'v';
|
p1.provolatile = 'v';
|
||||||
|
|
||||||
-- If oprrest is set, the operator must return boolean,
|
-- If oprrest is set, the operator must return boolean,
|
||||||
-- and it must link to a proc with the right signature
|
-- and it must link to a proc with the right signature
|
||||||
-- to be a restriction selectivity estimator.
|
-- to be a restriction selectivity estimator.
|
||||||
-- The proc signature we want is: float8 proc(internal, oid, internal, int4)
|
-- The proc signature we want is: float8 proc(internal, oid, internal, int4)
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
SELECT o1.oid, o1.oprname, p2.oid, p2.proname
|
||||||
FROM pg_operator AS p1, pg_proc AS p2
|
FROM pg_operator AS o1, pg_proc AS p2
|
||||||
WHERE p1.oprrest = p2.oid AND
|
WHERE o1.oprrest = p2.oid AND
|
||||||
(p1.oprresult != 'bool'::regtype OR
|
(o1.oprresult != 'bool'::regtype OR
|
||||||
p2.prorettype != 'float8'::regtype OR p2.proretset OR
|
p2.prorettype != 'float8'::regtype OR p2.proretset OR
|
||||||
p2.pronargs != 4 OR
|
p2.pronargs != 4 OR
|
||||||
p2.proargtypes[0] != 'internal'::regtype 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
|
-- (Note: the old signature with only 4 args is still allowed, but no core
|
||||||
-- estimator should be using it.)
|
-- estimator should be using it.)
|
||||||
|
|
||||||
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
SELECT o1.oid, o1.oprname, p2.oid, p2.proname
|
||||||
FROM pg_operator AS p1, pg_proc AS p2
|
FROM pg_operator AS o1, pg_proc AS p2
|
||||||
WHERE p1.oprjoin = p2.oid AND
|
WHERE o1.oprjoin = p2.oid AND
|
||||||
(p1.oprkind != 'b' OR p1.oprresult != 'bool'::regtype OR
|
(o1.oprkind != 'b' OR o1.oprresult != 'bool'::regtype OR
|
||||||
p2.prorettype != 'float8'::regtype OR p2.proretset OR
|
p2.prorettype != 'float8'::regtype OR p2.proretset OR
|
||||||
p2.pronargs != 5 OR
|
p2.pronargs != 5 OR
|
||||||
p2.proargtypes[0] != 'internal'::regtype OR
|
p2.proargtypes[0] != 'internal'::regtype OR
|
||||||
@ -720,10 +720,10 @@ WHERE p1.oprjoin = p2.oid AND
|
|||||||
p2.proargtypes[4] != 'internal'::regtype);
|
p2.proargtypes[4] != 'internal'::regtype);
|
||||||
|
|
||||||
-- Insist that all built-in pg_operator entries have descriptions
|
-- Insist that all built-in pg_operator entries have descriptions
|
||||||
SELECT p1.oid, p1.oprname
|
SELECT o1.oid, o1.oprname
|
||||||
FROM pg_operator as p1 LEFT JOIN pg_description as d
|
FROM pg_operator as o1 LEFT JOIN pg_description as d
|
||||||
ON p1.tableoid = d.classoid and p1.oid = d.objoid and d.objsubid = 0
|
ON o1.tableoid = d.classoid and o1.oid = d.objoid and d.objsubid = 0
|
||||||
WHERE d.classoid IS NULL AND p1.oid <= 9999;
|
WHERE d.classoid IS NULL AND o1.oid <= 9999;
|
||||||
|
|
||||||
-- Check that operators' underlying functions have suitable comments,
|
-- Check that operators' underlying functions have suitable comments,
|
||||||
-- namely 'implementation of XXX operator'. (Note: it's not necessary to
|
-- 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.
|
-- Look for illegal values in pg_aggregate fields.
|
||||||
|
|
||||||
SELECT ctid, aggfnoid::oid
|
SELECT ctid, aggfnoid::oid
|
||||||
FROM pg_aggregate as p1
|
FROM pg_aggregate as a
|
||||||
WHERE aggfnoid = 0 OR aggtransfn = 0 OR
|
WHERE aggfnoid = 0 OR aggtransfn = 0 OR
|
||||||
aggkind NOT IN ('n', 'o', 'h') OR
|
aggkind NOT IN ('n', 'o', 'h') OR
|
||||||
aggnumdirectargs < 0 OR
|
aggnumdirectargs < 0 OR
|
||||||
@ -893,12 +893,12 @@ WHERE a.aggfnoid = p.oid AND
|
|||||||
-- Check for inconsistent specifications of moving-aggregate columns.
|
-- Check for inconsistent specifications of moving-aggregate columns.
|
||||||
|
|
||||||
SELECT ctid, aggfnoid::oid
|
SELECT ctid, aggfnoid::oid
|
||||||
FROM pg_aggregate as p1
|
FROM pg_aggregate as a
|
||||||
WHERE aggmtranstype != 0 AND
|
WHERE aggmtranstype != 0 AND
|
||||||
(aggmtransfn = 0 OR aggminvtransfn = 0);
|
(aggmtransfn = 0 OR aggminvtransfn = 0);
|
||||||
|
|
||||||
SELECT ctid, aggfnoid::oid
|
SELECT ctid, aggfnoid::oid
|
||||||
FROM pg_aggregate as p1
|
FROM pg_aggregate as a
|
||||||
WHERE aggmtranstype = 0 AND
|
WHERE aggmtranstype = 0 AND
|
||||||
(aggmtransfn != 0 OR aggminvtransfn != 0 OR aggmfinalfn != 0 OR
|
(aggmtransfn != 0 OR aggminvtransfn != 0 OR aggmfinalfn != 0 OR
|
||||||
aggmtransspace != 0 OR aggminitval IS NOT NULL);
|
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
|
-- Look for illegal values in pg_opfamily fields
|
||||||
|
|
||||||
SELECT p1.oid
|
SELECT f.oid
|
||||||
FROM pg_opfamily as p1
|
FROM pg_opfamily as f
|
||||||
WHERE p1.opfmethod = 0 OR p1.opfnamespace = 0;
|
WHERE f.opfmethod = 0 OR f.opfnamespace = 0;
|
||||||
|
|
||||||
-- Look for opfamilies having no opclasses. While most validation of
|
-- Look for opfamilies having no opclasses. While most validation of
|
||||||
-- opfamilies is now handled by AM-specific amvalidate functions, that's
|
-- 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
|
-- Look for illegal values in pg_opclass fields
|
||||||
|
|
||||||
SELECT p1.oid
|
SELECT c1.oid
|
||||||
FROM pg_opclass AS p1
|
FROM pg_opclass AS c1
|
||||||
WHERE p1.opcmethod = 0 OR p1.opcnamespace = 0 OR p1.opcfamily = 0
|
WHERE c1.opcmethod = 0 OR c1.opcnamespace = 0 OR c1.opcfamily = 0
|
||||||
OR p1.opcintype = 0;
|
OR c1.opcintype = 0;
|
||||||
|
|
||||||
-- opcmethod must match owning opfamily's opfmethod
|
-- opcmethod must match owning opfamily's opfmethod
|
||||||
|
|
||||||
SELECT p1.oid, p2.oid
|
SELECT c1.oid, f1.oid
|
||||||
FROM pg_opclass AS p1, pg_opfamily AS p2
|
FROM pg_opclass AS c1, pg_opfamily AS f1
|
||||||
WHERE p1.opcfamily = p2.oid AND p1.opcmethod != p2.opfmethod;
|
WHERE c1.opcfamily = f1.oid AND c1.opcmethod != f1.opfmethod;
|
||||||
|
|
||||||
-- There should not be multiple entries in pg_opclass with opcdefault true
|
-- There should not be multiple entries in pg_opclass with opcdefault true
|
||||||
-- and the same opcmethod/opcintype combination.
|
-- and the same opcmethod/opcintype combination.
|
||||||
|
|
||||||
SELECT p1.oid, p2.oid
|
SELECT c1.oid, c2.oid
|
||||||
FROM pg_opclass AS p1, pg_opclass AS p2
|
FROM pg_opclass AS c1, pg_opclass AS c2
|
||||||
WHERE p1.oid != p2.oid AND
|
WHERE c1.oid != c2.oid AND
|
||||||
p1.opcmethod = p2.opcmethod AND p1.opcintype = p2.opcintype AND
|
c1.opcmethod = c2.opcmethod AND c1.opcintype = c2.opcintype AND
|
||||||
p1.opcdefault AND p2.opcdefault;
|
c1.opcdefault AND c2.opcdefault;
|
||||||
|
|
||||||
-- Ask access methods to validate opclasses
|
-- Ask access methods to validate opclasses
|
||||||
-- (this replaces a lot of SQL-level checks that used to be done in this file)
|
-- (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
|
-- Look for illegal values in pg_am fields
|
||||||
|
|
||||||
SELECT p1.oid, p1.amname
|
SELECT a1.oid, a1.amname
|
||||||
FROM pg_am AS p1
|
FROM pg_am AS a1
|
||||||
WHERE p1.amhandler = 0;
|
WHERE a1.amhandler = 0;
|
||||||
|
|
||||||
-- Check for index amhandler functions with the wrong signature
|
-- Check for index amhandler functions with the wrong signature
|
||||||
|
|
||||||
SELECT p1.oid, p1.amname, p2.oid, p2.proname
|
SELECT a1.oid, a1.amname, p1.oid, p1.proname
|
||||||
FROM pg_am AS p1, pg_proc AS p2
|
FROM pg_am AS a1, pg_proc AS p1
|
||||||
WHERE p2.oid = p1.amhandler AND p1.amtype = 'i' AND
|
WHERE p1.oid = a1.amhandler AND a1.amtype = 'i' AND
|
||||||
(p2.prorettype != 'index_am_handler'::regtype
|
(p1.prorettype != 'index_am_handler'::regtype
|
||||||
OR p2.proretset
|
OR p1.proretset
|
||||||
OR p2.pronargs != 1
|
OR p1.pronargs != 1
|
||||||
OR p2.proargtypes[0] != 'internal'::regtype);
|
OR p1.proargtypes[0] != 'internal'::regtype);
|
||||||
|
|
||||||
-- Check for table amhandler functions with the wrong signature
|
-- Check for table amhandler functions with the wrong signature
|
||||||
|
|
||||||
SELECT p1.oid, p1.amname, p2.oid, p2.proname
|
SELECT a1.oid, a1.amname, p1.oid, p1.proname
|
||||||
FROM pg_am AS p1, pg_proc AS p2
|
FROM pg_am AS a1, pg_proc AS p1
|
||||||
WHERE p2.oid = p1.amhandler AND p1.amtype = 's' AND
|
WHERE p1.oid = a1.amhandler AND a1.amtype = 's' AND
|
||||||
(p2.prorettype != 'table_am_handler'::regtype
|
(p1.prorettype != 'table_am_handler'::regtype
|
||||||
OR p2.proretset
|
OR p1.proretset
|
||||||
OR p2.pronargs != 1
|
OR p1.pronargs != 1
|
||||||
OR p2.proargtypes[0] != 'internal'::regtype);
|
OR p1.proargtypes[0] != 'internal'::regtype);
|
||||||
|
|
||||||
-- **************** pg_amop ****************
|
-- **************** pg_amop ****************
|
||||||
|
|
||||||
-- Look for illegal values in pg_amop fields
|
-- Look for illegal values in pg_amop fields
|
||||||
|
|
||||||
SELECT p1.amopfamily, p1.amopstrategy
|
SELECT a1.amopfamily, a1.amopstrategy
|
||||||
FROM pg_amop as p1
|
FROM pg_amop as a1
|
||||||
WHERE p1.amopfamily = 0 OR p1.amoplefttype = 0 OR p1.amoprighttype = 0
|
WHERE a1.amopfamily = 0 OR a1.amoplefttype = 0 OR a1.amoprighttype = 0
|
||||||
OR p1.amopopr = 0 OR p1.amopmethod = 0 OR p1.amopstrategy < 1;
|
OR a1.amopopr = 0 OR a1.amopmethod = 0 OR a1.amopstrategy < 1;
|
||||||
|
|
||||||
SELECT p1.amopfamily, p1.amopstrategy
|
SELECT a1.amopfamily, a1.amopstrategy
|
||||||
FROM pg_amop as p1
|
FROM pg_amop as a1
|
||||||
WHERE NOT ((p1.amoppurpose = 's' AND p1.amopsortfamily = 0) OR
|
WHERE NOT ((a1.amoppurpose = 's' AND a1.amopsortfamily = 0) OR
|
||||||
(p1.amoppurpose = 'o' AND p1.amopsortfamily <> 0));
|
(a1.amoppurpose = 'o' AND a1.amopsortfamily <> 0));
|
||||||
|
|
||||||
-- amopmethod must match owning opfamily's opfmethod
|
-- amopmethod must match owning opfamily's opfmethod
|
||||||
|
|
||||||
SELECT p1.oid, p2.oid
|
SELECT a1.oid, f1.oid
|
||||||
FROM pg_amop AS p1, pg_opfamily AS p2
|
FROM pg_amop AS a1, pg_opfamily AS f1
|
||||||
WHERE p1.amopfamily = p2.oid AND p1.amopmethod != p2.opfmethod;
|
WHERE a1.amopfamily = f1.oid AND a1.amopmethod != f1.opfmethod;
|
||||||
|
|
||||||
-- Make a list of all the distinct operator names being used in particular
|
-- 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
|
-- 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.
|
-- swapping two operators within a family.
|
||||||
|
|
||||||
SELECT DISTINCT amopmethod, amopstrategy, oprname
|
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;
|
ORDER BY 1, 2, 3;
|
||||||
|
|
||||||
-- Check that all opclass search operators have selectivity estimators.
|
-- Check that all opclass search operators have selectivity estimators.
|
||||||
-- This is not absolutely required, but it seems a reasonable thing
|
-- This is not absolutely required, but it seems a reasonable thing
|
||||||
-- to insist on for all standard datatypes.
|
-- to insist on for all standard datatypes.
|
||||||
|
|
||||||
SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
|
SELECT a1.amopfamily, a1.amopopr, o1.oid, o1.oprname
|
||||||
FROM pg_amop AS p1, pg_operator AS p2
|
FROM pg_amop AS a1, pg_operator AS o1
|
||||||
WHERE p1.amopopr = p2.oid AND p1.amoppurpose = 's' AND
|
WHERE a1.amopopr = o1.oid AND a1.amoppurpose = 's' AND
|
||||||
(p2.oprrest = 0 OR p2.oprjoin = 0);
|
(o1.oprrest = 0 OR o1.oprjoin = 0);
|
||||||
|
|
||||||
-- Check that each opclass in an opfamily has associated operators, that is
|
-- Check that each opclass in an opfamily has associated operators, that is
|
||||||
-- ones whose oprleft matches opcintype (possibly by coercion).
|
-- ones whose oprleft matches opcintype (possibly by coercion).
|
||||||
|
|
||||||
SELECT p1.opcname, p1.opcfamily
|
SELECT c1.opcname, c1.opcfamily
|
||||||
FROM pg_opclass AS p1
|
FROM pg_opclass AS c1
|
||||||
WHERE NOT EXISTS(SELECT 1 FROM pg_amop AS p2
|
WHERE NOT EXISTS(SELECT 1 FROM pg_amop AS a1
|
||||||
WHERE p2.amopfamily = p1.opcfamily
|
WHERE a1.amopfamily = c1.opcfamily
|
||||||
AND binary_coercible(p1.opcintype, p2.amoplefttype));
|
AND binary_coercible(c1.opcintype, a1.amoplefttype));
|
||||||
|
|
||||||
-- Check that each operator listed in pg_amop has an associated opclass,
|
-- Check that each operator listed in pg_amop has an associated opclass,
|
||||||
-- that is one whose opcintype matches oprleft (possibly by coercion).
|
-- 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
|
-- btree opfamilies, but in practice you'd expect there to be an opclass for
|
||||||
-- every datatype the family knows about.)
|
-- every datatype the family knows about.)
|
||||||
|
|
||||||
SELECT p1.amopfamily, p1.amopstrategy, p1.amopopr
|
SELECT a1.amopfamily, a1.amopstrategy, a1.amopopr
|
||||||
FROM pg_amop AS p1
|
FROM pg_amop AS a1
|
||||||
WHERE NOT EXISTS(SELECT 1 FROM pg_opclass AS p2
|
WHERE NOT EXISTS(SELECT 1 FROM pg_opclass AS c1
|
||||||
WHERE p2.opcfamily = p1.amopfamily
|
WHERE c1.opcfamily = a1.amopfamily
|
||||||
AND binary_coercible(p2.opcintype, p1.amoplefttype));
|
AND binary_coercible(c1.opcintype, a1.amoplefttype));
|
||||||
|
|
||||||
-- Operators that are primary members of opclasses must be immutable (else
|
-- Operators that are primary members of opclasses must be immutable (else
|
||||||
-- it suggests that the index ordering isn't fixed). Operators that are
|
-- it suggests that the index ordering isn't fixed). Operators that are
|
||||||
-- cross-type members need only be stable, since they are just shorthands
|
-- cross-type members need only be stable, since they are just shorthands
|
||||||
-- for index probe queries.
|
-- for index probe queries.
|
||||||
|
|
||||||
SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
|
SELECT a1.amopfamily, a1.amopopr, o1.oprname, p1.prosrc
|
||||||
FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
|
FROM pg_amop AS a1, pg_operator AS o1, pg_proc AS p1
|
||||||
WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
|
WHERE a1.amopopr = o1.oid AND o1.oprcode = p1.oid AND
|
||||||
p1.amoplefttype = p1.amoprighttype AND
|
a1.amoplefttype = a1.amoprighttype AND
|
||||||
p3.provolatile != 'i';
|
p1.provolatile != 'i';
|
||||||
|
|
||||||
SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
|
SELECT a1.amopfamily, a1.amopopr, o1.oprname, p1.prosrc
|
||||||
FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
|
FROM pg_amop AS a1, pg_operator AS o1, pg_proc AS p1
|
||||||
WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
|
WHERE a1.amopopr = o1.oid AND o1.oprcode = p1.oid AND
|
||||||
p1.amoplefttype != p1.amoprighttype AND
|
a1.amoplefttype != a1.amoprighttype AND
|
||||||
p3.provolatile = 'v';
|
p1.provolatile = 'v';
|
||||||
|
|
||||||
|
|
||||||
-- **************** pg_amproc ****************
|
-- **************** pg_amproc ****************
|
||||||
|
|
||||||
-- Look for illegal values in pg_amproc fields
|
-- Look for illegal values in pg_amproc fields
|
||||||
|
|
||||||
SELECT p1.amprocfamily, p1.amprocnum
|
SELECT a1.amprocfamily, a1.amprocnum
|
||||||
FROM pg_amproc as p1
|
FROM pg_amproc as a1
|
||||||
WHERE p1.amprocfamily = 0 OR p1.amproclefttype = 0 OR p1.amprocrighttype = 0
|
WHERE a1.amprocfamily = 0 OR a1.amproclefttype = 0 OR a1.amprocrighttype = 0
|
||||||
OR p1.amprocnum < 0 OR p1.amproc = 0;
|
OR a1.amprocnum < 0 OR a1.amproc = 0;
|
||||||
|
|
||||||
-- Support routines that are primary members of opfamilies must be immutable
|
-- Support routines that are primary members of opfamilies must be immutable
|
||||||
-- (else it suggests that the index ordering isn't fixed). But cross-type
|
-- (else it suggests that the index ordering isn't fixed). But cross-type
|
||||||
-- members need only be stable, since they are just shorthands
|
-- members need only be stable, since they are just shorthands
|
||||||
-- for index probe queries.
|
-- for index probe queries.
|
||||||
|
|
||||||
SELECT p1.amprocfamily, p1.amproc, p2.prosrc
|
SELECT a1.amprocfamily, a1.amproc, p1.prosrc
|
||||||
FROM pg_amproc AS p1, pg_proc AS p2
|
FROM pg_amproc AS a1, pg_proc AS p1
|
||||||
WHERE p1.amproc = p2.oid AND
|
WHERE a1.amproc = p1.oid AND
|
||||||
p1.amproclefttype = p1.amprocrighttype AND
|
a1.amproclefttype = a1.amprocrighttype AND
|
||||||
p2.provolatile != 'i';
|
p1.provolatile != 'i';
|
||||||
|
|
||||||
SELECT p1.amprocfamily, p1.amproc, p2.prosrc
|
SELECT a1.amprocfamily, a1.amproc, p1.prosrc
|
||||||
FROM pg_amproc AS p1, pg_proc AS p2
|
FROM pg_amproc AS a1, pg_proc AS p1
|
||||||
WHERE p1.amproc = p2.oid AND
|
WHERE a1.amproc = p1.oid AND
|
||||||
p1.amproclefttype != p1.amprocrighttype AND
|
a1.amproclefttype != a1.amprocrighttype AND
|
||||||
p2.provolatile = 'v';
|
p1.provolatile = 'v';
|
||||||
|
|
||||||
-- Almost all of the core distribution's Btree opclasses can use one of the
|
-- 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
|
-- 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.
|
-- Look for illegal values in pg_index fields.
|
||||||
|
|
||||||
SELECT p1.indexrelid, p1.indrelid
|
SELECT indexrelid, indrelid
|
||||||
FROM pg_index as p1
|
FROM pg_index
|
||||||
WHERE p1.indexrelid = 0 OR p1.indrelid = 0 OR
|
WHERE indexrelid = 0 OR indrelid = 0 OR
|
||||||
p1.indnatts <= 0 OR p1.indnatts > 32;
|
indnatts <= 0 OR indnatts > 32;
|
||||||
|
|
||||||
-- oidvector and int2vector fields should be of length indnatts.
|
-- oidvector and int2vector fields should be of length indnatts.
|
||||||
|
|
||||||
SELECT p1.indexrelid, p1.indrelid
|
SELECT indexrelid, indrelid
|
||||||
FROM pg_index as p1
|
FROM pg_index
|
||||||
WHERE array_lower(indkey, 1) != 0 OR array_upper(indkey, 1) != indnatts-1 OR
|
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(indclass, 1) != 0 OR array_upper(indclass, 1) != indnatts-1 OR
|
||||||
array_lower(indcollation, 1) != 0 OR array_upper(indcollation, 1) != indnatts-1 OR
|
array_lower(indcollation, 1) != 0 OR array_upper(indcollation, 1) != indnatts-1 OR
|
||||||
|
@ -16,94 +16,94 @@
|
|||||||
|
|
||||||
-- Look for illegal values in pg_type fields.
|
-- Look for illegal values in pg_type fields.
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname
|
SELECT t1.oid, t1.typname
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
WHERE p1.typnamespace = 0 OR
|
WHERE t1.typnamespace = 0 OR
|
||||||
(p1.typlen <= 0 AND p1.typlen != -1 AND p1.typlen != -2) OR
|
(t1.typlen <= 0 AND t1.typlen != -1 AND t1.typlen != -2) OR
|
||||||
(p1.typtype not in ('b', 'c', 'd', 'e', 'p', 'r', 'm')) OR
|
(t1.typtype not in ('b', 'c', 'd', 'e', 'p', 'r', 'm')) OR
|
||||||
NOT p1.typisdefined OR
|
NOT t1.typisdefined OR
|
||||||
(p1.typalign not in ('c', 's', 'i', 'd')) OR
|
(t1.typalign not in ('c', 's', 'i', 'd')) OR
|
||||||
(p1.typstorage not in ('p', 'x', 'e', 'm'));
|
(t1.typstorage not in ('p', 'x', 'e', 'm'));
|
||||||
|
|
||||||
-- Look for "pass by value" types that can't be passed by value.
|
-- Look for "pass by value" types that can't be passed by value.
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname
|
SELECT t1.oid, t1.typname
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
WHERE p1.typbyval AND
|
WHERE t1.typbyval AND
|
||||||
(p1.typlen != 1 OR p1.typalign != 'c') AND
|
(t1.typlen != 1 OR t1.typalign != 'c') AND
|
||||||
(p1.typlen != 2 OR p1.typalign != 's') AND
|
(t1.typlen != 2 OR t1.typalign != 's') AND
|
||||||
(p1.typlen != 4 OR p1.typalign != 'i') AND
|
(t1.typlen != 4 OR t1.typalign != 'i') AND
|
||||||
(p1.typlen != 8 OR p1.typalign != 'd');
|
(t1.typlen != 8 OR t1.typalign != 'd');
|
||||||
|
|
||||||
-- Look for "toastable" types that aren't varlena.
|
-- Look for "toastable" types that aren't varlena.
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname
|
SELECT t1.oid, t1.typname
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
WHERE p1.typstorage != 'p' AND
|
WHERE t1.typstorage != 'p' AND
|
||||||
(p1.typbyval OR p1.typlen != -1);
|
(t1.typbyval OR t1.typlen != -1);
|
||||||
|
|
||||||
-- Look for complex types that do not have a typrelid entry,
|
-- Look for complex types that do not have a typrelid entry,
|
||||||
-- or basic types that do.
|
-- or basic types that do.
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname
|
SELECT t1.oid, t1.typname
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
|
WHERE (t1.typtype = 'c' AND t1.typrelid = 0) OR
|
||||||
(p1.typtype != 'c' AND p1.typrelid != 0);
|
(t1.typtype != 'c' AND t1.typrelid != 0);
|
||||||
|
|
||||||
-- Look for types that should have an array type but don't.
|
-- Look for types that should have an array type but don't.
|
||||||
-- Generally anything that's not a pseudotype should have an array type.
|
-- Generally anything that's not a pseudotype should have an array type.
|
||||||
-- However, we do have a small number of exceptions.
|
-- However, we do have a small number of exceptions.
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname
|
SELECT t1.oid, t1.typname
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
WHERE p1.typtype not in ('p') AND p1.typname NOT LIKE E'\\_%'
|
WHERE t1.typtype not in ('p') AND t1.typname NOT LIKE E'\\_%'
|
||||||
AND NOT EXISTS
|
AND NOT EXISTS
|
||||||
(SELECT 1 FROM pg_type as p2
|
(SELECT 1 FROM pg_type as t2
|
||||||
WHERE p2.typname = ('_' || p1.typname)::name AND
|
WHERE t2.typname = ('_' || t1.typname)::name AND
|
||||||
p2.typelem = p1.oid and p1.typarray = p2.oid)
|
t2.typelem = t1.oid and t1.typarray = t2.oid)
|
||||||
ORDER BY p1.oid;
|
ORDER BY t1.oid;
|
||||||
|
|
||||||
-- Make sure typarray points to a "true" array type of our own base
|
-- Make sure typarray points to a "true" array type of our own base
|
||||||
SELECT p1.oid, p1.typname as basetype, p2.typname as arraytype,
|
SELECT t1.oid, t1.typname as basetype, t2.typname as arraytype,
|
||||||
p2.typsubscript
|
t2.typsubscript
|
||||||
FROM pg_type p1 LEFT JOIN pg_type p2 ON (p1.typarray = p2.oid)
|
FROM pg_type t1 LEFT JOIN pg_type t2 ON (t1.typarray = t2.oid)
|
||||||
WHERE p1.typarray <> 0 AND
|
WHERE t1.typarray <> 0 AND
|
||||||
(p2.oid IS NULL OR
|
(t2.oid IS NULL OR
|
||||||
p2.typsubscript <> 'array_subscript_handler'::regproc);
|
t2.typsubscript <> 'array_subscript_handler'::regproc);
|
||||||
|
|
||||||
-- Look for range types that do not have a pg_range entry
|
-- Look for range types that do not have a pg_range entry
|
||||||
SELECT p1.oid, p1.typname
|
SELECT t1.oid, t1.typname
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
WHERE p1.typtype = 'r' AND
|
WHERE t1.typtype = 'r' AND
|
||||||
NOT EXISTS(SELECT 1 FROM pg_range r WHERE rngtypid = p1.oid);
|
NOT EXISTS(SELECT 1 FROM pg_range r WHERE rngtypid = t1.oid);
|
||||||
|
|
||||||
-- Look for range types whose typalign isn't sufficient
|
-- Look for range types whose typalign isn't sufficient
|
||||||
SELECT p1.oid, p1.typname, p1.typalign, p2.typname, p2.typalign
|
SELECT t1.oid, t1.typname, t1.typalign, t2.typname, t2.typalign
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
LEFT JOIN pg_range as r ON rngtypid = p1.oid
|
LEFT JOIN pg_range as r ON rngtypid = t1.oid
|
||||||
LEFT JOIN pg_type as p2 ON rngsubtype = p2.oid
|
LEFT JOIN pg_type as t2 ON rngsubtype = t2.oid
|
||||||
WHERE p1.typtype = 'r' AND
|
WHERE t1.typtype = 'r' AND
|
||||||
(p1.typalign != (CASE WHEN p2.typalign = 'd' THEN 'd'::"char"
|
(t1.typalign != (CASE WHEN t2.typalign = 'd' THEN 'd'::"char"
|
||||||
ELSE 'i'::"char" END)
|
ELSE 'i'::"char" END)
|
||||||
OR p2.oid IS NULL);
|
OR t2.oid IS NULL);
|
||||||
|
|
||||||
-- Text conversion routines must be provided.
|
-- Text conversion routines must be provided.
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname
|
SELECT t1.oid, t1.typname
|
||||||
FROM pg_type as p1
|
FROM pg_type as t1
|
||||||
WHERE (p1.typinput = 0 OR p1.typoutput = 0);
|
WHERE (t1.typinput = 0 OR t1.typoutput = 0);
|
||||||
|
|
||||||
-- Check for bogus typinput routines
|
-- Check for bogus typinput routines
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typinput = p2.oid AND NOT
|
WHERE t1.typinput = p1.oid AND NOT
|
||||||
((p2.pronargs = 1 AND p2.proargtypes[0] = 'cstring'::regtype) OR
|
((p1.pronargs = 1 AND p1.proargtypes[0] = 'cstring'::regtype) OR
|
||||||
(p2.pronargs = 2 AND p2.proargtypes[0] = 'cstring'::regtype AND
|
(p1.pronargs = 2 AND p1.proargtypes[0] = 'cstring'::regtype AND
|
||||||
p2.proargtypes[1] = 'oid'::regtype) OR
|
p1.proargtypes[1] = 'oid'::regtype) OR
|
||||||
(p2.pronargs = 3 AND p2.proargtypes[0] = 'cstring'::regtype AND
|
(p1.pronargs = 3 AND p1.proargtypes[0] = 'cstring'::regtype AND
|
||||||
p2.proargtypes[1] = 'oid'::regtype AND
|
p1.proargtypes[1] = 'oid'::regtype AND
|
||||||
p2.proargtypes[2] = 'int4'::regtype));
|
p1.proargtypes[2] = 'int4'::regtype));
|
||||||
|
|
||||||
-- Check for type of the variadic array parameter's elements.
|
-- Check for type of the variadic array parameter's elements.
|
||||||
-- provariadic should be ANYOID if the type of the last element is ANYOID,
|
-- 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
|
-- As of 8.0, this check finds refcursor, which is borrowing
|
||||||
-- other types' I/O routines
|
-- other types' I/O routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
|
WHERE t1.typinput = p1.oid AND t1.typtype in ('b', 'p') AND NOT
|
||||||
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
|
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
|
||||||
(p2.prorettype = p1.oid AND NOT p2.proretset)
|
(p1.prorettype = t1.oid AND NOT p1.proretset)
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
|
|
||||||
-- Varlena array types will point to array_in
|
-- Varlena array types will point to array_in
|
||||||
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
|
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typinput = p2.oid AND
|
WHERE t1.typinput = p1.oid AND
|
||||||
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
|
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
|
||||||
(p2.oid = 'array_in'::regproc)
|
(p1.oid = 'array_in'::regproc)
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
|
|
||||||
-- typinput routines should not be volatile
|
-- typinput routines should not be volatile
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typinput = p2.oid AND p2.provolatile NOT IN ('i', 's');
|
WHERE t1.typinput = p1.oid AND p1.provolatile NOT IN ('i', 's');
|
||||||
|
|
||||||
-- Composites, domains, enums, multiranges, ranges should all use the same input routines
|
-- Composites, domains, enums, multiranges, ranges should all use the same input routines
|
||||||
SELECT DISTINCT typtype, typinput
|
SELECT DISTINCT typtype, typinput
|
||||||
FROM pg_type AS p1
|
FROM pg_type AS t1
|
||||||
WHERE p1.typtype not in ('b', 'p')
|
WHERE t1.typtype not in ('b', 'p')
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
|
|
||||||
-- Check for bogus typoutput routines
|
-- Check for bogus typoutput routines
|
||||||
|
|
||||||
-- As of 8.0, this check finds refcursor, which is borrowing
|
-- As of 8.0, this check finds refcursor, which is borrowing
|
||||||
-- other types' I/O routines
|
-- other types' I/O routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
|
WHERE t1.typoutput = p1.oid AND t1.typtype in ('b', 'p') AND NOT
|
||||||
(p2.pronargs = 1 AND
|
(p1.pronargs = 1 AND
|
||||||
(p2.proargtypes[0] = p1.oid OR
|
(p1.proargtypes[0] = t1.oid OR
|
||||||
(p2.oid = 'array_out'::regproc AND
|
(p1.oid = 'array_out'::regproc AND
|
||||||
p1.typelem != 0 AND p1.typlen = -1)))
|
t1.typelem != 0 AND t1.typlen = -1)))
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typoutput = p2.oid AND NOT
|
WHERE t1.typoutput = p1.oid AND NOT
|
||||||
(p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
|
(p1.prorettype = 'cstring'::regtype AND NOT p1.proretset);
|
||||||
|
|
||||||
-- typoutput routines should not be volatile
|
-- typoutput routines should not be volatile
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typoutput = p2.oid AND p2.provolatile NOT IN ('i', 's');
|
WHERE t1.typoutput = p1.oid AND p1.provolatile NOT IN ('i', 's');
|
||||||
|
|
||||||
-- Composites, enums, multiranges, ranges should all use the same output routines
|
-- Composites, enums, multiranges, ranges should all use the same output routines
|
||||||
SELECT DISTINCT typtype, typoutput
|
SELECT DISTINCT typtype, typoutput
|
||||||
FROM pg_type AS p1
|
FROM pg_type AS t1
|
||||||
WHERE p1.typtype not in ('b', 'd', 'p')
|
WHERE t1.typtype not in ('b', 'd', 'p')
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
|
|
||||||
-- Domains should have same typoutput as their base types
|
-- Domains should have same typoutput as their base types
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.typname
|
SELECT t1.oid, t1.typname, t2.oid, t2.typname
|
||||||
FROM pg_type AS p1 LEFT JOIN pg_type AS p2 ON p1.typbasetype = p2.oid
|
FROM pg_type AS t1 LEFT JOIN pg_type AS t2 ON t1.typbasetype = t2.oid
|
||||||
WHERE p1.typtype = 'd' AND p1.typoutput IS DISTINCT FROM p2.typoutput;
|
WHERE t1.typtype = 'd' AND t1.typoutput IS DISTINCT FROM t2.typoutput;
|
||||||
|
|
||||||
-- Check for bogus typreceive routines
|
-- Check for bogus typreceive routines
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typreceive = p2.oid AND NOT
|
WHERE t1.typreceive = p1.oid AND NOT
|
||||||
((p2.pronargs = 1 AND p2.proargtypes[0] = 'internal'::regtype) OR
|
((p1.pronargs = 1 AND p1.proargtypes[0] = 'internal'::regtype) OR
|
||||||
(p2.pronargs = 2 AND p2.proargtypes[0] = 'internal'::regtype AND
|
(p1.pronargs = 2 AND p1.proargtypes[0] = 'internal'::regtype AND
|
||||||
p2.proargtypes[1] = 'oid'::regtype) OR
|
p1.proargtypes[1] = 'oid'::regtype) OR
|
||||||
(p2.pronargs = 3 AND p2.proargtypes[0] = 'internal'::regtype AND
|
(p1.pronargs = 3 AND p1.proargtypes[0] = 'internal'::regtype AND
|
||||||
p2.proargtypes[1] = 'oid'::regtype AND
|
p1.proargtypes[1] = 'oid'::regtype AND
|
||||||
p2.proargtypes[2] = 'int4'::regtype));
|
p1.proargtypes[2] = 'int4'::regtype));
|
||||||
|
|
||||||
-- As of 7.4, this check finds refcursor, which is borrowing
|
-- As of 7.4, this check finds refcursor, which is borrowing
|
||||||
-- other types' I/O routines
|
-- other types' I/O routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND NOT
|
WHERE t1.typreceive = p1.oid AND t1.typtype in ('b', 'p') AND NOT
|
||||||
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
|
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
|
||||||
(p2.prorettype = p1.oid AND NOT p2.proretset)
|
(p1.prorettype = t1.oid AND NOT p1.proretset)
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
|
|
||||||
-- Varlena array types will point to array_recv
|
-- Varlena array types will point to array_recv
|
||||||
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
|
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typreceive = p2.oid AND
|
WHERE t1.typreceive = p1.oid AND
|
||||||
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
|
(t1.typelem != 0 AND t1.typlen < 0) AND NOT
|
||||||
(p2.oid = 'array_recv'::regproc)
|
(p1.oid = 'array_recv'::regproc)
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
|
|
||||||
-- Suspicious if typreceive doesn't take same number of args as typinput
|
-- 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
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname, p2.oid, p2.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2, pg_proc AS p3
|
FROM pg_type AS t1, pg_proc AS p1, pg_proc AS p2
|
||||||
WHERE p1.typinput = p2.oid AND p1.typreceive = p3.oid AND
|
WHERE t1.typinput = p1.oid AND t1.typreceive = p2.oid AND
|
||||||
p2.pronargs != p3.pronargs;
|
p1.pronargs != p2.pronargs;
|
||||||
|
|
||||||
-- typreceive routines should not be volatile
|
-- typreceive routines should not be volatile
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typreceive = p2.oid AND p2.provolatile NOT IN ('i', 's');
|
WHERE t1.typreceive = p1.oid AND p1.provolatile NOT IN ('i', 's');
|
||||||
|
|
||||||
-- Composites, domains, enums, multiranges, ranges should all use the same receive routines
|
-- Composites, domains, enums, multiranges, ranges should all use the same receive routines
|
||||||
SELECT DISTINCT typtype, typreceive
|
SELECT DISTINCT typtype, typreceive
|
||||||
FROM pg_type AS p1
|
FROM pg_type AS t1
|
||||||
WHERE p1.typtype not in ('b', 'p')
|
WHERE t1.typtype not in ('b', 'p')
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
|
|
||||||
-- Check for bogus typsend routines
|
-- Check for bogus typsend routines
|
||||||
|
|
||||||
-- As of 7.4, this check finds refcursor, which is borrowing
|
-- As of 7.4, this check finds refcursor, which is borrowing
|
||||||
-- other types' I/O routines
|
-- other types' I/O routines
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
|
WHERE t1.typsend = p1.oid AND t1.typtype in ('b', 'p') AND NOT
|
||||||
(p2.pronargs = 1 AND
|
(p1.pronargs = 1 AND
|
||||||
(p2.proargtypes[0] = p1.oid OR
|
(p1.proargtypes[0] = t1.oid OR
|
||||||
(p2.oid = 'array_send'::regproc AND
|
(p1.oid = 'array_send'::regproc AND
|
||||||
p1.typelem != 0 AND p1.typlen = -1)))
|
t1.typelem != 0 AND t1.typlen = -1)))
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typsend = p2.oid AND NOT
|
WHERE t1.typsend = p1.oid AND NOT
|
||||||
(p2.prorettype = 'bytea'::regtype AND NOT p2.proretset);
|
(p1.prorettype = 'bytea'::regtype AND NOT p1.proretset);
|
||||||
|
|
||||||
-- typsend routines should not be volatile
|
-- typsend routines should not be volatile
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typsend = p2.oid AND p2.provolatile NOT IN ('i', 's');
|
WHERE t1.typsend = p1.oid AND p1.provolatile NOT IN ('i', 's');
|
||||||
|
|
||||||
-- Composites, enums, multiranges, ranges should all use the same send routines
|
-- Composites, enums, multiranges, ranges should all use the same send routines
|
||||||
SELECT DISTINCT typtype, typsend
|
SELECT DISTINCT typtype, typsend
|
||||||
FROM pg_type AS p1
|
FROM pg_type AS t1
|
||||||
WHERE p1.typtype not in ('b', 'd', 'p')
|
WHERE t1.typtype not in ('b', 'd', 'p')
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
|
|
||||||
-- Domains should have same typsend as their base types
|
-- Domains should have same typsend as their base types
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.typname
|
SELECT t1.oid, t1.typname, t2.oid, t2.typname
|
||||||
FROM pg_type AS p1 LEFT JOIN pg_type AS p2 ON p1.typbasetype = p2.oid
|
FROM pg_type AS t1 LEFT JOIN pg_type AS t2 ON t1.typbasetype = t2.oid
|
||||||
WHERE p1.typtype = 'd' AND p1.typsend IS DISTINCT FROM p2.typsend;
|
WHERE t1.typtype = 'd' AND t1.typsend IS DISTINCT FROM t2.typsend;
|
||||||
|
|
||||||
-- Check for bogus typmodin routines
|
-- Check for bogus typmodin routines
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typmodin = p2.oid AND NOT
|
WHERE t1.typmodin = p1.oid AND NOT
|
||||||
(p2.pronargs = 1 AND
|
(p1.pronargs = 1 AND
|
||||||
p2.proargtypes[0] = 'cstring[]'::regtype AND
|
p1.proargtypes[0] = 'cstring[]'::regtype AND
|
||||||
p2.prorettype = 'int4'::regtype AND NOT p2.proretset);
|
p1.prorettype = 'int4'::regtype AND NOT p1.proretset);
|
||||||
|
|
||||||
-- typmodin routines should not be volatile
|
-- typmodin routines should not be volatile
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typmodin = p2.oid AND p2.provolatile NOT IN ('i', 's');
|
WHERE t1.typmodin = p1.oid AND p1.provolatile NOT IN ('i', 's');
|
||||||
|
|
||||||
-- Check for bogus typmodout routines
|
-- Check for bogus typmodout routines
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typmodout = p2.oid AND NOT
|
WHERE t1.typmodout = p1.oid AND NOT
|
||||||
(p2.pronargs = 1 AND
|
(p1.pronargs = 1 AND
|
||||||
p2.proargtypes[0] = 'int4'::regtype AND
|
p1.proargtypes[0] = 'int4'::regtype AND
|
||||||
p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
|
p1.prorettype = 'cstring'::regtype AND NOT p1.proretset);
|
||||||
|
|
||||||
-- typmodout routines should not be volatile
|
-- typmodout routines should not be volatile
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typmodout = p2.oid AND p2.provolatile NOT IN ('i', 's');
|
WHERE t1.typmodout = p1.oid AND p1.provolatile NOT IN ('i', 's');
|
||||||
|
|
||||||
-- Array types should have same typmodin/out as their element types
|
-- Array types should have same typmodin/out as their element types
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.typname
|
SELECT t1.oid, t1.typname, t2.oid, t2.typname
|
||||||
FROM pg_type AS p1, pg_type AS p2
|
FROM pg_type AS t1, pg_type AS t2
|
||||||
WHERE p1.typelem = p2.oid AND NOT
|
WHERE t1.typelem = t2.oid AND NOT
|
||||||
(p1.typmodin = p2.typmodin AND p1.typmodout = p2.typmodout);
|
(t1.typmodin = t2.typmodin AND t1.typmodout = t2.typmodout);
|
||||||
|
|
||||||
-- Array types should have same typdelim as their element types
|
-- Array types should have same typdelim as their element types
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.typname
|
SELECT t1.oid, t1.typname, t2.oid, t2.typname
|
||||||
FROM pg_type AS p1, pg_type AS p2
|
FROM pg_type AS t1, pg_type AS t2
|
||||||
WHERE p1.typarray = p2.oid AND NOT (p1.typdelim = p2.typdelim);
|
WHERE t1.typarray = t2.oid AND NOT (t1.typdelim = t2.typdelim);
|
||||||
|
|
||||||
-- Look for array types whose typalign isn't sufficient
|
-- Look for array types whose typalign isn't sufficient
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname, p1.typalign, p2.typname, p2.typalign
|
SELECT t1.oid, t1.typname, t1.typalign, t2.typname, t2.typalign
|
||||||
FROM pg_type AS p1, pg_type AS p2
|
FROM pg_type AS t1, pg_type AS t2
|
||||||
WHERE p1.typarray = p2.oid AND
|
WHERE t1.typarray = t2.oid AND
|
||||||
p2.typalign != (CASE WHEN p1.typalign = 'd' THEN 'd'::"char"
|
t2.typalign != (CASE WHEN t1.typalign = 'd' THEN 'd'::"char"
|
||||||
ELSE 'i'::"char" END);
|
ELSE 'i'::"char" END);
|
||||||
|
|
||||||
-- Check for typelem set without a handler
|
-- Check for typelem set without a handler
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname, p1.typelem
|
SELECT t1.oid, t1.typname, t1.typelem
|
||||||
FROM pg_type AS p1
|
FROM pg_type AS t1
|
||||||
WHERE p1.typelem != 0 AND p1.typsubscript = 0;
|
WHERE t1.typelem != 0 AND t1.typsubscript = 0;
|
||||||
|
|
||||||
-- Check for misuse of standard subscript handlers
|
-- Check for misuse of standard subscript handlers
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname,
|
SELECT t1.oid, t1.typname,
|
||||||
p1.typelem, p1.typlen, p1.typbyval
|
t1.typelem, t1.typlen, t1.typbyval
|
||||||
FROM pg_type AS p1
|
FROM pg_type AS t1
|
||||||
WHERE p1.typsubscript = 'array_subscript_handler'::regproc AND NOT
|
WHERE t1.typsubscript = 'array_subscript_handler'::regproc AND NOT
|
||||||
(p1.typelem != 0 AND p1.typlen = -1 AND NOT p1.typbyval);
|
(t1.typelem != 0 AND t1.typlen = -1 AND NOT t1.typbyval);
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname,
|
SELECT t1.oid, t1.typname,
|
||||||
p1.typelem, p1.typlen, p1.typbyval
|
t1.typelem, t1.typlen, t1.typbyval
|
||||||
FROM pg_type AS p1
|
FROM pg_type AS t1
|
||||||
WHERE p1.typsubscript = 'raw_array_subscript_handler'::regproc AND NOT
|
WHERE t1.typsubscript = 'raw_array_subscript_handler'::regproc AND NOT
|
||||||
(p1.typelem != 0 AND p1.typlen > 0 AND NOT p1.typbyval);
|
(t1.typelem != 0 AND t1.typlen > 0 AND NOT t1.typbyval);
|
||||||
|
|
||||||
-- Check for bogus typanalyze routines
|
-- Check for bogus typanalyze routines
|
||||||
|
|
||||||
SELECT p1.oid, p1.typname, p2.oid, p2.proname
|
SELECT t1.oid, t1.typname, p1.oid, p1.proname
|
||||||
FROM pg_type AS p1, pg_proc AS p2
|
FROM pg_type AS t1, pg_proc AS p1
|
||||||
WHERE p1.typanalyze = p2.oid AND NOT
|
WHERE t1.typanalyze = p1.oid AND NOT
|
||||||
(p2.pronargs = 1 AND
|
(p1.pronargs = 1 AND
|
||||||
p2.proargtypes[0] = 'internal'::regtype AND
|
p1.proargtypes[0] = 'internal'::regtype AND
|
||||||
p2.prorettype = 'bool'::regtype AND NOT p2.proretset);
|
p1.prorettype = 'bool'::regtype AND NOT p1.proretset);
|
||||||
|
|
||||||
-- there does not seem to be a reason to care about volatility of typanalyze
|
-- 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
|
-- Look for illegal values in pg_class fields
|
||||||
|
|
||||||
SELECT p1.oid, p1.relname
|
SELECT c1.oid, c1.relname
|
||||||
FROM pg_class as p1
|
FROM pg_class as c1
|
||||||
WHERE relkind NOT IN ('r', 'i', 'S', 't', 'v', 'm', 'c', 'f', 'p') OR
|
WHERE relkind NOT IN ('r', 'i', 'S', 't', 'v', 'm', 'c', 'f', 'p') OR
|
||||||
relpersistence NOT IN ('p', 'u', 't') OR
|
relpersistence NOT IN ('p', 'u', 't') OR
|
||||||
relreplident NOT IN ('d', 'n', 'f', 'i');
|
relreplident NOT IN ('d', 'n', 'f', 'i');
|
||||||
|
|
||||||
-- All tables and indexes should have an access method.
|
-- All tables and indexes should have an access method.
|
||||||
SELECT p1.oid, p1.relname
|
SELECT c1.oid, c1.relname
|
||||||
FROM pg_class as p1
|
FROM pg_class as c1
|
||||||
WHERE p1.relkind NOT IN ('S', 'v', 'f', 'c') and
|
WHERE c1.relkind NOT IN ('S', 'v', 'f', 'c') and
|
||||||
p1.relam = 0;
|
c1.relam = 0;
|
||||||
|
|
||||||
-- Conversely, sequences, views, types shouldn't have them
|
-- Conversely, sequences, views, types shouldn't have them
|
||||||
SELECT p1.oid, p1.relname
|
SELECT c1.oid, c1.relname
|
||||||
FROM pg_class as p1
|
FROM pg_class as c1
|
||||||
WHERE p1.relkind IN ('S', 'v', 'f', 'c') and
|
WHERE c1.relkind IN ('S', 'v', 'f', 'c') and
|
||||||
p1.relam != 0;
|
c1.relam != 0;
|
||||||
|
|
||||||
-- Indexes should have AMs of type 'i'
|
-- Indexes should have AMs of type 'i'
|
||||||
SELECT pc.oid, pc.relname, pa.amname, pa.amtype
|
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
|
-- Look for illegal values in pg_attribute fields
|
||||||
|
|
||||||
SELECT p1.attrelid, p1.attname
|
SELECT a1.attrelid, a1.attname
|
||||||
FROM pg_attribute as p1
|
FROM pg_attribute as a1
|
||||||
WHERE p1.attrelid = 0 OR p1.atttypid = 0 OR p1.attnum = 0 OR
|
WHERE a1.attrelid = 0 OR a1.atttypid = 0 OR a1.attnum = 0 OR
|
||||||
p1.attcacheoff != -1 OR p1.attinhcount < 0 OR
|
a1.attcacheoff != -1 OR a1.attinhcount < 0 OR
|
||||||
(p1.attinhcount = 0 AND NOT p1.attislocal);
|
(a1.attinhcount = 0 AND NOT a1.attislocal);
|
||||||
|
|
||||||
-- Cross-check attnum against parent relation
|
-- Cross-check attnum against parent relation
|
||||||
|
|
||||||
SELECT p1.attrelid, p1.attname, p2.oid, p2.relname
|
SELECT a1.attrelid, a1.attname, c1.oid, c1.relname
|
||||||
FROM pg_attribute AS p1, pg_class AS p2
|
FROM pg_attribute AS a1, pg_class AS c1
|
||||||
WHERE p1.attrelid = p2.oid AND p1.attnum > p2.relnatts;
|
WHERE a1.attrelid = c1.oid AND a1.attnum > c1.relnatts;
|
||||||
|
|
||||||
-- Detect missing pg_attribute entries: should have as many non-system
|
-- Detect missing pg_attribute entries: should have as many non-system
|
||||||
-- attributes as parent relation expects
|
-- attributes as parent relation expects
|
||||||
|
|
||||||
SELECT p1.oid, p1.relname
|
SELECT c1.oid, c1.relname
|
||||||
FROM pg_class AS p1
|
FROM pg_class AS c1
|
||||||
WHERE p1.relnatts != (SELECT count(*) FROM pg_attribute AS p2
|
WHERE c1.relnatts != (SELECT count(*) FROM pg_attribute AS a1
|
||||||
WHERE p2.attrelid = p1.oid AND p2.attnum > 0);
|
WHERE a1.attrelid = c1.oid AND a1.attnum > 0);
|
||||||
|
|
||||||
-- Cross-check against pg_type entry
|
-- Cross-check against pg_type entry
|
||||||
-- NOTE: we allow attstorage to be 'plain' even when typstorage is not;
|
-- NOTE: we allow attstorage to be 'plain' even when typstorage is not;
|
||||||
-- this is mainly for toast tables.
|
-- this is mainly for toast tables.
|
||||||
|
|
||||||
SELECT p1.attrelid, p1.attname, p2.oid, p2.typname
|
SELECT a1.attrelid, a1.attname, t1.oid, t1.typname
|
||||||
FROM pg_attribute AS p1, pg_type AS p2
|
FROM pg_attribute AS a1, pg_type AS t1
|
||||||
WHERE p1.atttypid = p2.oid AND
|
WHERE a1.atttypid = t1.oid AND
|
||||||
(p1.attlen != p2.typlen OR
|
(a1.attlen != t1.typlen OR
|
||||||
p1.attalign != p2.typalign OR
|
a1.attalign != t1.typalign OR
|
||||||
p1.attbyval != p2.typbyval OR
|
a1.attbyval != t1.typbyval OR
|
||||||
(p1.attstorage != p2.typstorage AND p1.attstorage != 'p'));
|
(a1.attstorage != t1.typstorage AND a1.attstorage != 'p'));
|
||||||
|
|
||||||
-- **************** pg_range ****************
|
-- **************** pg_range ****************
|
||||||
|
|
||||||
-- Look for illegal values in pg_range fields.
|
-- Look for illegal values in pg_range fields.
|
||||||
|
|
||||||
SELECT p1.rngtypid, p1.rngsubtype
|
SELECT r.rngtypid, r.rngsubtype
|
||||||
FROM pg_range as p1
|
FROM pg_range as r
|
||||||
WHERE p1.rngtypid = 0 OR p1.rngsubtype = 0 OR p1.rngsubopc = 0;
|
WHERE r.rngtypid = 0 OR r.rngsubtype = 0 OR r.rngsubopc = 0;
|
||||||
|
|
||||||
-- rngcollation should be specified iff subtype is collatable
|
-- rngcollation should be specified iff subtype is collatable
|
||||||
|
|
||||||
SELECT p1.rngtypid, p1.rngsubtype, p1.rngcollation, t.typcollation
|
SELECT r.rngtypid, r.rngsubtype, r.rngcollation, t.typcollation
|
||||||
FROM pg_range p1 JOIN pg_type t ON t.oid = p1.rngsubtype
|
FROM pg_range r JOIN pg_type t ON t.oid = r.rngsubtype
|
||||||
WHERE (rngcollation = 0) != (typcollation = 0);
|
WHERE (rngcollation = 0) != (typcollation = 0);
|
||||||
|
|
||||||
-- opclass had better be a btree opclass accepting the subtype.
|
-- opclass had better be a btree opclass accepting the subtype.
|
||||||
-- We must allow anyarray matches, cf IsBinaryCoercible()
|
-- We must allow anyarray matches, cf IsBinaryCoercible()
|
||||||
|
|
||||||
SELECT p1.rngtypid, p1.rngsubtype, o.opcmethod, o.opcname
|
SELECT r.rngtypid, r.rngsubtype, o.opcmethod, o.opcname
|
||||||
FROM pg_range p1 JOIN pg_opclass o ON o.oid = p1.rngsubopc
|
FROM pg_range r JOIN pg_opclass o ON o.oid = r.rngsubopc
|
||||||
WHERE o.opcmethod != 403 OR
|
WHERE o.opcmethod != 403 OR
|
||||||
((o.opcintype != p1.rngsubtype) AND NOT
|
((o.opcintype != r.rngsubtype) AND NOT
|
||||||
(o.opcintype = 'pg_catalog.anyarray'::regtype AND
|
(o.opcintype = 'pg_catalog.anyarray'::regtype AND
|
||||||
EXISTS(select 1 from pg_catalog.pg_type where
|
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)));
|
typsubscript = 'array_subscript_handler'::regproc)));
|
||||||
|
|
||||||
-- canonical function, if any, had better match the range type
|
-- canonical function, if any, had better match the range type
|
||||||
|
|
||||||
SELECT p1.rngtypid, p1.rngsubtype, p.proname
|
SELECT r.rngtypid, r.rngsubtype, p.proname
|
||||||
FROM pg_range p1 JOIN pg_proc p ON p.oid = p1.rngcanonical
|
FROM pg_range r JOIN pg_proc p ON p.oid = r.rngcanonical
|
||||||
WHERE pronargs != 1 OR proargtypes[0] != rngtypid OR prorettype != rngtypid;
|
WHERE pronargs != 1 OR proargtypes[0] != rngtypid OR prorettype != rngtypid;
|
||||||
|
|
||||||
-- subdiff function, if any, had better match the subtype
|
-- subdiff function, if any, had better match the subtype
|
||||||
|
|
||||||
SELECT p1.rngtypid, p1.rngsubtype, p.proname
|
SELECT r.rngtypid, r.rngsubtype, p.proname
|
||||||
FROM pg_range p1 JOIN pg_proc p ON p.oid = p1.rngsubdiff
|
FROM pg_range r JOIN pg_proc p ON p.oid = r.rngsubdiff
|
||||||
WHERE pronargs != 2
|
WHERE pronargs != 2
|
||||||
OR proargtypes[0] != rngsubtype OR proargtypes[1] != rngsubtype
|
OR proargtypes[0] != rngsubtype OR proargtypes[1] != rngsubtype
|
||||||
OR prorettype != 'pg_catalog.float8'::regtype;
|
OR prorettype != 'pg_catalog.float8'::regtype;
|
||||||
|
|
||||||
-- every range should have a valid multirange
|
-- every range should have a valid multirange
|
||||||
|
|
||||||
SELECT p1.rngtypid, p1.rngsubtype, p1.rngmultitypid
|
SELECT r.rngtypid, r.rngsubtype, r.rngmultitypid
|
||||||
FROM pg_range p1
|
FROM pg_range r
|
||||||
WHERE p1.rngmultitypid IS NULL OR p1.rngmultitypid = 0;
|
WHERE r.rngmultitypid IS NULL OR r.rngmultitypid = 0;
|
||||||
|
|
||||||
-- Create a table that holds all the known in-core data types and leave it
|
-- 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.
|
-- around so as pg_upgrade is able to test their binary compatibility.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user