1--
2-- Verify system catalog foreign key relationships
3--
4DO $doblock$
5declare
6  fk record;
7  nkeys integer;
8  cmd text;
9  err record;
10begin
11  for fk in select * from pg_get_catalog_foreign_keys()
12  loop
13    raise notice 'checking % % => % %',
14      fk.fktable, fk.fkcols, fk.pktable, fk.pkcols;
15    nkeys := array_length(fk.fkcols, 1);
16    cmd := 'SELECT ctid';
17    for i in 1 .. nkeys loop
18      cmd := cmd || ', ' || quote_ident(fk.fkcols[i]);
19    end loop;
20    if fk.is_array then
21      cmd := cmd || ' FROM (SELECT ctid';
22      for i in 1 .. nkeys-1 loop
23        cmd := cmd || ', ' || quote_ident(fk.fkcols[i]);
24      end loop;
25      cmd := cmd || ', unnest(' || quote_ident(fk.fkcols[nkeys]);
26      cmd := cmd || ') as ' || quote_ident(fk.fkcols[nkeys]);
27      cmd := cmd || ' FROM ' || fk.fktable::text || ') fk WHERE ';
28    else
29      cmd := cmd || ' FROM ' || fk.fktable::text || ' fk WHERE ';
30    end if;
31    if fk.is_opt then
32      for i in 1 .. nkeys loop
33        cmd := cmd || quote_ident(fk.fkcols[i]) || ' != 0 AND ';
34      end loop;
35    end if;
36    cmd := cmd || 'NOT EXISTS(SELECT 1 FROM ' || fk.pktable::text || ' pk WHERE ';
37    for i in 1 .. nkeys loop
38      if i > 1 then cmd := cmd || ' AND '; end if;
39      cmd := cmd || 'pk.' || quote_ident(fk.pkcols[i]);
40      cmd := cmd || ' = fk.' || quote_ident(fk.fkcols[i]);
41    end loop;
42    cmd := cmd || ')';
43    -- raise notice 'cmd = %', cmd;
44    for err in execute cmd loop
45      raise warning 'FK VIOLATION IN %(%): %', fk.fktable, fk.fkcols, err;
46    end loop;
47  end loop;
48end
49$doblock$;
50NOTICE:  checking pg_proc {pronamespace} => pg_namespace {oid}
51NOTICE:  checking pg_proc {proowner} => pg_authid {oid}
52NOTICE:  checking pg_proc {prolang} => pg_language {oid}
53NOTICE:  checking pg_proc {provariadic} => pg_type {oid}
54NOTICE:  checking pg_proc {prosupport} => pg_proc {oid}
55NOTICE:  checking pg_proc {prorettype} => pg_type {oid}
56NOTICE:  checking pg_proc {proargtypes} => pg_type {oid}
57NOTICE:  checking pg_proc {proallargtypes} => pg_type {oid}
58NOTICE:  checking pg_proc {protrftypes} => pg_type {oid}
59NOTICE:  checking pg_type {typnamespace} => pg_namespace {oid}
60NOTICE:  checking pg_type {typowner} => pg_authid {oid}
61NOTICE:  checking pg_type {typrelid} => pg_class {oid}
62NOTICE:  checking pg_type {typsubscript} => pg_proc {oid}
63NOTICE:  checking pg_type {typelem} => pg_type {oid}
64NOTICE:  checking pg_type {typarray} => pg_type {oid}
65NOTICE:  checking pg_type {typinput} => pg_proc {oid}
66NOTICE:  checking pg_type {typoutput} => pg_proc {oid}
67NOTICE:  checking pg_type {typreceive} => pg_proc {oid}
68NOTICE:  checking pg_type {typsend} => pg_proc {oid}
69NOTICE:  checking pg_type {typmodin} => pg_proc {oid}
70NOTICE:  checking pg_type {typmodout} => pg_proc {oid}
71NOTICE:  checking pg_type {typanalyze} => pg_proc {oid}
72NOTICE:  checking pg_type {typbasetype} => pg_type {oid}
73NOTICE:  checking pg_type {typcollation} => pg_collation {oid}
74NOTICE:  checking pg_attribute {attrelid} => pg_class {oid}
75NOTICE:  checking pg_attribute {atttypid} => pg_type {oid}
76NOTICE:  checking pg_attribute {attcollation} => pg_collation {oid}
77NOTICE:  checking pg_class {relnamespace} => pg_namespace {oid}
78NOTICE:  checking pg_class {reltype} => pg_type {oid}
79NOTICE:  checking pg_class {reloftype} => pg_type {oid}
80NOTICE:  checking pg_class {relowner} => pg_authid {oid}
81NOTICE:  checking pg_class {relam} => pg_am {oid}
82NOTICE:  checking pg_class {reltablespace} => pg_tablespace {oid}
83NOTICE:  checking pg_class {reltoastrelid} => pg_class {oid}
84NOTICE:  checking pg_class {relrewrite} => pg_class {oid}
85NOTICE:  checking pg_attrdef {adrelid} => pg_class {oid}
86NOTICE:  checking pg_attrdef {adrelid,adnum} => pg_attribute {attrelid,attnum}
87NOTICE:  checking pg_constraint {connamespace} => pg_namespace {oid}
88NOTICE:  checking pg_constraint {conrelid} => pg_class {oid}
89NOTICE:  checking pg_constraint {contypid} => pg_type {oid}
90NOTICE:  checking pg_constraint {conindid} => pg_class {oid}
91NOTICE:  checking pg_constraint {conparentid} => pg_constraint {oid}
92NOTICE:  checking pg_constraint {confrelid} => pg_class {oid}
93NOTICE:  checking pg_constraint {conpfeqop} => pg_operator {oid}
94NOTICE:  checking pg_constraint {conppeqop} => pg_operator {oid}
95NOTICE:  checking pg_constraint {conffeqop} => pg_operator {oid}
96NOTICE:  checking pg_constraint {conexclop} => pg_operator {oid}
97NOTICE:  checking pg_constraint {conrelid,conkey} => pg_attribute {attrelid,attnum}
98NOTICE:  checking pg_constraint {confrelid,confkey} => pg_attribute {attrelid,attnum}
99NOTICE:  checking pg_inherits {inhrelid} => pg_class {oid}
100NOTICE:  checking pg_inherits {inhparent} => pg_class {oid}
101NOTICE:  checking pg_index {indexrelid} => pg_class {oid}
102NOTICE:  checking pg_index {indrelid} => pg_class {oid}
103NOTICE:  checking pg_index {indcollation} => pg_collation {oid}
104NOTICE:  checking pg_index {indclass} => pg_opclass {oid}
105NOTICE:  checking pg_index {indrelid,indkey} => pg_attribute {attrelid,attnum}
106NOTICE:  checking pg_operator {oprnamespace} => pg_namespace {oid}
107NOTICE:  checking pg_operator {oprowner} => pg_authid {oid}
108NOTICE:  checking pg_operator {oprleft} => pg_type {oid}
109NOTICE:  checking pg_operator {oprright} => pg_type {oid}
110NOTICE:  checking pg_operator {oprresult} => pg_type {oid}
111NOTICE:  checking pg_operator {oprcom} => pg_operator {oid}
112NOTICE:  checking pg_operator {oprnegate} => pg_operator {oid}
113NOTICE:  checking pg_operator {oprcode} => pg_proc {oid}
114NOTICE:  checking pg_operator {oprrest} => pg_proc {oid}
115NOTICE:  checking pg_operator {oprjoin} => pg_proc {oid}
116NOTICE:  checking pg_opfamily {opfmethod} => pg_am {oid}
117NOTICE:  checking pg_opfamily {opfnamespace} => pg_namespace {oid}
118NOTICE:  checking pg_opfamily {opfowner} => pg_authid {oid}
119NOTICE:  checking pg_opclass {opcmethod} => pg_am {oid}
120NOTICE:  checking pg_opclass {opcnamespace} => pg_namespace {oid}
121NOTICE:  checking pg_opclass {opcowner} => pg_authid {oid}
122NOTICE:  checking pg_opclass {opcfamily} => pg_opfamily {oid}
123NOTICE:  checking pg_opclass {opcintype} => pg_type {oid}
124NOTICE:  checking pg_opclass {opckeytype} => pg_type {oid}
125NOTICE:  checking pg_am {amhandler} => pg_proc {oid}
126NOTICE:  checking pg_amop {amopfamily} => pg_opfamily {oid}
127NOTICE:  checking pg_amop {amoplefttype} => pg_type {oid}
128NOTICE:  checking pg_amop {amoprighttype} => pg_type {oid}
129NOTICE:  checking pg_amop {amopopr} => pg_operator {oid}
130NOTICE:  checking pg_amop {amopmethod} => pg_am {oid}
131NOTICE:  checking pg_amop {amopsortfamily} => pg_opfamily {oid}
132NOTICE:  checking pg_amproc {amprocfamily} => pg_opfamily {oid}
133NOTICE:  checking pg_amproc {amproclefttype} => pg_type {oid}
134NOTICE:  checking pg_amproc {amprocrighttype} => pg_type {oid}
135NOTICE:  checking pg_amproc {amproc} => pg_proc {oid}
136NOTICE:  checking pg_language {lanowner} => pg_authid {oid}
137NOTICE:  checking pg_language {lanplcallfoid} => pg_proc {oid}
138NOTICE:  checking pg_language {laninline} => pg_proc {oid}
139NOTICE:  checking pg_language {lanvalidator} => pg_proc {oid}
140NOTICE:  checking pg_largeobject_metadata {lomowner} => pg_authid {oid}
141NOTICE:  checking pg_largeobject {loid} => pg_largeobject_metadata {oid}
142NOTICE:  checking pg_aggregate {aggfnoid} => pg_proc {oid}
143NOTICE:  checking pg_aggregate {aggtransfn} => pg_proc {oid}
144NOTICE:  checking pg_aggregate {aggfinalfn} => pg_proc {oid}
145NOTICE:  checking pg_aggregate {aggcombinefn} => pg_proc {oid}
146NOTICE:  checking pg_aggregate {aggserialfn} => pg_proc {oid}
147NOTICE:  checking pg_aggregate {aggdeserialfn} => pg_proc {oid}
148NOTICE:  checking pg_aggregate {aggmtransfn} => pg_proc {oid}
149NOTICE:  checking pg_aggregate {aggminvtransfn} => pg_proc {oid}
150NOTICE:  checking pg_aggregate {aggmfinalfn} => pg_proc {oid}
151NOTICE:  checking pg_aggregate {aggsortop} => pg_operator {oid}
152NOTICE:  checking pg_aggregate {aggtranstype} => pg_type {oid}
153NOTICE:  checking pg_aggregate {aggmtranstype} => pg_type {oid}
154NOTICE:  checking pg_statistic {starelid} => pg_class {oid}
155NOTICE:  checking pg_statistic {staop1} => pg_operator {oid}
156NOTICE:  checking pg_statistic {staop2} => pg_operator {oid}
157NOTICE:  checking pg_statistic {staop3} => pg_operator {oid}
158NOTICE:  checking pg_statistic {staop4} => pg_operator {oid}
159NOTICE:  checking pg_statistic {staop5} => pg_operator {oid}
160NOTICE:  checking pg_statistic {stacoll1} => pg_collation {oid}
161NOTICE:  checking pg_statistic {stacoll2} => pg_collation {oid}
162NOTICE:  checking pg_statistic {stacoll3} => pg_collation {oid}
163NOTICE:  checking pg_statistic {stacoll4} => pg_collation {oid}
164NOTICE:  checking pg_statistic {stacoll5} => pg_collation {oid}
165NOTICE:  checking pg_statistic {starelid,staattnum} => pg_attribute {attrelid,attnum}
166NOTICE:  checking pg_statistic_ext {stxrelid} => pg_class {oid}
167NOTICE:  checking pg_statistic_ext {stxnamespace} => pg_namespace {oid}
168NOTICE:  checking pg_statistic_ext {stxowner} => pg_authid {oid}
169NOTICE:  checking pg_statistic_ext {stxrelid,stxkeys} => pg_attribute {attrelid,attnum}
170NOTICE:  checking pg_statistic_ext_data {stxoid} => pg_statistic_ext {oid}
171NOTICE:  checking pg_rewrite {ev_class} => pg_class {oid}
172NOTICE:  checking pg_trigger {tgrelid} => pg_class {oid}
173NOTICE:  checking pg_trigger {tgparentid} => pg_trigger {oid}
174NOTICE:  checking pg_trigger {tgfoid} => pg_proc {oid}
175NOTICE:  checking pg_trigger {tgconstrrelid} => pg_class {oid}
176NOTICE:  checking pg_trigger {tgconstrindid} => pg_class {oid}
177NOTICE:  checking pg_trigger {tgconstraint} => pg_constraint {oid}
178NOTICE:  checking pg_trigger {tgrelid,tgattr} => pg_attribute {attrelid,attnum}
179NOTICE:  checking pg_event_trigger {evtowner} => pg_authid {oid}
180NOTICE:  checking pg_event_trigger {evtfoid} => pg_proc {oid}
181NOTICE:  checking pg_description {classoid} => pg_class {oid}
182NOTICE:  checking pg_cast {castsource} => pg_type {oid}
183NOTICE:  checking pg_cast {casttarget} => pg_type {oid}
184NOTICE:  checking pg_cast {castfunc} => pg_proc {oid}
185NOTICE:  checking pg_enum {enumtypid} => pg_type {oid}
186NOTICE:  checking pg_namespace {nspowner} => pg_authid {oid}
187NOTICE:  checking pg_conversion {connamespace} => pg_namespace {oid}
188NOTICE:  checking pg_conversion {conowner} => pg_authid {oid}
189NOTICE:  checking pg_conversion {conproc} => pg_proc {oid}
190NOTICE:  checking pg_depend {classid} => pg_class {oid}
191NOTICE:  checking pg_depend {refclassid} => pg_class {oid}
192NOTICE:  checking pg_database {datdba} => pg_authid {oid}
193NOTICE:  checking pg_database {dattablespace} => pg_tablespace {oid}
194NOTICE:  checking pg_db_role_setting {setdatabase} => pg_database {oid}
195NOTICE:  checking pg_db_role_setting {setrole} => pg_authid {oid}
196NOTICE:  checking pg_tablespace {spcowner} => pg_authid {oid}
197NOTICE:  checking pg_auth_members {roleid} => pg_authid {oid}
198NOTICE:  checking pg_auth_members {member} => pg_authid {oid}
199NOTICE:  checking pg_auth_members {grantor} => pg_authid {oid}
200NOTICE:  checking pg_shdepend {dbid} => pg_database {oid}
201NOTICE:  checking pg_shdepend {classid} => pg_class {oid}
202NOTICE:  checking pg_shdepend {refclassid} => pg_class {oid}
203NOTICE:  checking pg_shdescription {classoid} => pg_class {oid}
204NOTICE:  checking pg_ts_config {cfgnamespace} => pg_namespace {oid}
205NOTICE:  checking pg_ts_config {cfgowner} => pg_authid {oid}
206NOTICE:  checking pg_ts_config {cfgparser} => pg_ts_parser {oid}
207NOTICE:  checking pg_ts_config_map {mapcfg} => pg_ts_config {oid}
208NOTICE:  checking pg_ts_config_map {mapdict} => pg_ts_dict {oid}
209NOTICE:  checking pg_ts_dict {dictnamespace} => pg_namespace {oid}
210NOTICE:  checking pg_ts_dict {dictowner} => pg_authid {oid}
211NOTICE:  checking pg_ts_dict {dicttemplate} => pg_ts_template {oid}
212NOTICE:  checking pg_ts_parser {prsnamespace} => pg_namespace {oid}
213NOTICE:  checking pg_ts_parser {prsstart} => pg_proc {oid}
214NOTICE:  checking pg_ts_parser {prstoken} => pg_proc {oid}
215NOTICE:  checking pg_ts_parser {prsend} => pg_proc {oid}
216NOTICE:  checking pg_ts_parser {prsheadline} => pg_proc {oid}
217NOTICE:  checking pg_ts_parser {prslextype} => pg_proc {oid}
218NOTICE:  checking pg_ts_template {tmplnamespace} => pg_namespace {oid}
219NOTICE:  checking pg_ts_template {tmplinit} => pg_proc {oid}
220NOTICE:  checking pg_ts_template {tmpllexize} => pg_proc {oid}
221NOTICE:  checking pg_extension {extowner} => pg_authid {oid}
222NOTICE:  checking pg_extension {extnamespace} => pg_namespace {oid}
223NOTICE:  checking pg_extension {extconfig} => pg_class {oid}
224NOTICE:  checking pg_foreign_data_wrapper {fdwowner} => pg_authid {oid}
225NOTICE:  checking pg_foreign_data_wrapper {fdwhandler} => pg_proc {oid}
226NOTICE:  checking pg_foreign_data_wrapper {fdwvalidator} => pg_proc {oid}
227NOTICE:  checking pg_foreign_server {srvowner} => pg_authid {oid}
228NOTICE:  checking pg_foreign_server {srvfdw} => pg_foreign_data_wrapper {oid}
229NOTICE:  checking pg_user_mapping {umuser} => pg_authid {oid}
230NOTICE:  checking pg_user_mapping {umserver} => pg_foreign_server {oid}
231NOTICE:  checking pg_foreign_table {ftrelid} => pg_class {oid}
232NOTICE:  checking pg_foreign_table {ftserver} => pg_foreign_server {oid}
233NOTICE:  checking pg_policy {polrelid} => pg_class {oid}
234NOTICE:  checking pg_policy {polroles} => pg_authid {oid}
235NOTICE:  checking pg_default_acl {defaclrole} => pg_authid {oid}
236NOTICE:  checking pg_default_acl {defaclnamespace} => pg_namespace {oid}
237NOTICE:  checking pg_init_privs {classoid} => pg_class {oid}
238NOTICE:  checking pg_seclabel {classoid} => pg_class {oid}
239NOTICE:  checking pg_shseclabel {classoid} => pg_class {oid}
240NOTICE:  checking pg_collation {collnamespace} => pg_namespace {oid}
241NOTICE:  checking pg_collation {collowner} => pg_authid {oid}
242NOTICE:  checking pg_partitioned_table {partrelid} => pg_class {oid}
243NOTICE:  checking pg_partitioned_table {partdefid} => pg_class {oid}
244NOTICE:  checking pg_partitioned_table {partclass} => pg_opclass {oid}
245NOTICE:  checking pg_partitioned_table {partcollation} => pg_collation {oid}
246NOTICE:  checking pg_partitioned_table {partrelid,partattrs} => pg_attribute {attrelid,attnum}
247NOTICE:  checking pg_range {rngtypid} => pg_type {oid}
248NOTICE:  checking pg_range {rngsubtype} => pg_type {oid}
249NOTICE:  checking pg_range {rngmultitypid} => pg_type {oid}
250NOTICE:  checking pg_range {rngcollation} => pg_collation {oid}
251NOTICE:  checking pg_range {rngsubopc} => pg_opclass {oid}
252NOTICE:  checking pg_range {rngcanonical} => pg_proc {oid}
253NOTICE:  checking pg_range {rngsubdiff} => pg_proc {oid}
254NOTICE:  checking pg_transform {trftype} => pg_type {oid}
255NOTICE:  checking pg_transform {trflang} => pg_language {oid}
256NOTICE:  checking pg_transform {trffromsql} => pg_proc {oid}
257NOTICE:  checking pg_transform {trftosql} => pg_proc {oid}
258NOTICE:  checking pg_sequence {seqrelid} => pg_class {oid}
259NOTICE:  checking pg_sequence {seqtypid} => pg_type {oid}
260NOTICE:  checking pg_publication {pubowner} => pg_authid {oid}
261NOTICE:  checking pg_publication_rel {prpubid} => pg_publication {oid}
262NOTICE:  checking pg_publication_rel {prrelid} => pg_class {oid}
263NOTICE:  checking pg_subscription {subdbid} => pg_database {oid}
264NOTICE:  checking pg_subscription {subowner} => pg_authid {oid}
265NOTICE:  checking pg_subscription_rel {srsubid} => pg_subscription {oid}
266NOTICE:  checking pg_subscription_rel {srrelid} => pg_class {oid}
267