ruby-oci8 2.0.4-x86-mingw32

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 (52) hide show
  1. data/ChangeLog +1912 -0
  2. data/Makefile +96 -0
  3. data/NEWS +223 -0
  4. data/README +86 -0
  5. data/VERSION +1 -0
  6. data/dist-files +77 -0
  7. data/doc/api.en.html +527 -0
  8. data/doc/api.en.rd +554 -0
  9. data/doc/api.ja.html +525 -0
  10. data/doc/api.ja.rd +557 -0
  11. data/doc/manual.css +35 -0
  12. data/lib/.document +1 -0
  13. data/lib/dbd/OCI8.rb +591 -0
  14. data/lib/oci8.rb +82 -0
  15. data/lib/oci8.rb.in +82 -0
  16. data/lib/oci8/.document +5 -0
  17. data/lib/oci8/bindtype.rb +319 -0
  18. data/lib/oci8/compat.rb +113 -0
  19. data/lib/oci8/datetime.rb +619 -0
  20. data/lib/oci8/encoding-init.rb +40 -0
  21. data/lib/oci8/encoding.yml +537 -0
  22. data/lib/oci8/metadata.rb +2077 -0
  23. data/lib/oci8/object.rb +562 -0
  24. data/lib/oci8/oci8.rb +571 -0
  25. data/lib/oci8/oracle_version.rb +144 -0
  26. data/lib/oci8lib_18.so +0 -0
  27. data/lib/oci8lib_191.so +0 -0
  28. data/metaconfig +142 -0
  29. data/pre-distclean.rb +7 -0
  30. data/ruby-oci8.gemspec +63 -0
  31. data/setup.rb +1331 -0
  32. data/test/README +4 -0
  33. data/test/config.rb +109 -0
  34. data/test/test_all.rb +50 -0
  35. data/test/test_appinfo.rb +63 -0
  36. data/test/test_array_dml.rb +333 -0
  37. data/test/test_bind_raw.rb +46 -0
  38. data/test/test_bind_time.rb +178 -0
  39. data/test/test_break.rb +83 -0
  40. data/test/test_clob.rb +79 -0
  41. data/test/test_connstr.rb +81 -0
  42. data/test/test_datetime.rb +622 -0
  43. data/test/test_dbi.rb +366 -0
  44. data/test/test_dbi_clob.rb +53 -0
  45. data/test/test_encoding.rb +100 -0
  46. data/test/test_metadata.rb +257 -0
  47. data/test/test_oci8.rb +434 -0
  48. data/test/test_oracle_version.rb +70 -0
  49. data/test/test_oradate.rb +256 -0
  50. data/test/test_oranumber.rb +655 -0
  51. data/test/test_rowid.rb +33 -0
  52. metadata +108 -0
@@ -0,0 +1,571 @@
1
+ # oci8.rb -- implements OCI8 and OCI8::Cursor
2
+ #
3
+ # Copyright (C) 2002-2009 KUBO Takehiro <kubo@jiubao.org>
4
+ #
5
+ # Original Copyright is:
6
+ # Oracle module for Ruby
7
+ # 1998-2000 by yoshidam
8
+ #
9
+
10
+ require 'date'
11
+
12
+ # A connection to a Oracle database server.
13
+ #
14
+ # example:
15
+ # # output the emp table's content as CSV format.
16
+ # conn = OCI8.new(username, password)
17
+ # conn.exec('select * from emp') do |row|
18
+ # puts row.join(',')
19
+ # end
20
+ #
21
+ # # execute PL/SQL block with bind variables.
22
+ # conn = OCI8.new(username, password)
23
+ # conn.exec('BEGIN procedure_name(:1, :2); END;',
24
+ # value_for_the_first_parameter,
25
+ # value_for_the_second_parameter)
26
+ class OCI8
27
+ # Executes the sql statement. The type of return value depends on
28
+ # the type of sql statement: select; insert, update and delete;
29
+ # create, alter and drop; and PL/SQL.
30
+ #
31
+ # When bindvars are specified, they are bound as bind variables
32
+ # before execution.
33
+ #
34
+ # == select statements without block
35
+ # It returns the instance of OCI8::Cursor.
36
+ #
37
+ # example:
38
+ # conn = OCI8.new('scott', 'tiger')
39
+ # cursor = conn.exec('SELECT * FROM emp')
40
+ # while r = cursor.fetch()
41
+ # puts r.join(',')
42
+ # end
43
+ # cursor.close
44
+ # conn.logoff
45
+ #
46
+ # == select statements with a block
47
+ # It acts as iterator and returns the processed row counts. Fetched
48
+ # data is passed to the block as array. NULL value becomes nil in ruby.
49
+ #
50
+ # example:
51
+ # conn = OCI8.new('scott', 'tiger')
52
+ # num_rows = conn.exec('SELECT * FROM emp') do |r|
53
+ # puts r.join(',')
54
+ # end
55
+ # puts num_rows.to_s + ' rows were processed.'
56
+ # conn.logoff
57
+ #
58
+ # == PL/SQL block (ruby-oci8 1.0)
59
+ # It returns the array of bind variables' values.
60
+ #
61
+ # example:
62
+ # conn = OCI8.new('scott', 'tiger')
63
+ # conn.exec("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;", 'ABCD', 123)
64
+ # # => ["0123", 123]
65
+ # conn.logoff
66
+ #
67
+ # Above example uses two bind variables which names are :str
68
+ # and :num. These initial values are "the string whose width
69
+ # is 4 and whose value is 'ABCD'" and "the number whose value is
70
+ # 123". This method returns the array of these bind variables,
71
+ # which may modified by PL/SQL statement. The order of array is
72
+ # same with that of bind variables.
73
+ #
74
+ # If a block is given, it is ignored.
75
+ #
76
+ # == PL/SQL block (ruby-oci8 2.0)
77
+ # It returns the number of processed rows.
78
+ #
79
+ # example:
80
+ # conn = OCI8.new('scott', 'tiger')
81
+ # conn.exec("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;", 'ABCD', 123)
82
+ # # => 1
83
+ # conn.logoff
84
+ #
85
+ # If a block is given, the bind variables' values are passed to the block after
86
+ # executed.
87
+ #
88
+ # conn = OCI8.new('scott', 'tiger')
89
+ # conn.exec("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;", 'ABCD', 123) do |str, num|
90
+ # puts str # => '0123'
91
+ # puts num # => 123
92
+ # end
93
+ # conn.logoff
94
+ #
95
+ # FYI, the following code do same on ruby-oci8 1.0 and ruby-oci8 2.0.
96
+ # conn.exec(sql, *bindvars) { |*outvars| outvars }
97
+ #
98
+ # == Other SQL statements
99
+ # It returns the number of processed rows.
100
+ #
101
+ # example:
102
+ # conn = OCI8.new('scott', 'tiger')
103
+ # num_rows = conn.exec('UPDATE emp SET sal = sal * 1.1')
104
+ # puts num_rows.to_s + ' rows were updated.'
105
+ # conn.logoff
106
+ #
107
+ # example:
108
+ # conn = OCI8.new('scott', 'tiger')
109
+ # conn.exec('CREATE TABLE test (col1 CHAR(6))') # => 0
110
+ # conn.logoff
111
+ #
112
+ def exec(sql, *bindvars)
113
+ begin
114
+ cursor = parse(sql)
115
+ ret = cursor.exec(*bindvars)
116
+ case cursor.type
117
+ when :select_stmt
118
+ if block_given?
119
+ cursor.fetch { |row| yield(row) } # for each row
120
+ ret = cursor.row_count()
121
+ else
122
+ ret = cursor
123
+ cursor = nil # unset cursor to skip cursor.close in ensure block
124
+ ret
125
+ end
126
+ when :begin_stmt, :declare_stmt # PL/SQL block
127
+ if block_given?
128
+ ary = []
129
+ cursor.keys.sort.each do |key|
130
+ ary << cursor[key]
131
+ end
132
+ yield(*ary)
133
+ else
134
+ ret
135
+ end
136
+ else
137
+ ret # number of rows processed
138
+ end
139
+ ensure
140
+ cursor.nil? || cursor.close
141
+ end
142
+ end # exec
143
+
144
+ # :call-seq:
145
+ # select_one(sql, *bindvars) -> first_one_row
146
+ #
147
+ def select_one(sql, *bindvars)
148
+ cursor = self.parse(sql)
149
+ begin
150
+ cursor.exec(*bindvars)
151
+ row = cursor.fetch
152
+ ensure
153
+ cursor.close
154
+ end
155
+ return row
156
+ end
157
+
158
+ def username
159
+ @username || begin
160
+ exec('select user from dual') do |row|
161
+ @username = row[0]
162
+ end
163
+ @username
164
+ end
165
+ end
166
+
167
+ def inspect
168
+ "#<OCI8:#{username}>"
169
+ end
170
+
171
+ # :call-seq:
172
+ # oracle_server_version -> oraver
173
+ #
174
+ # Returns an OCI8::OracleVersion of the Oracle server version.
175
+ #
176
+ # See also: OCI8.oracle_client_version
177
+ def oracle_server_version
178
+ unless defined? @oracle_server_version
179
+ if vernum = oracle_server_vernum
180
+ # If the Oracle client is Oracle 9i or upper,
181
+ # get the server version from the OCI function OCIServerRelease.
182
+ @oracle_server_version = OCI8::OracleVersion.new(vernum)
183
+ else
184
+ # Otherwise, get it from v$version.
185
+ self.exec('select banner from v$version') do |row|
186
+ if /^Oracle.*?(\d+\.\d+\.\d+\.\d+\.\d+)/ =~ row[0]
187
+ @oracle_server_version = OCI8::OracleVersion.new($1)
188
+ break
189
+ end
190
+ end
191
+ end
192
+ end
193
+ @oracle_server_version
194
+ end
195
+
196
+ # The instance of this class corresponds to cursor in the term of
197
+ # Oracle, which corresponds to java.sql.Statement of JDBC and statement
198
+ # handle $sth of Perl/DBI.
199
+ #
200
+ # Don't create the instance by calling 'new' method. Please create it by
201
+ # calling OCI8#exec or OCI8#parse.
202
+ class Cursor
203
+
204
+ # explicitly indicate the date type of fetched value. run this
205
+ # method within parse and exec. pos starts from 1. lentgh is used
206
+ # when type is String.
207
+ #
208
+ # example:
209
+ # cursor = conn.parse("SELECT ename, hiredate FROM emp")
210
+ # cursor.define(1, String, 20) # fetch the first column as String.
211
+ # cursor.define(2, Time) # fetch the second column as Time.
212
+ # cursor.exec()
213
+ def define(pos, type, length = nil)
214
+ __define(pos, make_bind_object(:type => type, :length => length))
215
+ self
216
+ end # define
217
+
218
+ # Binds variables explicitly.
219
+ #
220
+ # When key is number, it binds by position, which starts from 1.
221
+ # When key is string, it binds by the name of placeholder.
222
+ #
223
+ # example:
224
+ # cursor = conn.parse("SELECT * FROM emp WHERE ename = :ename")
225
+ # cursor.bind_param(1, 'SMITH') # bind by position
226
+ # ...or...
227
+ # cursor.bind_param(':ename', 'SMITH') # bind by name
228
+ #
229
+ # To bind as number, Fixnum and Float are available, but Bignum is
230
+ # not supported. If its initial value is NULL, please set nil to
231
+ # +type+ and Fixnum or Float to +val+.
232
+ #
233
+ # example:
234
+ # cursor.bind_param(1, 1234) # bind as Fixnum, Initial value is 1234.
235
+ # cursor.bind_param(1, 1234.0) # bind as Float, Initial value is 1234.0.
236
+ # cursor.bind_param(1, nil, Fixnum) # bind as Fixnum, Initial value is NULL.
237
+ # cursor.bind_param(1, nil, Float) # bind as Float, Initial value is NULL.
238
+ #
239
+ # In case of binding a string, set the string itself to
240
+ # +val+. When the bind variable is used as output, set the
241
+ # string whose length is enough to store or set the length.
242
+ #
243
+ # example:
244
+ # cursor = conn.parse("BEGIN :out := :in || '_OUT'; END;")
245
+ # cursor.bind_param(':in', 'DATA') # bind as String with width 4.
246
+ # cursor.bind_param(':out', nil, String, 7) # bind as String with width 7.
247
+ # cursor.exec()
248
+ # p cursor[':out'] # => 'DATA_OU'
249
+ # # Though the length of :out is 8 bytes in PL/SQL block, it is
250
+ # # bound as 7 bytes. So result is cut off at 7 byte.
251
+ #
252
+ # In case of binding a string as RAW, set OCI::RAW to +type+.
253
+ #
254
+ # example:
255
+ # cursor = conn.parse("INSERT INTO raw_table(raw_column) VALUE (:1)")
256
+ # cursor.bind_param(1, 'RAW_STRING', OCI8::RAW)
257
+ # cursor.exec()
258
+ # cursor.close()
259
+ def bind_param(key, param, type = nil, length = nil)
260
+ case param
261
+ when Hash
262
+ when Class
263
+ param = {:value => nil, :type => param, :length => length}
264
+ else
265
+ param = {:value => param, :type => type, :length => length}
266
+ end
267
+ __bind(key, make_bind_object(param))
268
+ self
269
+ end # bind_param
270
+
271
+ # Executes the SQL statement assigned the cursor. The type of
272
+ # return value depends on the type of sql statement: select;
273
+ # insert, update and delete; create, alter, drop and PL/SQL.
274
+ #
275
+ # In case of select statement, it returns the number of the
276
+ # select-list.
277
+ #
278
+ # In case of insert, update or delete statement, it returns the
279
+ # number of processed rows.
280
+ #
281
+ # In case of create, alter, drop and PL/SQL statement, it returns
282
+ # true. In contrast with OCI8#exec, it returns true even
283
+ # though PL/SQL. Use OCI8::Cursor#[] explicitly to get bind
284
+ # variables.
285
+ def exec(*bindvars)
286
+ bind_params(*bindvars)
287
+ __execute(nil) # Pass a nil to specify the statement isn't an Array DML
288
+ case type
289
+ when :select_stmt
290
+ define_columns()
291
+ else
292
+ row_count
293
+ end
294
+ end # exec
295
+
296
+ # Set the maximum array size for bind_param_array
297
+ #
298
+ # All the binds will be clean from cursor if instance variable max_array_size is set before
299
+ #
300
+ # Instance variable actual_array_size holds the size of the arrays users actually binds through bind_param_array
301
+ # all the binding arrays are required to be the same size
302
+ def max_array_size=(size)
303
+ raise "expect positive number for max_array_size." if size.nil? && size <=0
304
+ __clearBinds if !@max_array_size.nil?
305
+ @max_array_size = size
306
+ @actual_array_size = nil
307
+ end # max_array_size=
308
+
309
+ # Bind array explicitly
310
+ #
311
+ # When key is number, it binds by position, which starts from 1.
312
+ # When key is string, it binds by the name of placeholder.
313
+ #
314
+ # The max_array_size should be set before calling bind_param_array
315
+ #
316
+ # example:
317
+ # cursor = conn.parse("INSERT INTO test_table VALUES (:str)")
318
+ # cursor.max_array_size = 3
319
+ # cursor.bind_param_array(1, ['happy', 'new', 'year'], String, 30)
320
+ # cursor.exec_array
321
+ def bind_param_array(key, var_array, type = nil, max_item_length = nil)
322
+ raise "please call max_array_size= first." if @max_array_size.nil?
323
+ raise "expect array as input param for bind_param_array." if !var_array.nil? && !(var_array.is_a? Array)
324
+ raise "the size of var_array should not be greater than max_array_size." if !var_array.nil? && var_array.size > @max_array_size
325
+
326
+ if var_array.nil?
327
+ raise "all binding arrays should be the same size." unless @actual_array_size.nil? || @actual_array_size == 0
328
+ @actual_array_size = 0
329
+ else
330
+ raise "all binding arrays should be the same size." unless @actual_array_size.nil? || var_array.size == @actual_array_size
331
+ @actual_array_size = var_array.size if @actual_array_size.nil?
332
+ end
333
+
334
+ param = {:value => var_array, :type => type, :length => max_item_length, :max_array_size => @max_array_size}
335
+ first_non_nil_elem = var_array.nil? ? nil : var_array.find{|x| x!= nil}
336
+
337
+ if type.nil?
338
+ if first_non_nil_elem.nil?
339
+ raise "bind type is not given."
340
+ else
341
+ type = first_non_nil_elem.class
342
+ end
343
+ end
344
+
345
+ bindclass = OCI8::BindType::Mapping[type]
346
+ if bindclass.nil? and type.is_a? Class
347
+ bindclass = OCI8::BindType::Mapping[type.to_s]
348
+ OCI8::BindType::Mapping[type] = bindclass if bindclass
349
+ end
350
+ raise "unsupported dataType: #{type}" if bindclass.nil?
351
+ bindobj = bindclass.create(@con, var_array, param, @max_array_size)
352
+ __bind(key, bindobj)
353
+ self
354
+ end # bind_param_array
355
+
356
+ # Executes the SQL statement assigned the cursor with array binding
357
+ def exec_array
358
+ raise "please call max_array_size= first." if @max_array_size.nil?
359
+
360
+ if !@actual_array_size.nil? && @actual_array_size > 0
361
+ __execute(@actual_array_size)
362
+ else
363
+ raise "please set non-nil values to array binding parameters"
364
+ end
365
+
366
+ case type
367
+ when :update_stmt, :delete_stmt, :insert_stmt
368
+ row_count
369
+ else
370
+ true
371
+ end
372
+ end # exec_array
373
+
374
+ # Gets the names of select-list as array. Please use this
375
+ # method after exec.
376
+ def get_col_names
377
+ @names ||= @column_metadata.collect { |md| md.name }
378
+ end # get_col_names
379
+
380
+ # call-seq:
381
+ # column_metadata -> column information
382
+ #
383
+ # (new in 1.0.0 and 2.0)
384
+ #
385
+ # Gets an array of OCI8::Metadata::Column of a select statement.
386
+ #
387
+ # example:
388
+ # cursor = conn.exec('select * from tab')
389
+ # puts ' Name Type'
390
+ # puts ' ----------------------------------------- ----------------------------'
391
+ # cursor.column_metadata.each do |colinfo|
392
+ # puts format(' %-41s %s',
393
+ # colinfo.name,
394
+ # colinfo.type_string)
395
+ # end
396
+ def column_metadata
397
+ @column_metadata
398
+ end
399
+
400
+ # call-seq:
401
+ # fetch_hash
402
+ #
403
+ # get fetched data as a Hash. The hash keys are column names.
404
+ # If a block is given, acts as an iterator.
405
+ def fetch_hash
406
+ if iterator?
407
+ while ret = fetch_a_hash_row()
408
+ yield(ret)
409
+ end
410
+ else
411
+ fetch_a_hash_row
412
+ end
413
+ end # fetch_hash
414
+
415
+ # close the cursor.
416
+ def close
417
+ free()
418
+ @names = nil
419
+ @column_metadata = nil
420
+ end # close
421
+
422
+ private
423
+
424
+ def make_bind_object(param)
425
+ case param
426
+ when Hash
427
+ key = param[:type]
428
+ val = param[:value]
429
+ max_array_size = param[:max_array_size]
430
+
431
+ if key.nil?
432
+ if val.nil?
433
+ raise "bind type is not given."
434
+ elsif val.is_a? OCI8::Object::Base
435
+ key = :named_type
436
+ param = @con.get_tdo_by_class(val.class)
437
+ else
438
+ key = val.class
439
+ end
440
+ elsif key.class == Class && key < OCI8::Object::Base
441
+ param = @con.get_tdo_by_class(key)
442
+ key = :named_type
443
+ end
444
+ when OCI8::Metadata::Base
445
+ key = param.data_type
446
+ case key
447
+ when :named_type
448
+ if param.type_name == 'XMLTYPE'
449
+ key = :xmltype
450
+ else
451
+ param = @con.get_tdo_by_metadata(param.type_metadata)
452
+ end
453
+ end
454
+ else
455
+ raise "unknown param #{param.intern}"
456
+ end
457
+
458
+ bindclass = OCI8::BindType::Mapping[key]
459
+ if bindclass.nil? and key.is_a? Class
460
+ bindclass = OCI8::BindType::Mapping[key.to_s]
461
+ OCI8::BindType::Mapping[key] = bindclass if bindclass
462
+ end
463
+ raise "unsupported datatype: #{key}" if bindclass.nil?
464
+ bindclass.create(@con, val, param, max_array_size)
465
+ end
466
+
467
+ def define_columns
468
+ num_cols = __param_count
469
+ 1.upto(num_cols) do |i|
470
+ parm = __paramGet(i)
471
+ define_one_column(i, parm) unless __defined?(i)
472
+ @column_metadata[i - 1] = parm
473
+ end
474
+ num_cols
475
+ end # define_columns
476
+
477
+ def define_one_column(pos, param)
478
+ __define(pos, make_bind_object(param))
479
+ end # define_one_column
480
+
481
+ def bind_params(*bindvars)
482
+ bindvars.each_with_index do |val, i|
483
+ if val.is_a? Array
484
+ bind_param(i + 1, val[0], val[1], val[2])
485
+ else
486
+ bind_param(i + 1, val)
487
+ end
488
+ end
489
+ end # bind_params
490
+
491
+ def fetch_a_hash_row
492
+ if rs = fetch()
493
+ ret = {}
494
+ get_col_names.each do |name|
495
+ ret[name] = rs.shift
496
+ end
497
+ ret
498
+ else
499
+ nil
500
+ end
501
+ end # fetch_a_hash_row
502
+
503
+ end # OCI8::Cursor
504
+ end # OCI8
505
+
506
+ class OraDate
507
+ def to_time
508
+ begin
509
+ Time.local(year, month, day, hour, minute, second)
510
+ rescue ArgumentError
511
+ 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)
512
+ raise RangeError.new(msg)
513
+ end
514
+ end
515
+
516
+ def to_date
517
+ Date.new(year, month, day)
518
+ end
519
+
520
+ if defined? DateTime # ruby 1.8.0 or upper
521
+
522
+ # get timezone offset.
523
+ @@tz_offset = Time.now.utc_offset.to_r/86400
524
+
525
+ def to_datetime
526
+ DateTime.new(year, month, day, hour, minute, second, @@tz_offset)
527
+ end
528
+ end
529
+
530
+ def yaml_initialize(type, val) # :nodoc:
531
+ initialize(*val.split(/[ -\/:]+/).collect do |i| i.to_i end)
532
+ end
533
+
534
+ def to_yaml(opts = {}) # :nodoc:
535
+ YAML.quick_emit(object_id, opts) do |out|
536
+ out.scalar(taguri, self.to_s, :plain)
537
+ end
538
+ end
539
+
540
+ def to_json(options=nil) # :nodoc:
541
+ to_datetime.to_json(options)
542
+ end
543
+ end
544
+
545
+ class OraNumber
546
+ def yaml_initialize(type, val) # :nodoc:
547
+ initialize(val)
548
+ end
549
+
550
+ def to_yaml(opts = {}) # :nodoc:
551
+ YAML.quick_emit(object_id, opts) do |out|
552
+ out.scalar(taguri, self.to_s, :plain)
553
+ end
554
+ end
555
+
556
+ def to_json(options=nil) # :nodoc:
557
+ to_s
558
+ end
559
+ end
560
+
561
+ class Numeric
562
+ def to_onum
563
+ OraNumber.new(self)
564
+ end
565
+ end
566
+
567
+ class String
568
+ def to_onum(format = nil, nls_params = nil)
569
+ OraNumber.new(self, format, nls_params)
570
+ end
571
+ end