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

View file

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

View file

@ -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)
# 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) OID::Decimal.new(precision: precision, scale: scale)
end end
m.register_type OID_FOR_DECIMAL_TREATED_AS_INT do |_, sql_type|
precision = extract_precision(sql_type)
OID::Integer.new(precision: precision)
end end
load_additional_types(m) 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'
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'

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