Class: ActiveRecord::ConnectionAdapters::OracleEnhancedJDBCConnection
- Inherits:
-
OracleEnhancedConnection
- Object
- OracleEnhancedConnection
- ActiveRecord::ConnectionAdapters::OracleEnhancedJDBCConnection
- Defined in:
- lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb
Overview
JDBC database interface for JRuby
Instance Attribute Summary collapse
-
#active ⇒ Object
(also: #active?)
:nodoc:.
-
#auto_retry ⇒ Object
(also: #auto_retry?)
Returns the value of attribute auto_retry.
Attributes inherited from OracleEnhancedConnection
Instance Method Summary collapse
- #autocommit=(value) ⇒ Object
- #autocommit? ⇒ Boolean
- #commit ⇒ Object
-
#error_code(exception) ⇒ Object
Return NativeException / java.sql.SQLException error code.
- #exec(sql) ⇒ Object
- #exec_no_retry(sql) ⇒ Object
-
#exec_with_returning(sql) ⇒ Object
execute sql with RETURNING …
-
#initialize(config) ⇒ OracleEnhancedJDBCConnection
constructor
A new instance of OracleEnhancedJDBCConnection.
- #logoff ⇒ Object
-
#new_connection(config) ⇒ Object
modified method to support JNDI connections.
-
#ping ⇒ Object
Checks connection, returns true if active.
-
#reset! ⇒ Object
Resets connection, by logging off and creating a new connection.
- #returning_clause(quoted_pk) ⇒ Object
- #rollback ⇒ Object
- #select(sql, name = nil, return_column_names = false) ⇒ Object
- #select_no_retry(sql, name = nil, return_column_names = false) ⇒ Object
-
#with_retry(&block) ⇒ Object
mark connection as dead if connection lost.
- #write_lob(lob, value, is_binary = false) ⇒ Object
Methods inherited from OracleEnhancedConnection
create, #describe, #oracle_downcase
Constructor Details
#initialize(config) ⇒ OracleEnhancedJDBCConnection
Returns a new instance of OracleEnhancedJDBCConnection.
43 44 45 46 47 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 43 def initialize(config) @active = true @config = config new_connection(@config) end |
Instance Attribute Details
#active ⇒ Object Also known as: active?
:nodoc:
36 37 38 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 36 def active @active end |
#auto_retry ⇒ Object Also known as: auto_retry?
Returns the value of attribute auto_retry.
39 40 41 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 39 def auto_retry @auto_retry end |
Instance Method Details
#autocommit=(value) ⇒ Object
145 146 147 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 145 def autocommit=(value) @raw_connection.setAutoCommit(value) end |
#autocommit? ⇒ Boolean
141 142 143 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 141 def autocommit? @raw_connection.getAutoCommit end |
#commit ⇒ Object
133 134 135 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 133 def commit @raw_connection.commit end |
#error_code(exception) ⇒ Object
Return NativeException / java.sql.SQLException error code
312 313 314 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 312 def error_code(exception) exception.cause.getErrorCode end |
#exec(sql) ⇒ Object
195 196 197 198 199 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 195 def exec(sql) with_retry do exec_no_retry(sql) end end |
#exec_no_retry(sql) ⇒ Object
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 201 def exec_no_retry(sql) case sql when /\A\s*(UPDATE|INSERT|DELETE)/i s = @raw_connection.prepareStatement(sql) s.executeUpdate # it is safer for CREATE and DROP statements not to use PreparedStatement # as it does not allow creation of triggers with :NEW in their definition when /\A\s*(CREATE|DROP)/i s = @raw_connection.createStatement() s.execute(sql) true else s = @raw_connection.prepareStatement(sql) s.execute true end ensure s.close rescue nil end |
#exec_with_returning(sql) ⇒ Object
execute sql with RETURNING … INTO :insert_id and return :insert_id value
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 227 def exec_with_returning(sql) with_retry do begin # it will always be INSERT statement # TODO: need to investigate why PreparedStatement is giving strange exception "Protocol violation" # s = @raw_connection.prepareStatement(sql) # s.registerReturnParameter(1, ::Java::oracle.jdbc.OracleTypes::NUMBER) # count = s.executeUpdate # if count > 0 # rs = s.getReturnResultSet # if rs.next # # Assuming that primary key will not be larger as long max value # insert_id = rs.getLong(1) # rs.wasNull ? nil : insert_id # else # nil # end # else # nil # end # Workaround with CallableStatement s = @raw_connection.prepareCall("BEGIN #{sql}; END;") s.registerOutParameter(1, java.sql.Types::BIGINT) s.execute insert_id = s.getLong(1) s.wasNull ? nil : insert_id ensure # rs.close rescue nil s.close rescue nil end end end |
#logoff ⇒ Object
125 126 127 128 129 130 131 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 125 def logoff @active = false @raw_connection.close true rescue false end |
#new_connection(config) ⇒ Object
modified method to support JNDI connections
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 50 def new_connection(config) username = nil if config[:jndi] jndi = config[:jndi].to_s ctx = javax.naming.InitialContext.new ds = nil # tomcat needs first lookup method, oc4j (and maybe other application servers) need second method begin env = ctx.lookup('java:/comp/env') ds = env.lookup(jndi) rescue ds = ctx.lookup(jndi) end # check if datasource supports pooled connections, otherwise use default if ds.respond_to?(:pooled_connection) @raw_connection = ds.pooled_connection else @raw_connection = ds.connection end config[:driver] ||= @raw_connection..connection.java_class.name username = @raw_connection..user_name else username = config[:username].to_s password, database = config[:password].to_s, config[:database].to_s privilege = config[:privilege] && config[:privilege].to_s host, port = config[:host], config[:port] # connection using TNS alias if database && !host && !config[:url] && ENV['TNS_ADMIN'] url = "jdbc:oracle:thin:@#{database || 'XE'}" else url = config[:url] || "jdbc:oracle:thin:@#{host || 'localhost'}:#{port || 1521}:#{database || 'XE'}" end prefetch_rows = config[:prefetch_rows] || 100 # get session time_zone from configuration or from TZ environment variable time_zone = config[:time_zone] || ENV['TZ'] || java.util.TimeZone.default.getID properties = java.util.Properties.new properties.put("user", username) properties.put("password", password) properties.put("defaultRowPrefetch", "#{prefetch_rows}") if prefetch_rows properties.put("internal_logon", privilege) if privilege @raw_connection = java.sql.DriverManager.getConnection(url, properties) # Set session time zone to current time zone @raw_connection.setSessionTimeZone(time_zone) # Set default number of rows to prefetch # @raw_connection.setDefaultRowPrefetch(prefetch_rows) if prefetch_rows end # by default VARCHAR2 column size will be interpreted as max number of characters (and not bytes) nls_length_semantics = config[:nls_length_semantics] || 'CHAR' cursor_sharing = config[:cursor_sharing] || 'force' # from here it remaings common for both connections types exec %q{alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'} exec %q{alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS:FF6'} exec "alter session set cursor_sharing = #{cursor_sharing}" exec "alter session set nls_length_semantics = '#{nls_length_semantics}'" self.autocommit = true # default schema owner @owner = username.upcase unless username.nil? @raw_connection end |
#ping ⇒ Object
Checks connection, returns true if active. Note that ping actively checks the connection, while #active? simply returns the last known state.
152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 152 def ping exec_no_retry("select 1 from dual") @active = true rescue NativeException => e @active = false if e. =~ /^java\.sql\.SQLException/ raise OracleEnhancedConnectionException, e. else raise end end |
#reset! ⇒ Object
Resets connection, by logging off and creating a new connection.
165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 165 def reset! logoff rescue nil begin new_connection(@config) @active = true rescue NativeException => e @active = false if e. =~ /^java\.sql\.SQLException/ raise OracleEnhancedConnectionException, e. else raise end end end |
#returning_clause(quoted_pk) ⇒ Object
221 222 223 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 221 def returning_clause(quoted_pk) " RETURNING #{quoted_pk} INTO ?" end |
#rollback ⇒ Object
137 138 139 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 137 def rollback @raw_connection.rollback end |
#select(sql, name = nil, return_column_names = false) ⇒ Object
262 263 264 265 266 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 262 def select(sql, name = nil, return_column_names = false) with_retry do select_no_retry(sql, name, return_column_names) end end |
#select_no_retry(sql, name = nil, return_column_names = false) ⇒ Object
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 268 def select_no_retry(sql, name = nil, return_column_names = false) stmt = @raw_connection.prepareStatement(sql) rset = stmt.executeQuery # Reuse the same hash for all rows column_hash = {} = rset.getMetaData column_count = .getColumnCount cols_types_index = (1..column_count).map do |i| col_name = oracle_downcase(.getColumnName(i)) next if col_name == 'raw_rnum_' column_hash[col_name] = nil [col_name, .getColumnTypeName(i).to_sym, i] end cols_types_index.delete(nil) rows = [] get_lob_value = !(name == 'Writable Large Object') while rset.next hash = column_hash.dup cols_types_index.each do |col, column_type, i| hash[col] = get_ruby_value_from_result_set(rset, i, column_type, get_lob_value) end rows << hash end return_column_names ? [rows, cols_types_index.map(&:first)] : rows ensure rset.close rescue nil stmt.close rescue nil end |
#with_retry(&block) ⇒ Object
mark connection as dead if connection lost
181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 181 def with_retry(&block) should_retry = auto_retry? && autocommit? begin yield if block_given? rescue NativeException => e raise unless e. =~ /^java\.sql\.SQLException: (Closed Connection|Io exception:|No more data to read from socket)/ @active = false raise unless should_retry should_retry = false reset! rescue nil retry end end |
#write_lob(lob, value, is_binary = false) ⇒ Object
303 304 305 306 307 308 309 |
# File 'lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb', line 303 def write_lob(lob, value, is_binary = false) if is_binary lob.setBytes(1, value.to_java_bytes) else lob.setString(1,value) end end |