with fk as (select
o.conname,
(select nspname from pg_namespace where oid=f.relnamespace) as foreign_schema,
f.relname as foreign_table,
f.oid as foreign_table_oid,
unnest(o.confkey) AS foreign_col,
(select nspname from pg_namespace where oid=c.relnamespace) as target_schema,
c.relname as target_table,
c.oid as target_table_oid,
unnest(o.conkey) AS target_col
from pg_constraint o inner join pg_class c on c.oid = o.conrelid
inner join pg_class f on f.oid = o.confrelid
where o.contype = 'f' ),
fk_grouped as (
select fk.conname, fk.foreign_schema, foreign_table, array_agg(fk.foreign_table || '.' || a_foreign.attname order by a_foreign.attnum) as foreign_col,
fk.target_schema, fk.target_table, array_agg(fk.target_table || '.' || a_target.attname order by a_target.attnum) as target_col
from fk inner join pg_attribute a_foreign on fk.foreign_col = a_foreign.attnum and fk.foreign_table_oid = a_foreign.attrelid and a_foreign.attisdropped = false
inner join pg_attribute a_target on fk.target_col = a_target.attnum and fk.target_table_oid = a_target.attrelid and a_target.attisdropped = false
group by fk.conname, fk.foreign_schema, fk.foreign_table, fk.target_schema, fk.target_table),
fk_final as (select conname, foreign_schema as fschema, foreign_table as ftable, case when foreign_col@>target_col and foreign_col<@target_col then target_col else foreign_col || target_col end as columns
from fk_grouped
where foreign_schema=target_schema and foreign_table=target_table),
ck as (select
o.conname,
(select nspname from pg_namespace where oid=c.relnamespace) as target_schema,
c.relname as target_table,
c.oid as target_table_oid,
unnest(o.conkey) AS target_col
from pg_constraint o inner join pg_class c on c.oid = o.conrelid
where o.contype = 'c' and cardinality(o.conkey)>1),
ck_grouped as (
select ck.conname, ck.target_schema, ck.target_table, array_agg(ck.target_table || '.' || a_target.attname order by a_target.attnum) as target_col
from ck inner join pg_attribute a_target on ck.target_col = a_target.attnum and ck.target_table_oid = a_target.attrelid and a_target.attisdropped = false
group by ck.conname, ck.target_schema, ck.target_table),
ck_final as (select conname, target_schema as cschema, target_table as ctable, target_col as columns
from ck_grouped)
select conname, fschema as schema, ftable as table, columns
from fk_final
where not exists (select 1
from ck_final
where fk_final.fschema=ck_final.cschema and fk_final.ftable=ck_final.ctable and fk_final.columns@>ck_final.columns and fk_final.columns<@ck_final.columns)
order by fschema, ftable;