Oracle: BigDecimal support. Closes #5667.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4600 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
5241b97709
commit
0293c34459
|
@ -1,5 +1,7 @@
|
|||
*SVN*
|
||||
|
||||
* Oracle: BigDecimal support. #5667 [schoenm@earthlink.net]
|
||||
|
||||
* Numeric and decimal columns map to BigDecimal instead of Float. Those with scale 0 map to Integer. #5454 [robbat2@gentoo.org, work@ashleymoran.me.uk]
|
||||
|
||||
* Firebird migrations support. #5337 [Ken Kunz <kennethkunz@gmail.com>]
|
||||
|
|
|
@ -16,10 +16,8 @@ module ActiveRecord
|
|||
# +sql_type+ is only used to extract the column's length, if necessary. For example, <tt>company_name varchar(<b>60</b>)</tt>.
|
||||
# +null+ determines if this column allows +NULL+ values.
|
||||
def initialize(name, default, sql_type = nil, null = true)
|
||||
@name, @sql_type, @null, @limit = name, sql_type, null, extract_limit(sql_type)
|
||||
@precision, @scale = extract_precision(sql_type), extract_scale(sql_type)
|
||||
|
||||
# simplified_type may depend on #limit, type_cast depends on #type
|
||||
@name, @sql_type, @null = name, sql_type, null
|
||||
@limit, @precision, @scale = extract_limit(sql_type), extract_precision(sql_type), extract_scale(sql_type)
|
||||
@type = simplified_type(sql_type)
|
||||
@default = type_cast(default)
|
||||
|
||||
|
@ -163,13 +161,13 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def extract_precision(sql_type)
|
||||
$2.to_i if sql_type =~ /^(numeric|decimal)\((\d+)(,\d+)?\)/i
|
||||
$2.to_i if sql_type =~ /^(numeric|decimal|number)\((\d+)(,\d+)?\)/i
|
||||
end
|
||||
|
||||
def extract_scale(sql_type)
|
||||
case sql_type
|
||||
when /^(numeric|decimal)\((\d+)\)/i then 0
|
||||
when /^(numeric|decimal)\((\d+)(,(\d+))\)/i then $4.to_i
|
||||
when /^(numeric|decimal|number)\((\d+)\)/i then 0
|
||||
when /^(numeric|decimal|number)\((\d+)(,(\d+))\)/i then $4.to_i
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -179,7 +177,7 @@ module ActiveRecord
|
|||
:integer
|
||||
when /float|double/i
|
||||
:float
|
||||
when /decimal|numeric/i
|
||||
when /decimal|numeric|number/i
|
||||
extract_scale(field_type) == 0 ? :integer : :decimal
|
||||
when /datetime/i
|
||||
:datetime
|
||||
|
|
|
@ -76,13 +76,6 @@ begin
|
|||
module ConnectionAdapters #:nodoc:
|
||||
class OracleColumn < Column #:nodoc:
|
||||
|
||||
# overridden to add the concept of scale, required to differentiate
|
||||
# between integer and float fields
|
||||
def initialize(name, default, sql_type = nil, null = true, scale = nil)
|
||||
@scale = scale
|
||||
super(name, default, sql_type, null)
|
||||
end
|
||||
|
||||
def type_cast(value)
|
||||
return nil if value =~ /^\s*null\s*$/i
|
||||
return guess_date_or_time(value) if type == :datetime && OracleAdapter.emulate_dates
|
||||
|
@ -317,7 +310,7 @@ begin
|
|||
FROM user_indexes i, user_ind_columns c
|
||||
WHERE i.table_name = '#{table_name.to_s.upcase}'
|
||||
AND c.index_name = i.index_name
|
||||
AND i.index_name NOT IN (SELECT index_name FROM user_constraints WHERE constraint_type = 'P')
|
||||
AND i.index_name NOT IN (SELECT uc.index_name FROM user_constraints uc WHERE uc.constraint_type = 'P')
|
||||
ORDER BY i.index_name, c.column_position
|
||||
SQL
|
||||
|
||||
|
@ -342,6 +335,7 @@ begin
|
|||
table_cols = %Q{
|
||||
select column_name as name, data_type as sql_type, data_default, nullable,
|
||||
decode(data_type, 'NUMBER', data_precision,
|
||||
'FLOAT', data_precision,
|
||||
'VARCHAR2', data_length,
|
||||
null) as limit,
|
||||
decode(data_type, 'NUMBER', data_scale, null) as scale
|
||||
|
@ -352,16 +346,21 @@ begin
|
|||
}
|
||||
|
||||
select_all(table_cols, name).map do |row|
|
||||
row['sql_type'] += "(#{row['limit'].to_i})" if row['limit']
|
||||
limit, scale = row['limit'], row['scale']
|
||||
if limit || scale
|
||||
row['sql_type'] << "(#{(limit || 38).to_i}" + ((scale = scale.to_i) > 0 ? ",#{scale})" : ")")
|
||||
end
|
||||
|
||||
# clean up odd default spacing from Oracle
|
||||
if row['data_default']
|
||||
row['data_default'].sub!(/^(.*?)\s*$/, '\1')
|
||||
row['data_default'].sub!(/^'(.*)'$/, '\1')
|
||||
end
|
||||
|
||||
OracleColumn.new(oracle_downcase(row['name']),
|
||||
row['data_default'],
|
||||
row['sql_type'],
|
||||
row['nullable'] == 'Y',
|
||||
(s = row['scale']).nil? ? nil : s.to_i)
|
||||
row['nullable'] == 'Y')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -389,7 +388,7 @@ begin
|
|||
end
|
||||
|
||||
def change_column(table_name, column_name, type, options = {}) #:nodoc:
|
||||
change_column_sql = "ALTER TABLE #{table_name} MODIFY #{column_name} #{type_to_sql(type, options[:limit])}"
|
||||
change_column_sql = "ALTER TABLE #{table_name} MODIFY #{column_name} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
|
||||
add_column_options!(change_column_sql, options)
|
||||
execute(change_column_sql)
|
||||
end
|
||||
|
|
|
@ -39,7 +39,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
end
|
||||
Reminder.reset_column_information
|
||||
|
||||
%w(last_name key bio age height wealth birthday favorite_day
|
||||
%w(last_name key bio age height wealth birthday favorite_day male
|
||||
mail administrator).each do |column|
|
||||
Person.connection.remove_column('people', column) rescue nil
|
||||
end
|
||||
|
@ -200,7 +200,11 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
Person.reset_column_information
|
||||
|
||||
# Do a manual insertion
|
||||
Person.connection.execute "insert into people (wealth) values (12345678901234567890.0123456789)"
|
||||
if current_adapter?(:OracleAdapter)
|
||||
Person.connection.execute "insert into people (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789)"
|
||||
else
|
||||
Person.connection.execute "insert into people (wealth) values (12345678901234567890.0123456789)"
|
||||
end
|
||||
|
||||
# SELECT
|
||||
row = Person.find(:first)
|
||||
|
|
Loading…
Reference in New Issue