ctreatma-activerecord-oracle_enhanced-adapter 1.4.1.1

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