Skip to content

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.