mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Refactor ColumnDefinition
to contain options
hash
Column options are passed as an hash args then used as `options` hash in `add_column_options!`. Converting args to attributes is inconvinient for using options as an hash.
This commit is contained in:
parent
e2b425bc74
commit
ae39b1a03d
15 changed files with 59 additions and 128 deletions
|
@ -29,7 +29,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def visit_ColumnDefinition(o)
|
||||
o.sql_type ||= type_to_sql(o.type, o.limit, o.precision, o.scale)
|
||||
o.sql_type = type_to_sql(o.type, o.options)
|
||||
column_sql = "#{quote_column_name(o.name)} #{o.sql_type}"
|
||||
add_column_options!(column_sql, column_options(o)) unless o.type == :primary_key
|
||||
column_sql
|
||||
|
@ -96,18 +96,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def column_options(o)
|
||||
column_options = {}
|
||||
column_options[:null] = o.null unless o.null.nil?
|
||||
column_options[:default] = o.default unless o.default.nil?
|
||||
column_options[:column] = o
|
||||
column_options[:first] = o.first
|
||||
column_options[:after] = o.after
|
||||
column_options[:auto_increment] = o.auto_increment
|
||||
column_options[:primary_key] = o.primary_key
|
||||
column_options[:collation] = o.collation
|
||||
column_options[:comment] = o.comment
|
||||
column_options[:as] = o.as
|
||||
column_options
|
||||
o.options.merge(column: o)
|
||||
end
|
||||
|
||||
def add_column_options!(sql, options)
|
||||
|
|
|
@ -9,9 +9,21 @@ module ActiveRecord
|
|||
# are typically created by methods in TableDefinition, and added to the
|
||||
# +columns+ attribute of said TableDefinition object, in order to be used
|
||||
# for generating a number of table creation or table changing SQL statements.
|
||||
ColumnDefinition = Struct.new(:name, :type, :limit, :precision, :scale, :default, :null, :first, :after, :auto_increment, :primary_key, :collation, :sql_type, :comment, :as) do # :nodoc:
|
||||
ColumnDefinition = Struct.new(:name, :type, :options, :sql_type) do # :nodoc:
|
||||
def primary_key?
|
||||
primary_key || type.to_sym == :primary_key
|
||||
options[:primary_key]
|
||||
end
|
||||
|
||||
[:limit, :precision, :scale, :default, :null, :collation, :comment].each do |option_name|
|
||||
module_eval <<-CODE, __FILE__, __LINE__ + 1
|
||||
def #{option_name}
|
||||
options[:#{option_name}]
|
||||
end
|
||||
|
||||
def #{option_name}=(value)
|
||||
options[:#{option_name}] = value
|
||||
end
|
||||
CODE
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -360,28 +372,16 @@ module ActiveRecord
|
|||
end
|
||||
alias :belongs_to :references
|
||||
|
||||
def new_column_definition(name, type, options) # :nodoc:
|
||||
def new_column_definition(name, type, **options) # :nodoc:
|
||||
type = aliased_types(type.to_s, type)
|
||||
column = create_column_definition name, type
|
||||
|
||||
column.limit = options[:limit]
|
||||
column.precision = options[:precision]
|
||||
column.scale = options[:scale]
|
||||
column.default = options[:default]
|
||||
column.null = options[:null]
|
||||
column.first = options[:first]
|
||||
column.after = options[:after]
|
||||
column.auto_increment = options[:auto_increment]
|
||||
column.primary_key = type == :primary_key || options[:primary_key]
|
||||
column.collation = options[:collation]
|
||||
column.comment = options[:comment]
|
||||
column.as = options[:as]
|
||||
column
|
||||
options[:primary_key] ||= type == :primary_key
|
||||
options[:null] = false if options[:primary_key]
|
||||
create_column_definition(name, type, options)
|
||||
end
|
||||
|
||||
private
|
||||
def create_column_definition(name, type)
|
||||
ColumnDefinition.new name, type
|
||||
def create_column_definition(name, type, options)
|
||||
ColumnDefinition.new(name, type, options)
|
||||
end
|
||||
|
||||
def aliased_types(name, fallback)
|
||||
|
|
|
@ -1052,7 +1052,7 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc:
|
||||
def type_to_sql(type, limit: nil, precision: nil, scale: nil, **) # :nodoc:
|
||||
type = type.to_sym if type
|
||||
if native = native_database_types[type]
|
||||
column_type_sql = (native.is_a?(Hash) ? native[:name] : native).dup
|
||||
|
|
|
@ -574,7 +574,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
# Maps logical Rails types to MySQL-specific data types.
|
||||
def type_to_sql(type, limit = nil, precision = nil, scale = nil, unsigned = nil)
|
||||
def type_to_sql(type, limit: nil, precision: nil, scale: nil, unsigned: nil, **) # :nodoc:
|
||||
sql = \
|
||||
case type.to_s
|
||||
when "integer"
|
||||
|
@ -590,7 +590,7 @@ module ActiveRecord
|
|||
binary_to_sql(limit)
|
||||
end
|
||||
else
|
||||
super(type, limit, precision, scale)
|
||||
super
|
||||
end
|
||||
|
||||
sql << " unsigned" if unsigned && type != :primary_key
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
module MySQL
|
||||
class SchemaCreation < AbstractAdapter::SchemaCreation
|
||||
class SchemaCreation < AbstractAdapter::SchemaCreation # :nodoc:
|
||||
delegate :add_sql_comment!, :mariadb?, to: :@conn
|
||||
private :add_sql_comment!, :mariadb?
|
||||
|
||||
|
@ -11,11 +11,6 @@ module ActiveRecord
|
|||
"DROP FOREIGN KEY #{name}"
|
||||
end
|
||||
|
||||
def visit_ColumnDefinition(o)
|
||||
o.sql_type = type_to_sql(o.type, o.limit, o.precision, o.scale, o.unsigned)
|
||||
super
|
||||
end
|
||||
|
||||
def visit_AddColumnDefinition(o)
|
||||
add_column_position!(super, column_options(o.column))
|
||||
end
|
||||
|
@ -29,13 +24,6 @@ module ActiveRecord
|
|||
add_sql_comment!(super, options[:comment])
|
||||
end
|
||||
|
||||
def column_options(o)
|
||||
column_options = super
|
||||
column_options[:charset] = o.charset
|
||||
column_options[:stored] = o.stored
|
||||
column_options
|
||||
end
|
||||
|
||||
def add_column_options!(sql, options)
|
||||
if charset = options[:charset]
|
||||
sql << " CHARACTER SET #{charset}"
|
||||
|
|
|
@ -56,14 +56,10 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
class ColumnDefinition < ActiveRecord::ConnectionAdapters::ColumnDefinition
|
||||
attr_accessor :charset, :unsigned, :stored
|
||||
end
|
||||
|
||||
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
||||
include ColumnMethods
|
||||
|
||||
def new_column_definition(name, type, options) # :nodoc:
|
||||
def new_column_definition(name, type, **options) # :nodoc:
|
||||
case type
|
||||
when :virtual
|
||||
type = options[:type]
|
||||
|
@ -76,17 +72,8 @@ module ActiveRecord
|
|||
type = $~[:type].to_sym
|
||||
options[:unsigned] = true
|
||||
end
|
||||
column = super
|
||||
column.unsigned = options[:unsigned]
|
||||
column.charset = options[:charset]
|
||||
column.stored = options[:stored]
|
||||
column
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_column_definition(name, type)
|
||||
MySQL::ColumnDefinition.new(name, type)
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
module PostgreSQL
|
||||
class SchemaCreation < AbstractAdapter::SchemaCreation # :nodoc:
|
||||
private
|
||||
def add_column_options!(sql, options)
|
||||
if options[:collation]
|
||||
sql << " COLLATE \"#{options[:collation]}\""
|
||||
end
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -173,24 +173,8 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
class ColumnDefinition < ActiveRecord::ConnectionAdapters::ColumnDefinition
|
||||
attr_accessor :array
|
||||
end
|
||||
|
||||
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
||||
include ColumnMethods
|
||||
|
||||
def new_column_definition(name, type, options) # :nodoc:
|
||||
column = super
|
||||
column.array = options[:array]
|
||||
column
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_column_definition(name, type)
|
||||
PostgreSQL::ColumnDefinition.new name, type
|
||||
end
|
||||
end
|
||||
|
||||
class Table < ActiveRecord::ConnectionAdapters::Table
|
||||
|
|
|
@ -3,22 +3,6 @@ require "active_support/core_ext/string/strip"
|
|||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
module PostgreSQL
|
||||
class SchemaCreation < AbstractAdapter::SchemaCreation
|
||||
private
|
||||
|
||||
def visit_ColumnDefinition(o)
|
||||
o.sql_type = type_to_sql(o.type, o.limit, o.precision, o.scale, o.array)
|
||||
super
|
||||
end
|
||||
|
||||
def add_column_options!(sql, options)
|
||||
if options[:collation]
|
||||
sql << " COLLATE \"#{options[:collation]}\""
|
||||
end
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
module SchemaStatements
|
||||
# Drops the database specified on the +name+ attribute
|
||||
# and creates it again using the provided +options+.
|
||||
|
@ -486,7 +470,7 @@ module ActiveRecord
|
|||
clear_cache!
|
||||
quoted_table_name = quote_table_name(table_name)
|
||||
quoted_column_name = quote_column_name(column_name)
|
||||
sql_type = type_to_sql(type, options[:limit], options[:precision], options[:scale], options[:array])
|
||||
sql_type = type_to_sql(type, options)
|
||||
sql = "ALTER TABLE #{quoted_table_name} ALTER COLUMN #{quoted_column_name} TYPE #{sql_type}"
|
||||
if options[:collation]
|
||||
sql << " COLLATE \"#{options[:collation]}\""
|
||||
|
@ -494,7 +478,7 @@ module ActiveRecord
|
|||
if options[:using]
|
||||
sql << " USING #{options[:using]}"
|
||||
elsif options[:cast_as]
|
||||
cast_as_type = type_to_sql(options[:cast_as], options[:limit], options[:precision], options[:scale], options[:array])
|
||||
cast_as_type = type_to_sql(options[:cast_as], options)
|
||||
sql << " USING CAST(#{quoted_column_name} AS #{cast_as_type})"
|
||||
end
|
||||
execute sql
|
||||
|
@ -630,7 +614,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
# Maps logical Rails types to PostgreSQL-specific data types.
|
||||
def type_to_sql(type, limit = nil, precision = nil, scale = nil, array = nil)
|
||||
def type_to_sql(type, limit: nil, precision: nil, scale: nil, array: nil, **) # :nodoc:
|
||||
sql = \
|
||||
case type.to_s
|
||||
when "binary"
|
||||
|
@ -655,7 +639,7 @@ module ActiveRecord
|
|||
else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with scale 0 instead.")
|
||||
end
|
||||
else
|
||||
super(type, limit, precision, scale)
|
||||
super
|
||||
end
|
||||
|
||||
sql << "[]" if array && type != :primary_key
|
||||
|
|
|
@ -9,6 +9,7 @@ require "active_record/connection_adapters/postgresql/explain_pretty_printer"
|
|||
require "active_record/connection_adapters/postgresql/oid"
|
||||
require "active_record/connection_adapters/postgresql/quoting"
|
||||
require "active_record/connection_adapters/postgresql/referential_integrity"
|
||||
require "active_record/connection_adapters/postgresql/schema_creation"
|
||||
require "active_record/connection_adapters/postgresql/schema_definitions"
|
||||
require "active_record/connection_adapters/postgresql/schema_dumper"
|
||||
require "active_record/connection_adapters/postgresql/schema_statements"
|
||||
|
|
|
@ -1,15 +1,8 @@
|
|||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
module SQLite3
|
||||
class SchemaCreation < AbstractAdapter::SchemaCreation
|
||||
class SchemaCreation < AbstractAdapter::SchemaCreation # :nodoc:
|
||||
private
|
||||
|
||||
def column_options(o)
|
||||
options = super
|
||||
options[:null] = false if o.primary_key
|
||||
options
|
||||
end
|
||||
|
||||
def add_column_options!(sql, options)
|
||||
if options[:collation]
|
||||
sql << " COLLATE \"#{options[:collation]}\""
|
||||
|
|
|
@ -8,7 +8,7 @@ class Mysql2SqlTypesTest < ActiveRecord::Mysql2TestCase
|
|||
assert_equal "blob", type_to_sql(:binary)
|
||||
end
|
||||
|
||||
def type_to_sql(*args)
|
||||
ActiveRecord::Base.connection.type_to_sql(*args)
|
||||
def type_to_sql(type, limit = nil)
|
||||
ActiveRecord::Base.connection.type_to_sql(type, limit: limit)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,9 +32,9 @@ class PostgresqlByteaTest < ActiveRecord::PostgreSQLTestCase
|
|||
end
|
||||
|
||||
def test_binary_columns_are_limitless_the_upper_limit_is_one_GB
|
||||
assert_equal "bytea", @connection.type_to_sql(:binary, 100_000)
|
||||
assert_equal "bytea", @connection.type_to_sql(:binary, limit: 100_000)
|
||||
assert_raise ActiveRecord::ActiveRecordError do
|
||||
@connection.type_to_sql :binary, 4294967295
|
||||
@connection.type_to_sql(:binary, limit: 4294967295)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -61,9 +61,9 @@ class PostgresqlDataTypeTest < ActiveRecord::PostgreSQLTestCase
|
|||
end
|
||||
|
||||
def test_text_columns_are_limitless_the_upper_limit_is_one_GB
|
||||
assert_equal "text", @connection.type_to_sql(:text, 100_000)
|
||||
assert_equal "text", @connection.type_to_sql(:text, limit: 100_000)
|
||||
assert_raise ActiveRecord::ActiveRecordError do
|
||||
@connection.type_to_sql :text, 4294967295
|
||||
@connection.type_to_sql(:text, limit: 4294967295)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,27 +14,17 @@ module ActiveRecord
|
|||
# Avoid column definitions in create table statements like:
|
||||
# `title` varchar(255) DEFAULT NULL
|
||||
def test_should_not_include_default_clause_when_default_is_null
|
||||
column = Column.new("title", nil, SqlTypeMetadata.new(limit: 20))
|
||||
column_def = ColumnDefinition.new(
|
||||
column.name, "string",
|
||||
column.limit, column.precision, column.scale, column.default, column.null)
|
||||
column_def = ColumnDefinition.new("title", "string", limit: 20)
|
||||
assert_equal "title varchar(20)", @viz.accept(column_def)
|
||||
end
|
||||
|
||||
def test_should_include_default_clause_when_default_is_present
|
||||
column = Column.new("title", "Hello", SqlTypeMetadata.new(limit: 20))
|
||||
column_def = ColumnDefinition.new(
|
||||
column.name, "string",
|
||||
column.limit, column.precision, column.scale, column.default, column.null)
|
||||
column_def = ColumnDefinition.new("title", "string", limit: 20, default: "Hello")
|
||||
assert_equal "title varchar(20) DEFAULT 'Hello'", @viz.accept(column_def)
|
||||
end
|
||||
|
||||
def test_should_specify_not_null_if_null_option_is_false
|
||||
type_metadata = SqlTypeMetadata.new(limit: 20)
|
||||
column = Column.new("title", "Hello", type_metadata, false)
|
||||
column_def = ColumnDefinition.new(
|
||||
column.name, "string",
|
||||
column.limit, column.precision, column.scale, column.default, column.null)
|
||||
column_def = ColumnDefinition.new("title", "string", limit: 20, default: "Hello", null: false)
|
||||
assert_equal "title varchar(20) DEFAULT 'Hello' NOT NULL", @viz.accept(column_def)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue