Skip to content

Commit 3c6be5e

Browse files
committed
Default engine ENGINE=InnoDB is no longer dumped to make schema more agnostic
5 years ago, I made dumping full table options at #17569, especially to dump `ENGINE=InnoDB ROW_FORMAT=DYNAMIC` to use utf8mb4 with large key prefix. In that time, omitting the default engine `ENGINE=InnoDB` was not useful since `ROW_FORMAT=DYNAMIC` always remains as long as using utf8mb4 with large key prefix. But now, MySQL 5.7.9 has finally changed the default row format to DYNAMIC, utf8mb4 with large key prefix can be used without dumping the default engine and the row format explicitly. So now is a good time to make the default engine is omitted. Before: ```ruby create_table "accounts", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci", force: :cascade do |t| end ``` After: ```ruby create_table "accounts", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| end ``` To entirely omit `:options` option to make schema agnostic, I've added `:charset` and `:collation` table options to exclude `CHARSET` and `COLLATE` from `:options`. Fixes #26209. Closes #29472. See also #33608, #33853, and #34742.
1 parent fd8fd4a commit 3c6be5e

File tree

11 files changed

+87
-78
lines changed

11 files changed

+87
-78
lines changed

activerecord/CHANGELOG.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
1+
* Default engine `ENGINE=InnoDB` is no longer dumped to make schema more agnostic.
2+
3+
Before:
4+
5+
```ruby
6+
create_table "accounts", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci", force: :cascade do |t|
7+
end
8+
```
9+
10+
After:
11+
12+
```ruby
13+
create_table "accounts", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
14+
end
15+
```
16+
17+
*Ryuta Kamizono*
18+
119
* Added delegated type as an alternative to single-table inheritance for representing class hierarchies.
220
See ActiveRecord::DelegatedType for the full description.
3-
21+
422
*DHH*
523

624
* Deprecate aggregations with group by duplicated fields.

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

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def visit_TableDefinition(o)
5353
end
5454

5555
create_sql << "(#{statements.join(', ')})" if statements.present?
56-
add_table_options!(create_sql, table_options(o))
56+
add_table_options!(create_sql, o)
5757
create_sql << " AS #{to_sql(o.as)}" if o.as
5858
create_sql
5959
end
@@ -106,17 +106,8 @@ def supports_index_using?
106106
true
107107
end
108108

109-
def table_options(o)
110-
table_options = {}
111-
table_options[:comment] = o.comment
112-
table_options[:options] = o.options
113-
table_options
114-
end
115-
116-
def add_table_options!(create_sql, options)
117-
if options_sql = options[:options]
118-
create_sql << " #{options_sql}"
119-
end
109+
def add_table_options!(create_sql, o)
110+
create_sql << " #{o.options}" if o.options
120111
create_sql
121112
end
122113

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,8 @@ def initialize(
277277
if_not_exists: false,
278278
options: nil,
279279
as: nil,
280-
comment: nil
280+
comment: nil,
281+
**
281282
)
282283
@conn = conn
283284
@columns_hash = {}

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,7 @@ def primary_key(table_name)
295295
#
296296
# See also TableDefinition#column for details on how to create columns.
297297
def create_table(table_name, id: :primary_key, primary_key: nil, force: nil, **options)
298-
td = create_table_definition(
299-
table_name, **options.extract!(:temporary, :if_not_exists, :options, :as, :comment)
300-
)
298+
td = create_table_definition(table_name, **extract_table_options!(options))
301299

302300
if id && !td.as
303301
pk = primary_key || Base.get_primary_key(table_name.to_s.singularize)
@@ -1379,14 +1377,18 @@ def schema_creation
13791377
SchemaCreation.new(self)
13801378
end
13811379

1382-
def create_table_definition(*args, **options)
1383-
TableDefinition.new(self, *args, **options)
1380+
def create_table_definition(name, **options)
1381+
TableDefinition.new(self, name, **options)
13841382
end
13851383

13861384
def create_alter_table(name)
13871385
AlterTable.new create_table_definition(name)
13881386
end
13891387

1388+
def extract_table_options!(options)
1389+
options.extract!(:temporary, :if_not_exists, :options, :as, :comment, :charset, :collation)
1390+
end
1391+
13901392
def fetch_type_metadata(sql_type)
13911393
cast_type = lookup_cast_type(sql_type)
13921394
SqlTypeMetadata.new(

activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -414,24 +414,31 @@ def foreign_keys(table_name)
414414
end
415415

416416
def table_options(table_name) # :nodoc:
417-
table_options = {}
418-
419417
create_table_info = create_table_info(table_name)
420418

421419
# strip create_definitions and partition_options
422420
# Be aware that `create_table_info` might not include any table options due to `NO_TABLE_OPTIONS` sql mode.
423421
raw_table_options = create_table_info.sub(/\A.*\n\) ?/m, "").sub(/\n\/\*!.*\*\/\n\z/m, "").strip
424422

423+
return if raw_table_options.empty?
424+
425+
table_options = {}
426+
427+
if / DEFAULT CHARSET=(?<charset>\w+)(?: COLLATE=(?<collation>\w+))?/ =~ raw_table_options
428+
raw_table_options = $` + $' # before part + after part
429+
table_options[:charset] = charset
430+
table_options[:collation] = collation if collation
431+
end
432+
425433
# strip AUTO_INCREMENT
426434
raw_table_options.sub!(/(ENGINE=\w+)(?: AUTO_INCREMENT=\d+)/, '\1')
427435

428-
table_options[:options] = raw_table_options unless raw_table_options.blank?
429-
430436
# strip COMMENT
431437
if raw_table_options.sub!(/ COMMENT='.+'/, "")
432438
table_options[:comment] = table_comment(table_name)
433439
end
434440

441+
table_options[:options] = raw_table_options unless raw_table_options == "ENGINE=InnoDB"
435442
table_options
436443
end
437444

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,11 @@ def visit_IndexDefinition(o, create = false)
4040
add_sql_comment!(sql.join(" "), o.comment)
4141
end
4242

43-
def add_table_options!(create_sql, options)
44-
add_sql_comment!(super, options[:comment])
43+
def add_table_options!(create_sql, o)
44+
create_sql = super
45+
create_sql << " DEFAULT CHARSET=#{o.charset}" if o.charset
46+
create_sql << " COLLATE=#{o.collation}" if o.collation
47+
add_sql_comment!(create_sql, o.comment)
4548
end
4649

4750
def add_column_options!(sql, options)

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ module ColumnMethods
6060
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
6161
include ColumnMethods
6262

63+
attr_reader :charset, :collation
64+
65+
def initialize(conn, name, charset: nil, collation: nil, **)
66+
super
67+
@charset = charset
68+
@collation = collation
69+
end
70+
6371
def new_column_definition(name, type, **options) # :nodoc:
6472
case type
6573
when :virtual

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,8 @@ def schema_creation
154154
MySQL::SchemaCreation.new(self)
155155
end
156156

157-
def create_table_definition(*args, **options)
158-
MySQL::TableDefinition.new(self, *args, **options)
157+
def create_table_definition(name, **options)
158+
MySQL::TableDefinition.new(self, name, **options)
159159
end
160160

161161
def new_column_from_field(table_name, field)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -621,8 +621,8 @@ def schema_creation
621621
PostgreSQL::SchemaCreation.new(self)
622622
end
623623

624-
def create_table_definition(*args, **options)
625-
PostgreSQL::TableDefinition.new(self, *args, **options)
624+
def create_table_definition(name, **options)
625+
PostgreSQL::TableDefinition.new(self, name, **options)
626626
end
627627

628628
def create_alter_table(name)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ def schema_creation
8787
SQLite3::SchemaCreation.new(self)
8888
end
8989

90-
def create_table_definition(*args, **options)
91-
SQLite3::TableDefinition.new(self, *args, **options)
90+
def create_table_definition(name, **options)
91+
SQLite3::TableDefinition.new(self, name, **options)
9292
end
9393

9494
def validate_index_length!(table_name, new_name, internal = false)

0 commit comments

Comments
 (0)