mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #30337 from kamipo/refactor_schema_dumper
Refactor `SchemaDumper` to make it possible to adapter specific customization
This commit is contained in:
commit
f10a6467c5
15 changed files with 55 additions and 57 deletions
|
@ -1,3 +1,7 @@
|
|||
* Remove deprecated `#migration_keys`.
|
||||
|
||||
*Ryuta Kamizono*
|
||||
|
||||
* Automatically guess the inverse associations for STI.
|
||||
|
||||
*Yuichiro Kaneko*
|
||||
|
|
|
@ -4,31 +4,24 @@ require "active_support/core_ext/hash/compact"
|
|||
|
||||
module ActiveRecord
|
||||
module ConnectionAdapters # :nodoc:
|
||||
# The goal of this module is to move Adapter specific column
|
||||
# definitions to the Adapter instead of having it in the schema
|
||||
# dumper itself. This code represents the normal case.
|
||||
# We can then redefine how certain data types may be handled in the schema dumper on the
|
||||
# Adapter level by over-writing this code inside the database specific adapters
|
||||
module ColumnDumper
|
||||
def column_spec(column)
|
||||
[schema_type_with_virtual(column), prepare_column_options(column)]
|
||||
class SchemaDumper < SchemaDumper # :nodoc:
|
||||
def self.create(connection, options)
|
||||
new(connection, options)
|
||||
end
|
||||
|
||||
def column_spec_for_primary_key(column)
|
||||
return {} if default_primary_key?(column)
|
||||
spec = { id: schema_type(column).inspect }
|
||||
spec.merge!(prepare_column_options(column).except!(:null))
|
||||
spec[:default] ||= "nil" if explicit_primary_key_default?(column)
|
||||
spec
|
||||
end
|
||||
|
||||
# Lists the valid migration options
|
||||
def migration_keys # :nodoc:
|
||||
column_options_keys
|
||||
end
|
||||
deprecate :migration_keys
|
||||
|
||||
private
|
||||
def column_spec(column)
|
||||
[schema_type_with_virtual(column), prepare_column_options(column)]
|
||||
end
|
||||
|
||||
def column_spec_for_primary_key(column)
|
||||
return {} if default_primary_key?(column)
|
||||
spec = { id: schema_type(column).inspect }
|
||||
spec.merge!(prepare_column_options(column).except!(:null))
|
||||
spec[:default] ||= "nil" if explicit_primary_key_default?(column)
|
||||
spec
|
||||
end
|
||||
|
||||
def prepare_column_options(column)
|
||||
spec = {}
|
||||
spec[:limit] = schema_limit(column)
|
||||
|
@ -51,7 +44,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def schema_type_with_virtual(column)
|
||||
if supports_virtual_columns? && column.virtual?
|
||||
if @connection.supports_virtual_columns? && column.virtual?
|
||||
:virtual
|
||||
else
|
||||
schema_type(column)
|
||||
|
@ -68,7 +61,7 @@ module ActiveRecord
|
|||
|
||||
def schema_limit(column)
|
||||
limit = column.limit unless column.bigint?
|
||||
limit.inspect if limit && limit != native_database_types[column.type][:limit]
|
||||
limit.inspect if limit && limit != @connection.native_database_types[column.type][:limit]
|
||||
end
|
||||
|
||||
def schema_precision(column)
|
||||
|
@ -81,7 +74,7 @@ module ActiveRecord
|
|||
|
||||
def schema_default(column)
|
||||
return unless column.has_default?
|
||||
type = lookup_cast_type_from_column(column)
|
||||
type = @connection.lookup_cast_type_from_column(column)
|
||||
default = type.deserialize(column.default)
|
||||
if default.nil?
|
||||
schema_expression(column)
|
||||
|
|
|
@ -1174,6 +1174,10 @@ module ActiveRecord
|
|||
raise NotImplementedError, "#{self.class} does not support changing column comments"
|
||||
end
|
||||
|
||||
def create_schema_dumper(options) # :nodoc:
|
||||
SchemaDumper.create(self, options)
|
||||
end
|
||||
|
||||
private
|
||||
def column_options_keys
|
||||
[:limit, :precision, :scale, :default, :null, :collation, :comment]
|
||||
|
|
|
@ -72,7 +72,6 @@ module ActiveRecord
|
|||
include Quoting, DatabaseStatements, SchemaStatements
|
||||
include DatabaseLimits
|
||||
include QueryCache
|
||||
include ColumnDumper
|
||||
include Savepoints
|
||||
|
||||
SIMPLE_INT = /\A\d+\z/
|
||||
|
|
|
@ -17,7 +17,6 @@ module ActiveRecord
|
|||
module ConnectionAdapters
|
||||
class AbstractMysqlAdapter < AbstractAdapter
|
||||
include MySQL::Quoting
|
||||
include MySQL::ColumnDumper
|
||||
include MySQL::SchemaStatements
|
||||
|
||||
##
|
||||
|
|
|
@ -3,17 +3,13 @@
|
|||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
module MySQL
|
||||
module ColumnDumper # :nodoc:
|
||||
def migration_keys
|
||||
super + [:unsigned]
|
||||
end
|
||||
|
||||
class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc:
|
||||
private
|
||||
def prepare_column_options(column)
|
||||
spec = super
|
||||
spec[:unsigned] = "true" if column.unsigned?
|
||||
|
||||
if supports_virtual_columns? && column.virtual?
|
||||
if @connection.supports_virtual_columns? && column.virtual?
|
||||
spec[:as] = extract_expression_for_virtual_column(column)
|
||||
spec[:stored] = "true" if /\b(?:STORED|PERSISTENT)\b/.match?(column.extra)
|
||||
spec = { type: schema_type(column).inspect }.merge!(spec)
|
||||
|
@ -48,24 +44,27 @@ module ActiveRecord
|
|||
def schema_collation(column)
|
||||
if column.collation && table_name = column.table_name
|
||||
@table_collation_cache ||= {}
|
||||
@table_collation_cache[table_name] ||= exec_query("SHOW TABLE STATUS LIKE #{quote(table_name)}", "SCHEMA").first["Collation"]
|
||||
@table_collation_cache[table_name] ||=
|
||||
@connection.exec_query("SHOW TABLE STATUS LIKE #{@connection.quote(table_name)}", "SCHEMA").first["Collation"]
|
||||
column.collation.inspect if column.collation != @table_collation_cache[table_name]
|
||||
end
|
||||
end
|
||||
|
||||
def extract_expression_for_virtual_column(column)
|
||||
if mariadb? && version < "10.2.5"
|
||||
create_table_info = create_table_info(column.table_name)
|
||||
if %r/#{quote_column_name(column.name)} #{Regexp.quote(column.sql_type)}(?: COLLATE \w+)? AS \((?<expression>.+?)\) #{column.extra}/ =~ create_table_info
|
||||
if @connection.mariadb? && @connection.version < "10.2.5"
|
||||
create_table_info = @connection.send(:create_table_info, column.table_name)
|
||||
column_name = @connection.quote_column_name(column.name)
|
||||
if %r/#{column_name} #{Regexp.quote(column.sql_type)}(?: COLLATE \w+)? AS \((?<expression>.+?)\) #{column.extra}/ =~ create_table_info
|
||||
$~[:expression].inspect
|
||||
end
|
||||
else
|
||||
scope = quoted_scope(column.table_name)
|
||||
scope = @connection.send(:quoted_scope, column.table_name)
|
||||
column_name = @connection.quote(column.name)
|
||||
sql = "SELECT generation_expression FROM information_schema.columns" \
|
||||
" WHERE table_schema = #{scope[:schema]}" \
|
||||
" AND table_name = #{scope[:name]}" \
|
||||
" AND column_name = #{quote(column.name)}"
|
||||
query_value(sql, "SCHEMA").inspect
|
||||
" AND column_name = #{column_name}"
|
||||
@connection.query_value(sql, "SCHEMA").inspect
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -66,6 +66,10 @@ module ActiveRecord
|
|||
MySQL::Table.new(table_name, base)
|
||||
end
|
||||
|
||||
def create_schema_dumper(options)
|
||||
MySQL::SchemaDumper.create(self, options)
|
||||
end
|
||||
|
||||
private
|
||||
CHARSETS_OF_4BYTES_MAXLEN = ["utf8mb4", "utf16", "utf16le", "utf32"]
|
||||
|
||||
|
|
|
@ -3,12 +3,7 @@
|
|||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
module PostgreSQL
|
||||
module ColumnDumper # :nodoc:
|
||||
# Adds +:array+ as a valid migration key
|
||||
def migration_keys
|
||||
super + [:array]
|
||||
end
|
||||
|
||||
class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc:
|
||||
private
|
||||
def prepare_column_options(column)
|
||||
spec = super
|
||||
|
|
|
@ -590,6 +590,10 @@ module ActiveRecord
|
|||
PostgreSQL::Table.new(table_name, base)
|
||||
end
|
||||
|
||||
def create_schema_dumper(options) # :nodoc:
|
||||
PostgreSQL::SchemaDumper.create(self, options)
|
||||
end
|
||||
|
||||
private
|
||||
def schema_creation
|
||||
PostgreSQL::SchemaCreation.new(self)
|
||||
|
|
|
@ -121,7 +121,6 @@ module ActiveRecord
|
|||
include PostgreSQL::ReferentialIntegrity
|
||||
include PostgreSQL::SchemaStatements
|
||||
include PostgreSQL::DatabaseStatements
|
||||
include PostgreSQL::ColumnDumper
|
||||
|
||||
def supports_index_sort_order?
|
||||
true
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
module SQLite3
|
||||
module ColumnDumper # :nodoc:
|
||||
class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc:
|
||||
private
|
||||
|
||||
def default_primary_key?(column)
|
||||
schema_type(column) == :integer
|
||||
end
|
||||
|
|
|
@ -43,6 +43,10 @@ module ActiveRecord
|
|||
SQLite3::Table.new(table_name, base)
|
||||
end
|
||||
|
||||
def create_schema_dumper(options)
|
||||
SQLite3::SchemaDumper.create(self, options)
|
||||
end
|
||||
|
||||
private
|
||||
def schema_creation
|
||||
SQLite3::SchemaCreation.new(self)
|
||||
|
|
|
@ -57,7 +57,6 @@ module ActiveRecord
|
|||
ADAPTER_NAME = "SQLite".freeze
|
||||
|
||||
include SQLite3::Quoting
|
||||
include SQLite3::ColumnDumper
|
||||
include SQLite3::SchemaStatements
|
||||
|
||||
NATIVE_DATABASE_TYPES = {
|
||||
|
|
|
@ -19,7 +19,7 @@ module ActiveRecord
|
|||
|
||||
class << self
|
||||
def dump(connection = ActiveRecord::Base.connection, stream = STDOUT, config = ActiveRecord::Base)
|
||||
new(connection, generate_options(config)).dump(stream)
|
||||
connection.create_schema_dumper(generate_options(config)).dump(stream)
|
||||
stream
|
||||
end
|
||||
|
||||
|
@ -123,7 +123,7 @@ HEADER
|
|||
when String
|
||||
tbl.print ", primary_key: #{pk.inspect}" unless pk == "id"
|
||||
pkcol = columns.detect { |c| c.name == pk }
|
||||
pkcolspec = @connection.column_spec_for_primary_key(pkcol)
|
||||
pkcolspec = column_spec_for_primary_key(pkcol)
|
||||
if pkcolspec.present?
|
||||
tbl.print ", #{format_colspec(pkcolspec)}"
|
||||
end
|
||||
|
@ -145,7 +145,7 @@ HEADER
|
|||
columns.each do |column|
|
||||
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
|
||||
next if column.name == pk
|
||||
type, colspec = @connection.column_spec(column)
|
||||
type, colspec = column_spec(column)
|
||||
tbl.print " t.#{type} #{column.name.inspect}"
|
||||
tbl.print ", #{format_colspec(colspec)}" if colspec.present?
|
||||
tbl.puts
|
||||
|
|
|
@ -1112,10 +1112,6 @@ class CopyMigrationsTest < ActiveRecord::TestCase
|
|||
assert_deprecated { ActiveRecord::Base.connection.initialize_internal_metadata_table }
|
||||
end
|
||||
|
||||
def test_deprecate_migration_keys
|
||||
assert_deprecated { ActiveRecord::Base.connection.migration_keys }
|
||||
end
|
||||
|
||||
def test_deprecate_supports_migrations
|
||||
assert_deprecated { ActiveRecord::Base.connection.supports_migrations? }
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue