Index helpers don't respect `where` clause
We have a couple custom migration helpers for indexes, along with Rail's default ones:
add_concurrent_index
remove_concurrent_index
index_exists?
All methods support working with where: ?
clauses to support partial indexes. add_concurrent_index
is idempotent and therefore checks the existence of the index prior to its creation. However, it doesn't consider the where: ?
clause in the comparison. The same holds true for remove_concurrent_index
and index_exists?
.
This leads to inconsistencies where index creation is skipped in case another index with the same columns exists already (even if it has a different or no where
clause).
This has led to incidents like gitlab-com/gl-infra/production#2424 (comment 381214360).
Example
Suppose we have this index:
"merge_request_mentions_temp_index" btree (id) WHERE description ~~ '%@%'::text OR title::text ~~ '%@%'::text
Now we add a migration:
add_concurrent_index :merge_requests, :id, where: 'lock_version' IS NULL
This is expected to create a new index "index_merge_requests_on_id" btree (id) WHERE lock_version IS NULL
. However it does not - because the helper doesn't consider the where
clause, it sees the existing index merge_request_mentions_temp_index
as identical to the requested one - and skips its creation.
Expected behavior: Consider where
clause when checking for index existence and create the missing index correctly.