1
0
Fork 0
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:
Sean Griffin 2014-05-23 15:31:30 -07:00
parent 21f99b4be0
commit 6b2ff4fa20
6 changed files with 42 additions and 41 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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