mirror of
https://github.com/github/rails.git
synced 2026-01-29 00:08:15 -05:00
Oracle: use nonblocking queries if allow_concurrency is set, fix pessimistic locking, don't guess date vs. time by default (set OracleAdapter.emulate_dates = true for the old behavior), adapter cleanup. Closes #5635.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4574 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
*SVN*
|
||||
|
||||
* Oracle: use nonblocking queries if allow_concurrency is set, fix pessimistic locking, don't guess date vs. time by default (set OracleAdapter.emulate_dates = true for the old behavior), adapter cleanup. #5635 [schoenm@earthlink.net]
|
||||
|
||||
* Fixed a few Oracle issues: Allows Oracle's odd date handling to still work consistently within #to_xml, Passes test that hardcode insert statement by dropping the :id column, Updated RUNNING_UNIT_TESTS with Oracle instructions, Corrects method signature for #exec #5294 [schoenm@earthlink.net]
|
||||
|
||||
* Added :group to available options for finds done on associations #5516 [mike@michaeldewey.org]
|
||||
|
||||
@@ -113,7 +113,7 @@ module ActiveRecord
|
||||
time_hash[:sec_fraction] = microseconds(time_hash)
|
||||
time_array = time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction)
|
||||
# treat 0000-00-00 00:00:00 as nil
|
||||
Time.send(Base.default_timezone, *time_array) rescue nil
|
||||
Time.send(Base.default_timezone, *time_array) rescue DateTime.new(*time_array[0..5]) rescue nil
|
||||
end
|
||||
|
||||
def self.string_to_dummy_time(string)
|
||||
|
||||
@@ -76,57 +76,29 @@ begin
|
||||
module ConnectionAdapters #:nodoc:
|
||||
class OracleColumn < Column #:nodoc:
|
||||
|
||||
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 = nil, null = true, scale = nil)
|
||||
@scale = scale
|
||||
super_initialize(name, default, sql_type, null)
|
||||
super(name, default, sql_type, null)
|
||||
end
|
||||
|
||||
def type_cast(value)
|
||||
return nil if value.nil? || value =~ /^\s*null\s*$/i
|
||||
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)
|
||||
else value
|
||||
end
|
||||
return nil if value =~ /^\s*null\s*$/i
|
||||
return guess_date_or_time(value) if type == :datetime && OracleAdapter.emulate_dates
|
||||
super
|
||||
end
|
||||
|
||||
private
|
||||
def simplified_type(field_type)
|
||||
return :boolean if (OracleAdapter.emulate_booleans && field_type =~ /num/i && @limit == 1)
|
||||
return :boolean if OracleAdapter.emulate_booleans && field_type == 'NUMBER(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 /num/i : @scale == 0 ? :integer : :float
|
||||
when /date|time/i : :datetime
|
||||
else super
|
||||
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))
|
||||
end
|
||||
|
||||
def cast_to_time(value)
|
||||
return value if value.is_a? Time
|
||||
time_array = ParseDate.parsedate value
|
||||
time_array[0] ||= 2000; time_array[1] ||= 1; time_array[2] ||= 1;
|
||||
Time.send(Base.default_timezone, *time_array) rescue nil
|
||||
end
|
||||
|
||||
def guess_date_or_time(value)
|
||||
(value.hour == 0 and value.min == 0 and value.sec == 0) ?
|
||||
Date.new(value.year, value.month, value.day) : value
|
||||
@@ -171,6 +143,9 @@ begin
|
||||
@@emulate_booleans = true
|
||||
cattr_accessor :emulate_booleans
|
||||
|
||||
@@emulate_dates = false
|
||||
cattr_accessor :emulate_dates
|
||||
|
||||
def adapter_name #:nodoc:
|
||||
'Oracle'
|
||||
end
|
||||
@@ -209,28 +184,26 @@ begin
|
||||
name =~ /[A-Z]/ ? "\"#{name}\"" : name
|
||||
end
|
||||
|
||||
def quote_string(string) #:nodoc:
|
||||
string.gsub(/'/, "''")
|
||||
def quote_string(s) #:nodoc:
|
||||
s.gsub(/'/, "''")
|
||||
end
|
||||
|
||||
def quote(value, column = nil) #:nodoc:
|
||||
return value.quoted_id if value.respond_to?(:quoted_id)
|
||||
|
||||
if column && [:text, :binary].include?(column.type)
|
||||
%Q{empty_#{ column.sql_type rescue 'blob' }()}
|
||||
else
|
||||
case value
|
||||
when String : %Q{'#{quote_string(value)}'}
|
||||
when NilClass : 'null'
|
||||
when TrueClass : '1'
|
||||
when FalseClass : '0'
|
||||
when Numeric : value.to_s
|
||||
when Date, Time : %Q{'#{value.strftime("%Y-%m-%d %H:%M:%S")}'}
|
||||
else %Q{'#{quote_string(value.to_yaml)}'}
|
||||
end
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def quoted_true
|
||||
"1"
|
||||
end
|
||||
|
||||
def quoted_false
|
||||
"0"
|
||||
end
|
||||
|
||||
|
||||
# CONNECTION MANAGEMENT ====================================
|
||||
#
|
||||
@@ -567,11 +540,12 @@ begin
|
||||
# The OracleConnectionFactory factors out the code necessary to connect and
|
||||
# configure an Oracle/OCI connection.
|
||||
class OracleConnectionFactory #:nodoc:
|
||||
def new_connection(username, password, database)
|
||||
def new_connection(username, password, database, async)
|
||||
conn = OCI8.new username, password, database
|
||||
conn.exec %q{alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'}
|
||||
conn.exec %q{alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS'} rescue nil
|
||||
conn.autocommit = true
|
||||
conn.non_blocking = true if async
|
||||
conn
|
||||
end
|
||||
end
|
||||
@@ -596,9 +570,10 @@ begin
|
||||
|
||||
def initialize(config, factory = OracleConnectionFactory.new)
|
||||
@active = true
|
||||
@username, @password, @database = config[:username], config[:password], config[:database]
|
||||
@username, @password, @database, = config[:username], config[:password], config[:database]
|
||||
@async = config[:allow_concurrency]
|
||||
@factory = factory
|
||||
@connection = @factory.new_connection @username, @password, @database
|
||||
@connection = @factory.new_connection @username, @password, @database, @async
|
||||
super @connection
|
||||
end
|
||||
|
||||
@@ -617,7 +592,7 @@ begin
|
||||
def reset!
|
||||
logoff rescue nil
|
||||
begin
|
||||
@connection = @factory.new_connection @username, @password, @database
|
||||
@connection = @factory.new_connection @username, @password, @database, @async
|
||||
__setobj__ @connection
|
||||
@active = true
|
||||
rescue
|
||||
|
||||
@@ -1621,6 +1621,12 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_join_with_group
|
||||
assert_equal 2, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL', :group => "developers.name").size
|
||||
group = Developer.columns.inject([]) do |g, c|
|
||||
g << "developers.#{c.name}"
|
||||
g << "developers_projects_2.#{c.name}"
|
||||
end
|
||||
Project.columns.each { |c| group << "projects.#{c.name}" }
|
||||
|
||||
assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL', :group => group.join(",")).size
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user