Add testing to detect errors of omission in "pin" dependency creation.
It's essential that initdb.c's setup_depend() scan each system catalog
that could contain objects that need to have "p" (pin) entries in pg_depend
or pg_shdepend. Forgetting to add that, either when a catalog is first
invented or when it first acquires DATA() entries, is an obvious bug
hazard. We can detect such omissions at reasonable cost by probing every
OID-containing system catalog to see whether the lowest-numbered OID in it
is pinned. If so, the catalog must have been properly accounted for in
setup_depend(). If the lowest OID is above FirstNormalObjectId then the
catalog must have been empty at the end of initdb, so it doesn't matter.
There are a small number of catalogs whose first entry is made later in
initdb than setup_depend(), resulting in nonempty expected output of the
test, but these can be manually inspected to see that they are OK. Any
future mistake of this ilk will manifest as a new entry in the test's
output.
Since pg_conversion is already in the test's output, add it to the set of
catalogs scanned by setup_depend(). That has no effect today (hence, no
catversion bump here) but it will protect us if we ever do add pin-worthy
conversions.
This test is very much like the catalog sanity checks embodied in
opr_sanity.sql and type_sanity.sql, but testing pg_depend doesn't seem to
fit naturally into either of those scripts' charters. Hence, invent a new
test script misc_sanity.sql, which can be a home for this as well as tests
on any other catalogs we might want in future.
Discussion: https://postgr.es/m/8068.1498155068@sss.pgh.pa.us
2017-06-23 17:03:04 +02:00
|
|
|
--
|
|
|
|
-- MISC_SANITY
|
|
|
|
-- Sanity checks for common errors in making system tables that don't fit
|
|
|
|
-- comfortably into either opr_sanity or type_sanity.
|
|
|
|
--
|
|
|
|
-- Every test failure in this file should be closely inspected.
|
|
|
|
-- The description of the failing test should be read carefully before
|
|
|
|
-- adjusting the expected output. In most cases, the queries should
|
|
|
|
-- not find *any* matching entries.
|
|
|
|
--
|
|
|
|
-- NB: run this test early, because some later tests create bogus entries.
|
|
|
|
-- **************** pg_depend ****************
|
|
|
|
-- Look for illegal values in pg_depend fields.
|
|
|
|
-- classid/objid can be zero, but only in 'p' entries
|
|
|
|
SELECT *
|
|
|
|
FROM pg_depend as d1
|
|
|
|
WHERE refclassid = 0 OR refobjid = 0 OR
|
|
|
|
deptype NOT IN ('a', 'e', 'i', 'n', 'p') OR
|
|
|
|
(deptype != 'p' AND (classid = 0 OR objid = 0)) OR
|
|
|
|
(deptype = 'p' AND (classid != 0 OR objid != 0 OR objsubid != 0));
|
|
|
|
classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype
|
|
|
|
---------+-------+----------+------------+----------+-------------+---------
|
|
|
|
(0 rows)
|
|
|
|
|
|
|
|
-- **************** pg_shdepend ****************
|
|
|
|
-- Look for illegal values in pg_shdepend fields.
|
|
|
|
-- classid/objid can be zero, but only in 'p' entries
|
|
|
|
SELECT *
|
|
|
|
FROM pg_shdepend as d1
|
|
|
|
WHERE refclassid = 0 OR refobjid = 0 OR
|
|
|
|
deptype NOT IN ('a', 'o', 'p', 'r') OR
|
2017-08-28 16:14:20 +02:00
|
|
|
(deptype != 'p' AND (classid = 0 OR objid = 0)) OR
|
Add testing to detect errors of omission in "pin" dependency creation.
It's essential that initdb.c's setup_depend() scan each system catalog
that could contain objects that need to have "p" (pin) entries in pg_depend
or pg_shdepend. Forgetting to add that, either when a catalog is first
invented or when it first acquires DATA() entries, is an obvious bug
hazard. We can detect such omissions at reasonable cost by probing every
OID-containing system catalog to see whether the lowest-numbered OID in it
is pinned. If so, the catalog must have been properly accounted for in
setup_depend(). If the lowest OID is above FirstNormalObjectId then the
catalog must have been empty at the end of initdb, so it doesn't matter.
There are a small number of catalogs whose first entry is made later in
initdb than setup_depend(), resulting in nonempty expected output of the
test, but these can be manually inspected to see that they are OK. Any
future mistake of this ilk will manifest as a new entry in the test's
output.
Since pg_conversion is already in the test's output, add it to the set of
catalogs scanned by setup_depend(). That has no effect today (hence, no
catversion bump here) but it will protect us if we ever do add pin-worthy
conversions.
This test is very much like the catalog sanity checks embodied in
opr_sanity.sql and type_sanity.sql, but testing pg_depend doesn't seem to
fit naturally into either of those scripts' charters. Hence, invent a new
test script misc_sanity.sql, which can be a home for this as well as tests
on any other catalogs we might want in future.
Discussion: https://postgr.es/m/8068.1498155068@sss.pgh.pa.us
2017-06-23 17:03:04 +02:00
|
|
|
(deptype = 'p' AND (dbid != 0 OR classid != 0 OR objid != 0 OR objsubid != 0));
|
|
|
|
dbid | classid | objid | objsubid | refclassid | refobjid | deptype
|
|
|
|
------+---------+-------+----------+------------+----------+---------
|
|
|
|
(0 rows)
|
|
|
|
|
|
|
|
-- Check each OID-containing system catalog to see if its lowest-numbered OID
|
|
|
|
-- is pinned. If not, and if that OID was generated during initdb, then
|
|
|
|
-- perhaps initdb forgot to scan that catalog for pinnable entries.
|
|
|
|
-- Generally, it's okay for a catalog to be listed in the output of this
|
|
|
|
-- test if that catalog is scanned by initdb.c's setup_depend() function;
|
|
|
|
-- whatever OID the test is complaining about must have been added later
|
|
|
|
-- in initdb, where it intentionally isn't pinned. Legitimate exceptions
|
|
|
|
-- to that rule are listed in the comments in setup_depend().
|
|
|
|
do $$
|
|
|
|
declare relnm text;
|
|
|
|
reloid oid;
|
|
|
|
shared bool;
|
|
|
|
lowoid oid;
|
|
|
|
pinned bool;
|
|
|
|
begin
|
|
|
|
for relnm, reloid, shared in
|
|
|
|
select relname, oid, relisshared from pg_class
|
|
|
|
where relhasoids and oid < 16384 order by 1
|
|
|
|
loop
|
|
|
|
execute 'select min(oid) from ' || relnm into lowoid;
|
|
|
|
continue when lowoid is null or lowoid >= 16384;
|
|
|
|
if shared then
|
|
|
|
pinned := exists(select 1 from pg_shdepend
|
|
|
|
where refclassid = reloid and refobjid = lowoid
|
|
|
|
and deptype = 'p');
|
|
|
|
else
|
|
|
|
pinned := exists(select 1 from pg_depend
|
|
|
|
where refclassid = reloid and refobjid = lowoid
|
|
|
|
and deptype = 'p');
|
|
|
|
end if;
|
|
|
|
if not pinned then
|
|
|
|
raise notice '% contains unpinned initdb-created object(s)', relnm;
|
|
|
|
end if;
|
|
|
|
end loop;
|
|
|
|
end$$;
|
|
|
|
NOTICE: pg_constraint contains unpinned initdb-created object(s)
|
|
|
|
NOTICE: pg_conversion contains unpinned initdb-created object(s)
|
|
|
|
NOTICE: pg_database contains unpinned initdb-created object(s)
|
|
|
|
NOTICE: pg_extension contains unpinned initdb-created object(s)
|
|
|
|
NOTICE: pg_rewrite contains unpinned initdb-created object(s)
|
|
|
|
NOTICE: pg_tablespace contains unpinned initdb-created object(s)
|