Improved the Oracle OCI Adapter with better performance for column reflection...

Improved the Oracle OCI Adapter with better performance for column reflection (from #3210), fixes to migrations (from #3476 and #3742), tweaks to unit tests (from #3610), and improved documentation (from #2446) (closes #3879) [Aggregated by schoenm@earthlink.net]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3623 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
上级 e875b0db
*SVN*
* Improved the Oracle OCI Adapter with better performance for column reflection (from #3210), fixes to migrations (from #3476 and #3742), tweaks to unit tests (from #3610), and improved documentation (from #2446) #3879 [Aggregated by schoenm@earthlink.net]
* Fixed that the schema_info table used by ActiveRecord::Schema.define should respect table pre- and suffixes #3834 [rubyonrails@atyp.de]
* Added :select option to Base.count that'll allow you to select something else than * to be counted on. Especially important for count queries using DISTINCT #3839 [skaes]
* Correct syntax error in mysql DDL, and make AAACreateTablesTest run first [Bob Silva]
......
......@@ -56,7 +56,7 @@ def write_lobs() #:nodoc:
value = self[c.name]
next if value.nil? || (value == '')
lob = connection.select_one(
"select #{ c.name} from #{ self.class.table_name } WHERE #{ self.class.primary_key} = #{quote(id)}",
"SELECT #{ c.name} FROM #{ self.class.table_name } WHERE #{ self.class.primary_key} = #{quote(id)}",
'Writable Large Object')[c.name]
lob.write value
}
......@@ -149,6 +149,9 @@ def guess_date_or_time(value)
# * Default values that are functions (such as "SYSDATE") are not
# supported. This is a restriction of the way ActiveRecord supports
# default values.
# * Support for Oracle8 is limited by Rails' use of ANSI join syntax, which
# is supported in Oracle9i and later. You will need to use #finder_sql for
# has_and_belongs_to_many associations to run against Oracle8.
#
# Options:
#
......@@ -167,7 +170,7 @@ def supports_migrations? #:nodoc:
def native_database_types #:nodoc
{
:primary_key => "NUMBER(38) NOT NULL",
:primary_key => "NUMBER(38) NOT NULL PRIMARY KEY",
:string => { :name => "VARCHAR2", :limit => 255 },
:text => { :name => "LONG" },
:integer => { :name => "NUMBER", :limit => 38 },
......@@ -332,10 +335,7 @@ def indexes(table_name, name = nil) #:nodoc:
end
def columns(table_name, name = nil) #:nodoc:
table_name = table_name.to_s.upcase
owner = table_name.include?('.') ? "'#{table_name.split('.').first}'" : "user"
table = "'#{table_name.split('.').last}'"
scope = (owner == "user" ? "user" : "all")
table_info = @connection.object_info(table_name)
table_cols = %Q{
select column_name, data_type, data_default, nullable,
......@@ -343,25 +343,18 @@ def columns(table_name, name = nil) #:nodoc:
'VARCHAR2', data_length,
null) as length,
decode(data_type, 'NUMBER', data_scale, null) as scale
from #{scope}_catalog cat, #{scope}_synonyms syn, all_tab_columns col
where cat.table_name = #{table}
and syn.synonym_name (+)= cat.table_name
and col.table_name = nvl(syn.table_name, cat.table_name)
and col.owner = nvl(syn.table_owner, #{(scope == "all" ? "cat.owner" : "user")}) }
if scope == "all"
table_cols << %Q{
and cat.owner = #{owner}
and syn.owner (+)= cat.owner }
end
from all_tab_columns
where owner = '#{table_info.schema}'
and table_name = '#{table_info.name}'
}
select_all(table_cols, name).map do |row|
row['data_default'].sub!(/^'(.*)'\s*$/, '\1') if row['data_default']
OCIColumn.new(
oci_downcase(row['column_name']),
oci_downcase(row['column_name']),
row['data_default'],
row['data_type'],
row['length'],
row['data_type'],
row['length'],
row['scale'],
row['nullable'] == 'Y'
)
......@@ -370,17 +363,17 @@ def columns(table_name, name = nil) #:nodoc:
def create_table(name, options = {}) #:nodoc:
super(name, options)
execute "CREATE SEQUENCE #{name}_seq"
execute "CREATE SEQUENCE #{name}_seq" unless options[:id] == false
end
def rename_table(name, new_name) #:nodoc:
execute "RENAME #{name} TO #{new_name}"
execute "RENAME #{name}_seq TO #{new_name}_seq"
execute "RENAME #{name}_seq TO #{new_name}_seq" rescue nil
end
def drop_table(name) #:nodoc:
super(name)
execute "DROP SEQUENCE #{name}_seq"
execute "DROP SEQUENCE #{name}_seq" rescue nil
end
def remove_index(table_name, options = {}) #:nodoc:
......@@ -492,9 +485,10 @@ def oci_downcase(column_name)
end
# This OCI8 patch may not longer be required with the upcoming
# release of version 0.2.
class OCI8 #:nodoc:
# This OCI8 patch may not longer be required with the upcoming
# release of version 0.2.
class Cursor #:nodoc:
alias :define_a_column_pre_ar :define_a_column
def define_a_column(i)
......@@ -505,6 +499,33 @@ def define_a_column(i)
end
end
end
# missing constant from oci8
OCI_PTYPE_UNK = 0
def object_info(name)
OraObject.new describe(name.to_s, OCI_PTYPE_UNK)
end
def describe(name, type)
@desc ||= @@env.alloc(OCIDescribe)
@desc.describeAny(@svc, name, type)
@desc.attrGet(OCI_ATTR_PARAM)
end
class OraObject
attr_reader :schema, :name
def initialize(info)
case info.attrGet(OCI_ATTR_PTYPE)
when OCI_PTYPE_TABLE, OCI_PTYPE_VIEW
@schema = info.attrGet(OCI_ATTR_OBJ_SCHEMA)
@name = info.attrGet(OCI_ATTR_OBJ_NAME)
when OCI_PTYPE_SYN
@schema = info.attrGet(OCI_ATTR_SCHEMA_NAME)
@name = info.attrGet(OCI_ATTR_NAME)
end
end
end
end
......
......@@ -51,7 +51,7 @@ def self.define(info={}, &block)
"#{k} = #{v}"
end
update "UPDATE schema_info SET #{info.join(", ")}"
update "UPDATE #{Migrator.schema_info_table_name} SET #{info.join(", ")}"
end
end
end
......
......@@ -96,7 +96,7 @@ def test_has_many_find_conditions
end
def test_has_many_class_methods_called_by_method_missing
assert_equal categories(:general), authors(:david).categories.find_by_name('General')
assert_equal categories(:general), authors(:david).categories.find_all_by_name('General').first
# assert_equal nil, authors(:david).categories.find_by_name('Technology')
end
......
......@@ -17,8 +17,7 @@ create sequence companies_nonstd_seq minvalue 10000;
create table accounts (
id integer not null,
firm_id integer default null references companies initially deferred disable,
credit_limit integer default null,
primary key (id)
credit_limit integer default null
);
create sequence accounts_seq minvalue 10000;
......
......@@ -10,7 +10,7 @@ class TestOracleSynonym < Test::Unit::TestCase
def test_oracle_synonym
topic = Topic.new
subject = Subject.new
subject = Subject.new
assert_equal(topic.attributes, subject.attributes)
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册