75 lines
2 KiB
Ruby
75 lines
2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'spec_helper'
|
|
|
|
RSpec.describe SafelyChangeColumnDefault, feature_category: :database do
|
|
include Gitlab::Database::DynamicModelHelpers
|
|
before do
|
|
ApplicationRecord.connection.execute(<<~SQL)
|
|
CREATE TABLE _test_gitlab_main_data(
|
|
id bigserial primary key not null,
|
|
value bigint default 1
|
|
);
|
|
SQL
|
|
end
|
|
|
|
let!(:model) do
|
|
define_batchable_model('_test_gitlab_main_data', connection: ApplicationRecord.connection).tap do |model|
|
|
model.include(described_class)
|
|
model.columns_changing_default(:value)
|
|
model.columns # Force the schema cache to populate
|
|
end
|
|
end
|
|
|
|
def alter_default(new_default)
|
|
ApplicationRecord.connection.execute(<<~SQL)
|
|
ALTER TABLE _test_gitlab_main_data ALTER COLUMN value SET DEFAULT #{new_default}
|
|
SQL
|
|
end
|
|
|
|
def recorded_insert_queries(&block)
|
|
recorder = ActiveRecord::QueryRecorder.new
|
|
recorder.record(&block)
|
|
|
|
recorder.log.select { |q| q.include?('INSERT INTO') }
|
|
end
|
|
|
|
def query_includes_value_column?(query)
|
|
parsed = PgQuery.parse(query)
|
|
parsed.tree.stmts.first.stmt.insert_stmt.cols.any? { |node| node.res_target.name == 'value' }
|
|
end
|
|
|
|
it 'forces the column to be written on a change' do
|
|
queries = recorded_insert_queries do
|
|
model.create!(value: 1)
|
|
end
|
|
|
|
expect(queries.length).to eq(1)
|
|
|
|
expect(query_includes_value_column?(queries.first)).to be_truthy
|
|
end
|
|
|
|
it 'does not write the column without a change' do
|
|
queries = recorded_insert_queries do
|
|
model.create!
|
|
end
|
|
|
|
expect(queries.length).to eq(1)
|
|
expect(query_includes_value_column?(queries.first)).to be_falsey
|
|
end
|
|
|
|
it 'does not send the old column value if the default has changed' do
|
|
alter_default(2)
|
|
model.create!
|
|
|
|
expect(model.pluck(:value)).to contain_exactly(2)
|
|
end
|
|
|
|
it 'prevents writing new default in place of the old default' do
|
|
alter_default(2)
|
|
|
|
model.create!(value: 1)
|
|
|
|
expect(model.pluck(:value)).to contain_exactly(1)
|
|
end
|
|
end
|