Changeset 3718
- Timestamp:
- 03/01/06 16:01:53 (3 years ago)
- Files:
-
- trunk/activerecord/CHANGELOG (modified) (1 diff)
- trunk/activerecord/lib/active_record.rb (modified) (1 diff)
- trunk/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb (moved) (moved from trunk/activerecord/lib/active_record/connection_adapters/oci_adapter.rb) (19 diffs)
- trunk/activerecord/Rakefile (modified) (1 diff)
- trunk/activerecord/test/base_test.rb (modified) (4 diffs)
- trunk/activerecord/test/binary_test.rb (modified) (1 diff)
- trunk/activerecord/test/column_alias_test.rb (modified) (1 diff)
- trunk/activerecord/test/connections/native_oci (deleted)
- trunk/activerecord/test/connections/native_oracle (added)
- trunk/activerecord/test/connections/native_oracle/connection.rb (added)
- trunk/activerecord/test/fixtures_test.rb (modified) (2 diffs)
- trunk/activerecord/test/fixtures/db_definitions/create_oracle_db.sh (deleted)
- trunk/activerecord/test/fixtures/db_definitions/oracle.drop.sql (moved) (moved from trunk/activerecord/test/fixtures/db_definitions/oci.drop.sql)
- trunk/activerecord/test/fixtures/db_definitions/oracle.sql (moved) (moved from trunk/activerecord/test/fixtures/db_definitions/oci.sql) (2 diffs)
- trunk/activerecord/test/fixtures/db_definitions/oracle2.drop.sql (moved) (moved from trunk/activerecord/test/fixtures/db_definitions/oci2.drop.sql)
- trunk/activerecord/test/fixtures/db_definitions/oracle2.sql (moved) (moved from trunk/activerecord/test/fixtures/db_definitions/oci2.sql)
- trunk/activerecord/test/migration_test.rb (modified) (3 diffs)
- trunk/activerecord/test/readonly_test.rb (modified) (1 diff)
- trunk/activerecord/test/synonym_test_oracle.rb (moved) (moved from trunk/activerecord/test/synonym_test_oci.rb)
- trunk/railties/configs/databases/oracle.yml (added)
- trunk/railties/lib/rails_generator/generators/applications/app/app_generator.rb (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/activerecord/CHANGELOG
r3708 r3718 1 1 *SVN* 2 3 * Renamed the "oci" adapter to "oracle", but kept the old name as an alias #4017 [schoenm@earthlink.net] 2 4 3 5 * Fixed that Base.save should always return false if the save didn't succeed, including if it has halted by before_save's #1861, #2477 [DHH] trunk/activerecord/lib/active_record.rb
r3646 r3718 69 69 70 70 unless defined?(RAILS_CONNECTION_ADAPTERS) 71 RAILS_CONNECTION_ADAPTERS = %w(mysql postgresql sqlite firebird sqlserver db2 o ci)71 RAILS_CONNECTION_ADAPTERS = %w(mysql postgresql sqlite firebird sqlserver db2 oracle) 72 72 end 73 73 trunk/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb
r3647 r3718 1 # o ci_adapter.rb -- ActiveRecord adapter for Oracle 8i, 9i, 10g1 # oracle_adapter.rb -- ActiveRecord adapter for Oracle 8i, 9i, 10g 2 2 # 3 3 # Original author: Graham Jenkins … … 31 31 module ActiveRecord 32 32 class Base 33 def self.oracle_connection(config) #:nodoc: 34 # Use OCI8AutoRecover instead of normal OCI8 driver. 35 ConnectionAdapters::OracleAdapter.new OCI8AutoRecover.new(config), logger 36 end 37 38 # for backwards-compatibility 33 39 def self.oci_connection(config) #:nodoc: 34 # Use OCI8AutoRecover instead of normal OCI8 driver.35 ConnectionAdapters::OCIAdapter.new OCI8AutoRecover.new(config), logger40 config[:database] = config[:host] 41 self.oracle_connection(config) 36 42 end 37 43 … … 39 45 # This is preferable to inserting the hard-coded value here, because the insert method 40 46 # needs to know the id value explicitly. 41 alias :attributes_with_quotes_pre_o ci:attributes_with_quotes #:nodoc:47 alias :attributes_with_quotes_pre_oracle :attributes_with_quotes #:nodoc: 42 48 def attributes_with_quotes(creating = true) #:nodoc: 43 aq = attributes_with_quotes_pre_o cicreating44 if connection.class == ConnectionAdapters::O CIAdapter49 aq = attributes_with_quotes_pre_oracle creating 50 if connection.class == ConnectionAdapters::OracleAdapter 45 51 aq[self.class.primary_key] = ":id" if creating && aq[self.class.primary_key].nil? 46 52 end … … 52 58 after_save :write_lobs 53 59 def write_lobs() #:nodoc: 54 if connection.is_a?(ConnectionAdapters::O CIAdapter)60 if connection.is_a?(ConnectionAdapters::OracleAdapter) 55 61 self.class.columns.select { |c| c.type == :binary }.each { |c| 56 62 value = self[c.name] … … 69 75 70 76 module ConnectionAdapters #:nodoc: 71 class O CIColumn < Column #:nodoc:77 class OracleColumn < Column #:nodoc: 72 78 attr_reader :sql_type 73 79 … … 154 160 # has_and_belongs_to_many associations to run against Oracle8. 155 161 # 156 # Options:162 # Required parameters: 157 163 # 158 # * <tt>:username</tt> -- Defaults to root159 # * <tt>:password</tt> -- Defaults to nothing160 # * <tt>: host</tt> -- Defaults to localhost161 class O CIAdapter < AbstractAdapter164 # * <tt>:username</tt> 165 # * <tt>:password</tt> 166 # * <tt>:database</tt> 167 class OracleAdapter < AbstractAdapter 162 168 163 169 def adapter_name #:nodoc: 164 'O CI'170 'Oracle' 165 171 end 166 172 … … 173 179 :primary_key => "NUMBER(38) NOT NULL PRIMARY KEY", 174 180 :string => { :name => "VARCHAR2", :limit => 255 }, 175 :text => { :name => " LONG" },181 :text => { :name => "BLOB" }, 176 182 :integer => { :name => "NUMBER", :limit => 38 }, 177 183 :float => { :name => "NUMBER" }, … … 215 221 216 222 217 # CONNECTION MANAGEMENT ====================================# 223 # CONNECTION MANAGEMENT ==================================== 224 # 218 225 219 226 # Returns true if the connection is active. … … 224 231 # gone stale since the last use. 225 232 @connection.ping 226 rescue OCIE rror233 rescue OCIException 227 234 false 228 235 end … … 231 238 def reconnect! 232 239 @connection.reset! 233 rescue OCIE rror=> e240 rescue OCIException => e 234 241 @logger.warn "#{adapter_name} automatic reconnection failed: #{e.message}" 242 end 243 244 # Disconnects from the database. 245 def disconnect! 246 @connection.logoff rescue nil 247 @connection.active = false 235 248 end 236 249 … … 347 360 where owner = '#{table_info.schema}' 348 361 and table_name = '#{table_info.name}' 362 order by column_id 349 363 } 350 364 351 365 select_all(table_cols, name).map do |row| 352 366 row['data_default'].sub!(/^'(.*)'\s*$/, '\1') if row['data_default'] 353 O CIColumn.new(354 o ci_downcase(row['column_name']),367 OracleColumn.new( 368 oracle_downcase(row['column_name']), 355 369 row['data_default'], 356 370 row['data_type'], 357 row['length'] ,358 row['scale'] ,371 row['length'].to_i, 372 row['scale'].to_i, 359 373 row['nullable'] == 'Y' 360 374 ) … … 445 459 def select(sql, name = nil) 446 460 cursor = log(sql, name) { @connection.exec sql } 447 cols = cursor.get_col_names.map { |x| o ci_downcase(x) }461 cols = cursor.get_col_names.map { |x| oracle_downcase(x) } 448 462 rows = [] 449 463 … … 477 491 # camelCase column name. I imagine other dbs handle this different, since there's a 478 492 # unit test that's currently failing test_oci. 479 def o ci_downcase(column_name)493 def oracle_downcase(column_name) 480 494 column_name =~ /[a-z]/ ? column_name : column_name.downcase 481 495 end … … 501 515 end 502 516 503 # missing constant from oci8 504 OCI_PTYPE_UNK = 0 517 # missing constant from oci8 < 0.1.14 518 OCI_PTYPE_UNK = 0 unless defined?(OCI_PTYPE_UNK) 505 519 506 520 def object_info(name) … … 530 544 531 545 532 # The O CIConnectionFactory factors out the code necessary to connect and533 # configure an O CI connection.534 class O CIConnectionFactory #:nodoc:535 def new_connection(username, password, host)536 conn = OCI8.new username, password, host546 # The OracleConnectionFactory factors out the code necessary to connect and 547 # configure an Oracle/OCI connection. 548 class OracleConnectionFactory #:nodoc: 549 def new_connection(username, password, database) 550 conn = OCI8.new username, password, database 537 551 conn.exec %q{alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'} 538 552 conn.exec %q{alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS'} rescue nil … … 560 574 @@auto_retry = false 561 575 562 def initialize(config, factory = O CIConnectionFactory.new)576 def initialize(config, factory = OracleConnectionFactory.new) 563 577 @active = true 564 @username, @password, @ host = config[:username], config[:password], config[:host]578 @username, @password, @database = config[:username], config[:password], config[:database] 565 579 @factory = factory 566 @connection = @factory.new_connection @username, @password, @ host580 @connection = @factory.new_connection @username, @password, @database 567 581 super @connection 568 582 end … … 583 597 logoff rescue nil 584 598 begin 585 @connection = @factory.new_connection @username, @password, @ host599 @connection = @factory.new_connection @username, @password, @database 586 600 __setobj__ @connection 587 601 @active = true … … 606 620 begin 607 621 @connection.exec(sql, *bindvars) 608 rescue OCIE rror=> e622 rescue OCIException => e 609 623 raise unless LOST_CONNECTION_ERROR_CODES.include?(e.code) 610 624 @active = false … … 622 636 module ActiveRecord # :nodoc: 623 637 class Base 638 def self.oracle_connection(config) # :nodoc: 639 # Set up a reasonable error message 640 raise LoadError, "Oracle/OCI libraries could not be loaded." 641 end 624 642 def self.oci_connection(config) # :nodoc: 625 643 # Set up a reasonable error message trunk/activerecord/Rakefile
r3647 r3718 28 28 # Run the unit tests 29 29 30 for adapter in %w( mysql postgresql sqlite sqlite3 firebird sqlserver sqlserver_odbc db2 o ci)30 for adapter in %w( mysql postgresql sqlite sqlite3 firebird sqlserver sqlserver_odbc db2 oracle ) 31 31 Rake::TestTask.new("test_#{adapter}") { |t| 32 32 t.libs << "test" << "test/connections/native_#{adapter}" trunk/activerecord/test/base_test.rb
r3679 r3718 18 18 class Computer < ActiveRecord::Base; end 19 19 class NonExistentTable < ActiveRecord::Base; end 20 class TestO CIDefault < ActiveRecord::Base; end20 class TestOracleDefault < ActiveRecord::Base; end 21 21 22 22 class LoosePerson < ActiveRecord::Base … … 527 527 # Oracle has some funky default handling, so it requires a bit of 528 528 # extra testing. See ticket #2788. 529 if current_adapter?(:O CIAdapter)530 test = TestO CIDefault.new529 if current_adapter?(:OracleAdapter) 530 test = TestOracleDefault.new 531 531 assert_equal "X", test.test_char 532 532 assert_equal "hello", test.test_string … … 537 537 def test_utc_as_time_zone 538 538 # Oracle and SQLServer do not have a TIME datatype. 539 return true if current_adapter?(:SQLServerAdapter) || current_adapter?(:O CIAdapter)539 return true if current_adapter?(:SQLServerAdapter) || current_adapter?(:OracleAdapter) 540 540 541 541 Topic.default_timezone = :utc … … 705 705 def test_attributes_on_dummy_time 706 706 # Oracle and SQL Server do not have a TIME datatype. 707 return true if current_adapter?(:SQLServerAdapter) || current_adapter?(:O CIAdapter)707 return true if current_adapter?(:SQLServerAdapter) || current_adapter?(:OracleAdapter) 708 708 709 709 attributes = { trunk/activerecord/test/binary_test.rb
r3052 r3718 21 21 # BLOB data with DB2 or Firebird, because the length of a statement 22 22 # is limited to 32KB. 23 unless %w(SQLServer DB2 O CIFirebird).include? ActiveRecord::Base.connection.adapter_name23 unless %w(SQLServer DB2 Oracle Firebird).include? ActiveRecord::Base.connection.adapter_name 24 24 def test_load_save 25 25 bin = Binary.new trunk/activerecord/test/column_alias_test.rb
r2714 r3718 5 5 fixtures :topics 6 6 7 QUERY = if 'O CI' == ActiveRecord::Base.connection.adapter_name7 QUERY = if 'Oracle' == ActiveRecord::Base.connection.adapter_name 8 8 'SELECT id AS pk FROM topics WHERE ROWNUM < 2' 9 9 else trunk/activerecord/test/fixtures_test.rb
r3708 r3718 62 62 t.column :bonus_time, :time 63 63 t.column :last_read, :date 64 t.column :content, : text64 t.column :content, :string 65 65 t.column :approved, :boolean, :default => true 66 66 t.column :replies_count, :integer, :default => 0 … … 79 79 topics = create_fixtures("topics") 80 80 81 firstRow = ActiveRecord::Base.connection.select_one("SELECT * FROM prefix_topics_suffix WHERE author_name = 'David'") 82 assert_equal("The First Topic", firstRow["title"]) 83 84 secondRow = ActiveRecord::Base.connection.select_one("SELECT * FROM prefix_topics_suffix WHERE author_name = 'Mary'") 85 assert_nil(secondRow["author_email_address"]) 86 ensure 81 87 # Restore prefix/suffix to its previous values 82 88 ActiveRecord::Base.table_name_prefix = old_prefix 83 89 ActiveRecord::Base.table_name_suffix = old_suffix 84 90 85 firstRow = ActiveRecord::Base.connection.select_one("SELECT * FROM prefix_topics_suffix WHERE author_name = 'David'")86 assert_equal("The First Topic", firstRow["title"])87 88 secondRow = ActiveRecord::Base.connection.select_one("SELECT * FROM prefix_topics_suffix WHERE author_name = 'Mary'")89 assert_nil(secondRow["author_email_address"])90 ensure91 91 ActiveRecord::Base.connection.drop_table :prefix_topics_suffix rescue nil 92 92 end trunk/activerecord/test/fixtures/db_definitions/oracle.sql
r3695 r3718 276 276 create sequence keyboards_seq minvalue 10000; 277 277 278 create table test_o ci_defaults (278 create table test_oracle_defaults ( 279 279 id integer not null primary key, 280 280 test_char char(1) default 'X' not null, … … 282 282 test_int integer default 3 not null 283 283 ); 284 create sequence test_o ci_defaults_seq minvalue 10000;284 create sequence test_oracle_defaults_seq minvalue 10000; 285 285 286 286 --This table has an altered lock_version column name. trunk/activerecord/test/migration_test.rb
r3327 r3718 85 85 86 86 assert_equal "hello", one.default 87 if current_adapter?(:O CIAdapter)87 if current_adapter?(:OracleAdapter) 88 88 # Oracle doesn't support native booleans 89 89 assert_equal true, two.default == 1 … … 154 154 assert_equal Time, bob.birthday.class 155 155 156 if current_adapter?(:SQLServerAdapter) or current_adapter?(:O CIAdapter)156 if current_adapter?(:SQLServerAdapter) or current_adapter?(:OracleAdapter) 157 157 # SQL Server and Oracle don't differentiate between date/time 158 158 assert_equal Time, bob.favorite_day.class … … 242 242 243 243 assert_nothing_raised do 244 if current_adapter?(:O CIAdapter)244 if current_adapter?(:OracleAdapter) 245 245 # Oracle requires the explicit sequence for the pk 246 246 ActiveRecord::Base.connection.execute "INSERT INTO octopi (id, url) VALUES (octopi_seq.nextval, 'http://www.foreverflying.com/octopus-black7.jpg')" trunk/activerecord/test/readonly_test.rb
r2888 r3718 80 80 # Oracle barfs on this because the join includes unqualified and 81 81 # conflicting column names 82 unless current_adapter?(:O CIAdapter)82 unless current_adapter?(:OracleAdapter) 83 83 Post.with_scope(:find => { :joins => ', developers' }) do 84 84 assert Post.find(1).readonly? trunk/railties/lib/rails_generator/generators/applications/app/app_generator.rb
r3711 r3718 5 5 Config::CONFIG['ruby_install_name']) 6 6 7 DATABASES = %w( mysql sqlite2 sqlite3 postgresql)7 DATABASES = %w( mysql oracle postgresql sqlite2 sqlite3 ) 8 8 9 9 default_options :db => "mysql", :shebang => DEFAULT_SHEBANG … … 98 98 99 99 opt.on("-d", "--database=name", String, 100 "Preconfigure for selected database (options: mysql/ postgresql/sqlite2/sqlite3).",100 "Preconfigure for selected database (options: mysql/oracle/postgresql/sqlite2/sqlite3).", 101 101 "Default: mysql") { |options[:db]| } 102 102 end