Skip to content

Commit

Permalink
Merge branch 'iamadalek-support-for-generated-columns'
Browse files Browse the repository at this point in the history
# Conflicts:
#	Gemfile.lock
  • Loading branch information
coding-chimp committed Feb 7, 2025
2 parents 2191303 + f56f0e4 commit ccb0a0c
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 5 deletions.
5 changes: 3 additions & 2 deletions lib/lhm/intersection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
module Lhm
# Determine and format columns common to origin and destination.
class Intersection
def initialize(origin, destination, renames = {})
def initialize(origin, destination, renames = {}, generated_column_names = [])
@origin = origin
@destination = destination
@renames = renames
@generated_column_names = generated_column_names
end

def origin
Expand All @@ -21,7 +22,7 @@ def destination
private

def common
(@origin.columns.keys & @destination.columns.keys).sort
((@origin.columns.keys & @destination.columns.keys) - @generated_column_names).sort
end

module Joiners
Expand Down
5 changes: 3 additions & 2 deletions lib/lhm/migration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,21 @@ module Lhm
class Migration
attr_reader :origin, :destination, :conditions, :renames

def initialize(origin, destination, conditions = nil, renames = {}, time = Time.now)
def initialize(origin, destination, conditions = nil, renames = {}, time = Time.now, generated_column_names = [])
@origin = origin
@destination = destination
@conditions = conditions
@renames = renames
@table_name = TableName.new(@origin.name, time)
@generated_column_names = generated_column_names
end

def archive_name
@archive_name ||= @table_name.archived
end

def intersection
Intersection.new(@origin, @destination, @renames)
Intersection.new(@origin, @destination, @renames, @generated_column_names)
end

def origin_name
Expand Down
6 changes: 5 additions & 1 deletion lib/lhm/migrator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,11 @@ def execute
@statements.each do |stmt|
@connection.execute(tagged(stmt))
end
Migration.new(@origin, destination_read, conditions, renames)
Migration.new(@origin, destination_read, conditions, renames, Time.now, generated_column_names)
end

def generated_column_names
@connection.columns(@origin.name).select(&:virtual?).map(&:name)
end

def destination_create
Expand Down
55 changes: 55 additions & 0 deletions spec/integration/lhm_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,61 @@
end
end

it 'works when table has generated columns' do
table_create(:users)
execute("insert into `users` set id = 1, `username` = 'memyself'")
execute("insert into `users` set id = 2, `username` = 'youyourself'")

# Add a generated column
Lhm.change_table(:users) do |t|
t.add_column(:sample_generated_column, 'VARCHAR(255) GENERATED ALWAYS AS (SUBSTRING(`username`, -2))')
end

# Without the handling of generated columns
Lhm::Migrator.any_instance.stubs(:generated_column_names).returns([])
# without the Migration passing in generated columns to Intersection, we observe an error as an attempt to write
# directly into generated columns will fail.
exception = assert_raises ActiveRecord::StatementInvalid do
Lhm.change_table(:users) do |t|
t.add_column(:sample_additional_column, "VARCHAR(255)")
end
end
assert_match "The value specified for generated column 'sample_generated_column' in table 'lhmn_users' is not allowed.", exception.message

Lhm.cleanup(true)

# With the handling of generated columns
Lhm::Migrator.any_instance.unstub(:generated_column_names)
# As we are now skipping the writing to generated columns, this migration should succeed
Lhm.change_table(:users) do |t|
t.add_column(:sample_additional_column, "VARCHAR(255)")
end

slave do
# new column is added
value(table_read(:users).columns['sample_additional_column']).must_equal({
:type => 'varchar(255)',
:is_nullable => 'YES',
:column_default => nil,
:comment => '',
:collate => 'utf8_general_ci',
})

# generated column remains intact
value(table_read(:users).columns['sample_generated_column']).must_equal({
:type => 'varchar(255)',
:is_nullable => 'YES',
:column_default => nil,
:comment => '',
:collate => 'utf8_general_ci',
})
end

result = select_one('SELECT sample_generated_column FROM users')
# generated column populated appropriately
assert_match "lf", result["sample_generated_column"]
end

it 'works when mysql reserved words are used' do
table_create(:lines)
execute("insert into `lines` set id = 1, `between` = 'foo'")
Expand Down

0 comments on commit ccb0a0c

Please sign in to comment.