mirror of
https://github.com/github/rails.git
synced 2026-04-26 03:00:59 -04:00
Fixed mysql change_column_default to not make the column always nullable.
Also added change_column_null to both mysql and sqlite to keep the api features closer to postgresql. [#617 state:resolved]
This commit is contained in:
committed by
Jeremy Kemper
parent
8f72bc92e2
commit
07578ac855
@@ -1,5 +1,7 @@
|
||||
*Edge*
|
||||
|
||||
* change_column_default preserves the not-null constraint. #617 [Tarmo Tänav]
|
||||
|
||||
* Fixed that create database statements would always include "DEFAULT NULL" (Nick Sieger) [#334]
|
||||
|
||||
* Add :accessible option to associations for allowing (opt-in) mass assignment. #474. [David Dollar] Example :
|
||||
|
||||
@@ -437,18 +437,29 @@ module ActiveRecord
|
||||
end
|
||||
|
||||
def change_column_default(table_name, column_name, default) #:nodoc:
|
||||
current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'")["Type"]
|
||||
column = column_for(table_name, column_name)
|
||||
change_column table_name, column_name, column.sql_type, :default => default
|
||||
end
|
||||
|
||||
execute("ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{current_type} DEFAULT #{quote(default)}")
|
||||
def change_column_null(table_name, column_name, null, default = nil)
|
||||
column = column_for(table_name, column_name)
|
||||
|
||||
unless null || default.nil?
|
||||
execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
|
||||
end
|
||||
|
||||
change_column table_name, column_name, column.sql_type, :null => null
|
||||
end
|
||||
|
||||
def change_column(table_name, column_name, type, options = {}) #:nodoc:
|
||||
column = column_for(table_name, column_name)
|
||||
|
||||
unless options_include_default?(options)
|
||||
if column = columns(table_name).find { |c| c.name == column_name.to_s }
|
||||
options[:default] = column.default
|
||||
else
|
||||
raise "No such column: #{table_name}.#{column_name}"
|
||||
end
|
||||
options[:default] = column.default
|
||||
end
|
||||
|
||||
unless options.has_key?(:null)
|
||||
options[:null] = column.null
|
||||
end
|
||||
|
||||
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])}"
|
||||
@@ -460,6 +471,7 @@ module ActiveRecord
|
||||
options = {}
|
||||
if column = columns(table_name).find { |c| c.name == column_name.to_s }
|
||||
options[:default] = column.default
|
||||
options[:null] = column.null
|
||||
else
|
||||
raise ActiveRecordError, "No such column: #{table_name}.#{column_name}"
|
||||
end
|
||||
@@ -536,6 +548,13 @@ module ActiveRecord
|
||||
def version
|
||||
@version ||= @connection.server_info.scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i }
|
||||
end
|
||||
|
||||
def column_for(table_name, column_name)
|
||||
unless column = columns(table_name).find { |c| c.name == column_name.to_s }
|
||||
raise "No such column: #{table_name}.#{column_name}"
|
||||
end
|
||||
column
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -238,6 +238,15 @@ module ActiveRecord
|
||||
end
|
||||
end
|
||||
|
||||
def change_column_null(table_name, column_name, null, default = nil)
|
||||
unless null || default.nil?
|
||||
execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
|
||||
end
|
||||
alter_table(table_name) do |definition|
|
||||
definition[column_name].null = null
|
||||
end
|
||||
end
|
||||
|
||||
def change_column(table_name, column_name, type, options = {}) #:nodoc:
|
||||
alter_table(table_name) do |definition|
|
||||
include_default = options_include_default?(options)
|
||||
|
||||
@@ -703,6 +703,55 @@ if ActiveRecord::Base.connection.supports_migrations?
|
||||
Person.connection.drop_table :testings rescue nil
|
||||
end
|
||||
|
||||
def test_keeping_default_and_notnull_constaint_on_change
|
||||
Person.connection.create_table :testings do |t|
|
||||
t.column :title, :string
|
||||
end
|
||||
person_klass = Class.new(Person)
|
||||
person_klass.set_table_name 'testings'
|
||||
|
||||
person_klass.connection.add_column "testings", "wealth", :integer, :null => false, :default => 99
|
||||
person_klass.reset_column_information
|
||||
assert_equal 99, person_klass.columns_hash["wealth"].default
|
||||
assert_equal false, person_klass.columns_hash["wealth"].null
|
||||
assert_nothing_raised {person_klass.connection.execute("insert into testings (title) values ('tester')")}
|
||||
|
||||
# change column default to see that column doesn't lose its not null definition
|
||||
person_klass.connection.change_column_default "testings", "wealth", 100
|
||||
person_klass.reset_column_information
|
||||
assert_equal 100, person_klass.columns_hash["wealth"].default
|
||||
assert_equal false, person_klass.columns_hash["wealth"].null
|
||||
|
||||
# rename column to see that column doesn't lose its not null and/or default definition
|
||||
person_klass.connection.rename_column "testings", "wealth", "money"
|
||||
person_klass.reset_column_information
|
||||
assert_nil person_klass.columns_hash["wealth"]
|
||||
assert_equal 100, person_klass.columns_hash["money"].default
|
||||
assert_equal false, person_klass.columns_hash["money"].null
|
||||
|
||||
# change column
|
||||
person_klass.connection.change_column "testings", "money", :integer, :null => false, :default => 1000
|
||||
person_klass.reset_column_information
|
||||
assert_equal 1000, person_klass.columns_hash["money"].default
|
||||
assert_equal false, person_klass.columns_hash["money"].null
|
||||
|
||||
# change column, make it nullable and clear default
|
||||
person_klass.connection.change_column "testings", "money", :integer, :null => true, :default => nil
|
||||
person_klass.reset_column_information
|
||||
assert_nil person_klass.columns_hash["money"].default
|
||||
assert_equal true, person_klass.columns_hash["money"].null
|
||||
|
||||
# change_column_null, make it not nullable and set null values to a default value
|
||||
person_klass.connection.execute('UPDATE testings SET money = NULL')
|
||||
person_klass.connection.change_column_null "testings", "money", false, 2000
|
||||
person_klass.reset_column_information
|
||||
assert_nil person_klass.columns_hash["money"].default
|
||||
assert_equal false, person_klass.columns_hash["money"].null
|
||||
assert_equal [2000], Person.connection.select_values("SELECT money FROM testings").map { |s| s.to_i }.sort
|
||||
ensure
|
||||
Person.connection.drop_table :testings rescue nil
|
||||
end
|
||||
|
||||
def test_change_column_default_to_null
|
||||
Person.connection.change_column_default "people", "first_name", nil
|
||||
Person.reset_column_information
|
||||
|
||||
Reference in New Issue
Block a user