ruby-oci8 1.0.7 → 2.0.0

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