Skip to content

Commit

Permalink
Add support for Mysql column positioning via #add_column and #change_…
Browse files Browse the repository at this point in the history
…column

add_column and change_column in the Mysql adapter now accept some
additional options:
:first => true        # Put the column in front of all the columns
:after => column_name # Put the colmn after 'column_name'

add_column :new_col, :string, :first => true
add_column :another_col, :integer, :default => 0, :after => :new_col

[#3286 state:committed]

Signed-off-by: Jeremy Kemper <jeremy@bitsweat.net>
  • Loading branch information
bmarini authored and jeremy committed Dec 4, 2009
1 parent c253d7b commit ccb197b
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 0 deletions.
2 changes: 2 additions & 0 deletions activerecord/CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
*2.3.6 (pending)*

* MySQL: add_ and change_column support positioning. #3286 [Ben Marini]

* Reset your Active Record counter caches with the reset_counter_cache class method. #1211 [Mike Breen]


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,13 @@ def rename_table(table_name, new_name)
execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
end

def add_column(table_name, column_name, type, options = {})
add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
add_column_options!(add_column_sql, options)
add_column_position!(add_column_sql, options)
execute(add_column_sql)
end

def change_column_default(table_name, column_name, default) #:nodoc:
column = column_for(table_name, column_name)
change_column table_name, column_name, column.sql_type, :default => default
Expand Down Expand Up @@ -508,6 +515,7 @@ def change_column(table_name, column_name, type, options = {}) #:nodoc:

change_column_sql = "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
add_column_options!(change_column_sql, options)
add_column_position!(change_column_sql, options)
execute(change_column_sql)
end

Expand Down Expand Up @@ -539,6 +547,13 @@ def type_to_sql(type, limit = nil, precision = nil, scale = nil)
end
end

def add_column_position!(sql, options)
if options[:first]
sql << " FIRST"
elsif options[:after]
sql << " AFTER #{quote_column_name(options[:after])}"
end
end

# SHOW VARIABLES LIKE 'name'
def show_variable(name)
Expand Down
47 changes: 47 additions & 0 deletions activerecord/test/cases/migration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,53 @@ def test_add_remove_single_field_using_symbol_arguments
assert !Person.column_methods_hash.include?(:last_name)
end

if current_adapter?(:MysqlAdapter)
def testing_table_for_positioning
Person.connection.create_table :testings, :id => false do |t|
t.column :first, :integer
t.column :second, :integer
t.column :third, :integer
end

yield Person.connection
ensure
Person.connection.drop_table :testings rescue nil
end
protected :testing_table_for_positioning

def test_column_positioning
testing_table_for_positioning do |conn|
assert_equal %w(first second third), conn.columns(:testings).map {|c| c.name }
end
end

def test_add_column_with_positioning
testing_table_for_positioning do |conn|
conn.add_column :testings, :new_col, :integer
assert_equal %w(first second third new_col), conn.columns(:testings).map {|c| c.name }
end
testing_table_for_positioning do |conn|
conn.add_column :testings, :new_col, :integer, :first => true
assert_equal %w(new_col first second third), conn.columns(:testings).map {|c| c.name }
end
testing_table_for_positioning do |conn|
conn.add_column :testings, :new_col, :integer, :after => :first
assert_equal %w(first new_col second third), conn.columns(:testings).map {|c| c.name }
end
end

def test_change_column_with_positioning
testing_table_for_positioning do |conn|
conn.change_column :testings, :second, :integer, :first => true
assert_equal %w(second first third), conn.columns(:testings).map {|c| c.name }
end
testing_table_for_positioning do |conn|
conn.change_column :testings, :second, :integer, :after => :third
assert_equal %w(first third second), conn.columns(:testings).map {|c| c.name }
end
end
end

def test_add_rename
Person.delete_all

Expand Down

0 comments on commit ccb197b

Please sign in to comment.