Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/support_specs/database/duplicate_indexes_spec.rb')
-rw-r--r--spec/support_specs/database/duplicate_indexes_spec.rb108
1 files changed, 108 insertions, 0 deletions
diff --git a/spec/support_specs/database/duplicate_indexes_spec.rb b/spec/support_specs/database/duplicate_indexes_spec.rb
new file mode 100644
index 00000000000..bbcb80f0593
--- /dev/null
+++ b/spec/support_specs/database/duplicate_indexes_spec.rb
@@ -0,0 +1,108 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Database::DuplicateIndexes, feature_category: :database do
+ index_class = ActiveRecord::ConnectionAdapters::IndexDefinition
+ let(:default_index_options) { { using: :btree, orders: {}, unique: false, opclasses: {}, where: nil } }
+
+ let(:table_name) { 'foobar' }
+ let(:index1) { instance_double(index_class, default_index_options.merge(name: 'index1', columns: %w[user_id])) }
+ let(:index1_copy) { instance_double(index_class, default_index_options.merge(name: 'index1b', columns: %w[user_id])) }
+ let(:index2) { instance_double(index_class, default_index_options.merge(name: 'index2', columns: %w[project_id])) }
+ let(:index3) do
+ instance_double(index_class, default_index_options.merge(name: 'index3', columns: %w[user_id project_id]))
+ end
+
+ let(:index3_inverse) do
+ instance_double(index_class, default_index_options.merge(name: 'index3_inverse', columns: %w[project_id user_id]))
+ end
+
+ let(:index1_unique) do
+ instance_double(index_class, default_index_options.merge(name: 'index1_unique', columns: %w[user_id], unique: true))
+ end
+
+ let(:index1_desc) do
+ instance_double(
+ index_class,
+ default_index_options.merge(name: 'index1', columns: %w[user_id], orders: { user_id: 'desc' })
+ )
+ end
+
+ let(:index3_with_where) do
+ instance_double(
+ index_class,
+ default_index_options.merge(name: 'index3_with_where', columns: %w[user_id project_id], where: "id > 100")
+ )
+ end
+
+ subject(:duplicate_indexes) do
+ described_class.new(table_name, indexes).duplicate_indexes
+ end
+
+ context 'when there are no duplicate indexes' do
+ let(:indexes) { [index1, index2] }
+
+ it { expect(duplicate_indexes).to be_empty }
+ end
+
+ context 'when overlapping indexes' do
+ let(:indexes) { [index1, index3] }
+
+ it 'detects a duplicate index between index1 and index3' do
+ expected_duplicate_indexes = { index_struct(index3) => [index_struct(index1)] }
+
+ expect(duplicate_indexes).to eq(expected_duplicate_indexes)
+ end
+ end
+
+ context 'when the indexes have the inverse order of columns' do
+ let(:indexes) { [index3, index3_inverse] }
+
+ it 'does not detect duplicate indexes between index3 and index3_inverse' do
+ expect(duplicate_indexes).to eq({})
+ end
+ 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.
+ context 'when the index with matching sub-columns is unique' do
+ let(:indexes) { [index3, index1_unique] }
+
+ it 'does not detect duplicate indexes between index3 and index1_unique' do
+ expect(duplicate_indexes).to eq({})
+ end
+ end
+
+ context 'when the one of the indexes is a conditional index' do
+ let(:indexes) { [index3, index3_with_where] }
+
+ it 'does not detect duplicate indexes between index3 and index3_with_where' do
+ expect(duplicate_indexes).to eq({})
+ end
+ end
+
+ context 'when identical indexes' do
+ let(:indexes) { [index1, index1_copy] }
+
+ it 'detects a duplicate index between index1 and index3' do
+ expected_duplicate_indexes = {
+ index_struct(index1) => [index_struct(index1_copy)],
+ index_struct(index1_copy) => [index_struct(index1)]
+ }
+
+ expect(duplicate_indexes).to eq(expected_duplicate_indexes)
+ end
+ end
+
+ context 'when indexes have the same columns but with different order' do
+ let(:indexes) { [index1, index1_desc] }
+
+ it { expect(duplicate_indexes).to be_empty }
+ end
+
+ def index_struct(index)
+ Database::DuplicateIndexes.btree_index_struct(index)
+ end
+end