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

Sign up to get free protection for your applications and to get access to all the features.
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