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)
|
||||
spec = {}
|
||||
spec[:name] = column.name.inspect
|
||||
|
||||
# AR has an optimization which handles zero-scale decimals as integers. This
|
||||
# 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[:type] = column.type.to_s
|
||||
spec[:limit] = column.limit.inspect if column.limit != types[column.type][:limit]
|
||||
spec[:precision] = column.precision.inspect if column.precision
|
||||
spec[:scale] = column.scale.inspect if column.scale
|
||||
spec[:null] = 'false' unless column.null
|
||||
|
|
|
@ -396,7 +396,7 @@ module ActiveRecord
|
|||
precision = extract_precision(sql_type)
|
||||
|
||||
if scale == 0
|
||||
Type::Integer.new(precision: precision)
|
||||
Type::DecimalWithoutScale.new(precision: precision)
|
||||
else
|
||||
Type::Decimal.new(precision: precision, scale: scale)
|
||||
end
|
||||
|
|
|
@ -543,7 +543,7 @@ module ActiveRecord
|
|||
load_additional_types(type_map, [oid])
|
||||
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."
|
||||
Type::Value.new.tap do |cast_type|
|
||||
type_map.register_type(oid, cast_type)
|
||||
|
@ -551,23 +551,6 @@ module ActiveRecord
|
|||
}
|
||||
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)
|
||||
register_class_with_limit m, 'int2', OID::Integer
|
||||
m.alias_type 'int4', 'int2'
|
||||
|
@ -610,20 +593,27 @@ module ActiveRecord
|
|||
m.alias_type 'lseg', '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)
|
||||
OID::DateTime.new(precision: precision)
|
||||
end
|
||||
|
||||
m.register_type 'numeric' do |_, sql_type|
|
||||
m.register_type 'numeric' do |_, fmod, sql_type|
|
||||
precision = extract_precision(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|
|
||||
precision = extract_precision(sql_type)
|
||||
OID::Integer.new(precision: precision)
|
||||
# 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 fmod && (fmod - 4 & 0xffff).zero?
|
||||
Type::DecimalWithoutScale.new(precision: precision)
|
||||
else
|
||||
OID::Decimal.new(precision: precision, scale: scale)
|
||||
end
|
||||
end
|
||||
|
||||
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_time'
|
||||
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/integer'
|
||||
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, 'smallint'
|
||||
assert_lookup_type :integer, 'bigint'
|
||||
assert_lookup_type :integer, 'decimal(2)'
|
||||
assert_lookup_type :integer, 'decimal(2,0)'
|
||||
assert_lookup_type :integer, 'numeric(2)'
|
||||
assert_lookup_type :integer, 'numeric(2,0)'
|
||||
assert_lookup_type :integer, 'number(2)'
|
||||
assert_lookup_type :integer, 'number(2,0)'
|
||||
end
|
||||
|
||||
def test_decimal_without_scale
|
||||
types = %w{decimal(2) decimal(2,0) numeric(2) numeric(2,0) number(2) number(2,0)}
|
||||
types.each do |type|
|
||||
cast_type = @connection.type_map.lookup(type)
|
||||
|
||||
assert_equal :decimal, cast_type.type
|
||||
assert_equal 2, cast_type.type_cast(2.1)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
|
Loading…
Reference in a new issue