diff options
author | Ryuta Kamizono <kamipo@gmail.com> | 2017-12-03 15:00:05 +0900 |
---|---|---|
committer | Ryuta Kamizono <kamipo@gmail.com> | 2017-12-03 15:12:23 +0900 |
commit | d0f5dce492696019ddf409892829f89bee5f45ef (patch) | |
tree | c0339a27fee2b8ee4f38e398f7f3a6ecd688c673 /activerecord/lib/active_record | |
parent | 8c5a7fbefd3cad403e7594d0b6a5488d80d4c98e (diff) | |
download | rails-d0f5dce492696019ddf409892829f89bee5f45ef.tar.gz rails-d0f5dce492696019ddf409892829f89bee5f45ef.tar.bz2 rails-d0f5dce492696019ddf409892829f89bee5f45ef.zip |
`change_column_default` should be executed after type changing
If do not execute a type changing first, filling in default value may be
failed.
```
% ARCONN=postgresql be ruby -w -Itest test/cases/migration/compatibility_test.rb -n test_legacy_change_column_with_null_executes_update
Using postgresql
Run options: -n test_legacy_change_column_with_null_executes_update --seed 20459
E
Error:
ActiveRecord::Migration::CompatibilityTest#test_legacy_change_column_with_null_executes_update:
StandardError: An error has occurred, this and all later migrations canceled:
PG::StringDataRightTruncation: ERROR: value too long for type character varying(5)
: UPDATE "testings" SET "foo"='foobar' WHERE "foo" IS NULL
```
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb | 15 | ||||
-rw-r--r-- | activerecord/lib/active_record/migration/compatibility.rb | 17 |
2 files changed, 18 insertions, 14 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb index 2e9e74403b..bf5fbb30e1 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb @@ -393,9 +393,9 @@ module ActiveRecord end def change_column(table_name, column_name, type, options = {}) #:nodoc: - quoted_table_name = quote_table_name(table_name) + clear_cache! sqls, procs = change_column_for_alter(table_name, column_name, type, options) - execute "ALTER TABLE #{quoted_table_name} #{sqls.join(", ")}" + execute "ALTER TABLE #{quote_table_name(table_name)} #{sqls.join(", ")}" procs.each(&:call) end @@ -646,8 +646,7 @@ module ActiveRecord end end - def change_column_for_alter(table_name, column_name, type, options = {}) - clear_cache! + def change_column_sql(table_name, column_name, type, options = {}) quoted_column_name = quote_column_name(column_name) sql_type = type_to_sql(type, options) sql = "ALTER COLUMN #{quoted_column_name} TYPE #{sql_type}".dup @@ -661,7 +660,11 @@ module ActiveRecord sql << " USING CAST(#{quoted_column_name} AS #{cast_as_type})" end - sqls = [sql] + sql + end + + def change_column_for_alter(table_name, column_name, type, options = {}) + sqls = [change_column_sql(table_name, column_name, type, options)] procs = [] sqls << change_column_default_for_alter(table_name, column_name, options[:default]) if options.key?(:default) sqls << change_column_null_for_alter(table_name, column_name, options[:null], options[:default]) if options.key?(:null) @@ -673,7 +676,6 @@ module ActiveRecord # Changes the default value of a table column. def change_column_default_for_alter(table_name, column_name, default_or_changes) # :nodoc: - clear_cache! column = column_for(table_name, column_name) return unless column @@ -689,7 +691,6 @@ module ActiveRecord end def change_column_null_for_alter(table_name, column_name, null, default = nil) #:nodoc: - clear_cache! "ALTER #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL" end diff --git a/activerecord/lib/active_record/migration/compatibility.rb b/activerecord/lib/active_record/migration/compatibility.rb index da307c1723..bd8c054c28 100644 --- a/activerecord/lib/active_record/migration/compatibility.rb +++ b/activerecord/lib/active_record/migration/compatibility.rb @@ -16,13 +16,16 @@ module ActiveRecord V5_2 = Current class V5_1 < V5_2 - if adapter_name == "PostgreSQL" - def change_column(table_name, column_name, type, options = {}) - unless options[:null] || options[:default].nil? - column = connection.send(:column_for, table_name, column_name) - connection.execute("UPDATE #{connection.quote_table_name(table_name)} SET #{connection.quote_column_name(column_name)}=#{connection.quote_default_expression(options[:default], column)} WHERE #{connection.quote_column_name(column_name)} IS NULL") if column - end - connection.change_column(table_name, column_name, type, options) + def change_column(table_name, column_name, type, options = {}) + if adapter_name == "PostgreSQL" + clear_cache! + sql = connection.send(:change_column_sql, table_name, column_name, type, options) + execute "ALTER TABLE #{quote_table_name(table_name)} #{sql}" + change_column_default(table_name, column_name, options[:default]) if options.key?(:default) + change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null) + change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment) + else + super end end end |