pmacs-activerecord-oracle_enhanced-adapter 1.4.2.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.rspec +2 -0
 - data/Gemfile +52 -0
 - data/History.md +284 -0
 - data/License.txt +20 -0
 - data/README.md +403 -0
 - data/RUNNING_TESTS.md +45 -0
 - data/Rakefile +59 -0
 - data/VERSION +1 -0
 - data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +5 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced.rake +105 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_activerecord_patches.rb +41 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +1408 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +118 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +141 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +135 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +359 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +25 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_cpk.rb +21 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +44 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +565 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +491 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +260 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +231 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +257 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +397 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +265 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +294 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +17 -0
 - data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +1 -0
 - data/lib/pmacs-activerecord-oracle_enhanced-adapter.rb +25 -0
 - data/pmacs-activerecord-oracle_enhanced-adapter.gemspec +131 -0
 - data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +778 -0
 - data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +332 -0
 - data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +427 -0
 - data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +19 -0
 - data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +113 -0
 - data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +1376 -0
 - data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +69 -0
 - data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +141 -0
 - data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +25 -0
 - data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +378 -0
 - data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +438 -0
 - data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +1280 -0
 - data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +339 -0
 - data/spec/spec_helper.rb +187 -0
 - metadata +302 -0
 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "bigdecimal"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            unless BigDecimal.method_defined?(:to_d)
         
     | 
| 
      
 4 
     | 
    
         
            +
              BigDecimal.class_eval do
         
     | 
| 
      
 5 
     | 
    
         
            +
                def to_d #:nodoc:
         
     | 
| 
      
 6 
     | 
    
         
            +
                  self
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
            end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            unless Bignum.method_defined?(:to_d)
         
     | 
| 
      
 12 
     | 
    
         
            +
              Bignum.class_eval do
         
     | 
| 
      
 13 
     | 
    
         
            +
                def to_d #:nodoc:
         
     | 
| 
      
 14 
     | 
    
         
            +
                  BigDecimal.new(self.to_s)
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            unless Fixnum.method_defined?(:to_d)
         
     | 
| 
      
 20 
     | 
    
         
            +
              Fixnum.class_eval do
         
     | 
| 
      
 21 
     | 
    
         
            +
                def to_d #:nodoc:
         
     | 
| 
      
 22 
     | 
    
         
            +
                  BigDecimal.new(self.to_s)
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ActiveRecord #:nodoc:
         
     | 
| 
      
 2 
     | 
    
         
            +
              module ConnectionAdapters #:nodoc:
         
     | 
| 
      
 3 
     | 
    
         
            +
                module OracleEnhancedCpk #:nodoc:
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  # This mightn't be in Core, but count(distinct x,y) doesn't work for me.
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # Return that not supported if composite_primary_keys gem is required.
         
     | 
| 
      
 7 
     | 
    
         
            +
                  def supports_count_distinct? #:nodoc:
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @supports_count_distinct ||= ! defined?(CompositePrimaryKeys)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
                  
         
     | 
| 
      
 11 
     | 
    
         
            +
                  def concat(*columns) #:nodoc:
         
     | 
| 
      
 12 
     | 
    
         
            +
                    "(#{columns.join('||')})"
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
                  
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
         
     | 
| 
      
 20 
     | 
    
         
            +
              include ActiveRecord::ConnectionAdapters::OracleEnhancedCpk
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,44 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ActiveRecord #:nodoc:
         
     | 
| 
      
 2 
     | 
    
         
            +
              module ConnectionAdapters #:nodoc:
         
     | 
| 
      
 3 
     | 
    
         
            +
                module OracleEnhancedDirty #:nodoc:
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  module InstanceMethods #:nodoc:
         
     | 
| 
      
 6 
     | 
    
         
            +
                    private
         
     | 
| 
      
 7 
     | 
    
         
            +
                    
         
     | 
| 
      
 8 
     | 
    
         
            +
                    def _field_changed?(attr, old, value)
         
     | 
| 
      
 9 
     | 
    
         
            +
                      if column = column_for_attribute(attr)
         
     | 
| 
      
 10 
     | 
    
         
            +
                        # Added also :decimal type
         
     | 
| 
      
 11 
     | 
    
         
            +
                        if (column.type == :integer || column.type == :decimal) && column.null && (old.nil? || old == 0) && value.blank?
         
     | 
| 
      
 12 
     | 
    
         
            +
                          # For nullable integer columns, NULL gets stored in database for blank (i.e. '') values.
         
     | 
| 
      
 13 
     | 
    
         
            +
                          # Hence we don't record it as a change if the value changes from nil to ''.
         
     | 
| 
      
 14 
     | 
    
         
            +
                          # If an old value of 0 is set to '' we want this to get changed to nil as otherwise it'll
         
     | 
| 
      
 15 
     | 
    
         
            +
                          # be typecast back to 0 (''.to_i => 0)
         
     | 
| 
      
 16 
     | 
    
         
            +
                          value = nil
         
     | 
| 
      
 17 
     | 
    
         
            +
                        # Oracle stores empty string '' as NULL
         
     | 
| 
      
 18 
     | 
    
         
            +
                        # therefore need to convert empty string value to nil if old value is nil
         
     | 
| 
      
 19 
     | 
    
         
            +
                        elsif column.type == :string && column.null && old.nil?
         
     | 
| 
      
 20 
     | 
    
         
            +
                          value = nil if value == ''
         
     | 
| 
      
 21 
     | 
    
         
            +
                        else
         
     | 
| 
      
 22 
     | 
    
         
            +
                          value = column.type_cast(value)
         
     | 
| 
      
 23 
     | 
    
         
            +
                        end
         
     | 
| 
      
 24 
     | 
    
         
            +
                      end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                      old != value
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                    
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            if ActiveRecord::Base.method_defined?(:changed?)
         
     | 
| 
      
 36 
     | 
    
         
            +
              ActiveRecord::Base.class_eval do
         
     | 
| 
      
 37 
     | 
    
         
            +
                include ActiveRecord::ConnectionAdapters::OracleEnhancedDirty::InstanceMethods
         
     | 
| 
      
 38 
     | 
    
         
            +
                # Starting with rails 3.2.9 the method #field_changed?
         
     | 
| 
      
 39 
     | 
    
         
            +
                # was renamed to #_field_changed?
         
     | 
| 
      
 40 
     | 
    
         
            +
                if private_method_defined?(:field_changed?)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  alias_method :field_changed?, :_field_changed?
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,565 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            begin
         
     | 
| 
      
 2 
     | 
    
         
            +
              require "java"
         
     | 
| 
      
 3 
     | 
    
         
            +
              require "jruby"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              # ojdbc6.jar or ojdbc5.jar file should be in JRUBY_HOME/lib or should be in ENV['PATH'] or load path
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              java_version = java.lang.System.getProperty("java.version")
         
     | 
| 
      
 8 
     | 
    
         
            +
              ojdbc_jar = if java_version =~ /^1.5/
         
     | 
| 
      
 9 
     | 
    
         
            +
                "ojdbc5.jar"
         
     | 
| 
      
 10 
     | 
    
         
            +
              elsif java_version >= '1.6'
         
     | 
| 
      
 11 
     | 
    
         
            +
                "ojdbc6.jar"
         
     | 
| 
      
 12 
     | 
    
         
            +
              else
         
     | 
| 
      
 13 
     | 
    
         
            +
                nil
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              unless ojdbc_jar.nil? || ENV_JAVA['java.class.path'] =~ Regexp.new(ojdbc_jar)
         
     | 
| 
      
 17 
     | 
    
         
            +
                # On Unix environment variable should be PATH, on Windows it is sometimes Path
         
     | 
| 
      
 18 
     | 
    
         
            +
                env_path = (ENV["PATH"] || ENV["Path"] || '').split(/[:;]/)
         
     | 
| 
      
 19 
     | 
    
         
            +
                # Look for JDBC driver at first in lib subdirectory (application specific JDBC file version)
         
     | 
| 
      
 20 
     | 
    
         
            +
                # then in Ruby load path and finally in environment PATH
         
     | 
| 
      
 21 
     | 
    
         
            +
                if ojdbc_jar_path = ['./lib'].concat($LOAD_PATH).concat(env_path).find{|d| File.exists?(File.join(d,ojdbc_jar))}
         
     | 
| 
      
 22 
     | 
    
         
            +
                  require File.join(ojdbc_jar_path,ojdbc_jar)
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              ORACLE_DRIVER = Java::oracle.jdbc.OracleDriver.new
         
     | 
| 
      
 27 
     | 
    
         
            +
              java.sql.DriverManager.registerDriver ORACLE_DRIVER
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              # set tns_admin property from TNS_ADMIN environment variable
         
     | 
| 
      
 30 
     | 
    
         
            +
              if !java.lang.System.get_property("oracle.net.tns_admin") && ENV["TNS_ADMIN"]
         
     | 
| 
      
 31 
     | 
    
         
            +
                java.lang.System.set_property("oracle.net.tns_admin", ENV["TNS_ADMIN"])
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            rescue LoadError, NameError
         
     | 
| 
      
 35 
     | 
    
         
            +
              # JDBC driver is unavailable.
         
     | 
| 
      
 36 
     | 
    
         
            +
              raise LoadError, "ERROR: ActiveRecord oracle_enhanced adapter could not load Oracle JDBC driver. Please install #{ojdbc_jar || "Oracle JDBC"} library."
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 41 
     | 
    
         
            +
              module ConnectionAdapters
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                # JDBC database interface for JRuby
         
     | 
| 
      
 44 
     | 
    
         
            +
                class OracleEnhancedJDBCConnection < OracleEnhancedConnection #:nodoc:
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                  attr_accessor :active
         
     | 
| 
      
 47 
     | 
    
         
            +
                  alias :active? :active
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  attr_accessor :auto_retry
         
     | 
| 
      
 50 
     | 
    
         
            +
                  alias :auto_retry? :auto_retry
         
     | 
| 
      
 51 
     | 
    
         
            +
                  @auto_retry = false
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  def initialize(config)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    @active = true
         
     | 
| 
      
 55 
     | 
    
         
            +
                    @config = config
         
     | 
| 
      
 56 
     | 
    
         
            +
                    new_connection(@config)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  # modified method to support JNDI connections
         
     | 
| 
      
 60 
     | 
    
         
            +
                  def new_connection(config)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    username = nil
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    if config[:jndi]
         
     | 
| 
      
 64 
     | 
    
         
            +
                      jndi = config[:jndi].to_s
         
     | 
| 
      
 65 
     | 
    
         
            +
                      ctx = javax.naming.InitialContext.new
         
     | 
| 
      
 66 
     | 
    
         
            +
                      ds = nil
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                      # tomcat needs first lookup method, oc4j (and maybe other application servers) need second method
         
     | 
| 
      
 69 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 70 
     | 
    
         
            +
                        env = ctx.lookup('java:/comp/env')
         
     | 
| 
      
 71 
     | 
    
         
            +
                        ds = env.lookup(jndi)
         
     | 
| 
      
 72 
     | 
    
         
            +
                      rescue
         
     | 
| 
      
 73 
     | 
    
         
            +
                        ds = ctx.lookup(jndi)
         
     | 
| 
      
 74 
     | 
    
         
            +
                      end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                      # check if datasource supports pooled connections, otherwise use default
         
     | 
| 
      
 77 
     | 
    
         
            +
                      if ds.respond_to?(:pooled_connection)
         
     | 
| 
      
 78 
     | 
    
         
            +
                        @raw_connection = ds.pooled_connection
         
     | 
| 
      
 79 
     | 
    
         
            +
                      else
         
     | 
| 
      
 80 
     | 
    
         
            +
                        @raw_connection = ds.connection
         
     | 
| 
      
 81 
     | 
    
         
            +
                      end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                      # get Oracle JDBC connection when using DBCP in Tomcat or jBoss
         
     | 
| 
      
 84 
     | 
    
         
            +
                      if @raw_connection.respond_to?(:getInnermostDelegate)
         
     | 
| 
      
 85 
     | 
    
         
            +
                        @pooled_connection = @raw_connection
         
     | 
| 
      
 86 
     | 
    
         
            +
                        @raw_connection = @raw_connection.innermost_delegate
         
     | 
| 
      
 87 
     | 
    
         
            +
                      elsif @raw_connection.respond_to?(:getUnderlyingConnection)
         
     | 
| 
      
 88 
     | 
    
         
            +
                        @pooled_connection = @raw_connection
         
     | 
| 
      
 89 
     | 
    
         
            +
                        @raw_connection = @raw_connection.underlying_connection            
         
     | 
| 
      
 90 
     | 
    
         
            +
                      end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                      config[:driver] ||= @raw_connection.meta_data.connection.java_class.name
         
     | 
| 
      
 93 
     | 
    
         
            +
                      username = @raw_connection.meta_data.user_name
         
     | 
| 
      
 94 
     | 
    
         
            +
                    else
         
     | 
| 
      
 95 
     | 
    
         
            +
                      # to_s needed if username, password or database is specified as number in database.yml file
         
     | 
| 
      
 96 
     | 
    
         
            +
                      username = config[:username] && config[:username].to_s
         
     | 
| 
      
 97 
     | 
    
         
            +
                      password = config[:password] && config[:password].to_s
         
     | 
| 
      
 98 
     | 
    
         
            +
                      database = config[:database] && config[:database].to_s || 'XE'
         
     | 
| 
      
 99 
     | 
    
         
            +
                      host, port = config[:host], config[:port]
         
     | 
| 
      
 100 
     | 
    
         
            +
                      privilege = config[:privilege] && config[:privilege].to_s
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                      # connection using TNS alias
         
     | 
| 
      
 103 
     | 
    
         
            +
                      if database && !host && !config[:url] && ENV['TNS_ADMIN']
         
     | 
| 
      
 104 
     | 
    
         
            +
                        url = "jdbc:oracle:thin:@#{database}"
         
     | 
| 
      
 105 
     | 
    
         
            +
                      else
         
     | 
| 
      
 106 
     | 
    
         
            +
                        unless database.match(/^(\:|\/)/)
         
     | 
| 
      
 107 
     | 
    
         
            +
                          # assume database is a SID if no colon or slash are supplied (backward-compatibility)
         
     | 
| 
      
 108 
     | 
    
         
            +
                          database = ":#{database}"
         
     | 
| 
      
 109 
     | 
    
         
            +
                        end
         
     | 
| 
      
 110 
     | 
    
         
            +
                        url = config[:url] || "jdbc:oracle:thin:@#{host || 'localhost'}:#{port || 1521}#{database}"
         
     | 
| 
      
 111 
     | 
    
         
            +
                      end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                      prefetch_rows = config[:prefetch_rows] || 100
         
     | 
| 
      
 114 
     | 
    
         
            +
                      # get session time_zone from configuration or from TZ environment variable
         
     | 
| 
      
 115 
     | 
    
         
            +
                      time_zone = config[:time_zone] || ENV['TZ'] || java.util.TimeZone.default.getID
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                      properties = java.util.Properties.new
         
     | 
| 
      
 118 
     | 
    
         
            +
                      properties.put("user", username)
         
     | 
| 
      
 119 
     | 
    
         
            +
                      properties.put("password", password)
         
     | 
| 
      
 120 
     | 
    
         
            +
                      properties.put("defaultRowPrefetch", "#{prefetch_rows}") if prefetch_rows
         
     | 
| 
      
 121 
     | 
    
         
            +
                      properties.put("internal_logon", privilege) if privilege
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 124 
     | 
    
         
            +
                        @raw_connection = java.sql.DriverManager.getConnection(url, properties)
         
     | 
| 
      
 125 
     | 
    
         
            +
                      rescue
         
     | 
| 
      
 126 
     | 
    
         
            +
                        # bypass DriverManager to work in cases where ojdbc*.jar
         
     | 
| 
      
 127 
     | 
    
         
            +
                        # is added to the load path at runtime and not on the
         
     | 
| 
      
 128 
     | 
    
         
            +
                        # system classpath
         
     | 
| 
      
 129 
     | 
    
         
            +
                        @raw_connection = ORACLE_DRIVER.connect(url, properties)
         
     | 
| 
      
 130 
     | 
    
         
            +
                      end
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                      # Set session time zone to current time zone
         
     | 
| 
      
 133 
     | 
    
         
            +
                      @raw_connection.setSessionTimeZone(time_zone)
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                      # Set default number of rows to prefetch
         
     | 
| 
      
 136 
     | 
    
         
            +
                      # @raw_connection.setDefaultRowPrefetch(prefetch_rows) if prefetch_rows
         
     | 
| 
      
 137 
     | 
    
         
            +
                    end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                    cursor_sharing = config[:cursor_sharing] || 'force'
         
     | 
| 
      
 140 
     | 
    
         
            +
                    exec "alter session set cursor_sharing = #{cursor_sharing}"
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                    # Initialize NLS parameters
         
     | 
| 
      
 143 
     | 
    
         
            +
                    OracleEnhancedAdapter::DEFAULT_NLS_PARAMETERS.each do |key, default_value|
         
     | 
| 
      
 144 
     | 
    
         
            +
                      value = config[key] || ENV[key.to_s.upcase] || default_value
         
     | 
| 
      
 145 
     | 
    
         
            +
                      if value
         
     | 
| 
      
 146 
     | 
    
         
            +
                        exec "alter session set #{key} = '#{value}'"
         
     | 
| 
      
 147 
     | 
    
         
            +
                      end
         
     | 
| 
      
 148 
     | 
    
         
            +
                    end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                    self.autocommit = true
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                    # default schema owner
         
     | 
| 
      
 153 
     | 
    
         
            +
                    @owner = username.upcase unless username.nil?
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                    @raw_connection
         
     | 
| 
      
 156 
     | 
    
         
            +
                  end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                  def logoff
         
     | 
| 
      
 159 
     | 
    
         
            +
                    @active = false
         
     | 
| 
      
 160 
     | 
    
         
            +
                    if defined?(@pooled_connection)
         
     | 
| 
      
 161 
     | 
    
         
            +
                      @pooled_connection.close
         
     | 
| 
      
 162 
     | 
    
         
            +
                    else
         
     | 
| 
      
 163 
     | 
    
         
            +
                      @raw_connection.close
         
     | 
| 
      
 164 
     | 
    
         
            +
                    end
         
     | 
| 
      
 165 
     | 
    
         
            +
                    true
         
     | 
| 
      
 166 
     | 
    
         
            +
                  rescue
         
     | 
| 
      
 167 
     | 
    
         
            +
                    false
         
     | 
| 
      
 168 
     | 
    
         
            +
                  end
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
      
 170 
     | 
    
         
            +
                  def commit
         
     | 
| 
      
 171 
     | 
    
         
            +
                    @raw_connection.commit
         
     | 
| 
      
 172 
     | 
    
         
            +
                  end
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
                  def rollback
         
     | 
| 
      
 175 
     | 
    
         
            +
                    @raw_connection.rollback
         
     | 
| 
      
 176 
     | 
    
         
            +
                  end
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
                  def autocommit?
         
     | 
| 
      
 179 
     | 
    
         
            +
                    @raw_connection.getAutoCommit
         
     | 
| 
      
 180 
     | 
    
         
            +
                  end
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                  def autocommit=(value)
         
     | 
| 
      
 183 
     | 
    
         
            +
                    @raw_connection.setAutoCommit(value)
         
     | 
| 
      
 184 
     | 
    
         
            +
                  end
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                  # Checks connection, returns true if active. Note that ping actively
         
     | 
| 
      
 187 
     | 
    
         
            +
                  # checks the connection, while #active? simply returns the last
         
     | 
| 
      
 188 
     | 
    
         
            +
                  # known state.
         
     | 
| 
      
 189 
     | 
    
         
            +
                  def ping
         
     | 
| 
      
 190 
     | 
    
         
            +
                    exec_no_retry("select 1 from dual")
         
     | 
| 
      
 191 
     | 
    
         
            +
                    @active = true
         
     | 
| 
      
 192 
     | 
    
         
            +
                  rescue NativeException => e
         
     | 
| 
      
 193 
     | 
    
         
            +
                    @active = false
         
     | 
| 
      
 194 
     | 
    
         
            +
                    if e.message =~ /^java\.sql\.SQL(Recoverable)?Exception/
         
     | 
| 
      
 195 
     | 
    
         
            +
                      raise OracleEnhancedConnectionException, e.message
         
     | 
| 
      
 196 
     | 
    
         
            +
                    else
         
     | 
| 
      
 197 
     | 
    
         
            +
                      raise
         
     | 
| 
      
 198 
     | 
    
         
            +
                    end
         
     | 
| 
      
 199 
     | 
    
         
            +
                  end
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
      
 201 
     | 
    
         
            +
                  # Resets connection, by logging off and creating a new connection.
         
     | 
| 
      
 202 
     | 
    
         
            +
                  def reset!
         
     | 
| 
      
 203 
     | 
    
         
            +
                    logoff rescue nil
         
     | 
| 
      
 204 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 205 
     | 
    
         
            +
                      new_connection(@config)
         
     | 
| 
      
 206 
     | 
    
         
            +
                      @active = true
         
     | 
| 
      
 207 
     | 
    
         
            +
                    rescue NativeException => e
         
     | 
| 
      
 208 
     | 
    
         
            +
                      @active = false
         
     | 
| 
      
 209 
     | 
    
         
            +
                      if e.message =~ /^java\.sql\.SQL(Recoverable)?Exception/
         
     | 
| 
      
 210 
     | 
    
         
            +
                        raise OracleEnhancedConnectionException, e.message
         
     | 
| 
      
 211 
     | 
    
         
            +
                      else
         
     | 
| 
      
 212 
     | 
    
         
            +
                        raise
         
     | 
| 
      
 213 
     | 
    
         
            +
                      end
         
     | 
| 
      
 214 
     | 
    
         
            +
                    end
         
     | 
| 
      
 215 
     | 
    
         
            +
                  end
         
     | 
| 
      
 216 
     | 
    
         
            +
             
     | 
| 
      
 217 
     | 
    
         
            +
                  # mark connection as dead if connection lost
         
     | 
| 
      
 218 
     | 
    
         
            +
                  def with_retry(&block)
         
     | 
| 
      
 219 
     | 
    
         
            +
                    should_retry = auto_retry? && autocommit?
         
     | 
| 
      
 220 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 221 
     | 
    
         
            +
                      yield if block_given?
         
     | 
| 
      
 222 
     | 
    
         
            +
                    rescue NativeException => e
         
     | 
| 
      
 223 
     | 
    
         
            +
                      raise unless e.message =~ /^java\.sql\.SQL(Recoverable)?Exception: (Closed Connection|Io exception:|No more data to read from socket|IO Error:)/
         
     | 
| 
      
 224 
     | 
    
         
            +
                      @active = false
         
     | 
| 
      
 225 
     | 
    
         
            +
                      raise unless should_retry
         
     | 
| 
      
 226 
     | 
    
         
            +
                      should_retry = false
         
     | 
| 
      
 227 
     | 
    
         
            +
                      reset! rescue nil
         
     | 
| 
      
 228 
     | 
    
         
            +
                      retry
         
     | 
| 
      
 229 
     | 
    
         
            +
                    end
         
     | 
| 
      
 230 
     | 
    
         
            +
                  end
         
     | 
| 
      
 231 
     | 
    
         
            +
             
     | 
| 
      
 232 
     | 
    
         
            +
                  def exec(sql)
         
     | 
| 
      
 233 
     | 
    
         
            +
                    with_retry do
         
     | 
| 
      
 234 
     | 
    
         
            +
                      exec_no_retry(sql)
         
     | 
| 
      
 235 
     | 
    
         
            +
                    end
         
     | 
| 
      
 236 
     | 
    
         
            +
                  end
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                  def exec_no_retry(sql)
         
     | 
| 
      
 239 
     | 
    
         
            +
                    case sql
         
     | 
| 
      
 240 
     | 
    
         
            +
                    when /\A\s*(UPDATE|INSERT|DELETE)/i
         
     | 
| 
      
 241 
     | 
    
         
            +
                      s = @raw_connection.prepareStatement(sql)
         
     | 
| 
      
 242 
     | 
    
         
            +
                      s.executeUpdate
         
     | 
| 
      
 243 
     | 
    
         
            +
                    # it is safer for CREATE and DROP statements not to use PreparedStatement
         
     | 
| 
      
 244 
     | 
    
         
            +
                    # as it does not allow creation of triggers with :NEW in their definition
         
     | 
| 
      
 245 
     | 
    
         
            +
                    when /\A\s*(CREATE|DROP)/i
         
     | 
| 
      
 246 
     | 
    
         
            +
                      s = @raw_connection.createStatement()
         
     | 
| 
      
 247 
     | 
    
         
            +
                      # this disables SQL92 syntax processing of {...} which can result in statement execution errors
         
     | 
| 
      
 248 
     | 
    
         
            +
                      # if sql contains {...} in strings or comments
         
     | 
| 
      
 249 
     | 
    
         
            +
                      s.setEscapeProcessing(false)
         
     | 
| 
      
 250 
     | 
    
         
            +
                      s.execute(sql)
         
     | 
| 
      
 251 
     | 
    
         
            +
                      true
         
     | 
| 
      
 252 
     | 
    
         
            +
                    else
         
     | 
| 
      
 253 
     | 
    
         
            +
                      s = @raw_connection.prepareStatement(sql)
         
     | 
| 
      
 254 
     | 
    
         
            +
                      s.execute
         
     | 
| 
      
 255 
     | 
    
         
            +
                      true
         
     | 
| 
      
 256 
     | 
    
         
            +
                    end
         
     | 
| 
      
 257 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 258 
     | 
    
         
            +
                    s.close rescue nil
         
     | 
| 
      
 259 
     | 
    
         
            +
                  end
         
     | 
| 
      
 260 
     | 
    
         
            +
             
     | 
| 
      
 261 
     | 
    
         
            +
                  def returning_clause(quoted_pk)
         
     | 
| 
      
 262 
     | 
    
         
            +
                    " RETURNING #{quoted_pk} INTO ?"
         
     | 
| 
      
 263 
     | 
    
         
            +
                  end
         
     | 
| 
      
 264 
     | 
    
         
            +
             
     | 
| 
      
 265 
     | 
    
         
            +
                  # execute sql with RETURNING ... INTO :insert_id
         
     | 
| 
      
 266 
     | 
    
         
            +
                  # and return :insert_id value
         
     | 
| 
      
 267 
     | 
    
         
            +
                  def exec_with_returning(sql)
         
     | 
| 
      
 268 
     | 
    
         
            +
                    with_retry do
         
     | 
| 
      
 269 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 270 
     | 
    
         
            +
                        # it will always be INSERT statement
         
     | 
| 
      
 271 
     | 
    
         
            +
             
     | 
| 
      
 272 
     | 
    
         
            +
                        # TODO: need to investigate why PreparedStatement is giving strange exception "Protocol violation"
         
     | 
| 
      
 273 
     | 
    
         
            +
                        # s = @raw_connection.prepareStatement(sql)
         
     | 
| 
      
 274 
     | 
    
         
            +
                        # s.registerReturnParameter(1, ::Java::oracle.jdbc.OracleTypes::NUMBER)
         
     | 
| 
      
 275 
     | 
    
         
            +
                        # count = s.executeUpdate
         
     | 
| 
      
 276 
     | 
    
         
            +
                        # if count > 0
         
     | 
| 
      
 277 
     | 
    
         
            +
                        #   rs = s.getReturnResultSet
         
     | 
| 
      
 278 
     | 
    
         
            +
                        #   if rs.next
         
     | 
| 
      
 279 
     | 
    
         
            +
                        #     # Assuming that primary key will not be larger as long max value
         
     | 
| 
      
 280 
     | 
    
         
            +
                        #     insert_id = rs.getLong(1)
         
     | 
| 
      
 281 
     | 
    
         
            +
                        #     rs.wasNull ? nil : insert_id
         
     | 
| 
      
 282 
     | 
    
         
            +
                        #   else
         
     | 
| 
      
 283 
     | 
    
         
            +
                        #     nil
         
     | 
| 
      
 284 
     | 
    
         
            +
                        #   end
         
     | 
| 
      
 285 
     | 
    
         
            +
                        # else
         
     | 
| 
      
 286 
     | 
    
         
            +
                        #   nil
         
     | 
| 
      
 287 
     | 
    
         
            +
                        # end
         
     | 
| 
      
 288 
     | 
    
         
            +
                        
         
     | 
| 
      
 289 
     | 
    
         
            +
                        # Workaround with CallableStatement
         
     | 
| 
      
 290 
     | 
    
         
            +
                        s = @raw_connection.prepareCall("BEGIN #{sql}; END;")
         
     | 
| 
      
 291 
     | 
    
         
            +
                        s.registerOutParameter(1, java.sql.Types::BIGINT)
         
     | 
| 
      
 292 
     | 
    
         
            +
                        s.execute
         
     | 
| 
      
 293 
     | 
    
         
            +
                        insert_id = s.getLong(1)
         
     | 
| 
      
 294 
     | 
    
         
            +
                        s.wasNull ? nil : insert_id
         
     | 
| 
      
 295 
     | 
    
         
            +
                      ensure
         
     | 
| 
      
 296 
     | 
    
         
            +
                        # rs.close rescue nil
         
     | 
| 
      
 297 
     | 
    
         
            +
                        s.close rescue nil
         
     | 
| 
      
 298 
     | 
    
         
            +
                      end
         
     | 
| 
      
 299 
     | 
    
         
            +
                    end
         
     | 
| 
      
 300 
     | 
    
         
            +
                  end
         
     | 
| 
      
 301 
     | 
    
         
            +
             
     | 
| 
      
 302 
     | 
    
         
            +
                  def prepare(sql)
         
     | 
| 
      
 303 
     | 
    
         
            +
                    Cursor.new(self, @raw_connection.prepareStatement(sql))
         
     | 
| 
      
 304 
     | 
    
         
            +
                  end
         
     | 
| 
      
 305 
     | 
    
         
            +
             
     | 
| 
      
 306 
     | 
    
         
            +
                  class Cursor
         
     | 
| 
      
 307 
     | 
    
         
            +
                    def initialize(connection, raw_statement)
         
     | 
| 
      
 308 
     | 
    
         
            +
                      @connection = connection
         
     | 
| 
      
 309 
     | 
    
         
            +
                      @raw_statement = raw_statement
         
     | 
| 
      
 310 
     | 
    
         
            +
                    end
         
     | 
| 
      
 311 
     | 
    
         
            +
             
     | 
| 
      
 312 
     | 
    
         
            +
                    def bind_param(position, value, col_type = nil)
         
     | 
| 
      
 313 
     | 
    
         
            +
                      java_value = ruby_to_java_value(value, col_type)
         
     | 
| 
      
 314 
     | 
    
         
            +
                      case value
         
     | 
| 
      
 315 
     | 
    
         
            +
                      when Integer
         
     | 
| 
      
 316 
     | 
    
         
            +
                        @raw_statement.setLong(position, java_value)
         
     | 
| 
      
 317 
     | 
    
         
            +
                      when Float
         
     | 
| 
      
 318 
     | 
    
         
            +
                        @raw_statement.setFloat(position, java_value)
         
     | 
| 
      
 319 
     | 
    
         
            +
                      when BigDecimal
         
     | 
| 
      
 320 
     | 
    
         
            +
                        @raw_statement.setBigDecimal(position, java_value)
         
     | 
| 
      
 321 
     | 
    
         
            +
                      when String
         
     | 
| 
      
 322 
     | 
    
         
            +
                        case col_type
         
     | 
| 
      
 323 
     | 
    
         
            +
                        when :text
         
     | 
| 
      
 324 
     | 
    
         
            +
                          @raw_statement.setClob(position, java_value)
         
     | 
| 
      
 325 
     | 
    
         
            +
                        when :binary
         
     | 
| 
      
 326 
     | 
    
         
            +
                          @raw_statement.setBlob(position, java_value)
         
     | 
| 
      
 327 
     | 
    
         
            +
                        when :raw
         
     | 
| 
      
 328 
     | 
    
         
            +
                          @raw_statement.setString(position, OracleEnhancedAdapter.encode_raw(java_value))
         
     | 
| 
      
 329 
     | 
    
         
            +
                        when :decimal
         
     | 
| 
      
 330 
     | 
    
         
            +
                          @raw_statement.setBigDecimal(position, java_value)
         
     | 
| 
      
 331 
     | 
    
         
            +
                        else
         
     | 
| 
      
 332 
     | 
    
         
            +
                          @raw_statement.setString(position, java_value)
         
     | 
| 
      
 333 
     | 
    
         
            +
                        end
         
     | 
| 
      
 334 
     | 
    
         
            +
                      when Date, DateTime
         
     | 
| 
      
 335 
     | 
    
         
            +
                        @raw_statement.setDATE(position, java_value)
         
     | 
| 
      
 336 
     | 
    
         
            +
                      when Time
         
     | 
| 
      
 337 
     | 
    
         
            +
                        @raw_statement.setTimestamp(position, java_value)
         
     | 
| 
      
 338 
     | 
    
         
            +
                      when NilClass
         
     | 
| 
      
 339 
     | 
    
         
            +
                        # TODO: currently nil is always bound as NULL with VARCHAR type.
         
     | 
| 
      
 340 
     | 
    
         
            +
                        # When nils will actually be used by ActiveRecord as bound parameters
         
     | 
| 
      
 341 
     | 
    
         
            +
                        # then need to pass actual column type.
         
     | 
| 
      
 342 
     | 
    
         
            +
                        @raw_statement.setNull(position, java.sql.Types::VARCHAR)
         
     | 
| 
      
 343 
     | 
    
         
            +
                      else
         
     | 
| 
      
 344 
     | 
    
         
            +
                        raise ArgumentError, "Don't know how to bind variable with type #{value.class}"
         
     | 
| 
      
 345 
     | 
    
         
            +
                      end
         
     | 
| 
      
 346 
     | 
    
         
            +
                    end
         
     | 
| 
      
 347 
     | 
    
         
            +
             
     | 
| 
      
 348 
     | 
    
         
            +
                    def bind_returning_param(position, bind_type)
         
     | 
| 
      
 349 
     | 
    
         
            +
                      @returning_positions ||= []
         
     | 
| 
      
 350 
     | 
    
         
            +
                      @returning_positions << position
         
     | 
| 
      
 351 
     | 
    
         
            +
                      if bind_type == Integer
         
     | 
| 
      
 352 
     | 
    
         
            +
                        @raw_statement.registerReturnParameter(position, java.sql.Types::BIGINT)
         
     | 
| 
      
 353 
     | 
    
         
            +
                      end
         
     | 
| 
      
 354 
     | 
    
         
            +
                    end
         
     | 
| 
      
 355 
     | 
    
         
            +
             
     | 
| 
      
 356 
     | 
    
         
            +
                    def exec
         
     | 
| 
      
 357 
     | 
    
         
            +
                      @raw_result_set = @raw_statement.executeQuery
         
     | 
| 
      
 358 
     | 
    
         
            +
                      true
         
     | 
| 
      
 359 
     | 
    
         
            +
                    end
         
     | 
| 
      
 360 
     | 
    
         
            +
             
     | 
| 
      
 361 
     | 
    
         
            +
                    def exec_update
         
     | 
| 
      
 362 
     | 
    
         
            +
                      @raw_statement.executeUpdate
         
     | 
| 
      
 363 
     | 
    
         
            +
                    end
         
     | 
| 
      
 364 
     | 
    
         
            +
             
     | 
| 
      
 365 
     | 
    
         
            +
                    def metadata
         
     | 
| 
      
 366 
     | 
    
         
            +
                      @metadata ||= @raw_result_set.getMetaData
         
     | 
| 
      
 367 
     | 
    
         
            +
                    end
         
     | 
| 
      
 368 
     | 
    
         
            +
             
     | 
| 
      
 369 
     | 
    
         
            +
                    def column_types
         
     | 
| 
      
 370 
     | 
    
         
            +
                      @column_types ||= (1..metadata.getColumnCount).map{|i| metadata.getColumnTypeName(i).to_sym}
         
     | 
| 
      
 371 
     | 
    
         
            +
                    end
         
     | 
| 
      
 372 
     | 
    
         
            +
             
     | 
| 
      
 373 
     | 
    
         
            +
                    def column_names
         
     | 
| 
      
 374 
     | 
    
         
            +
                      @column_names ||= (1..metadata.getColumnCount).map{|i| metadata.getColumnName(i)}
         
     | 
| 
      
 375 
     | 
    
         
            +
                    end
         
     | 
| 
      
 376 
     | 
    
         
            +
                    alias :get_col_names :column_names
         
     | 
| 
      
 377 
     | 
    
         
            +
             
     | 
| 
      
 378 
     | 
    
         
            +
                    def fetch(options={})
         
     | 
| 
      
 379 
     | 
    
         
            +
                      if @raw_result_set.next
         
     | 
| 
      
 380 
     | 
    
         
            +
                        get_lob_value = options[:get_lob_value]
         
     | 
| 
      
 381 
     | 
    
         
            +
                        row_values = []
         
     | 
| 
      
 382 
     | 
    
         
            +
                        column_types.each_with_index do |column_type, i|
         
     | 
| 
      
 383 
     | 
    
         
            +
                          row_values <<
         
     | 
| 
      
 384 
     | 
    
         
            +
                            @connection.get_ruby_value_from_result_set(@raw_result_set, i+1, column_type, get_lob_value)
         
     | 
| 
      
 385 
     | 
    
         
            +
                        end
         
     | 
| 
      
 386 
     | 
    
         
            +
                        row_values
         
     | 
| 
      
 387 
     | 
    
         
            +
                      else
         
     | 
| 
      
 388 
     | 
    
         
            +
                        @raw_result_set.close
         
     | 
| 
      
 389 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 390 
     | 
    
         
            +
                      end
         
     | 
| 
      
 391 
     | 
    
         
            +
                    end
         
     | 
| 
      
 392 
     | 
    
         
            +
             
     | 
| 
      
 393 
     | 
    
         
            +
                    def get_returning_param(position, type)
         
     | 
| 
      
 394 
     | 
    
         
            +
                      rs_position = @returning_positions.index(position) + 1
         
     | 
| 
      
 395 
     | 
    
         
            +
                      rs = @raw_statement.getReturnResultSet
         
     | 
| 
      
 396 
     | 
    
         
            +
                      if rs.next
         
     | 
| 
      
 397 
     | 
    
         
            +
                        # Assuming that primary key will not be larger as long max value
         
     | 
| 
      
 398 
     | 
    
         
            +
                        returning_id = rs.getLong(rs_position)
         
     | 
| 
      
 399 
     | 
    
         
            +
                        rs.wasNull ? nil : returning_id
         
     | 
| 
      
 400 
     | 
    
         
            +
                      else
         
     | 
| 
      
 401 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 402 
     | 
    
         
            +
                      end
         
     | 
| 
      
 403 
     | 
    
         
            +
                    end
         
     | 
| 
      
 404 
     | 
    
         
            +
             
     | 
| 
      
 405 
     | 
    
         
            +
                    def close
         
     | 
| 
      
 406 
     | 
    
         
            +
                      @raw_statement.close
         
     | 
| 
      
 407 
     | 
    
         
            +
                    end
         
     | 
| 
      
 408 
     | 
    
         
            +
             
     | 
| 
      
 409 
     | 
    
         
            +
                    private
         
     | 
| 
      
 410 
     | 
    
         
            +
             
     | 
| 
      
 411 
     | 
    
         
            +
                    def ruby_to_java_value(value, col_type = nil)
         
     | 
| 
      
 412 
     | 
    
         
            +
                      case value
         
     | 
| 
      
 413 
     | 
    
         
            +
                      when Fixnum, Float
         
     | 
| 
      
 414 
     | 
    
         
            +
                        value
         
     | 
| 
      
 415 
     | 
    
         
            +
                      when String
         
     | 
| 
      
 416 
     | 
    
         
            +
                        case col_type
         
     | 
| 
      
 417 
     | 
    
         
            +
                        when :text
         
     | 
| 
      
 418 
     | 
    
         
            +
                          clob = Java::OracleSql::CLOB.createTemporary(@connection.raw_connection, false, Java::OracleSql::CLOB::DURATION_SESSION)
         
     | 
| 
      
 419 
     | 
    
         
            +
                          clob.setString(1, value)
         
     | 
| 
      
 420 
     | 
    
         
            +
                          clob
         
     | 
| 
      
 421 
     | 
    
         
            +
                        when :binary
         
     | 
| 
      
 422 
     | 
    
         
            +
                          blob = Java::OracleSql::BLOB.createTemporary(@connection.raw_connection, false, Java::OracleSql::BLOB::DURATION_SESSION)
         
     | 
| 
      
 423 
     | 
    
         
            +
                          blob.setBytes(1, value.to_java_bytes)
         
     | 
| 
      
 424 
     | 
    
         
            +
                          blob
         
     | 
| 
      
 425 
     | 
    
         
            +
                        when :decimal
         
     | 
| 
      
 426 
     | 
    
         
            +
                          java.math.BigDecimal.new(value.to_s)
         
     | 
| 
      
 427 
     | 
    
         
            +
                        else
         
     | 
| 
      
 428 
     | 
    
         
            +
                          value
         
     | 
| 
      
 429 
     | 
    
         
            +
                        end
         
     | 
| 
      
 430 
     | 
    
         
            +
                      when BigDecimal
         
     | 
| 
      
 431 
     | 
    
         
            +
                        java.math.BigDecimal.new(value.to_s)
         
     | 
| 
      
 432 
     | 
    
         
            +
                      when Date, DateTime
         
     | 
| 
      
 433 
     | 
    
         
            +
                        Java::oracle.sql.DATE.new(value.strftime("%Y-%m-%d %H:%M:%S"))
         
     | 
| 
      
 434 
     | 
    
         
            +
                      when Time
         
     | 
| 
      
 435 
     | 
    
         
            +
                        Java::java.sql.Timestamp.new(value.year-1900, value.month-1, value.day, value.hour, value.min, value.sec, value.usec * 1000)
         
     | 
| 
      
 436 
     | 
    
         
            +
                      else
         
     | 
| 
      
 437 
     | 
    
         
            +
                        value
         
     | 
| 
      
 438 
     | 
    
         
            +
                      end
         
     | 
| 
      
 439 
     | 
    
         
            +
                    end
         
     | 
| 
      
 440 
     | 
    
         
            +
             
     | 
| 
      
 441 
     | 
    
         
            +
                  end
         
     | 
| 
      
 442 
     | 
    
         
            +
             
     | 
| 
      
 443 
     | 
    
         
            +
                  def select(sql, name = nil, return_column_names = false)
         
     | 
| 
      
 444 
     | 
    
         
            +
                    with_retry do
         
     | 
| 
      
 445 
     | 
    
         
            +
                      select_no_retry(sql, name, return_column_names)
         
     | 
| 
      
 446 
     | 
    
         
            +
                    end
         
     | 
| 
      
 447 
     | 
    
         
            +
                  end
         
     | 
| 
      
 448 
     | 
    
         
            +
             
     | 
| 
      
 449 
     | 
    
         
            +
                  def select_no_retry(sql, name = nil, return_column_names = false)
         
     | 
| 
      
 450 
     | 
    
         
            +
                    stmt = @raw_connection.prepareStatement(sql)
         
     | 
| 
      
 451 
     | 
    
         
            +
                    rset = stmt.executeQuery
         
     | 
| 
      
 452 
     | 
    
         
            +
             
     | 
| 
      
 453 
     | 
    
         
            +
                    # Reuse the same hash for all rows
         
     | 
| 
      
 454 
     | 
    
         
            +
                    column_hash = {}
         
     | 
| 
      
 455 
     | 
    
         
            +
             
     | 
| 
      
 456 
     | 
    
         
            +
                    metadata = rset.getMetaData
         
     | 
| 
      
 457 
     | 
    
         
            +
                    column_count = metadata.getColumnCount
         
     | 
| 
      
 458 
     | 
    
         
            +
             
     | 
| 
      
 459 
     | 
    
         
            +
                    cols_types_index = (1..column_count).map do |i|
         
     | 
| 
      
 460 
     | 
    
         
            +
                      col_name = oracle_downcase(metadata.getColumnName(i))
         
     | 
| 
      
 461 
     | 
    
         
            +
                      next if col_name == 'raw_rnum_'
         
     | 
| 
      
 462 
     | 
    
         
            +
                      column_hash[col_name] = nil
         
     | 
| 
      
 463 
     | 
    
         
            +
                      [col_name, metadata.getColumnTypeName(i).to_sym, i]
         
     | 
| 
      
 464 
     | 
    
         
            +
                    end
         
     | 
| 
      
 465 
     | 
    
         
            +
                    cols_types_index.delete(nil)
         
     | 
| 
      
 466 
     | 
    
         
            +
             
     | 
| 
      
 467 
     | 
    
         
            +
                    rows = []
         
     | 
| 
      
 468 
     | 
    
         
            +
                    get_lob_value = !(name == 'Writable Large Object')
         
     | 
| 
      
 469 
     | 
    
         
            +
             
     | 
| 
      
 470 
     | 
    
         
            +
                    while rset.next
         
     | 
| 
      
 471 
     | 
    
         
            +
                      hash = column_hash.dup
         
     | 
| 
      
 472 
     | 
    
         
            +
                      cols_types_index.each do |col, column_type, i|
         
     | 
| 
      
 473 
     | 
    
         
            +
                        hash[col] = get_ruby_value_from_result_set(rset, i, column_type, get_lob_value)
         
     | 
| 
      
 474 
     | 
    
         
            +
                      end
         
     | 
| 
      
 475 
     | 
    
         
            +
                      rows << hash
         
     | 
| 
      
 476 
     | 
    
         
            +
                    end
         
     | 
| 
      
 477 
     | 
    
         
            +
             
     | 
| 
      
 478 
     | 
    
         
            +
                    return_column_names ? [rows, cols_types_index.map(&:first)] : rows
         
     | 
| 
      
 479 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 480 
     | 
    
         
            +
                    rset.close rescue nil
         
     | 
| 
      
 481 
     | 
    
         
            +
                    stmt.close rescue nil
         
     | 
| 
      
 482 
     | 
    
         
            +
                  end
         
     | 
| 
      
 483 
     | 
    
         
            +
             
     | 
| 
      
 484 
     | 
    
         
            +
                  def write_lob(lob, value, is_binary = false)
         
     | 
| 
      
 485 
     | 
    
         
            +
                    if is_binary
         
     | 
| 
      
 486 
     | 
    
         
            +
                      lob.setBytes(1, value.to_java_bytes)
         
     | 
| 
      
 487 
     | 
    
         
            +
                    else
         
     | 
| 
      
 488 
     | 
    
         
            +
                      lob.setString(1,value)
         
     | 
| 
      
 489 
     | 
    
         
            +
                    end
         
     | 
| 
      
 490 
     | 
    
         
            +
                  end
         
     | 
| 
      
 491 
     | 
    
         
            +
             
     | 
| 
      
 492 
     | 
    
         
            +
                  # Return NativeException / java.sql.SQLException error code
         
     | 
| 
      
 493 
     | 
    
         
            +
                  def error_code(exception)
         
     | 
| 
      
 494 
     | 
    
         
            +
                    case exception
         
     | 
| 
      
 495 
     | 
    
         
            +
                    when NativeException
         
     | 
| 
      
 496 
     | 
    
         
            +
                      exception.cause.getErrorCode
         
     | 
| 
      
 497 
     | 
    
         
            +
                    else
         
     | 
| 
      
 498 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 499 
     | 
    
         
            +
                    end
         
     | 
| 
      
 500 
     | 
    
         
            +
                  end
         
     | 
| 
      
 501 
     | 
    
         
            +
             
     | 
| 
      
 502 
     | 
    
         
            +
                  def get_ruby_value_from_result_set(rset, i, type_name, get_lob_value = true)
         
     | 
| 
      
 503 
     | 
    
         
            +
                    case type_name
         
     | 
| 
      
 504 
     | 
    
         
            +
                    when :NUMBER
         
     | 
| 
      
 505 
     | 
    
         
            +
                      d = rset.getNUMBER(i)
         
     | 
| 
      
 506 
     | 
    
         
            +
                      if d.nil?
         
     | 
| 
      
 507 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 508 
     | 
    
         
            +
                      elsif d.isInt
         
     | 
| 
      
 509 
     | 
    
         
            +
                        Integer(d.stringValue)
         
     | 
| 
      
 510 
     | 
    
         
            +
                      else
         
     | 
| 
      
 511 
     | 
    
         
            +
                        BigDecimal.new(d.stringValue)
         
     | 
| 
      
 512 
     | 
    
         
            +
                      end
         
     | 
| 
      
 513 
     | 
    
         
            +
                    when :VARCHAR2, :CHAR, :LONG, :NVARCHAR2, :NCHAR
         
     | 
| 
      
 514 
     | 
    
         
            +
                      rset.getString(i)
         
     | 
| 
      
 515 
     | 
    
         
            +
                    when :DATE
         
     | 
| 
      
 516 
     | 
    
         
            +
                      if dt = rset.getDATE(i)
         
     | 
| 
      
 517 
     | 
    
         
            +
                        d = dt.dateValue
         
     | 
| 
      
 518 
     | 
    
         
            +
                        t = dt.timeValue
         
     | 
| 
      
 519 
     | 
    
         
            +
                        if OracleEnhancedAdapter.emulate_dates && t.hours == 0 && t.minutes == 0 && t.seconds == 0
         
     | 
| 
      
 520 
     | 
    
         
            +
                          Date.new(d.year + 1900, d.month + 1, d.date)
         
     | 
| 
      
 521 
     | 
    
         
            +
                        else
         
     | 
| 
      
 522 
     | 
    
         
            +
                          Time.send(Base.default_timezone, d.year + 1900, d.month + 1, d.date, t.hours, t.minutes, t.seconds)
         
     | 
| 
      
 523 
     | 
    
         
            +
                        end
         
     | 
| 
      
 524 
     | 
    
         
            +
                      else
         
     | 
| 
      
 525 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 526 
     | 
    
         
            +
                      end
         
     | 
| 
      
 527 
     | 
    
         
            +
                    when :TIMESTAMP, :TIMESTAMPTZ, :TIMESTAMPLTZ, :"TIMESTAMP WITH TIME ZONE", :"TIMESTAMP WITH LOCAL TIME ZONE"
         
     | 
| 
      
 528 
     | 
    
         
            +
                      ts = rset.getTimestamp(i)
         
     | 
| 
      
 529 
     | 
    
         
            +
                      ts && Time.send(Base.default_timezone, ts.year + 1900, ts.month + 1, ts.date, ts.hours, ts.minutes, ts.seconds,
         
     | 
| 
      
 530 
     | 
    
         
            +
                        ts.nanos / 1000)
         
     | 
| 
      
 531 
     | 
    
         
            +
                    when :CLOB
         
     | 
| 
      
 532 
     | 
    
         
            +
                      get_lob_value ? lob_to_ruby_value(rset.getClob(i)) : rset.getClob(i)
         
     | 
| 
      
 533 
     | 
    
         
            +
                    when :BLOB
         
     | 
| 
      
 534 
     | 
    
         
            +
                      get_lob_value ? lob_to_ruby_value(rset.getBlob(i)) : rset.getBlob(i)
         
     | 
| 
      
 535 
     | 
    
         
            +
                    when :RAW
         
     | 
| 
      
 536 
     | 
    
         
            +
                      raw_value = rset.getRAW(i)
         
     | 
| 
      
 537 
     | 
    
         
            +
                      raw_value && raw_value.getBytes.to_a.pack('C*')
         
     | 
| 
      
 538 
     | 
    
         
            +
                    else
         
     | 
| 
      
 539 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 540 
     | 
    
         
            +
                    end
         
     | 
| 
      
 541 
     | 
    
         
            +
                  end
         
     | 
| 
      
 542 
     | 
    
         
            +
             
     | 
| 
      
 543 
     | 
    
         
            +
                  private
         
     | 
| 
      
 544 
     | 
    
         
            +
             
     | 
| 
      
 545 
     | 
    
         
            +
                  def lob_to_ruby_value(val)
         
     | 
| 
      
 546 
     | 
    
         
            +
                    case val
         
     | 
| 
      
 547 
     | 
    
         
            +
                    when ::Java::OracleSql::CLOB
         
     | 
| 
      
 548 
     | 
    
         
            +
                      if val.isEmptyLob
         
     | 
| 
      
 549 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 550 
     | 
    
         
            +
                      else
         
     | 
| 
      
 551 
     | 
    
         
            +
                        val.getSubString(1, val.length)
         
     | 
| 
      
 552 
     | 
    
         
            +
                      end
         
     | 
| 
      
 553 
     | 
    
         
            +
                    when ::Java::OracleSql::BLOB
         
     | 
| 
      
 554 
     | 
    
         
            +
                      if val.isEmptyLob
         
     | 
| 
      
 555 
     | 
    
         
            +
                        nil
         
     | 
| 
      
 556 
     | 
    
         
            +
                      else
         
     | 
| 
      
 557 
     | 
    
         
            +
                        String.from_java_bytes(val.getBytes(1, val.length))
         
     | 
| 
      
 558 
     | 
    
         
            +
                      end
         
     | 
| 
      
 559 
     | 
    
         
            +
                    end
         
     | 
| 
      
 560 
     | 
    
         
            +
                  end
         
     | 
| 
      
 561 
     | 
    
         
            +
             
     | 
| 
      
 562 
     | 
    
         
            +
                end
         
     | 
| 
      
 563 
     | 
    
         
            +
             
     | 
| 
      
 564 
     | 
    
         
            +
              end
         
     | 
| 
      
 565 
     | 
    
         
            +
            end
         
     |