Fix Oracle boolean support and tests. Closes #5139. [schoenm@earthlink.net]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4351 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
422cba934c
commit
d22f9c9488
|
@ -1,5 +1,7 @@
|
|||
*SVN*
|
||||
|
||||
* Fix Oracle boolean support and tests. Closes #5139. [schoenm@earthlink.net]
|
||||
|
||||
* create! no longer blows up when no attributes are passed and a :create scope is in effect (e.g. foo.bars.create! failed whereas foo.bars.create!({}) didn't.) [Jeremy Kemper]
|
||||
|
||||
* Call Inflector#demodulize on the class name when eagerly including an STI model. Closes #5077 [info@loobmedia.com]
|
||||
|
|
|
@ -1183,7 +1183,7 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
return false unless conditions.any?
|
||||
conditions.join(' ').scan(/(\w+)\.\w+/).flatten.any? do |condition_table_name|
|
||||
conditions.join(' ').scan(/([\.\w]+)\.\w+/).flatten.any? do |condition_table_name|
|
||||
condition_table_name != table_name
|
||||
end
|
||||
end
|
||||
|
@ -1192,7 +1192,7 @@ module ActiveRecord
|
|||
def include_eager_order?(options)
|
||||
order = options[:order]
|
||||
return false unless order
|
||||
order.scan(/(\w+)\.\w+/).flatten.any? do |order_table_name|
|
||||
order.scan(/([\.\w]+)\.\w+/).flatten.any? do |order_table_name|
|
||||
order_table_name != table_name
|
||||
end
|
||||
end
|
||||
|
@ -1391,7 +1391,7 @@ module ActiveRecord
|
|||
@parent = parent
|
||||
@reflection = reflection
|
||||
@aliased_prefix = "t#{ join_dependency.joins.size }"
|
||||
@aliased_table_name = table_name # start with the table name
|
||||
@aliased_table_name = table_name #.tr('.', '_') # start with the table name, sub out any .'s
|
||||
@parent_table_name = parent.active_record.table_name
|
||||
|
||||
if !parent.table_joins.blank? && parent.table_joins.to_s.downcase =~ %r{join(\s+\w+)?\s+#{aliased_table_name.downcase}\son}
|
||||
|
|
|
@ -14,11 +14,12 @@ 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, @type, @null = name, simplified_type(sql_type), null
|
||||
@sql_type = sql_type
|
||||
# have to do this one separately because type_cast depends on #type
|
||||
@name, @sql_type, @null, @limit = name, sql_type, null, extract_limit(sql_type)
|
||||
|
||||
# simplified_type may depend on #limit, type_cast depends on #type
|
||||
@type = simplified_type(sql_type)
|
||||
@default = type_cast(default)
|
||||
@limit = extract_limit(sql_type) unless sql_type.nil?
|
||||
|
||||
@primary = nil
|
||||
@text = [:string, :text].include? @type
|
||||
@number = [:float, :integer].include? @type
|
||||
|
@ -133,6 +134,7 @@ module ActiveRecord
|
|||
|
||||
private
|
||||
def extract_limit(sql_type)
|
||||
return unless sql_type
|
||||
$1.to_i if sql_type =~ /\((.*)\)/
|
||||
end
|
||||
|
||||
|
|
|
@ -75,19 +75,13 @@ begin
|
|||
|
||||
module ConnectionAdapters #:nodoc:
|
||||
class OracleColumn < Column #:nodoc:
|
||||
attr_reader :sql_type
|
||||
|
||||
alias_method :super_initialize, :initialize
|
||||
# overridden to add the concept of scale, required to differentiate
|
||||
# between integer and float fields
|
||||
def initialize(name, default, sql_type, limit, scale, null)
|
||||
@name, @limit, @sql_type, @scale, @null = name, limit, sql_type, scale, null
|
||||
|
||||
@type = simplified_type(sql_type)
|
||||
@default = type_cast(default)
|
||||
|
||||
@primary = nil
|
||||
@text = [:string, :text].include? @type
|
||||
@number = [:float, :integer].include? @type
|
||||
def initialize(name, default, sql_type = nil, null = true, scale = nil)
|
||||
@scale = scale
|
||||
super_initialize(name, default, sql_type, null)
|
||||
end
|
||||
|
||||
def type_cast(value)
|
||||
|
@ -95,6 +89,7 @@ begin
|
|||
case type
|
||||
when :string then value
|
||||
when :integer then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
|
||||
when :boolean then cast_to_boolean(value)
|
||||
when :float then value.to_f
|
||||
when :datetime then cast_to_date_or_time(value)
|
||||
when :time then cast_to_time(value)
|
||||
|
@ -104,19 +99,25 @@ begin
|
|||
|
||||
private
|
||||
def simplified_type(field_type)
|
||||
return :boolean if (OracleAdapter.emulate_booleans && field_type =~ /num/i && @limit == 1)
|
||||
case field_type
|
||||
when /char/i : :string
|
||||
when /num|float|double|dec|real|int/i : @scale == 0 ? :integer : :float
|
||||
when /date|time/i : @name =~ /_at$/ ? :time : :datetime
|
||||
when /clob/i : :text
|
||||
when /blob/i : :binary
|
||||
when /clob/i : :text
|
||||
when /blob/i : :binary
|
||||
end
|
||||
end
|
||||
|
||||
def cast_to_boolean(value)
|
||||
return value if value.is_a? TrueClass or value.is_a? FalseClass
|
||||
value.to_i == 0 ? false : true
|
||||
end
|
||||
|
||||
def cast_to_date_or_time(value)
|
||||
return value if value.is_a? Date
|
||||
return nil if value.blank?
|
||||
guess_date_or_time (value.is_a? Time) ? value : cast_to_time(value)
|
||||
guess_date_or_time((value.is_a? Time) ? value : cast_to_time(value))
|
||||
end
|
||||
|
||||
def cast_to_time(value)
|
||||
|
@ -167,6 +168,9 @@ begin
|
|||
# * <tt>:database</tt>
|
||||
class OracleAdapter < AbstractAdapter
|
||||
|
||||
@@emulate_booleans = true
|
||||
cattr_accessor :emulate_booleans
|
||||
|
||||
def adapter_name #:nodoc:
|
||||
'Oracle'
|
||||
end
|
||||
|
@ -277,8 +281,8 @@ begin
|
|||
elsif id_value # Pre-assigned id
|
||||
log(sql, name) { @connection.exec sql }
|
||||
else # Assume the sql contains a bind-variable for the id
|
||||
id_value = select_one("select #{sequence_name}.nextval id from dual")['id']
|
||||
log(sql, name) { @connection.exec sql, id_value }
|
||||
id_value = select_one("select #{sequence_name}.nextval id from dual")['id'].to_i
|
||||
log(sql.sub(/\B:id\b/, id_value.to_s), name) { @connection.exec sql, id_value }
|
||||
end
|
||||
|
||||
id_value
|
||||
|
@ -361,10 +365,10 @@ begin
|
|||
(owner, table_name) = @connection.describe(table_name)
|
||||
|
||||
table_cols = %Q{
|
||||
select column_name, data_type, data_default, nullable,
|
||||
select column_name as name, data_type as sql_type, data_default, nullable,
|
||||
decode(data_type, 'NUMBER', data_precision,
|
||||
'VARCHAR2', data_length,
|
||||
null) as length,
|
||||
null) as limit,
|
||||
decode(data_type, 'NUMBER', data_scale, null) as scale
|
||||
from all_tab_columns
|
||||
where owner = '#{owner}'
|
||||
|
@ -373,18 +377,16 @@ begin
|
|||
}
|
||||
|
||||
select_all(table_cols, name).map do |row|
|
||||
row['sql_type'] += "(#{row['limit'].to_i})" if row['limit']
|
||||
if row['data_default']
|
||||
row['data_default'].sub!(/^(.*?)\s*$/, '\1')
|
||||
row['data_default'].sub!(/^'(.*)'$/, '\1')
|
||||
end
|
||||
OracleColumn.new(
|
||||
oracle_downcase(row['column_name']),
|
||||
row['data_default'],
|
||||
row['data_type'],
|
||||
(l = row['length']).nil? ? nil : l.to_i,
|
||||
(s = row['scale']).nil? ? nil : s.to_i,
|
||||
row['nullable'] == 'Y'
|
||||
)
|
||||
OracleColumn.new(oracle_downcase(row['name']),
|
||||
row['data_default'],
|
||||
row['sql_type'],
|
||||
row['nullable'] == 'Y',
|
||||
(s = row['scale']).nil? ? nil : s.to_i)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ create table topics (
|
|||
bonus_time timestamp default null,
|
||||
last_read timestamp default null,
|
||||
content varchar(4000),
|
||||
approved integer default 1,
|
||||
approved number(1) default 1,
|
||||
replies_count integer default 0,
|
||||
parent_id integer references topics initially deferred disable,
|
||||
type varchar(50) default null,
|
||||
|
@ -53,7 +53,7 @@ create table topics (
|
|||
bonus_time date default null,
|
||||
last_read date default null,
|
||||
content varchar(4000),
|
||||
approved integer default 1,
|
||||
approved number(1) default 1,
|
||||
replies_count integer default 0,
|
||||
parent_id integer references topics initially deferred disable,
|
||||
type varchar(50) default null,
|
||||
|
|
|
@ -106,14 +106,8 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
four = columns.detect { |c| c.name == "four" }
|
||||
|
||||
assert_equal "hello", one.default
|
||||
if current_adapter?(:OracleAdapter)
|
||||
# Oracle doesn't support native booleans
|
||||
assert_equal true, two.default == 1
|
||||
assert_equal false, three.default != 0
|
||||
else
|
||||
assert_equal true, two.default
|
||||
assert_equal false, three.default
|
||||
end
|
||||
assert_equal true, two.default
|
||||
assert_equal false, three.default
|
||||
assert_equal 1, four.default
|
||||
|
||||
ensure
|
||||
|
@ -147,6 +141,11 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
assert_equal 'smallint', one.sql_type
|
||||
assert_equal 'integer', four.sql_type
|
||||
assert_equal 'bigint', eight.sql_type
|
||||
elsif current_adapter?(:OracleAdapter)
|
||||
assert_equal 'NUMBER(38)', default.sql_type
|
||||
assert_equal 'NUMBER(1)', one.sql_type
|
||||
assert_equal 'NUMBER(4)', four.sql_type
|
||||
assert_equal 'NUMBER(8)', eight.sql_type
|
||||
end
|
||||
ensure
|
||||
Person.connection.drop_table :testings rescue nil
|
||||
|
@ -328,6 +327,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
new_columns = Topic.connection.columns(Topic.table_name, "#{name} Columns")
|
||||
assert_nil new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
|
||||
assert new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == false }
|
||||
assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => true }
|
||||
end
|
||||
|
||||
def test_change_column_with_new_default
|
||||
|
|
Loading…
Reference in New Issue