Permalink
Browse files

Improved the Oracle OCI Adapter with better performance for column re…

…flection (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
  • Loading branch information...
1 parent e875b0d commit 7a2ce50a9386a46387c114945354ba89c5fc9c30 @dhh dhh committed Feb 21, 2006
View
@@ -1,5 +1,9 @@
*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,36 +335,26 @@ 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,
decode(data_type, 'NUMBER', data_precision,
'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

0 comments on commit 7a2ce50

Please sign in to comment.