mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Remove special case in schema dumper for decimal without scale
This commit is contained in:
parent
21f99b4be0
commit
6b2ff4fa20
6 changed files with 42 additions and 41 deletions
|
@ -20,15 +20,8 @@ module ActiveRecord
|
||||||
def prepare_column_options(column, types)
|
def prepare_column_options(column, types)
|
||||||
spec = {}
|
spec = {}
|
||||||
spec[:name] = column.name.inspect
|
spec[:name] = column.name.inspect
|
||||||
|
spec[:type] = column.type.to_s
|
||||||
# AR has an optimization which handles zero-scale decimals as integers. This
|
spec[:limit] = column.limit.inspect if column.limit != types[column.type][:limit]
|
||||||
# code ensures that the dumper still dumps the column as a decimal.
|
|
||||||
spec[:type] = if column.type == :integer && /^(numeric|decimal)/ =~ column.sql_type
|
|
||||||
'decimal'
|
|
||||||
else
|
|
||||||
column.type.to_s
|
|
||||||
end
|
|
||||||
spec[:limit] = column.limit.inspect if column.limit != types[column.type][:limit] && spec[:type] != 'decimal'
|
|
||||||
spec[:precision] = column.precision.inspect if column.precision
|
spec[:precision] = column.precision.inspect if column.precision
|
||||||
spec[:scale] = column.scale.inspect if column.scale
|
spec[:scale] = column.scale.inspect if column.scale
|
||||||
spec[:null] = 'false' unless column.null
|
spec[:null] = 'false' unless column.null
|
||||||
|
|
|
@ -396,7 +396,7 @@ module ActiveRecord
|
||||||
precision = extract_precision(sql_type)
|
precision = extract_precision(sql_type)
|
||||||
|
|
||||||
if scale == 0
|
if scale == 0
|
||||||
Type::Integer.new(precision: precision)
|
Type::DecimalWithoutScale.new(precision: precision)
|
||||||
else
|
else
|
||||||
Type::Decimal.new(precision: precision, scale: scale)
|
Type::Decimal.new(precision: precision, scale: scale)
|
||||||
end
|
end
|
||||||
|
|
|
@ -543,7 +543,7 @@ module ActiveRecord
|
||||||
load_additional_types(type_map, [oid])
|
load_additional_types(type_map, [oid])
|
||||||
end
|
end
|
||||||
|
|
||||||
type_map.fetch(normalize_oid_type(oid, fmod), sql_type) {
|
type_map.fetch(oid, fmod, sql_type) {
|
||||||
warn "unknown OID #{oid}: failed to recognize type of '#{column_name}'. It will be treated as String."
|
warn "unknown OID #{oid}: failed to recognize type of '#{column_name}'. It will be treated as String."
|
||||||
Type::Value.new.tap do |cast_type|
|
Type::Value.new.tap do |cast_type|
|
||||||
type_map.register_type(oid, cast_type)
|
type_map.register_type(oid, cast_type)
|
||||||
|
@ -551,23 +551,6 @@ module ActiveRecord
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
OID_FOR_DECIMAL_TREATED_AS_INT = 23 # :nodoc:
|
|
||||||
|
|
||||||
def normalize_oid_type(ftype, fmod)
|
|
||||||
# The type for the numeric depends on the width of the field,
|
|
||||||
# so we'll do something special here.
|
|
||||||
#
|
|
||||||
# When dealing with decimal columns:
|
|
||||||
#
|
|
||||||
# places after decimal = fmod - 4 & 0xffff
|
|
||||||
# places before decimal = (fmod - 4) >> 16 & 0xffff
|
|
||||||
if ftype == 1700 && (fmod - 4 & 0xffff).zero?
|
|
||||||
OID_FOR_DECIMAL_TREATED_AS_INT
|
|
||||||
else
|
|
||||||
ftype
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize_type_map(m)
|
def initialize_type_map(m)
|
||||||
register_class_with_limit m, 'int2', OID::Integer
|
register_class_with_limit m, 'int2', OID::Integer
|
||||||
m.alias_type 'int4', 'int2'
|
m.alias_type 'int4', 'int2'
|
||||||
|
@ -610,20 +593,27 @@ module ActiveRecord
|
||||||
m.alias_type 'lseg', 'varchar'
|
m.alias_type 'lseg', 'varchar'
|
||||||
m.alias_type 'box', 'varchar'
|
m.alias_type 'box', 'varchar'
|
||||||
|
|
||||||
m.register_type 'timestamp' do |_, sql_type|
|
m.register_type 'timestamp' do |_, _, sql_type|
|
||||||
precision = extract_precision(sql_type)
|
precision = extract_precision(sql_type)
|
||||||
OID::DateTime.new(precision: precision)
|
OID::DateTime.new(precision: precision)
|
||||||
end
|
end
|
||||||
|
|
||||||
m.register_type 'numeric' do |_, sql_type|
|
m.register_type 'numeric' do |_, fmod, sql_type|
|
||||||
precision = extract_precision(sql_type)
|
precision = extract_precision(sql_type)
|
||||||
scale = extract_scale(sql_type)
|
scale = extract_scale(sql_type)
|
||||||
OID::Decimal.new(precision: precision, scale: scale)
|
|
||||||
end
|
|
||||||
|
|
||||||
m.register_type OID_FOR_DECIMAL_TREATED_AS_INT do |_, sql_type|
|
# The type for the numeric depends on the width of the field,
|
||||||
precision = extract_precision(sql_type)
|
# so we'll do something special here.
|
||||||
OID::Integer.new(precision: precision)
|
#
|
||||||
|
# When dealing with decimal columns:
|
||||||
|
#
|
||||||
|
# places after decimal = fmod - 4 & 0xffff
|
||||||
|
# places before decimal = (fmod - 4) >> 16 & 0xffff
|
||||||
|
if fmod && (fmod - 4 & 0xffff).zero?
|
||||||
|
Type::DecimalWithoutScale.new(precision: precision)
|
||||||
|
else
|
||||||
|
OID::Decimal.new(precision: precision, scale: scale)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
load_additional_types(m)
|
load_additional_types(m)
|
||||||
|
|
|
@ -7,6 +7,7 @@ require 'active_record/connection_adapters/type/boolean'
|
||||||
require 'active_record/connection_adapters/type/date'
|
require 'active_record/connection_adapters/type/date'
|
||||||
require 'active_record/connection_adapters/type/date_time'
|
require 'active_record/connection_adapters/type/date_time'
|
||||||
require 'active_record/connection_adapters/type/decimal'
|
require 'active_record/connection_adapters/type/decimal'
|
||||||
|
require 'active_record/connection_adapters/type/decimal_without_scale'
|
||||||
require 'active_record/connection_adapters/type/float'
|
require 'active_record/connection_adapters/type/float'
|
||||||
require 'active_record/connection_adapters/type/integer'
|
require 'active_record/connection_adapters/type/integer'
|
||||||
require 'active_record/connection_adapters/type/string'
|
require 'active_record/connection_adapters/type/string'
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
require 'active_record/connection_adapters/type/integer'
|
||||||
|
|
||||||
|
module ActiveRecord
|
||||||
|
module ConnectionAdapters
|
||||||
|
module Type
|
||||||
|
class DecimalWithoutScale < Integer # :nodoc:
|
||||||
|
def type
|
||||||
|
:decimal
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -77,12 +77,16 @@ module ActiveRecord
|
||||||
assert_lookup_type :integer, 'tinyint'
|
assert_lookup_type :integer, 'tinyint'
|
||||||
assert_lookup_type :integer, 'smallint'
|
assert_lookup_type :integer, 'smallint'
|
||||||
assert_lookup_type :integer, 'bigint'
|
assert_lookup_type :integer, 'bigint'
|
||||||
assert_lookup_type :integer, 'decimal(2)'
|
end
|
||||||
assert_lookup_type :integer, 'decimal(2,0)'
|
|
||||||
assert_lookup_type :integer, 'numeric(2)'
|
def test_decimal_without_scale
|
||||||
assert_lookup_type :integer, 'numeric(2,0)'
|
types = %w{decimal(2) decimal(2,0) numeric(2) numeric(2,0) number(2) number(2,0)}
|
||||||
assert_lookup_type :integer, 'number(2)'
|
types.each do |type|
|
||||||
assert_lookup_type :integer, 'number(2,0)'
|
cast_type = @connection.type_map.lookup(type)
|
||||||
|
|
||||||
|
assert_equal :decimal, cast_type.type
|
||||||
|
assert_equal 2, cast_type.type_cast(2.1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
Loading…
Reference in a new issue