173 lines
5.3 KiB
Ruby
173 lines
5.3 KiB
Ruby
# 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
|