mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Restructure pg_opclass, pg_amop, and pg_amproc per previous discussions in
pgsql-hackers. pg_opclass now has a row for each opclass supported by each index AM, not a row for each opclass name. This allows pg_opclass to show directly whether an AM supports an opclass, and furthermore makes it possible to store additional information about an opclass that might be AM-dependent. pg_opclass and pg_amop now store "lossy" and "haskeytype" information that we previously expected the user to remember to provide in CREATE INDEX commands. Lossiness is no longer an index-level property, but is associated with the use of a particular operator in a particular index opclass. Along the way, IndexSupportInitialize now uses the syscaches to retrieve pg_amop and pg_amproc entries. I find this reduces backend launch time by about ten percent, at the cost of a couple more special cases in catcache.c's IndexScanOK. Initial work by Oleg Bartunov and Teodor Sigaev, further hacking by Tom Lane. initdb forced.
This commit is contained in:
@ -121,14 +121,6 @@ WHERE pg_am.amcostestimate != 0 AND
|
||||
------+----------------
|
||||
(0 rows)
|
||||
|
||||
SELECT ctid, pg_amop.amopid
|
||||
FROM pg_amop
|
||||
WHERE pg_amop.amopid != 0 AND
|
||||
NOT EXISTS(SELECT * FROM pg_am AS t1 WHERE t1.oid = pg_amop.amopid);
|
||||
ctid | amopid
|
||||
------+--------
|
||||
(0 rows)
|
||||
|
||||
SELECT ctid, pg_amop.amopclaid
|
||||
FROM pg_amop
|
||||
WHERE pg_amop.amopclaid != 0 AND
|
||||
@ -145,14 +137,6 @@ WHERE pg_amop.amopopr != 0 AND
|
||||
------+---------
|
||||
(0 rows)
|
||||
|
||||
SELECT ctid, pg_amproc.amid
|
||||
FROM pg_amproc
|
||||
WHERE pg_amproc.amid != 0 AND
|
||||
NOT EXISTS(SELECT * FROM pg_am AS t1 WHERE t1.oid = pg_amproc.amid);
|
||||
ctid | amid
|
||||
------+------
|
||||
(0 rows)
|
||||
|
||||
SELECT ctid, pg_amproc.amopclaid
|
||||
FROM pg_amproc
|
||||
WHERE pg_amproc.amopclaid != 0 AND
|
||||
@ -241,12 +225,20 @@ WHERE pg_index.indrelid != 0 AND
|
||||
------+----------
|
||||
(0 rows)
|
||||
|
||||
SELECT ctid, pg_opclass.opcdeftype
|
||||
SELECT ctid, pg_opclass.opcamid
|
||||
FROM pg_opclass
|
||||
WHERE pg_opclass.opcdeftype != 0 AND
|
||||
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_opclass.opcdeftype);
|
||||
ctid | opcdeftype
|
||||
------+------------
|
||||
WHERE pg_opclass.opcamid != 0 AND
|
||||
NOT EXISTS(SELECT * FROM pg_am AS t1 WHERE t1.oid = pg_opclass.opcamid);
|
||||
ctid | opcamid
|
||||
------+---------
|
||||
(0 rows)
|
||||
|
||||
SELECT ctid, pg_opclass.opcintype
|
||||
FROM pg_opclass
|
||||
WHERE pg_opclass.opcintype != 0 AND
|
||||
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_opclass.opcintype);
|
||||
ctid | opcintype
|
||||
------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT ctid, pg_operator.oprleft
|
||||
|
@ -508,45 +508,50 @@ WHERE p1.aggtransfn = p2.oid AND p2.proisstrict AND
|
||||
(0 rows)
|
||||
|
||||
-- **************** pg_opclass ****************
|
||||
-- There should not be multiple entries in pg_opclass with the same
|
||||
-- nonzero opcdeftype value, because there can be only one default opclass
|
||||
-- for a datatype. (But multiple entries with zero opcdeftype are OK.)
|
||||
-- Look for illegal values in pg_opclass fields
|
||||
SELECT p1.oid
|
||||
FROM pg_opclass as p1
|
||||
WHERE p1.opcamid = 0 OR p1.opcintype = 0;
|
||||
oid
|
||||
-----
|
||||
(0 rows)
|
||||
|
||||
-- There should not be multiple entries in pg_opclass with opcdefault true
|
||||
-- and the same opcamid/opcintype combination.
|
||||
SELECT p1.oid, p2.oid
|
||||
FROM pg_opclass AS p1, pg_opclass AS p2
|
||||
WHERE p1.oid != p2.oid AND
|
||||
p1.opcdeftype = p2.opcdeftype AND
|
||||
p1.opcdeftype != 0;
|
||||
p1.opcamid = p2.opcamid AND p1.opcintype = p2.opcintype AND
|
||||
p1.opcdefault AND p2.opcdefault;
|
||||
oid | oid
|
||||
-----+-----
|
||||
(0 rows)
|
||||
|
||||
-- **************** pg_amop ****************
|
||||
-- Look for illegal values in pg_amop fields
|
||||
SELECT p1.amopclaid, p1.amopopr, p1.amopid
|
||||
SELECT p1.amopclaid, p1.amopstrategy
|
||||
FROM pg_amop as p1
|
||||
WHERE p1.amopid = 0 OR p1.amopclaid = 0 OR p1.amopopr = 0 OR
|
||||
p1.amopstrategy <= 0;
|
||||
amopclaid | amopopr | amopid
|
||||
-----------+---------+--------
|
||||
WHERE p1.amopclaid = 0 OR p1.amopstrategy <= 0 OR p1.amopopr = 0;
|
||||
amopclaid | amopstrategy
|
||||
-----------+--------------
|
||||
(0 rows)
|
||||
|
||||
-- Cross-check amopstrategy index against parent AM
|
||||
SELECT p1.amopclaid, p1.amopopr, p1.amopid, p2.oid, p2.amname
|
||||
FROM pg_amop AS p1, pg_am AS p2
|
||||
WHERE p1.amopid = p2.oid AND p1.amopstrategy > p2.amstrategies;
|
||||
amopclaid | amopopr | amopid | oid | amname
|
||||
-----------+---------+--------+-----+--------
|
||||
SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.amname
|
||||
FROM pg_amop AS p1, pg_am AS p2, pg_opclass AS p3
|
||||
WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND
|
||||
p1.amopstrategy > p2.amstrategies;
|
||||
amopclaid | amopopr | oid | amname
|
||||
-----------+---------+-----+--------
|
||||
(0 rows)
|
||||
|
||||
-- Detect missing pg_amop entries: should have as many strategy functions
|
||||
-- as AM expects for each opclass, unless there are none at all
|
||||
-- (some opclasses only offer support for a limited set of AMs...)
|
||||
-- as AM expects for each opclass for the AM
|
||||
SELECT p1.oid, p1.amname, p2.oid, p2.opcname
|
||||
FROM pg_am AS p1, pg_opclass AS p2
|
||||
WHERE p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3
|
||||
WHERE p3.amopid = p1.oid AND p3.amopclaid = p2.oid)
|
||||
AND EXISTS (SELECT * FROM pg_amop AS p3
|
||||
WHERE p3.amopid = p1.oid AND p3.amopclaid = p2.oid);
|
||||
WHERE p2.opcamid = p1.oid AND
|
||||
p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3
|
||||
WHERE p3.amopclaid = p2.oid);
|
||||
oid | amname | oid | opcname
|
||||
-----+--------+-----+---------
|
||||
(0 rows)
|
||||
@ -555,51 +560,48 @@ WHERE p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3
|
||||
-- operator yielding boolean.
|
||||
-- NOTE: for 7.1, add restriction that operator inputs are of same type.
|
||||
-- We used to have opclasses like "int24_ops" but these were broken.
|
||||
SELECT p1.amopclaid, p1.amopopr, p1.amopid, p2.oid, p2.oprname
|
||||
SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname
|
||||
FROM pg_amop AS p1, pg_operator AS p2
|
||||
WHERE p1.amopopr = p2.oid AND
|
||||
(p2.oprkind != 'b' OR p2.oprresult != 16 OR p2.oprleft != p2.oprright);
|
||||
amopclaid | amopopr | amopid | oid | oprname
|
||||
-----------+---------+--------+-----+---------
|
||||
amopclaid | amopopr | oid | oprname
|
||||
-----------+---------+-----+---------
|
||||
(0 rows)
|
||||
|
||||
-- If opclass is for a specific type, operator inputs should be of that type
|
||||
SELECT p1.amopclaid, p1.amopopr, p1.amopid, p2.oid, p2.oprname, p3.oid, p3.opcname
|
||||
-- Check that operator input types match the opclass
|
||||
SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname
|
||||
FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3
|
||||
WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND
|
||||
p3.opcdeftype != 0 AND
|
||||
(p3.opcdeftype != p2.oprleft OR p3.opcdeftype != p2.oprright);
|
||||
amopclaid | amopopr | amopid | oid | oprname | oid | opcname
|
||||
-----------+---------+--------+-----+---------+-----+---------
|
||||
(p3.opcintype != p2.oprleft OR p3.opcintype != p2.oprright);
|
||||
amopclaid | amopopr | oid | oprname | opcname
|
||||
-----------+---------+-----+---------+---------
|
||||
(0 rows)
|
||||
|
||||
-- **************** pg_amproc ****************
|
||||
-- Look for illegal values in pg_amproc fields
|
||||
SELECT p1.amid, p1.amopclaid, p1.amprocnum
|
||||
SELECT p1.amopclaid, p1.amprocnum
|
||||
FROM pg_amproc as p1
|
||||
WHERE p1.amid = 0 OR p1.amopclaid = 0 OR p1.amproc = 0 OR
|
||||
p1.amprocnum <= 0;
|
||||
amid | amopclaid | amprocnum
|
||||
------+-----------+-----------
|
||||
WHERE p1.amopclaid = 0 OR p1.amprocnum <= 0 OR p1.amproc = 0;
|
||||
amopclaid | amprocnum
|
||||
-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
-- Cross-check amprocnum index against parent AM
|
||||
SELECT p1.amid, p1.amopclaid, p1.amprocnum, p2.oid, p2.amname
|
||||
FROM pg_amproc AS p1, pg_am AS p2
|
||||
WHERE p1.amid = p2.oid AND p1.amprocnum > p2.amsupport;
|
||||
amid | amopclaid | amprocnum | oid | amname
|
||||
------+-----------+-----------+-----+--------
|
||||
SELECT p1.amopclaid, p1.amprocnum, p2.oid, p2.amname
|
||||
FROM pg_amproc AS p1, pg_am AS p2, pg_opclass AS p3
|
||||
WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND
|
||||
p1.amprocnum > p2.amsupport;
|
||||
amopclaid | amprocnum | oid | amname
|
||||
-----------+-----------+-----+--------
|
||||
(0 rows)
|
||||
|
||||
-- Detect missing pg_amproc entries: should have as many support functions
|
||||
-- as AM expects for each opclass, unless there are none at all
|
||||
-- (some opclasses only offer support for a limited set of AMs...)
|
||||
-- as AM expects for each opclass for the AM
|
||||
SELECT p1.oid, p1.amname, p2.oid, p2.opcname
|
||||
FROM pg_am AS p1, pg_opclass AS p2
|
||||
WHERE p1.amsupport != (SELECT count(*) FROM pg_amproc AS p3
|
||||
WHERE p3.amid = p1.oid AND p3.amopclaid = p2.oid)
|
||||
AND EXISTS (SELECT * FROM pg_amproc AS p3
|
||||
WHERE p3.amid = p1.oid AND p3.amopclaid = p2.oid);
|
||||
WHERE p2.opcamid = p1.oid AND
|
||||
p1.amsupport != (SELECT count(*) FROM pg_amproc AS p3
|
||||
WHERE p3.amopclaid = p2.oid);
|
||||
oid | amname | oid | opcname
|
||||
-----+--------+-----+---------
|
||||
(0 rows)
|
||||
@ -609,49 +611,19 @@ WHERE p1.amsupport != (SELECT count(*) FROM pg_amproc AS p3
|
||||
-- or different base data types.
|
||||
-- We can check that all the referenced instances of the same support
|
||||
-- routine number take the same number of parameters, but that's about it...
|
||||
SELECT p1.amid, p1.amopclaid, p1.amprocnum,
|
||||
SELECT p1.amopclaid, p1.amprocnum,
|
||||
p2.oid, p2.proname,
|
||||
p3.amid, p3.amopclaid, p3.amprocnum,
|
||||
p4.oid, p4.proname
|
||||
FROM pg_amproc AS p1, pg_proc AS p2, pg_amproc AS p3, pg_proc AS p4
|
||||
WHERE p1.amid = p3.amid AND p1.amprocnum = p3.amprocnum AND
|
||||
p1.amproc = p2.oid AND p3.amproc = p4.oid AND
|
||||
(p2.proretset OR p4.proretset OR p2.pronargs != p4.pronargs);
|
||||
amid | amopclaid | amprocnum | oid | proname | amid | amopclaid | amprocnum | oid | proname
|
||||
------+-----------+-----------+-----+---------+------+-----------+-----------+-----+---------
|
||||
(0 rows)
|
||||
|
||||
-- Cross-check that each opclass that has any entries for a given AM
|
||||
-- has all the entries that any other opclass does. This catches cases
|
||||
-- where an opclass has pg_amop but not pg_amproc entries or vice versa.
|
||||
-- (The above tests for missing pg_amop or pg_amproc entries are redundant
|
||||
-- with this, but I'll leave them in place anyway.)
|
||||
-- All the strategy index numbers used for each AM
|
||||
CREATE TEMP TABLE amopstrategies AS
|
||||
SELECT DISTINCT amopid, amopstrategy FROM pg_amop;
|
||||
-- All the support proc numbers used for each AM
|
||||
CREATE TEMP TABLE amprocnums AS
|
||||
SELECT DISTINCT amid, amprocnum FROM pg_amproc;
|
||||
-- All the opclasses that claim to have support for each AM in either table.
|
||||
-- UNION implies DISTINCT, so we do not need DISTINCT in the sub-selects.
|
||||
CREATE TEMP TABLE amopclassids AS
|
||||
SELECT amid, amopclaid FROM pg_amproc UNION
|
||||
SELECT amopid, amopclaid FROM pg_amop;
|
||||
-- Look for AMs that are missing one or more strategy operators
|
||||
SELECT * FROM amopclassids c, amopstrategies s
|
||||
WHERE c.amid = s.amopid AND NOT EXISTS
|
||||
(SELECT 1 FROM pg_amop a WHERE a.amopid = c.amid AND
|
||||
a.amopclaid = c.amopclaid AND a.amopstrategy = s.amopstrategy);
|
||||
amid | amopclaid | amopid | amopstrategy
|
||||
------+-----------+--------+--------------
|
||||
(0 rows)
|
||||
|
||||
-- Look for AMs that are missing one or more support procs
|
||||
SELECT * FROM amopclassids c, amprocnums p
|
||||
WHERE c.amid = p.amid AND NOT EXISTS
|
||||
(SELECT 1 FROM pg_amproc a WHERE a.amid = c.amid AND
|
||||
a.amopclaid = c.amopclaid AND a.amprocnum = p.amprocnum);
|
||||
amid | amopclaid | amid | amprocnum
|
||||
------+-----------+------+-----------
|
||||
p3.opcname,
|
||||
p4.amopclaid, p4.amprocnum,
|
||||
p5.oid, p5.proname,
|
||||
p6.opcname
|
||||
FROM pg_amproc AS p1, pg_proc AS p2, pg_opclass AS p3,
|
||||
pg_amproc AS p4, pg_proc AS p5, pg_opclass AS p6
|
||||
WHERE p1.amopclaid = p3.oid AND p4.amopclaid = p6.oid AND
|
||||
p3.opcamid = p6.opcamid AND p1.amprocnum = p4.amprocnum AND
|
||||
p1.amproc = p2.oid AND p4.amproc = p5.oid AND
|
||||
(p2.proretset OR p5.proretset OR p2.pronargs != p5.pronargs);
|
||||
amopclaid | amprocnum | oid | proname | opcname | amopclaid | amprocnum | oid | proname | opcname
|
||||
-----------+-----------+-----+---------+---------+-----------+-----------+-----+---------+---------
|
||||
(0 rows)
|
||||
|
||||
|
@ -61,10 +61,6 @@ SELECT ctid, pg_am.amcostestimate
|
||||
FROM pg_am
|
||||
WHERE pg_am.amcostestimate != 0 AND
|
||||
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.amcostestimate);
|
||||
SELECT ctid, pg_amop.amopid
|
||||
FROM pg_amop
|
||||
WHERE pg_amop.amopid != 0 AND
|
||||
NOT EXISTS(SELECT * FROM pg_am AS t1 WHERE t1.oid = pg_amop.amopid);
|
||||
SELECT ctid, pg_amop.amopclaid
|
||||
FROM pg_amop
|
||||
WHERE pg_amop.amopclaid != 0 AND
|
||||
@ -73,10 +69,6 @@ SELECT ctid, pg_amop.amopopr
|
||||
FROM pg_amop
|
||||
WHERE pg_amop.amopopr != 0 AND
|
||||
NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_amop.amopopr);
|
||||
SELECT ctid, pg_amproc.amid
|
||||
FROM pg_amproc
|
||||
WHERE pg_amproc.amid != 0 AND
|
||||
NOT EXISTS(SELECT * FROM pg_am AS t1 WHERE t1.oid = pg_amproc.amid);
|
||||
SELECT ctid, pg_amproc.amopclaid
|
||||
FROM pg_amproc
|
||||
WHERE pg_amproc.amopclaid != 0 AND
|
||||
@ -121,10 +113,14 @@ SELECT ctid, pg_index.indrelid
|
||||
FROM pg_index
|
||||
WHERE pg_index.indrelid != 0 AND
|
||||
NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_index.indrelid);
|
||||
SELECT ctid, pg_opclass.opcdeftype
|
||||
SELECT ctid, pg_opclass.opcamid
|
||||
FROM pg_opclass
|
||||
WHERE pg_opclass.opcdeftype != 0 AND
|
||||
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_opclass.opcdeftype);
|
||||
WHERE pg_opclass.opcamid != 0 AND
|
||||
NOT EXISTS(SELECT * FROM pg_am AS t1 WHERE t1.oid = pg_opclass.opcamid);
|
||||
SELECT ctid, pg_opclass.opcintype
|
||||
FROM pg_opclass
|
||||
WHERE pg_opclass.opcintype != 0 AND
|
||||
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_opclass.opcintype);
|
||||
SELECT ctid, pg_operator.oprleft
|
||||
FROM pg_operator
|
||||
WHERE pg_operator.oprleft != 0 AND
|
||||
|
@ -425,85 +425,85 @@ WHERE p1.aggtransfn = p2.oid AND p2.proisstrict AND
|
||||
|
||||
-- **************** pg_opclass ****************
|
||||
|
||||
-- There should not be multiple entries in pg_opclass with the same
|
||||
-- nonzero opcdeftype value, because there can be only one default opclass
|
||||
-- for a datatype. (But multiple entries with zero opcdeftype are OK.)
|
||||
-- Look for illegal values in pg_opclass fields
|
||||
|
||||
SELECT p1.oid
|
||||
FROM pg_opclass as p1
|
||||
WHERE p1.opcamid = 0 OR p1.opcintype = 0;
|
||||
|
||||
-- There should not be multiple entries in pg_opclass with opcdefault true
|
||||
-- and the same opcamid/opcintype combination.
|
||||
|
||||
SELECT p1.oid, p2.oid
|
||||
FROM pg_opclass AS p1, pg_opclass AS p2
|
||||
WHERE p1.oid != p2.oid AND
|
||||
p1.opcdeftype = p2.opcdeftype AND
|
||||
p1.opcdeftype != 0;
|
||||
p1.opcamid = p2.opcamid AND p1.opcintype = p2.opcintype AND
|
||||
p1.opcdefault AND p2.opcdefault;
|
||||
|
||||
-- **************** pg_amop ****************
|
||||
|
||||
-- Look for illegal values in pg_amop fields
|
||||
|
||||
SELECT p1.amopclaid, p1.amopopr, p1.amopid
|
||||
SELECT p1.amopclaid, p1.amopstrategy
|
||||
FROM pg_amop as p1
|
||||
WHERE p1.amopid = 0 OR p1.amopclaid = 0 OR p1.amopopr = 0 OR
|
||||
p1.amopstrategy <= 0;
|
||||
WHERE p1.amopclaid = 0 OR p1.amopstrategy <= 0 OR p1.amopopr = 0;
|
||||
|
||||
-- Cross-check amopstrategy index against parent AM
|
||||
|
||||
SELECT p1.amopclaid, p1.amopopr, p1.amopid, p2.oid, p2.amname
|
||||
FROM pg_amop AS p1, pg_am AS p2
|
||||
WHERE p1.amopid = p2.oid AND p1.amopstrategy > p2.amstrategies;
|
||||
SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.amname
|
||||
FROM pg_amop AS p1, pg_am AS p2, pg_opclass AS p3
|
||||
WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND
|
||||
p1.amopstrategy > p2.amstrategies;
|
||||
|
||||
-- Detect missing pg_amop entries: should have as many strategy functions
|
||||
-- as AM expects for each opclass, unless there are none at all
|
||||
-- (some opclasses only offer support for a limited set of AMs...)
|
||||
-- as AM expects for each opclass for the AM
|
||||
|
||||
SELECT p1.oid, p1.amname, p2.oid, p2.opcname
|
||||
FROM pg_am AS p1, pg_opclass AS p2
|
||||
WHERE p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3
|
||||
WHERE p3.amopid = p1.oid AND p3.amopclaid = p2.oid)
|
||||
AND EXISTS (SELECT * FROM pg_amop AS p3
|
||||
WHERE p3.amopid = p1.oid AND p3.amopclaid = p2.oid);
|
||||
WHERE p2.opcamid = p1.oid AND
|
||||
p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3
|
||||
WHERE p3.amopclaid = p2.oid);
|
||||
|
||||
-- Check that amopopr points at a reasonable-looking operator, ie a binary
|
||||
-- operator yielding boolean.
|
||||
-- NOTE: for 7.1, add restriction that operator inputs are of same type.
|
||||
-- We used to have opclasses like "int24_ops" but these were broken.
|
||||
|
||||
SELECT p1.amopclaid, p1.amopopr, p1.amopid, p2.oid, p2.oprname
|
||||
SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname
|
||||
FROM pg_amop AS p1, pg_operator AS p2
|
||||
WHERE p1.amopopr = p2.oid AND
|
||||
(p2.oprkind != 'b' OR p2.oprresult != 16 OR p2.oprleft != p2.oprright);
|
||||
|
||||
-- If opclass is for a specific type, operator inputs should be of that type
|
||||
-- Check that operator input types match the opclass
|
||||
|
||||
SELECT p1.amopclaid, p1.amopopr, p1.amopid, p2.oid, p2.oprname, p3.oid, p3.opcname
|
||||
SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname
|
||||
FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3
|
||||
WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND
|
||||
p3.opcdeftype != 0 AND
|
||||
(p3.opcdeftype != p2.oprleft OR p3.opcdeftype != p2.oprright);
|
||||
(p3.opcintype != p2.oprleft OR p3.opcintype != p2.oprright);
|
||||
|
||||
-- **************** pg_amproc ****************
|
||||
|
||||
-- Look for illegal values in pg_amproc fields
|
||||
|
||||
SELECT p1.amid, p1.amopclaid, p1.amprocnum
|
||||
SELECT p1.amopclaid, p1.amprocnum
|
||||
FROM pg_amproc as p1
|
||||
WHERE p1.amid = 0 OR p1.amopclaid = 0 OR p1.amproc = 0 OR
|
||||
p1.amprocnum <= 0;
|
||||
WHERE p1.amopclaid = 0 OR p1.amprocnum <= 0 OR p1.amproc = 0;
|
||||
|
||||
-- Cross-check amprocnum index against parent AM
|
||||
|
||||
SELECT p1.amid, p1.amopclaid, p1.amprocnum, p2.oid, p2.amname
|
||||
FROM pg_amproc AS p1, pg_am AS p2
|
||||
WHERE p1.amid = p2.oid AND p1.amprocnum > p2.amsupport;
|
||||
SELECT p1.amopclaid, p1.amprocnum, p2.oid, p2.amname
|
||||
FROM pg_amproc AS p1, pg_am AS p2, pg_opclass AS p3
|
||||
WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND
|
||||
p1.amprocnum > p2.amsupport;
|
||||
|
||||
-- Detect missing pg_amproc entries: should have as many support functions
|
||||
-- as AM expects for each opclass, unless there are none at all
|
||||
-- (some opclasses only offer support for a limited set of AMs...)
|
||||
-- as AM expects for each opclass for the AM
|
||||
|
||||
SELECT p1.oid, p1.amname, p2.oid, p2.opcname
|
||||
FROM pg_am AS p1, pg_opclass AS p2
|
||||
WHERE p1.amsupport != (SELECT count(*) FROM pg_amproc AS p3
|
||||
WHERE p3.amid = p1.oid AND p3.amopclaid = p2.oid)
|
||||
AND EXISTS (SELECT * FROM pg_amproc AS p3
|
||||
WHERE p3.amid = p1.oid AND p3.amopclaid = p2.oid);
|
||||
WHERE p2.opcamid = p1.oid AND
|
||||
p1.amsupport != (SELECT count(*) FROM pg_amproc AS p3
|
||||
WHERE p3.amopclaid = p2.oid);
|
||||
|
||||
-- Unfortunately, we can't check the amproc link very well because the
|
||||
-- signature of the function may be different for different support routines
|
||||
@ -511,43 +511,15 @@ WHERE p1.amsupport != (SELECT count(*) FROM pg_amproc AS p3
|
||||
-- We can check that all the referenced instances of the same support
|
||||
-- routine number take the same number of parameters, but that's about it...
|
||||
|
||||
SELECT p1.amid, p1.amopclaid, p1.amprocnum,
|
||||
SELECT p1.amopclaid, p1.amprocnum,
|
||||
p2.oid, p2.proname,
|
||||
p3.amid, p3.amopclaid, p3.amprocnum,
|
||||
p4.oid, p4.proname
|
||||
FROM pg_amproc AS p1, pg_proc AS p2, pg_amproc AS p3, pg_proc AS p4
|
||||
WHERE p1.amid = p3.amid AND p1.amprocnum = p3.amprocnum AND
|
||||
p1.amproc = p2.oid AND p3.amproc = p4.oid AND
|
||||
(p2.proretset OR p4.proretset OR p2.pronargs != p4.pronargs);
|
||||
|
||||
-- Cross-check that each opclass that has any entries for a given AM
|
||||
-- has all the entries that any other opclass does. This catches cases
|
||||
-- where an opclass has pg_amop but not pg_amproc entries or vice versa.
|
||||
-- (The above tests for missing pg_amop or pg_amproc entries are redundant
|
||||
-- with this, but I'll leave them in place anyway.)
|
||||
|
||||
-- All the strategy index numbers used for each AM
|
||||
CREATE TEMP TABLE amopstrategies AS
|
||||
SELECT DISTINCT amopid, amopstrategy FROM pg_amop;
|
||||
|
||||
-- All the support proc numbers used for each AM
|
||||
CREATE TEMP TABLE amprocnums AS
|
||||
SELECT DISTINCT amid, amprocnum FROM pg_amproc;
|
||||
|
||||
-- All the opclasses that claim to have support for each AM in either table.
|
||||
-- UNION implies DISTINCT, so we do not need DISTINCT in the sub-selects.
|
||||
CREATE TEMP TABLE amopclassids AS
|
||||
SELECT amid, amopclaid FROM pg_amproc UNION
|
||||
SELECT amopid, amopclaid FROM pg_amop;
|
||||
|
||||
-- Look for AMs that are missing one or more strategy operators
|
||||
SELECT * FROM amopclassids c, amopstrategies s
|
||||
WHERE c.amid = s.amopid AND NOT EXISTS
|
||||
(SELECT 1 FROM pg_amop a WHERE a.amopid = c.amid AND
|
||||
a.amopclaid = c.amopclaid AND a.amopstrategy = s.amopstrategy);
|
||||
|
||||
-- Look for AMs that are missing one or more support procs
|
||||
SELECT * FROM amopclassids c, amprocnums p
|
||||
WHERE c.amid = p.amid AND NOT EXISTS
|
||||
(SELECT 1 FROM pg_amproc a WHERE a.amid = c.amid AND
|
||||
a.amopclaid = c.amopclaid AND a.amprocnum = p.amprocnum);
|
||||
p3.opcname,
|
||||
p4.amopclaid, p4.amprocnum,
|
||||
p5.oid, p5.proname,
|
||||
p6.opcname
|
||||
FROM pg_amproc AS p1, pg_proc AS p2, pg_opclass AS p3,
|
||||
pg_amproc AS p4, pg_proc AS p5, pg_opclass AS p6
|
||||
WHERE p1.amopclaid = p3.oid AND p4.amopclaid = p6.oid AND
|
||||
p3.opcamid = p6.opcamid AND p1.amprocnum = p4.amprocnum AND
|
||||
p1.amproc = p2.oid AND p4.amproc = p5.oid AND
|
||||
(p2.proretset OR p5.proretset OR p2.pronargs != p5.pronargs);
|
||||
|
Reference in New Issue
Block a user