debian-mirror-gitlab/spec/models/concerns/safely_change_column_default_spec.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

76 lines
2 KiB
Ruby
Raw Permalink Normal View History

2023-03-17 16:20:25 +05:30
# 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