Fix copying virtual columns when altering a table in sqlite3

This commit is contained in:
fatkodima 2024-04-09 20:22:55 +03:00
parent 8feeab2338
commit a457b121a0
2 changed files with 30 additions and 10 deletions

View File

@ -578,12 +578,6 @@ module ActiveRecord
options[:rename][column.name.to_sym] ||
column.name) : column.name
if column.has_default?
type = lookup_cast_type_from_column(column)
default = type.deserialize(column.default)
default = -> { column.default_function } if default.nil?
end
column_options = {
limit: column.limit,
precision: column.precision,
@ -593,19 +587,31 @@ module ActiveRecord
primary_key: column_name == from_primary_key
}
unless column.auto_increment?
column_options[:default] = default
if column.virtual?
column_options[:as] = column.default_function
column_options[:stored] = column.virtual_stored?
column_options[:type] = column.type
elsif column.has_default?
type = lookup_cast_type_from_column(column)
default = type.deserialize(column.default)
default = -> { column.default_function } if default.nil?
unless column.auto_increment?
column_options[:default] = default
end
end
column_type = column.bigint? ? :bigint : column.type
column_type = column.virtual? ? :virtual : (column.bigint? ? :bigint : column.type)
@definition.column(column_name, column_type, **column_options)
end
yield @definition if block_given?
end
copy_table_indexes(from, to, options[:rename] || {})
columns_to_copy = @definition.columns.reject { |col| col.options.key?(:as) }.map(&:name)
copy_table_contents(from, to,
@definition.columns.map(&:name),
columns_to_copy,
options[:rename] || {})
end

View File

@ -85,6 +85,20 @@ class CopyTableTest < ActiveRecord::SQLite3TestCase
test_copy_table "binaries", "binaries2"
end
def test_copy_table_with_virtual_column
@connection.create_table :virtual_columns, force: true do |t|
t.string :name
t.virtual :upper_name, type: :string, as: "UPPER(name)", stored: true
end
test_copy_table("virtual_columns", "virtual_columns2") do
column = @connection.columns("virtual_columns2").find { |col| col.name == "upper_name" }
assert_predicate column, :virtual_stored?
assert_equal :string, column.type
assert_equal "UPPER(name)", column.default_function
end
end
private
def copy_table(from, to, options = {})
@connection.send(:copy_table, from, to, { temporary: true }.merge(options))