58 lines
1.7 KiB
PL/PgSQL
58 lines
1.7 KiB
PL/PgSQL
-- Errors if FKs do not have an index
|
|
CREATE OR REPLACE FUNCTION fk_missing_index ()
|
|
RETURNS void
|
|
AS $$
|
|
DECLARE
|
|
item record;
|
|
BEGIN
|
|
FOR item IN
|
|
SELECT
|
|
c.conrelid::regclass AS "table",
|
|
/* list of key column names in order */
|
|
string_agg(a.attname, ',' ORDER BY x.n) AS columns,
|
|
pg_catalog.pg_size_pretty(pg_catalog.pg_relation_size(c.conrelid)) AS size,
|
|
c.conname AS constraint,
|
|
c.confrelid::regclass AS referenced_table
|
|
FROM
|
|
pg_catalog.pg_constraint c
|
|
/* enumerated key column numbers per foreign key */
|
|
CROSS JOIN LATERAL unnest(c.conkey)
|
|
WITH ORDINALITY AS x (attnum, n)
|
|
/* name for each key column */
|
|
JOIN pg_catalog.pg_attribute a ON a.attnum = x.attnum
|
|
AND a.attrelid = c.conrelid
|
|
WHERE
|
|
NOT EXISTS
|
|
/* is there a matching index for the constraint? */
|
|
(
|
|
SELECT
|
|
1
|
|
FROM
|
|
pg_catalog.pg_index i
|
|
WHERE
|
|
i.indrelid = c.conrelid
|
|
/* the first index columns must be the same as the
|
|
key columns, but order doesn't matter */
|
|
AND (i.indkey::smallint[])[0:cardinality(c.conkey) - 1] @> c.conkey)
|
|
AND c.contype = 'f'
|
|
GROUP BY
|
|
c.conrelid,
|
|
c.conname,
|
|
c.confrelid
|
|
ORDER BY
|
|
pg_catalog.pg_relation_size(c.conrelid) DESC LOOP
|
|
RAISE WARNING 'CREATE INDEX "idx_%_fk_%" ON "%" ("%");', item.table, item.columns, item.table, item.columns USING HINT = to_json(item);
|
|
END LOOP;
|
|
IF FOUND THEN
|
|
RAISE EXCEPTION ' We require ALL FOREIGN keys TO have an INDEX defined. ';
|
|
END IF;
|
|
END;
|
|
$$
|
|
LANGUAGE plpgsql;
|
|
|
|
SELECT
|
|
*
|
|
FROM
|
|
fk_missing_index ();
|
|
|