diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-10-19 15:57:54 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-10-19 15:57:54 +0300 |
commit | 419c53ec62de6e97a517abd5fdd4cbde3a942a34 (patch) | |
tree | 1f43a548b46bca8a5fb8fe0c31cef1883d49c5b6 /spec/lib/gitlab/database/migration_helpers/swapping_spec.rb | |
parent | 1da20d9135b3ad9e75e65b028bffc921aaf8deb7 (diff) |
Add latest changes from gitlab-org/gitlab@16-5-stable-eev16.5.0-rc42
Diffstat (limited to 'spec/lib/gitlab/database/migration_helpers/swapping_spec.rb')
-rw-r--r-- | spec/lib/gitlab/database/migration_helpers/swapping_spec.rb | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/spec/lib/gitlab/database/migration_helpers/swapping_spec.rb b/spec/lib/gitlab/database/migration_helpers/swapping_spec.rb new file mode 100644 index 00000000000..0940c6f4c30 --- /dev/null +++ b/spec/lib/gitlab/database/migration_helpers/swapping_spec.rb @@ -0,0 +1,172 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Database::MigrationHelpers::Swapping, feature_category: :database do + let(:connection) { ApplicationRecord.connection } + let(:migration_context) do + ActiveRecord::Migration + .new + .extend(described_class) + .extend(Gitlab::Database::MigrationHelpers) + end + + let(:service_instance) { instance_double('Gitlab::Database::Migrations::SwapColumns', execute: nil) } + + describe '#reset_trigger_function' do + let(:trigger_function_name) { 'existing_trigger_function' } + + before do + connection.execute(<<~SQL) + CREATE FUNCTION #{trigger_function_name}() RETURNS trigger + LANGUAGE plpgsql + AS $$ + BEGIN + NEW."bigint_column" := NEW."integer_column"; + RETURN NEW; + END; + $$; + SQL + end + + it 'resets' do + recorder = ActiveRecord::QueryRecorder.new do + migration_context.reset_trigger_function(trigger_function_name) + end + expect(recorder.log).to include(/ALTER FUNCTION "existing_trigger_function" RESET ALL/) + end + end + + describe '#swap_columns' do + let(:table) { :ci_pipeline_variables } + let(:column1) { :pipeline_id } + let(:column2) { :pipeline_id_convert_to_bigint } + + it 'calls service' do + expect(::Gitlab::Database::Migrations::SwapColumns).to receive(:new).with( + migration_context: migration_context, + table: table, + column1: column1, + column2: column2 + ).and_return(service_instance) + + migration_context.swap_columns(table, column1, column2) + end + end + + describe '#swap_columns_default' do + let(:table) { :_test_table } + let(:column1) { :pipeline_id } + let(:column2) { :pipeline_id_convert_to_bigint } + + it 'calls service' do + expect(::Gitlab::Database::Migrations::SwapColumnsDefault).to receive(:new).with( + migration_context: migration_context, + table: table, + column1: column1, + column2: column2 + ).and_return(service_instance) + + migration_context.swap_columns_default(table, column1, column2) + end + end + + describe '#swap_foreign_keys' do + let(:table) { :_test_swap_foreign_keys } + let(:referenced_table) { "#{table}_referenced" } + let(:foreign_key1) { :fkey_on_integer_column } + let(:foreign_key2) { :fkey_on_bigint_column } + + before do + connection.execute(<<~SQL) + CREATE TABLE #{table} ( + integer_column integer NOT NULL, + bigint_column bigint DEFAULT 0 NOT NULL + ); + CREATE TABLE #{referenced_table} ( + id bigint NOT NULL + ); + + ALTER TABLE ONLY #{referenced_table} + ADD CONSTRAINT pk PRIMARY KEY (id); + + ALTER TABLE ONLY #{table} + ADD CONSTRAINT #{foreign_key1} + FOREIGN KEY (integer_column) REFERENCES #{referenced_table}(id) ON DELETE SET NULL; + + ALTER TABLE ONLY #{table} + ADD CONSTRAINT #{foreign_key2} + FOREIGN KEY (bigint_column) REFERENCES #{referenced_table}(id) ON DELETE SET NULL; + SQL + end + + shared_examples_for 'swapping foreign keys correctly' do + specify do + expect { migration_context.swap_foreign_keys(table, foreign_key1, foreign_key2) } + .to change { + find_foreign_key_by(foreign_key1).options[:column] + }.from('integer_column').to('bigint_column') + .and change { + find_foreign_key_by(foreign_key2).options[:column] + }.from('bigint_column').to('integer_column') + end + end + + it_behaves_like 'swapping foreign keys correctly' + + context 'when foreign key names are 63 bytes' do + let(:foreign_key1) { :f1_012345678901234567890123456789012345678901234567890123456789 } + let(:foreign_key2) { :f2_012345678901234567890123456789012345678901234567890123456789 } + + it_behaves_like 'swapping foreign keys correctly' + end + + private + + def find_foreign_key_by(name) + connection.foreign_keys(table).find { |k| k.options[:name].to_s == name.to_s } + end + end + + describe '#swap_indexes' do + let(:table) { :_test_swap_indexes } + let(:index1) { :index_on_integer } + let(:index2) { :index_on_bigint } + + before do + connection.execute(<<~SQL) + CREATE TABLE #{table} ( + integer_column integer NOT NULL, + bigint_column bigint DEFAULT 0 NOT NULL + ); + + CREATE INDEX #{index1} ON #{table} USING btree (integer_column); + + CREATE INDEX #{index2} ON #{table} USING btree (bigint_column); + SQL + end + + shared_examples_for 'swapping indexes correctly' do + specify do + expect { migration_context.swap_indexes(table, index1, index2) } + .to change { find_index_by(index1).columns }.from(['integer_column']).to(['bigint_column']) + .and change { find_index_by(index2).columns }.from(['bigint_column']).to(['integer_column']) + end + end + + it_behaves_like 'swapping indexes correctly' + + context 'when index names are 63 bytes' do + let(:index1) { :i1_012345678901234567890123456789012345678901234567890123456789 } + let(:index2) { :i2_012345678901234567890123456789012345678901234567890123456789 } + + it_behaves_like 'swapping indexes correctly' + end + + private + + def find_index_by(name) + connection.indexes(table).find { |c| c.name == name.to_s } + end + end +end |