It's OK for it to fail (and, for my logic, revert the whole transaction), but I don't want this failure to take 2ms instead of 40 seconds.
Running the actual DELETE
query (with EXPLAIN ANALYZE
wrapper or not) is considerably more expensive than checking with a SELECT
whether any FK reference will prevent the operation.
Identify FK constraints pointing to your table:
SELECT c.conrelid::regclass::text AS referencing_table
, pg_get_constraintdef(c.oid) AS fk
FROM pg_constraint c
WHERE c.confrelid = 'public.bigtype'::regclass
AND c.contype = 'f'
ORDER BY 1, 2;
See:
You get 0-n rows of the form:
referencing_tbl | FOREIGN KEY (referencing_col, ...) REFERENCES matches(referenced_col, ...) ...
Based on this, the fastest possible query would be:
SELECT EXISTS (
SELECT FROM matches m
WHERE WHERE id = 1
AND (EXISTS (SELECT FROM referencing_tbl t WHERE (t.referencing_col, ...) = (m.referenced_col, ...))
-- OR EXISTS ... -- one predicate per FK
)
);
true
... At least one row is being referenced. DELETE
will fail.
false
... No references. DELETE
will succeed.
Of course, if there isWith concurrent write access, there is a possible race condition. Probably unimportant for your case.
If your relational design is not stable, you might generate that SELECT query completely dynamically ...