ruby-oci8 2.0.4-x86-mingw32

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