gitlab-ce/spec/support/helpers/database/duplicate_indexes.rb

78 lines
2.4 KiB
Ruby

# frozen_string_literal: true
module Database
class DuplicateIndexes
attr_accessor :table_name, :indexes
BTREE_INDEX_STRUCT = Struct.new(:name, :columns, :unique)
def initialize(table_name, indexes)
@table_name = table_name
@indexes = indexes
end
def duplicate_indexes
ret = {}
btree_indexes.each do |btree_index|
matching_indexes = matching_indexes_for(btree_index)
next unless matching_indexes.any?
ret[btree_index] = matching_indexes
end
ret
end
def self.btree_index_struct(index)
BTREE_INDEX_STRUCT.new(
index.name,
Array.wrap(index.columns).map do |column|
# https://apidock.com/rails/ActiveRecord/ConnectionAdapters/PostgreSQL/SchemaStatements/indexes
# asc is the default order
column_order = index.orders.is_a?(Symbol) ? index.orders : (index.orders[column] || :asc)
{ name: column, order: column_order }
end,
index.unique
)
end
private
def btree_indexes
return @btree_indexes if @btree_indexes
# We only scan non-conditional btree indexes
@btree_indexes = indexes.select do |index|
index.using == :btree && index.where.nil? && index.opclasses.blank?
end
@btree_indexes = @btree_indexes.map { |index| self.class.btree_index_struct(index) }
end
def matching_indexes_for(btree_index)
all_matching_indexes = []
# When comparing btree_index with other_index. btree_index is the index that can have more columns
# than the other_index.
(1..btree_index.columns.length).each do |subset_length|
columns = btree_index.columns.first(subset_length)
matching_indexes = btree_indexes.reject { |other_index| other_index == btree_index }.select do |other_index|
other_index.columns == columns
end
# For now we ignore other indexes that are UNIQUE and have a matching columns subset of
# the btree_index columns, as UNIQUE indexes are still needed to enforce uniqueness
# constraints on subset of the columns.
matching_indexes = matching_indexes.reject do |other_index|
(other_index.unique && (other_index.columns.length < btree_index.columns.length))
end
all_matching_indexes += matching_indexes
end
all_matching_indexes
end
end
end