Skip to content
Snippets Groups Projects
Commit 7518d63c authored by Matt Kasa's avatar Matt Kasa :five:
Browse files

Add find_duplicate_indexes helper

Relates to #370275
parent e60c2f2a
No related branches found
No related tags found
2 merge requests!97251Synchronize ruby3 branch manually due to conflicts,!95000Add find_duplicate_indexes helper to aid in partitioning index renames
......@@ -77,8 +77,42 @@ def remove_concurrent_partitioned_index_by_name(table_name, index_name)
end
end
# Finds duplicate indexes for a given schema and table. This finds
# indexes where the index definition is identical but the names are
# different. Returns an array of arrays containing duplicate index name
# pairs.
#
# Example:
#
# find_duplicate_indexes('table_name_goes_here')
def find_duplicate_indexes(table_name, schema_name: connection.current_schema)
find_indexes(table_name, schema_name: schema_name)
.group_by { |r| r['index_id'] }
.select { |_, v| v.size > 1 }
.map { |_, indexes| indexes.map { |index| index['index_name'] } }
end
private
def find_indexes(table_name, schema_name: connection.current_schema)
indexes = connection.select_all(<<~SQL, 'SQL', [schema_name, table_name])
SELECT n.nspname AS schema_name,
c.relname AS table_name,
i.relname AS index_name,
regexp_replace(pg_get_indexdef(i.oid), 'INDEX .*? USING', '_') AS index_id
FROM pg_index x
JOIN pg_class c ON c.oid = x.indrelid
JOIN pg_class i ON i.oid = x.indexrelid
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE (c.relkind = ANY (ARRAY['r'::"char", 'm'::"char", 'p'::"char"]))
AND (i.relkind = ANY (ARRAY['i'::"char", 'I'::"char"]))
AND n.nspname = $1
AND c.relname = $2;
SQL
indexes.to_a
end
def find_partitioned_table(table_name)
partitioned_table = Gitlab::Database::PostgresPartitionedTable.find_by_name_in_current_schema(table_name)
......
......@@ -26,6 +26,7 @@
CREATE TABLE #{table_name} (
id serial NOT NULL,
created_at timestamptz NOT NULL,
updated_at timestamptz NOT NULL,
PRIMARY KEY (id, created_at)
) PARTITION BY RANGE (created_at);
......@@ -204,4 +205,30 @@ def expect_add_concurrent_index_and_call_original(table, column, index)
end
end
end
describe '#find_duplicate_indexes' do
context 'when duplicate and non-duplicate indexes exist' do
let(:nonduplicate_column_name) { 'updated_at' }
let(:nonduplicate_index_name) { 'updated_at_idx' }
let(:duplicate_column_name) { 'created_at' }
let(:duplicate_index_name1) { 'created_at_idx' }
let(:duplicate_index_name2) { 'index_on_created_at' }
before do
connection.execute(<<~SQL)
CREATE INDEX #{nonduplicate_index_name} ON #{table_name} (#{nonduplicate_column_name});
CREATE INDEX #{duplicate_index_name1} ON #{table_name} (#{duplicate_column_name});
CREATE INDEX #{duplicate_index_name2} ON #{table_name} (#{duplicate_column_name});
SQL
end
subject do
migration.find_duplicate_indexes(table_name)
end
it 'finds the duplicate index' do
expect(subject).to match_array([match_array([duplicate_index_name1, duplicate_index_name2])])
end
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment