Why this matters
An unindexed foreign-key column makes parent-side `DELETE` / `UPDATE` perform a sequential scan of the child table to enforce the constraint. The check is cross-statement: it scans `CREATE TABLE`, `CREATE INDEX`, and `ALTER TABLE ADD CONSTRAINT` in the same file, and only requires an index whose leading column is the FK column. The PRIMARY KEY index already counts.
Examples
Incorrect
CREATE TABLE t (
id integer PRIMARY KEY,
fid integer REFERENCES other(id)
);
-- No CREATE INDEX on t.fid in this file.Correct
CREATE TABLE t (
id integer PRIMARY KEY,
fid integer REFERENCES other(id)
);
CREATE INDEX idx_t_fid ON t (fid);Configure it
// eslint.config.js
import postgresql from "eslint-plugin-postgresql";
export default [
{
files: ["**/*.sql"],
languageOptions: {
parser: postgresql.configs.recommended.languageOptions.parser,
},
plugins: { postgresql },
rules: {
"postgresql/require-index-on-fk-column": "warn",
},
},
]; Options
Edit the SQL — only require-index-on-fk-column is enabled.
Pre-filled with the first incorrect example. Toggle off in the rule shelf to see how the diagnostic disappears.
Diagnostics
No issues found.
2 rules enabled.
Rule under test
require-index-on-fk-column — plus no-syntax-error as a safety net.