1
0
Fork 0
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:
Ryuta Kamizono 2017-08-24 21:16:08 +09:00 committed by GitHub
commit f10a6467c5
15 changed files with 55 additions and 57 deletions

View file

@ -1,3 +1,7 @@
* Remove deprecated `#migration_keys`.
*Ryuta Kamizono*
* Automatically guess the inverse associations for STI.
*Yuichiro Kaneko*

View file

@ -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)

View file

@ -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]

View file

@ -72,7 +72,6 @@ module ActiveRecord
include Quoting, DatabaseStatements, SchemaStatements
include DatabaseLimits
include QueryCache
include ColumnDumper
include Savepoints
SIMPLE_INT = /\A\d+\z/

View file

@ -17,7 +17,6 @@ module ActiveRecord
module ConnectionAdapters
class AbstractMysqlAdapter < AbstractAdapter
include MySQL::Quoting
include MySQL::ColumnDumper
include MySQL::SchemaStatements
##

View file

@ -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

View file

@ -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"]

View file

@ -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

View file

@ -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)

View file

@ -121,7 +121,6 @@ module ActiveRecord
include PostgreSQL::ReferentialIntegrity
include PostgreSQL::SchemaStatements
include PostgreSQL::DatabaseStatements
include PostgreSQL::ColumnDumper
def supports_index_sort_order?
true

View file

@ -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

View file

@ -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)

View file

@ -57,7 +57,6 @@ module ActiveRecord
ADAPTER_NAME = "SQLite".freeze
include SQLite3::Quoting
include SQLite3::ColumnDumper
include SQLite3::SchemaStatements
NATIVE_DATABASE_TYPES = {

View file

@ -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

View file

@ -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