Skip to content

Commit

Permalink
Support INCLUDE indexes in extaneous_indexes (#133)
Browse files Browse the repository at this point in the history
  • Loading branch information
fatkodima committed Jun 8, 2024
1 parent 100164d commit 75452bb
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 2 deletions.
13 changes: 11 additions & 2 deletions lib/active_record_doctor/detectors/extraneous_indexes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,12 @@ def replaceable_with?(index1, index2)

case [index1.unique, index2.unique]
when [true, true]
(index2_columns - index1_columns).empty?
contains_all?(index1_columns, index2_columns)
when [true, false]
false
else
prefix?(index1_columns, index2_columns)
prefix?(index1_columns, index2_columns) &&
contains_all?(index2_columns + includes(index2), includes(index1))
end
end

Expand All @@ -96,6 +97,14 @@ def opclasses(index)
def prefix?(lhs, rhs)
lhs.count <= rhs.count && rhs[0...lhs.count] == lhs
end

def contains_all?(array1, array2)
(array2 - array1).empty?
end

def includes(index)
index.respond_to?(:include) ? Array(index.include) : []
end
end
end
end
48 changes: 48 additions & 0 deletions test/active_record_doctor/detectors/extraneous_indexes_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,54 @@ def test_single_column_covered_by_multi_column_on_materialized_view_is_duplicate
end
end

def test_include_index_covered_by_other_non_include_index
skip("ActiveRecord < 7.1 doesn't support include indexes") if ActiveRecord::VERSION::STRING < "7.1"
skip("Only PostgreSQL supports include indexes") unless postgresql?

Context.create_table(:users) do |t|
t.string :first_name
t.string :last_name
t.index [:last_name, :first_name]
t.index :last_name, include: :first_name
end

assert_problems(<<OUTPUT)
remove the index index_users_on_last_name from the table users - queries should be able to use the following index instead: index_users_on_last_name_and_first_name
OUTPUT
end

def test_include_index_covered_by_other_include_index
skip("ActiveRecord < 7.1 doesn't support include indexes") if ActiveRecord::VERSION::STRING < "7.1"
skip("Only PostgreSQL supports include indexes") unless postgresql?

Context.create_table(:users) do |t|
t.string :first_name
t.string :last_name
t.integer :age
t.index :last_name, include: [:age, :first_name], name: "index1_users_on_last_name"
t.index :last_name, include: :first_name, name: "index2_users_on_last_name"
end

assert_problems(<<OUTPUT)
remove the index index2_users_on_last_name from the table users - queries should be able to use the following index instead: index1_users_on_last_name
OUTPUT
end

def test_include_index_not_covered_by_other_index
skip("ActiveRecord < 7.1 doesn't support include indexes") if ActiveRecord::VERSION::STRING < "7.1"
skip("Only PostgreSQL supports include indexes") unless postgresql?

Context.create_table(:users) do |t|
t.string :first_name
t.string :last_name
t.integer :age
t.index [:first_name, :last_name]
t.index :last_name, include: :first_name
end

refute_problems
end

def test_config_ignore_tables
# The detector recognizes two kinds of errors and both must take
# ignore_tables into account. We trigger those errors by indexing the
Expand Down

0 comments on commit 75452bb

Please sign in to comment.