Skip to content

Commit 1288289

Browse files
authored
Merge pull request rails#45697 from adrianna-chang-shopify/ac-change-column-default-mysql
Use SET DEFAULT when changing a column default in MySQL
2 parents e1f566a + b9b8852 commit 1288289

File tree

7 files changed

+32
-17
lines changed

7 files changed

+32
-17
lines changed

activerecord/lib/active_record/connection_adapters.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module ConnectionAdapters
1818
autoload :IndexDefinition
1919
autoload :ColumnDefinition
2020
autoload :ChangeColumnDefinition
21+
autoload :ChangeColumnDefaultDefinition
2122
autoload :ForeignKeyDefinition
2223
autoload :CheckConstraintDefinition
2324
autoload :TableDefinition

activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ def aliased_types(name, fallback)
9494

9595
ChangeColumnDefinition = Struct.new(:column, :name, :ddl) # :nodoc:
9696

97+
ChangeColumnDefaultDefinition = Struct.new(:column, :default, :ddl) # :nodoc:
98+
9799
CreateIndexDefinition = Struct.new(:index, :algorithm, :if_not_exists, :ddl) # :nodoc:
98100

99101
PrimaryKeyDefinition = Struct.new(:name) # :nodoc:

activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1692,6 +1692,14 @@ def add_column_for_alter(table_name, column_name, type, **options)
16921692
schema_creation.accept(AddColumnDefinition.new(cd))
16931693
end
16941694

1695+
def change_column_default_for_alter(table_name, column_name, default_or_changes)
1696+
column = column_for(table_name, column_name)
1697+
return unless column
1698+
1699+
default = extract_new_default_value(default_or_changes)
1700+
schema_creation.accept(ChangeColumnDefaultDefinition.new(column, default))
1701+
end
1702+
16951703
def rename_column_sql(table_name, column_name, new_column_name)
16961704
"RENAME COLUMN #{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}"
16971705
end

activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,8 +347,7 @@ def rename_index(table_name, old_name, new_name)
347347
end
348348

349349
def change_column_default(table_name, column_name, default_or_changes) # :nodoc:
350-
default = extract_new_default_value(default_or_changes)
351-
change_column table_name, column_name, nil, default: default
350+
execute "ALTER TABLE #{quote_table_name(table_name)} #{change_column_default_for_alter(table_name, column_name, default_or_changes)}"
352351
end
353352

354353
def change_column_null(table_name, column_name, null, default = nil) # :nodoc:

activerecord/lib/active_record/connection_adapters/mysql/schema_creation.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ def visit_ChangeColumnDefinition(o)
2424
o.ddl = add_column_position!(change_column_sql, column_options(o.column))
2525
end
2626

27+
def visit_ChangeColumnDefaultDefinition(o)
28+
sql = +"ALTER COLUMN #{quote_column_name(o.column.name)} SET DEFAULT "
29+
if o.default.nil?
30+
sql << "NULL"
31+
else
32+
sql << quote_default_expression(o.default, o.column)
33+
end
34+
o.ddl = sql
35+
end
36+
2737
def visit_CreateIndexDefinition(o)
2838
sql = visit_IndexDefinition(o.index, true)
2939
sql << " #{o.algorithm}" if o.algorithm

activerecord/lib/active_record/connection_adapters/postgresql/schema_creation.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ def visit_ChangeColumnDefinition(o)
8787
o.ddl = change_column_sql
8888
end
8989

90+
def visit_ChangeColumnDefaultDefinition(o)
91+
sql = +"ALTER COLUMN #{quote_column_name(o.column.name)} "
92+
if o.default.nil?
93+
sql << "DROP DEFAULT"
94+
else
95+
sql << "SET DEFAULT #{quote_default_expression(o.default, o.column)}"
96+
end
97+
o.ddl = sql
98+
end
99+
90100
def add_column_options!(sql, options)
91101
if options[:collation]
92102
sql << " COLLATE \"#{options[:collation]}\""

activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -855,21 +855,6 @@ def change_column_for_alter(table_name, column_name, type, **options)
855855
sqls
856856
end
857857

858-
def change_column_default_for_alter(table_name, column_name, default_or_changes)
859-
column = column_for(table_name, column_name)
860-
return unless column
861-
862-
default = extract_new_default_value(default_or_changes)
863-
alter_column_query = "ALTER COLUMN #{quote_column_name(column_name)} %s"
864-
if default.nil?
865-
# <tt>DEFAULT NULL</tt> results in the same behavior as <tt>DROP DEFAULT</tt>. However, PostgreSQL will
866-
# cast the default to the columns type, which leaves us with a default like "default NULL::character varying".
867-
alter_column_query % "DROP DEFAULT"
868-
else
869-
alter_column_query % "SET DEFAULT #{quote_default_expression(default, column)}"
870-
end
871-
end
872-
873858
def change_column_null_for_alter(table_name, column_name, null, default = nil)
874859
if default.nil?
875860
"ALTER COLUMN #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL"

0 commit comments

Comments
 (0)