All rules Rule BP007
note
hosted, paid — --remote

Partial or expression index the migration's own queries cannot use

Note — this works and blocks nothing, but a performance regression is likely.

What it catches

A partial index only serves queries whose WHERE clause provably implies its predicate; an expression index only serves queries that use the identical expression. An index on lower(email) does nothing for WHERE email = …, and an index WHERE status = 'archived' does nothing for WHERE status = 'active'. When the migration itself contains such a query, the mismatch is visible before it ships.

Fires on

CREATE INDEX idx_users_lower_email ON users (lower(email));
UPDATE users SET verified = true WHERE email = 'a@example.com';

Do this instead

Match the shapes: query through the same expression (WHERE lower(email) = …) or index the plain column; give the partial index the predicate the queries actually use. Queries elsewhere in the application are not visible here — the rule only reads this file.

CREATE INDEX CONCURRENTLY idx_users_lower_email ON users (lower(email));
-- and query through the same expression: WHERE lower(email) = lower($1)
Catch this before it ships

This rule runs in the hosted service on Startup and above — add --remote with a team token, or use the GitHub Action: npx bolvrk check migration.sql