Ticket #4017: oracle_adapter.patch
| File oracle_adapter.patch, 21.0 kB (added by anonymous, 3 years ago) |
|---|
-
activerecord/test/connections/native_oracle/connection.rb
old new 1 print "Using Oracle\n" 2 require_dependency 'fixtures/course' 3 require 'logger' 4 5 ActiveRecord::Base.logger = Logger.new STDOUT 6 ActiveRecord::Base.logger.level = Logger::WARN 7 8 # Set these to your database connection strings 9 db = 'activerecord_unit_tests' 10 11 ActiveRecord::Base.establish_connection( 12 :adapter => 'oracle', 13 :username => 'arunit', 14 :password => 'arunit', 15 :database => db 16 ) 17 18 Course.establish_connection( 19 :adapter => 'oracle', 20 :username => 'arunit2', 21 :password => 'arunit2', 22 :database => db 23 ) -
activerecord/test/column_alias_test.rb
old new 4 4 class TestColumnAlias < Test::Unit::TestCase 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 10 10 'SELECT id AS pk FROM topics' -
activerecord/test/fixtures_test.rb
old new 61 61 t.column :written_on, :datetime 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 67 67 t.column :parent_id, :integer … … 78 78 79 79 topics = create_fixtures("topics") 80 80 81 # Restore prefix/suffix to its previous values82 ActiveRecord::Base.table_name_prefix = old_prefix83 ActiveRecord::Base.table_name_suffix = old_suffix84 85 81 firstRow = ActiveRecord::Base.connection.select_one("SELECT * FROM prefix_topics_suffix WHERE author_name = 'David'") 86 82 assert_equal("The First Topic", firstRow["title"]) 87 83 88 84 secondRow = ActiveRecord::Base.connection.select_one("SELECT * FROM prefix_topics_suffix WHERE author_name = 'Mary'") 89 85 assert_nil(secondRow["author_email_address"]) 90 86 ensure 87 # Restore prefix/suffix to its previous values 88 ActiveRecord::Base.table_name_prefix = old_prefix 89 ActiveRecord::Base.table_name_suffix = old_suffix 90 91 91 ActiveRecord::Base.connection.drop_table :prefix_topics_suffix rescue nil 92 92 end 93 93 end -
activerecord/test/base_test.rb
old new 17 17 class Post < ActiveRecord::Base; end 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 23 23 attr_protected :credit_rating, :administrator … … 526 526 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 533 533 assert_equal 3, test.test_int … … 536 536 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 542 542 attributes = { "bonus_time" => "5:42:00AM" } … … 704 704 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 = { 710 710 "bonus_time" => "5:42:00AM" -
activerecord/test/binary_test.rb
old new 20 20 # Without using prepared statements, it makes no sense to test 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 26 26 bin.data = @data -
activerecord/test/migration_test.rb
old new 84 84 four = columns.detect { |c| c.name == "four" } 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 90 90 assert_equal false, three.default != 0 … … 153 153 assert_equal Fixnum, bob.age.class 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 159 159 else … … 241 241 ActiveRecord::Base.connection.rename_table :octopuses, :octopi 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')" 247 247 else -
activerecord/test/fixtures/db_definitions/oracle.sql
old new 275 275 ); 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, 281 281 test_string varchar2(20) default 'hello' 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. 287 287 create table legacy_things ( -
activerecord/test/readonly_test.rb
old new 79 79 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? 85 85 assert Post.find(1, :readonly => true).readonly? -
activerecord/Rakefile
old new 27 27 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}" 33 33 t.pattern = "test/*_test{,_#{adapter}}.rb" -
activerecord/lib/active_record/connection_adapters/oracle_adapter.rb
old new 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 4 4 # … … 30 30 31 31 module ActiveRecord 32 32 class Base 33 def self.o ci_connection(config) #:nodoc:33 def self.oracle_connection(config) #:nodoc: 34 34 # Use OCI8AutoRecover instead of normal OCI8 driver. 35 ConnectionAdapters::O CIAdapter.new OCI8AutoRecover.new(config), logger35 ConnectionAdapters::OracleAdapter.new OCI8AutoRecover.new(config), logger 36 36 end 37 37 38 # for backwards-compatibility 39 def self.oci_connection(config) #:nodoc: 40 config[:database] = config[:host] 41 self.oracle_connection(config) 42 end 43 38 44 # Enable the id column to be bound into the sql later, by the adapter's insert method. 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 47 53 aq … … 51 57 # and write back the data. 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] 57 63 next if value.nil? || (value == '') … … 68 74 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 74 80 # overridden to add the concept of scale, required to differentiate … … 153 159 # is supported in Oracle9i and later. You will need to use #finder_sql for 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 167 173 def supports_migrations? #:nodoc: … … 172 178 { 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" }, 178 184 :datetime => { :name => "DATE" }, … … 214 220 end 215 221 216 222 217 # CONNECTION MANAGEMENT ====================================# 223 # CONNECTION MANAGEMENT ==================================== 224 # 218 225 219 226 # Returns true if the connection is active. 220 227 def active? … … 223 230 # last known state, which isn't good enough if the connection has 224 231 # gone stale since the last use. 225 232 @connection.ping 226 rescue OCIE rror233 rescue OCIException 227 234 false 228 235 end 229 236 230 237 # Reconnects to the database. 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}" 235 242 end 236 243 244 # Disconnects from the database. 245 def disconnect! 246 @connection.logoff rescue nil 247 @connection.active = false 248 end 237 249 250 238 251 # DATABASE STATEMENTS ====================================== 239 252 # 240 253 # see: abstract/database_statements.rb … … 346 359 from all_tab_columns 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 ) 361 375 end … … 444 458 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 450 464 while row = cursor.fetch … … 476 490 # I don't know anybody who does this, but we'll handle the theoretical case of a 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 482 496 … … 500 514 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) 507 521 OraObject.new describe(name.to_s, OCI_PTYPE_UNK) … … 529 543 end 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 539 553 conn.autocommit = true … … 559 573 end 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 569 583 … … 582 596 def reset! 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 588 602 rescue … … 605 619 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 611 625 raise unless should_retry … … 621 635 # OCI8 driver is unavailable. 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 626 644 raise LoadError, "Oracle/OCI libraries could not be loaded." -
activerecord/lib/active_record.rb
old new 68 68 end 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 74 74 RAILS_CONNECTION_ADAPTERS.each do |adapter| -
railties/configs/databases/oracle.yml
old new 1 # Oracle/OCI 8i, 9, 10g 2 # 3 # Requires Ruby/OCI8: 4 # http://rubyforge.org/projects/ruby-oci8/ 5 # 6 # Specify your database using any valid connection syntax, such as a 7 # tnsnames.ora service name, or a sql connect url string of the form: 8 # 9 # //host:[port][/service name] 10 11 development: 12 adapter: oracle 13 database: <%= app_name %>_development 14 username: <%= app_name %> 15 password: 16 17 # Warning: The database defined as 'test' will be erased and 18 # re-generated from your development database when you run 'rake'. 19 # Do not set this db to the same as development or production. 20 test: 21 adapter: oracle 22 database: <%= app_name %>_test 23 username: <%= app_name %> 24 password: 25 26 production: 27 adapter: oracle 28 database: <%= app_name %>_production 29 username: <%= app_name %> 30 password: -
railties/lib/rails_generator/generators/applications/app/app_generator.rb
old new 4 4 DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'], 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 10 10 mandatory_options :source => "#{File.dirname(__FILE__)}/../../../../.." … … 97 97 "Default: #{DEFAULT_SHEBANG}") { |options[: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 103 103