ruby-oci8 1.0.7-x86-mswin32-60 → 2.0.1-x86-mswin32-60

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.
Files changed (58) hide show
  1. data/ChangeLog +1289 -383
  2. data/Makefile +48 -12
  3. data/NEWS +5 -419
  4. data/README +56 -385
  5. data/VERSION +1 -1
  6. data/dist-files +27 -27
  7. data/lib/.document +2 -0
  8. data/lib/dbd/OCI8.rb +2 -17
  9. data/lib/oci8.rb +48 -1622
  10. data/lib/oci8.rb.in +48 -1622
  11. data/lib/oci8/.document +5 -0
  12. data/lib/oci8/compat.rb +108 -0
  13. data/lib/oci8/datetime.rb +491 -0
  14. data/lib/oci8/encoding-init.rb +40 -0
  15. data/lib/oci8/encoding.yml +537 -0
  16. data/lib/oci8/metadata.rb +2077 -0
  17. data/lib/oci8/object.rb +548 -0
  18. data/lib/oci8/oci8.rb +798 -0
  19. data/lib/oci8/oracle_version.rb +144 -0
  20. data/lib/oci8lib_18.so +0 -0
  21. data/lib/oci8lib_191.so +0 -0
  22. data/metaconfig +3 -3
  23. data/ruby-oci8.gemspec +24 -15
  24. data/setup.rb +4 -4
  25. data/test/config.rb +64 -84
  26. data/test/test_all.rb +14 -21
  27. data/test/test_array_dml.rb +333 -0
  28. data/test/test_bind_raw.rb +18 -25
  29. data/test/test_bind_time.rb +78 -91
  30. data/test/test_break.rb +37 -35
  31. data/test/test_clob.rb +33 -89
  32. data/test/test_connstr.rb +5 -4
  33. data/test/test_datetime.rb +469 -0
  34. data/test/test_dbi.rb +99 -60
  35. data/test/test_dbi_clob.rb +3 -8
  36. data/test/test_metadata.rb +65 -51
  37. data/test/test_oci8.rb +151 -55
  38. data/test/test_oracle_version.rb +70 -0
  39. data/test/test_oradate.rb +76 -83
  40. data/test/test_oranumber.rb +405 -71
  41. data/test/test_rowid.rb +6 -11
  42. metadata +21 -25
  43. data/ext/oci8/oci8lib.so +0 -0
  44. data/ruby-oci8.spec +0 -62
  45. data/support/README +0 -4
  46. data/support/runit/assert.rb +0 -281
  47. data/support/runit/cui/testrunner.rb +0 -101
  48. data/support/runit/error.rb +0 -4
  49. data/support/runit/method_mappable.rb +0 -20
  50. data/support/runit/robserver.rb +0 -25
  51. data/support/runit/setuppable.rb +0 -15
  52. data/support/runit/teardownable.rb +0 -16
  53. data/support/runit/testcase.rb +0 -113
  54. data/support/runit/testfailure.rb +0 -25
  55. data/support/runit/testresult.rb +0 -121
  56. data/support/runit/testsuite.rb +0 -43
  57. data/support/runit/version.rb +0 -3
  58. data/test/test_describe.rb +0 -137
@@ -0,0 +1,798 @@
1
+ # --*- ruby -*--
2
+ # This is based on yoshidam's oracle.rb.
3
+
4
+ require 'date'
5
+
6
+ # The database connection class.
7
+ class OCI8
8
+ # Executes the sql statement. The type of return value depends on
9
+ # the type of sql statement: select; insert, update and delete;
10
+ # create, alter and drop; and PL/SQL.
11
+ #
12
+ # When bindvars are specified, they are bound as bind variables
13
+ # before execution.
14
+ #
15
+ # == select statements without block
16
+ # It returns the instance of OCI8::Cursor.
17
+ #
18
+ # example:
19
+ # conn = OCI8.new('scott', 'tiger')
20
+ # cursor = conn.exec('SELECT * FROM emp')
21
+ # while r = cursor.fetch()
22
+ # puts r.join(',')
23
+ # end
24
+ # cursor.close
25
+ # conn.logoff
26
+ #
27
+ # == select statements with a block
28
+ # It acts as iterator and returns the processed row counts. Fetched
29
+ # data is passed to the block as array. NULL value becomes nil in ruby.
30
+ #
31
+ # example:
32
+ # conn = OCI8.new('scott', 'tiger')
33
+ # num_rows = conn.exec('SELECT * FROM emp') do |r|
34
+ # puts r.join(',')
35
+ # end
36
+ # puts num_rows.to_s + ' rows were processed.'
37
+ # conn.logoff
38
+ #
39
+ # == PL/SQL block (ruby-oci8 1.0)
40
+ # It returns the array of bind variables' values.
41
+ #
42
+ # example:
43
+ # conn = OCI8.new('scott', 'tiger')
44
+ # conn.exec("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;", 'ABCD', 123)
45
+ # # => ["0123", 123]
46
+ # conn.logoff
47
+ #
48
+ # Above example uses two bind variables which names are :str
49
+ # and :num. These initial values are "the string whose width
50
+ # is 4 and whose value is 'ABCD'" and "the number whose value is
51
+ # 123". This method returns the array of these bind variables,
52
+ # which may modified by PL/SQL statement. The order of array is
53
+ # same with that of bind variables.
54
+ #
55
+ # If a block is given, it is ignored.
56
+ #
57
+ # == PL/SQL block (ruby-oci8 2.0)
58
+ # It returns the number of processed rows.
59
+ #
60
+ # example:
61
+ # conn = OCI8.new('scott', 'tiger')
62
+ # conn.exec("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;", 'ABCD', 123)
63
+ # # => 1
64
+ # conn.logoff
65
+ #
66
+ # If a block is given, the bind variables' values are passed to the block after
67
+ # executed.
68
+ #
69
+ # conn = OCI8.new('scott', 'tiger')
70
+ # conn.exec("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;", 'ABCD', 123) do |str, num|
71
+ # puts str # => '0123'
72
+ # puts num # => 123
73
+ # end
74
+ # conn.logoff
75
+ #
76
+ # FYI, the following code do same on ruby-oci8 1.0 and ruby-oci8 2.0.
77
+ # conn.exec(sql, *bindvars) { |*outvars| outvars }
78
+ #
79
+ # == Other SQL statements
80
+ # It returns the number of processed rows.
81
+ #
82
+ # example:
83
+ # conn = OCI8.new('scott', 'tiger')
84
+ # num_rows = conn.exec('UPDATE emp SET sal = sal * 1.1')
85
+ # puts num_rows.to_s + ' rows were updated.'
86
+ # conn.logoff
87
+ #
88
+ # example:
89
+ # conn = OCI8.new('scott', 'tiger')
90
+ # conn.exec('CREATE TABLE test (col1 CHAR(6))') # => 0
91
+ # conn.logoff
92
+ #
93
+ def exec(sql, *bindvars)
94
+ begin
95
+ cursor = parse(sql)
96
+ ret = cursor.exec(*bindvars)
97
+ case cursor.type
98
+ when :select_stmt
99
+ if block_given?
100
+ cursor.fetch { |row| yield(row) } # for each row
101
+ ret = cursor.row_count()
102
+ else
103
+ ret = cursor
104
+ cursor = nil # unset cursor to skip cursor.close in ensure block
105
+ ret
106
+ end
107
+ when :begin_stmt, :declare_stmt # PL/SQL block
108
+ if block_given?
109
+ ary = []
110
+ cursor.keys.sort.each do |key|
111
+ ary << cursor[key]
112
+ end
113
+ yield(*ary)
114
+ else
115
+ ret
116
+ end
117
+ else
118
+ ret # number of rows processed
119
+ end
120
+ ensure
121
+ cursor.nil? || cursor.close
122
+ end
123
+ end # exec
124
+
125
+ def username
126
+ @username || begin
127
+ exec('select user from dual') do |row|
128
+ @username = row[0]
129
+ end
130
+ @username
131
+ end
132
+ end
133
+
134
+ def inspect
135
+ "#<OCI8:#{username}>"
136
+ end
137
+
138
+ # :call-seq:
139
+ # oracle_server_version -> oraver
140
+ #
141
+ # Returns an OCI8::OracleVersion of the Oracle server version.
142
+ #
143
+ # See also: OCI8.oracle_client_version
144
+ def oracle_server_version
145
+ unless defined? @oracle_server_version
146
+ if vernum = oracle_server_vernum
147
+ # If the Oracle client is Oracle 9i or upper,
148
+ # get the server version from the OCI function OCIServerRelease.
149
+ @oracle_server_version = OCI8::OracleVersion.new(vernum)
150
+ else
151
+ # Otherwise, get it from v$version.
152
+ self.exec('select banner from v$version') do |row|
153
+ if /^Oracle.*?(\d+\.\d+\.\d+\.\d+\.\d+)/ =~ row[0]
154
+ @oracle_server_version = OCI8::OracleVersion.new($1)
155
+ break
156
+ end
157
+ end
158
+ end
159
+ end
160
+ @oracle_server_version
161
+ end
162
+
163
+ module BindType
164
+ Mapping = {}
165
+
166
+ class Base
167
+ def self.create(con, val, param, max_array_size)
168
+ self.new(con, val, param, max_array_size)
169
+ end
170
+ end
171
+
172
+ # get/set Date
173
+ class Date < OCI8::BindType::OraDate
174
+ def set(val)
175
+ super(val && ::OraDate.new(val.year, val.mon, val.mday))
176
+ end
177
+ def get()
178
+ (val = super()) && val.to_date
179
+ end
180
+ end
181
+
182
+ # get/set Number (for OCI8::SQLT_NUM)
183
+ class Number
184
+ def self.create(con, val, param, max_array_size)
185
+ if param.is_a? OCI8::Metadata::Base
186
+ precision = param.precision
187
+ scale = param.scale
188
+ end
189
+ if scale == -127
190
+ if precision == 0
191
+ # NUMBER declared without its scale and precision. (Oracle 9.2.0.3 or above)
192
+ klass = OCI8::BindType::Mapping[:number_no_prec_setting]
193
+ else
194
+ # FLOAT or FLOAT(p)
195
+ klass = OCI8::BindType::Float
196
+ end
197
+ elsif scale == 0
198
+ if precision == 0
199
+ # NUMBER whose scale and precision is unknown
200
+ # or
201
+ # NUMBER declared without its scale and precision. (Oracle 9.2.0.2 or below)
202
+ klass = OCI8::BindType::Mapping[:number_unknown_prec]
203
+ else
204
+ # NUMBER(p, 0)
205
+ klass = OCI8::BindType::Integer
206
+ end
207
+ else
208
+ # NUMBER(p, s)
209
+ if precision < 15 # the precision of double.
210
+ klass = OCI8::BindType::Float
211
+ else
212
+ # use BigDecimal instead?
213
+ klass = OCI8::BindType::OraNumber
214
+ end
215
+ end
216
+ klass.new(con, val, nil, max_array_size)
217
+ end
218
+ end
219
+
220
+ class String
221
+ def self.create(con, val, param, max_array_size)
222
+ case param
223
+ when Hash
224
+ # 1333 = ceil(4000 (max size of char) / 3 (NLS ratio of UTF8))
225
+ length = 1333 # default length
226
+ if param[:length]
227
+ length = param[:length]
228
+ elsif val.respond_to? :to_str and val.to_str.size > length
229
+ length = val.to_str.size
230
+ end
231
+ when OCI8::Metadata::Base
232
+ case param.data_type
233
+ when :char, :varchar2
234
+ length = param.data_size
235
+ # character size may become large on character set conversion.
236
+ # The length of a Japanese half-width kana is one in Shift_JIS,
237
+ # two in EUC-JP, three in UTF-8.
238
+ length *= 3 unless param.char_used?
239
+ when :raw
240
+ # HEX needs twice space.
241
+ length = param.data_size * 2
242
+ else
243
+ length = 100
244
+ end
245
+ end
246
+ self.new(con, val, length, max_array_size)
247
+ end
248
+ end
249
+
250
+ class RAW
251
+ def self.create(con, val, param, max_array_size)
252
+ case param
253
+ when Hash
254
+ length = 400 # default length
255
+ if param[:length]
256
+ length = param[:length]
257
+ elsif val.respond_to? :to_str and val.to_str.size > length
258
+ length = val.to_str.size
259
+ end
260
+ when OCI8::Metadata::Base
261
+ length = param.data_size
262
+ end
263
+ self.new(con, val, length, max_array_size)
264
+ end
265
+ end
266
+
267
+ class Long < OCI8::BindType::String
268
+ def self.create(con, val, param, max_array_size)
269
+ self.new(con, val, con.long_read_len, max_array_size)
270
+ end
271
+ end
272
+
273
+ class LongRaw < OCI8::BindType::RAW
274
+ def self.create(con, val, param, max_array_size)
275
+ self.new(con, val, con.long_read_len, max_array_size)
276
+ end
277
+ end
278
+
279
+ class CLOB
280
+ def self.create(con, val, param, max_array_size)
281
+ if param.is_a? OCI8::Metadata::Base and param.charset_form == :nchar
282
+ OCI8::BindType::NCLOB.new(con, val, nil, max_array_size)
283
+ else
284
+ OCI8::BindType::CLOB.new(con, val, nil, max_array_size)
285
+ end
286
+ end
287
+ end
288
+ end # BindType
289
+
290
+ # The instance of this class corresponds to cursor in the term of
291
+ # Oracle, which corresponds to java.sql.Statement of JDBC and statement
292
+ # handle $sth of Perl/DBI.
293
+ #
294
+ # Don't create the instance by calling 'new' method. Please create it by
295
+ # calling OCI8#exec or OCI8#parse.
296
+ class Cursor
297
+
298
+ # explicitly indicate the date type of fetched value. run this
299
+ # method within parse and exec. pos starts from 1. lentgh is used
300
+ # when type is String.
301
+ #
302
+ # example:
303
+ # cursor = conn.parse("SELECT ename, hiredate FROM emp")
304
+ # cursor.define(1, String, 20) # fetch the first column as String.
305
+ # cursor.define(2, Time) # fetch the second column as Time.
306
+ # cursor.exec()
307
+ def define(pos, type, length = nil)
308
+ __define(pos, make_bind_object(:type => type, :length => length))
309
+ self
310
+ end # define
311
+
312
+ # Binds variables explicitly.
313
+ #
314
+ # When key is number, it binds by position, which starts from 1.
315
+ # When key is string, it binds by the name of placeholder.
316
+ #
317
+ # example:
318
+ # cursor = conn.parse("SELECT * FROM emp WHERE ename = :ename")
319
+ # cursor.bind_param(1, 'SMITH') # bind by position
320
+ # ...or...
321
+ # cursor.bind_param(':ename', 'SMITH') # bind by name
322
+ #
323
+ # To bind as number, Fixnum and Float are available, but Bignum is
324
+ # not supported. If its initial value is NULL, please set nil to
325
+ # +type+ and Fixnum or Float to +val+.
326
+ #
327
+ # example:
328
+ # cursor.bind_param(1, 1234) # bind as Fixnum, Initial value is 1234.
329
+ # cursor.bind_param(1, 1234.0) # bind as Float, Initial value is 1234.0.
330
+ # cursor.bind_param(1, nil, Fixnum) # bind as Fixnum, Initial value is NULL.
331
+ # cursor.bind_param(1, nil, Float) # bind as Float, Initial value is NULL.
332
+ #
333
+ # In case of binding a string, set the string itself to
334
+ # +val+. When the bind variable is used as output, set the
335
+ # string whose length is enough to store or set the length.
336
+ #
337
+ # example:
338
+ # cursor = conn.parse("BEGIN :out := :in || '_OUT'; END;")
339
+ # cursor.bind_param(':in', 'DATA') # bind as String with width 4.
340
+ # cursor.bind_param(':out', nil, String, 7) # bind as String with width 7.
341
+ # cursor.exec()
342
+ # p cursor[':out'] # => 'DATA_OU'
343
+ # # Though the length of :out is 8 bytes in PL/SQL block, it is
344
+ # # bound as 7 bytes. So result is cut off at 7 byte.
345
+ #
346
+ # In case of binding a string as RAW, set OCI::RAW to +type+.
347
+ #
348
+ # example:
349
+ # cursor = conn.parse("INSERT INTO raw_table(raw_column) VALUE (:1)")
350
+ # cursor.bind_param(1, 'RAW_STRING', OCI8::RAW)
351
+ # cursor.exec()
352
+ # cursor.close()
353
+ def bind_param(key, param, type = nil, length = nil)
354
+ case param
355
+ when Hash
356
+ when Class
357
+ param = {:value => nil, :type => param, :length => length}
358
+ else
359
+ param = {:value => param, :type => type, :length => length}
360
+ end
361
+ __bind(key, make_bind_object(param))
362
+ self
363
+ end # bind_param
364
+
365
+ # Executes the SQL statement assigned the cursor. The type of
366
+ # return value depends on the type of sql statement: select;
367
+ # insert, update and delete; create, alter, drop and PL/SQL.
368
+ #
369
+ # In case of select statement, it returns the number of the
370
+ # select-list.
371
+ #
372
+ # In case of insert, update or delete statement, it returns the
373
+ # number of processed rows.
374
+ #
375
+ # In case of create, alter, drop and PL/SQL statement, it returns
376
+ # true. In contrast with OCI8#exec, it returns true even
377
+ # though PL/SQL. Use OCI8::Cursor#[] explicitly to get bind
378
+ # variables.
379
+ def exec(*bindvars)
380
+ bind_params(*bindvars)
381
+ __execute(nil) # Pass a nil to specify the statement isn't an Array DML
382
+ case type
383
+ when :select_stmt
384
+ define_columns()
385
+ else
386
+ row_count
387
+ end
388
+ end # exec
389
+
390
+ # Set the maximum array size for bind_param_array
391
+ #
392
+ # All the binds will be clean from cursor if instance variable max_array_size is set before
393
+ #
394
+ # Instance variable actual_array_size holds the size of the arrays users actually binds through bind_param_array
395
+ # all the binding arrays are required to be the same size
396
+ def max_array_size=(size)
397
+ raise "expect positive number for max_array_size." if size.nil? && size <=0
398
+ __clearBinds if !@max_array_size.nil?
399
+ @max_array_size = size
400
+ @actual_array_size = nil
401
+ end # max_array_size=
402
+
403
+ # Bind array explicitly
404
+ #
405
+ # When key is number, it binds by position, which starts from 1.
406
+ # When key is string, it binds by the name of placeholder.
407
+ #
408
+ # The max_array_size should be set before calling bind_param_array
409
+ #
410
+ # example:
411
+ # cursor = conn.parse("INSERT INTO test_table VALUES (:str)")
412
+ # cursor.max_array_size = 3
413
+ # cursor.bind_param_array(1, ['happy', 'new', 'year'], String, 30)
414
+ # cursor.exec_array
415
+ def bind_param_array(key, var_array, type = nil, max_item_length = nil)
416
+ raise "please call max_array_size= first." if @max_array_size.nil?
417
+ raise "expect array as input param for bind_param_array." if !var_array.nil? && !(var_array.is_a? Array)
418
+ raise "the size of var_array should not be greater than max_array_size." if !var_array.nil? && var_array.size > @max_array_size
419
+
420
+ if var_array.nil?
421
+ raise "all binding arrays should be the same size." unless @actual_array_size.nil? || @actual_array_size == 0
422
+ @actual_array_size = 0
423
+ else
424
+ raise "all binding arrays should be the same size." unless @actual_array_size.nil? || var_array.size == @actual_array_size
425
+ @actual_array_size = var_array.size if @actual_array_size.nil?
426
+ end
427
+
428
+ param = {:value => var_array, :type => type, :length => max_item_length, :max_array_size => @max_array_size}
429
+ first_non_nil_elem = var_array.nil? ? nil : var_array.find{|x| x!= nil}
430
+
431
+ if type.nil?
432
+ if first_non_nil_elem.nil?
433
+ raise "bind type is not given."
434
+ else
435
+ type = first_non_nil_elem.class
436
+ end
437
+ end
438
+
439
+ bindclass = OCI8::BindType::Mapping[type]
440
+ raise "unsupported dataType: #{type}" if bindclass.nil?
441
+ bindobj = bindclass.create(@con, var_array, param, @max_array_size)
442
+ __bind(key, bindobj)
443
+ self
444
+ end # bind_param_array
445
+
446
+ # Executes the SQL statement assigned the cursor with array binding
447
+ def exec_array
448
+ raise "please call max_array_size= first." if @max_array_size.nil?
449
+
450
+ if !@actual_array_size.nil? && @actual_array_size > 0
451
+ __execute(@actual_array_size)
452
+ else
453
+ raise "please set non-nil values to array binding parameters"
454
+ end
455
+
456
+ case type
457
+ when :update_stmt, :delete_stmt, :insert_stmt
458
+ row_count
459
+ else
460
+ true
461
+ end
462
+ end # exec_array
463
+
464
+ # Gets the names of select-list as array. Please use this
465
+ # method after exec.
466
+ def get_col_names
467
+ @names ||= @column_metadata.collect { |md| md.name }
468
+ end # get_col_names
469
+
470
+ # call-seq:
471
+ # column_metadata -> column information
472
+ #
473
+ # (new in 1.0.0 and 2.0)
474
+ #
475
+ # Gets an array of OCI8::Metadata::Column of a select statement.
476
+ #
477
+ # example:
478
+ # cursor = conn.exec('select * from tab')
479
+ # puts ' Name Type'
480
+ # puts ' ----------------------------------------- ----------------------------'
481
+ # cursor.column_metadata.each do |colinfo|
482
+ # puts format(' %-41s %s',
483
+ # colinfo.name,
484
+ # colinfo.type_string)
485
+ # end
486
+ def column_metadata
487
+ @column_metadata
488
+ end
489
+
490
+ # call-seq:
491
+ # fetch_hash
492
+ #
493
+ # get fetched data as a Hash. The hash keys are column names.
494
+ # If a block is given, acts as an iterator.
495
+ def fetch_hash
496
+ if iterator?
497
+ while ret = fetch_a_hash_row()
498
+ yield(ret)
499
+ end
500
+ else
501
+ fetch_a_hash_row
502
+ end
503
+ end # fetch_hash
504
+
505
+ # close the cursor.
506
+ def close
507
+ free()
508
+ @names = nil
509
+ @column_metadata = nil
510
+ end # close
511
+
512
+ private
513
+
514
+ def make_bind_object(param)
515
+ case param
516
+ when Hash
517
+ key = param[:type]
518
+ val = param[:value]
519
+ max_array_size = param[:max_array_size]
520
+
521
+ if key.nil?
522
+ if val.nil?
523
+ raise "bind type is not given."
524
+ elsif val.is_a? OCI8::Object::Base
525
+ key = :named_type
526
+ param = @con.get_tdo_by_class(val.class)
527
+ else
528
+ key = val.class
529
+ end
530
+ elsif key.class == Class && key < OCI8::Object::Base
531
+ param = @con.get_tdo_by_class(key)
532
+ key = :named_type
533
+ end
534
+ when OCI8::Metadata::Base
535
+ key = param.data_type
536
+ case key
537
+ when :named_type
538
+ if param.type_name == 'XMLTYPE'
539
+ key = :xmltype
540
+ else
541
+ param = @con.get_tdo_by_metadata(param.type_metadata)
542
+ end
543
+ end
544
+ else
545
+ raise "unknown param #{param.intern}"
546
+ end
547
+
548
+ bindclass = OCI8::BindType::Mapping[key]
549
+ raise "unsupported datatype: #{key}" if bindclass.nil?
550
+ bindclass.create(@con, val, param, max_array_size)
551
+ end
552
+
553
+ def define_columns
554
+ num_cols = __param_count
555
+ 1.upto(num_cols) do |i|
556
+ parm = __paramGet(i)
557
+ define_one_column(i, parm) unless __defined?(i)
558
+ @column_metadata[i - 1] = parm
559
+ end
560
+ num_cols
561
+ end # define_columns
562
+
563
+ def define_one_column(pos, param)
564
+ __define(pos, make_bind_object(param))
565
+ end # define_one_column
566
+
567
+ def bind_params(*bindvars)
568
+ bindvars.each_with_index do |val, i|
569
+ if val.is_a? Array
570
+ bind_param(i + 1, val[0], val[1], val[2])
571
+ else
572
+ bind_param(i + 1, val)
573
+ end
574
+ end
575
+ end # bind_params
576
+
577
+ def fetch_a_hash_row
578
+ if rs = fetch()
579
+ ret = {}
580
+ get_col_names.each do |name|
581
+ ret[name] = rs.shift
582
+ end
583
+ ret
584
+ else
585
+ nil
586
+ end
587
+ end # fetch_a_hash_row
588
+
589
+ end # OCI8::Cursor
590
+ end # OCI8
591
+
592
+ class OraDate
593
+ def to_time
594
+ begin
595
+ Time.local(year, month, day, hour, minute, second)
596
+ rescue ArgumentError
597
+ msg = format("out of range of Time (expect between 1970-01-01 00:00:00 UTC and 2037-12-31 23:59:59, but %04d-%02d-%02d %02d:%02d:%02d %s)", year, month, day, hour, minute, second, Time.at(0).zone)
598
+ raise RangeError.new(msg)
599
+ end
600
+ end
601
+
602
+ def to_date
603
+ Date.new(year, month, day)
604
+ end
605
+
606
+ if defined? DateTime # ruby 1.8.0 or upper
607
+
608
+ # get timezone offset.
609
+ @@tz_offset = Time.now.utc_offset.to_r/86400
610
+
611
+ def to_datetime
612
+ DateTime.new(year, month, day, hour, minute, second, @@tz_offset)
613
+ end
614
+ end
615
+
616
+ def yaml_initialize(type, val) # :nodoc:
617
+ initialize(*val.split(/[ -\/:]+/).collect do |i| i.to_i end)
618
+ end
619
+
620
+ def to_yaml(opts = {}) # :nodoc:
621
+ YAML.quick_emit(object_id, opts) do |out|
622
+ out.scalar(taguri, self.to_s, :plain)
623
+ end
624
+ end
625
+
626
+ def to_json(options=nil) # :nodoc:
627
+ to_datetime.to_json(options)
628
+ end
629
+ end
630
+
631
+ class OraNumber
632
+ def yaml_initialize(type, val) # :nodoc:
633
+ initialize(val)
634
+ end
635
+
636
+ def to_yaml(opts = {}) # :nodoc:
637
+ YAML.quick_emit(object_id, opts) do |out|
638
+ out.scalar(taguri, self.to_s, :plain)
639
+ end
640
+ end
641
+
642
+ def to_json(options=nil) # :nodoc:
643
+ to_s
644
+ end
645
+ end
646
+
647
+ class Numeric
648
+ def to_onum
649
+ OraNumber.new(self)
650
+ end
651
+ end
652
+
653
+ class String
654
+ def to_onum(format = nil, nls_params = nil)
655
+ OraNumber.new(self, format, nls_params)
656
+ end
657
+ end
658
+
659
+ # bind or explicitly define
660
+ OCI8::BindType::Mapping[String] = OCI8::BindType::String
661
+ OCI8::BindType::Mapping[OraNumber] = OCI8::BindType::OraNumber
662
+ OCI8::BindType::Mapping[Fixnum] = OCI8::BindType::Integer
663
+ OCI8::BindType::Mapping[Float] = OCI8::BindType::Float
664
+ OCI8::BindType::Mapping[Integer] = OCI8::BindType::Integer
665
+ OCI8::BindType::Mapping[Bignum] = OCI8::BindType::Integer
666
+ OCI8::BindType::Mapping[OraDate] = OCI8::BindType::OraDate
667
+ OCI8::BindType::Mapping[Time] = OCI8::BindType::Time
668
+ OCI8::BindType::Mapping[Date] = OCI8::BindType::Date
669
+ OCI8::BindType::Mapping[DateTime] = OCI8::BindType::DateTime
670
+ OCI8::BindType::Mapping[OCI8::CLOB] = OCI8::BindType::CLOB
671
+ OCI8::BindType::Mapping[OCI8::NCLOB] = OCI8::BindType::NCLOB
672
+ OCI8::BindType::Mapping[OCI8::BLOB] = OCI8::BindType::BLOB
673
+ OCI8::BindType::Mapping[OCI8::BFILE] = OCI8::BindType::BFILE
674
+ OCI8::BindType::Mapping[OCI8::Cursor] = OCI8::BindType::Cursor
675
+
676
+ # implicitly define
677
+
678
+ # datatype type size prec scale
679
+ # -------------------------------------------------
680
+ # CHAR(1) SQLT_AFC 1 0 0
681
+ # CHAR(10) SQLT_AFC 10 0 0
682
+ OCI8::BindType::Mapping[:char] = OCI8::BindType::String
683
+
684
+ # datatype type size prec scale
685
+ # -------------------------------------------------
686
+ # VARCHAR(1) SQLT_CHR 1 0 0
687
+ # VARCHAR(10) SQLT_CHR 10 0 0
688
+ # VARCHAR2(1) SQLT_CHR 1 0 0
689
+ # VARCHAR2(10) SQLT_CHR 10 0 0
690
+ OCI8::BindType::Mapping[:varchar2] = OCI8::BindType::String
691
+
692
+ # datatype type size prec scale
693
+ # -------------------------------------------------
694
+ # RAW(1) SQLT_BIN 1 0 0
695
+ # RAW(10) SQLT_BIN 10 0 0
696
+ OCI8::BindType::Mapping[:raw] = OCI8::BindType::RAW
697
+
698
+ # datatype type size prec scale
699
+ # -------------------------------------------------
700
+ # LONG SQLT_LNG 0 0 0
701
+ OCI8::BindType::Mapping[:long] = OCI8::BindType::Long
702
+
703
+ # datatype type size prec scale
704
+ # -------------------------------------------------
705
+ # LONG RAW SQLT_LBI 0 0 0
706
+ OCI8::BindType::Mapping[:long_raw] = OCI8::BindType::LongRaw
707
+
708
+ # datatype type size prec scale
709
+ # -------------------------------------------------
710
+ # CLOB SQLT_CLOB 4000 0 0
711
+ OCI8::BindType::Mapping[:clob] = OCI8::BindType::CLOB
712
+ OCI8::BindType::Mapping[:nclob] = OCI8::BindType::NCLOB
713
+
714
+ # datatype type size prec scale
715
+ # -------------------------------------------------
716
+ # BLOB SQLT_BLOB 4000 0 0
717
+ OCI8::BindType::Mapping[:blob] = OCI8::BindType::BLOB
718
+
719
+ # datatype type size prec scale
720
+ # -------------------------------------------------
721
+ # BFILE SQLT_BFILE 4000 0 0
722
+ OCI8::BindType::Mapping[:bfile] = OCI8::BindType::BFILE
723
+
724
+ # datatype type size prec scale
725
+ # -------------------------------------------------
726
+ # DATE SQLT_DAT 7 0 0
727
+ OCI8::BindType::Mapping[:date] = OCI8::BindType::Time
728
+
729
+ if OCI8.oracle_client_version >= OCI8::ORAVER_9_0
730
+ OCI8::BindType::Mapping[:timestamp] = OCI8::BindType::Time
731
+ OCI8::BindType::Mapping[:timestamp_tz] = OCI8::BindType::Time
732
+ OCI8::BindType::Mapping[:timestamp_ltz] = OCI8::BindType::Time
733
+ OCI8::BindType::Mapping[:interval_ym] = OCI8::BindType::IntervalYM
734
+ OCI8::BindType::Mapping[:interval_ds] = OCI8::BindType::IntervalDS
735
+ end
736
+
737
+ # datatype type size prec scale
738
+ # -------------------------------------------------
739
+ # ROWID SQLT_RDD 4 0 0
740
+ OCI8::BindType::Mapping[:rowid] = OCI8::BindType::String
741
+
742
+ # datatype type size prec scale
743
+ # -----------------------------------------------------
744
+ # FLOAT SQLT_NUM 22 126 -127
745
+ # FLOAT(1) SQLT_NUM 22 1 -127
746
+ # FLOAT(126) SQLT_NUM 22 126 -127
747
+ # DOUBLE PRECISION SQLT_NUM 22 126 -127
748
+ # REAL SQLT_NUM 22 63 -127
749
+ # NUMBER SQLT_NUM 22 0 0
750
+ # NUMBER(1) SQLT_NUM 22 1 0
751
+ # NUMBER(38) SQLT_NUM 22 38 0
752
+ # NUMBER(1, 0) SQLT_NUM 22 1 0
753
+ # NUMBER(38, 0) SQLT_NUM 22 38 0
754
+ # NUMERIC SQLT_NUM 22 38 0
755
+ # INT SQLT_NUM 22 38 0
756
+ # INTEGER SQLT_NUM 22 38 0
757
+ # SMALLINT SQLT_NUM 22 38 0
758
+ OCI8::BindType::Mapping[:number] = OCI8::BindType::Number
759
+
760
+ # mapping for calculated number values.
761
+ #
762
+ # for example:
763
+ # select col1 * 1.1 from tab1;
764
+ #
765
+ # For Oracle 9.2.0.2 or below, this is also used for NUMBER
766
+ # datatypes that have no explicit setting of their precision
767
+ # and scale.
768
+ #
769
+ # The default mapping is Float for ruby-oci8 1.0. It is OraNumber
770
+ # for ruby-oci8 2.0.
771
+ OCI8::BindType::Mapping[:number_unknown_prec] = OCI8::BindType::OraNumber
772
+
773
+ # mapping for number without precision and scale.
774
+ #
775
+ # for example:
776
+ # create table tab1 (col1 number);
777
+ # select col1 from tab1;
778
+ #
779
+ # note: This is available only on Oracle 9.2.0.3 or above.
780
+ # see: Oracle 9.2.0.x Patch Set Notes.
781
+ #
782
+ # The default mapping is Float for ruby-oci8 1.0. It is OraNumber
783
+ # for ruby-oci8 2.0.
784
+ OCI8::BindType::Mapping[:number_no_prec_setting] = OCI8::BindType::OraNumber
785
+
786
+ if defined? OCI8::BindType::BinaryDouble
787
+ OCI8::BindType::Mapping[:binary_float] = OCI8::BindType::BinaryDouble
788
+ OCI8::BindType::Mapping[:binary_double] = OCI8::BindType::BinaryDouble
789
+ else
790
+ OCI8::BindType::Mapping[:binary_float] = OCI8::BindType::Float
791
+ OCI8::BindType::Mapping[:binary_double] = OCI8::BindType::Float
792
+ end
793
+
794
+ # Cursor
795
+ OCI8::BindType::Mapping[:cursor] = OCI8::BindType::Cursor
796
+
797
+ # XMLType (This mapping will be changed before release.)
798
+ OCI8::BindType::Mapping[:xmltype] = OCI8::BindType::Long