ruby-oci8 2.1.5.1-x64-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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +17 -0
  3. data/COPYING +30 -0
  4. data/COPYING_old +64 -0
  5. data/ChangeLog +2779 -0
  6. data/Makefile +92 -0
  7. data/NEWS +660 -0
  8. data/README.md +43 -0
  9. data/VERSION +1 -0
  10. data/dist-files +91 -0
  11. data/docs/install-binary-package.md +40 -0
  12. data/docs/install-full-client.md +116 -0
  13. data/docs/install-instant-client.md +167 -0
  14. data/docs/platform-specific-issues.md +197 -0
  15. data/docs/report-installation-issue.md +50 -0
  16. data/lib/.document +1 -0
  17. data/lib/dbd/OCI8.rb +591 -0
  18. data/lib/oci8.rb +147 -0
  19. data/lib/oci8.rb.in +147 -0
  20. data/lib/oci8/.document +8 -0
  21. data/lib/oci8/bindtype.rb +350 -0
  22. data/lib/oci8/compat.rb +113 -0
  23. data/lib/oci8/connection_pool.rb +108 -0
  24. data/lib/oci8/cursor.rb +564 -0
  25. data/lib/oci8/datetime.rb +605 -0
  26. data/lib/oci8/encoding-init.rb +79 -0
  27. data/lib/oci8/encoding.yml +537 -0
  28. data/lib/oci8/metadata.rb +2092 -0
  29. data/lib/oci8/object.rb +605 -0
  30. data/lib/oci8/oci8.rb +560 -0
  31. data/lib/oci8/ocihandle.rb +607 -0
  32. data/lib/oci8/oracle_version.rb +143 -0
  33. data/lib/oci8/properties.rb +134 -0
  34. data/lib/oci8lib_200.so +0 -0
  35. data/metaconfig +142 -0
  36. data/pre-distclean.rb +7 -0
  37. data/ruby-oci8.gemspec +80 -0
  38. data/setup.rb +1333 -0
  39. data/test/README +42 -0
  40. data/test/config.rb +184 -0
  41. data/test/setup_test_object.sql +171 -0
  42. data/test/test_all.rb +54 -0
  43. data/test/test_appinfo.rb +63 -0
  44. data/test/test_array_dml.rb +333 -0
  45. data/test/test_bind_raw.rb +46 -0
  46. data/test/test_bind_string.rb +106 -0
  47. data/test/test_bind_time.rb +178 -0
  48. data/test/test_break.rb +124 -0
  49. data/test/test_clob.rb +98 -0
  50. data/test/test_connection_pool.rb +125 -0
  51. data/test/test_connstr.rb +81 -0
  52. data/test/test_datetime.rb +581 -0
  53. data/test/test_dbi.rb +366 -0
  54. data/test/test_dbi_clob.rb +53 -0
  55. data/test/test_encoding.rb +104 -0
  56. data/test/test_error.rb +88 -0
  57. data/test/test_metadata.rb +1485 -0
  58. data/test/test_object.rb +462 -0
  59. data/test/test_oci8.rb +489 -0
  60. data/test/test_oracle_version.rb +70 -0
  61. data/test/test_oradate.rb +256 -0
  62. data/test/test_oranumber.rb +787 -0
  63. data/test/test_rowid.rb +33 -0
  64. metadata +109 -0
data/lib/oci8/oci8.rb ADDED
@@ -0,0 +1,560 @@
1
+ # oci8.rb -- OCI8
2
+ #
3
+ # Copyright (C) 2002-2013 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
+ require 'yaml'
12
+
13
+ # A connection to a Oracle database server.
14
+ #
15
+ # example:
16
+ # # output the emp table's content as CSV format.
17
+ # conn = OCI8.new(username, password)
18
+ # conn.exec('select * from emp') do |row|
19
+ # puts row.join(',')
20
+ # end
21
+ #
22
+ # # execute PL/SQL block with bind variables.
23
+ # conn = OCI8.new(username, password)
24
+ # conn.exec('BEGIN procedure_name(:1, :2); END;',
25
+ # value_for_the_first_parameter,
26
+ # value_for_the_second_parameter)
27
+ class OCI8
28
+
29
+ # @return [OCIError]
30
+ attr_accessor :last_error
31
+
32
+ # @overload initialize(username, password, dbname = nil, privilege = nil)
33
+ #
34
+ # Connects to an Oracle database server by +username+ and +password+
35
+ # at +dbname+ as +privilege+.
36
+ #
37
+ # === connecting to the local server
38
+ #
39
+ # Set +username+ and +password+ or pass "username/password" as a
40
+ # single argument.
41
+ #
42
+ # OCI8.new('scott', 'tiger')
43
+ # or
44
+ # OCI8.new('scott/tiger')
45
+ #
46
+ # === connecting to a remote server
47
+ #
48
+ # Set +username+, +password+ and +dbname+ or pass
49
+ # "username/password@dbname" as a single argument.
50
+ #
51
+ # OCI8.new('scott', 'tiger', 'orcl.world')
52
+ # or
53
+ # OCI8.new('scott/tiger@orcl.world')
54
+ #
55
+ # The +dbname+ is a net service name or an easy connectection
56
+ # identifier. The former is a name listed in the file tnsnames.ora.
57
+ # Ask to your DBA if you don't know what it is. The latter has the
58
+ # syntax as "//host:port/service_name".
59
+ #
60
+ # OCI8.new('scott', 'tiger', '//remote-host:1521/XE')
61
+ # or
62
+ # OCI8.new('scott/tiger@//remote-host:1521/XE')
63
+ #
64
+ # === connecting as a privileged user
65
+ #
66
+ # Set :SYSDBA or :SYSOPER to +privilege+, otherwise
67
+ # "username/password as sysdba" or "username/password as sysoper"
68
+ # as a single argument.
69
+ #
70
+ # OCI8.new('sys', 'change_on_install', nil, :SYSDBA)
71
+ # or
72
+ # OCI8.new('sys/change_on_install as sysdba')
73
+ #
74
+ # === external OS authentication
75
+ #
76
+ # Set nil to +username+ and +password+, or "/" as a single argument.
77
+ #
78
+ # OCI8.new(nil, nil)
79
+ # or
80
+ # OCI8.new('/')
81
+ #
82
+ # To connect to a remote host:
83
+ #
84
+ # OCI8.new(nil, nil, 'dbname')
85
+ # or
86
+ # OCI8.new('/@dbname')
87
+ #
88
+ # === proxy authentication
89
+ #
90
+ # Enclose end user's username with square brackets and add it at the
91
+ # end of proxy user's username.
92
+ #
93
+ # OCI8.new('proxy_user_name[end_user_name]', 'proxy_password')
94
+ # or
95
+ # OCI8.new('proxy_user_name[end_user_name]/proxy_password')
96
+ #
97
+ def initialize(*args)
98
+ if args.length == 1
99
+ username, password, dbname, mode = parse_connect_string(args[0])
100
+ else
101
+ username, password, dbname, mode = args
102
+ end
103
+
104
+ if username.nil? and password.nil?
105
+ cred = OCI_CRED_EXT
106
+ end
107
+ case mode
108
+ when :SYSDBA
109
+ mode = OCI_SYSDBA
110
+ when :SYSOPER
111
+ mode = OCI_SYSOPER
112
+ when :SYSASM
113
+ if OCI8.oracle_client_version < OCI8::ORAVER_11_1
114
+ raise "SYSASM is not supported on Oracle version #{OCI8.oracle_client_version}"
115
+ end
116
+ mode = OCI_SYSASM
117
+ when nil
118
+ # do nothing
119
+ else
120
+ raise "unknown privilege type #{mode}"
121
+ end
122
+
123
+ stmt_cache_size = OCI8.properties[:statement_cache_size]
124
+ stmt_cache_size = nil if stmt_cache_size == 0
125
+
126
+ attach_mode = 0
127
+ if dbname.is_a? OCI8::ConnectionPool
128
+ @pool = dbname # to prevent GC from freeing the connection pool.
129
+ dbname = dbname.send(:pool_name)
130
+ attach_mode |= 0x0200 # OCI_CPOOL and OCI_LOGON2_CPOOL
131
+ end
132
+ if stmt_cache_size
133
+ # enable statement caching
134
+ attach_mode |= 0x0004 # OCI_STMT_CACHE and OCI_LOGON2_STMTCACHE
135
+ end
136
+
137
+ if true
138
+ # logon by the OCI function OCISessionBegin().
139
+ allocate_handles()
140
+ @session_handle.send(:attr_set_string, OCI_ATTR_USERNAME, username) if username
141
+ @session_handle.send(:attr_set_string, OCI_ATTR_PASSWORD, password) if password
142
+ if @@oracle_client_version >= ORAVER_11_1
143
+ # 'rubyoci8' is displayed in V$SESSION_CONNECT_INFO.CLIENT_DRIVER
144
+ # if both the client and the server are Oracle 11g or upper.
145
+ # 424: OCI_ATTR_DRIVER_NAME
146
+ @session_handle.send(:attr_set_string, 424, 'rubyoci8')
147
+ end
148
+ server_attach(dbname, attach_mode)
149
+ session_begin(cred ? cred : OCI_CRED_RDBMS, mode ? mode : OCI_DEFAULT)
150
+ else
151
+ # logon by the OCI function OCILogon2().
152
+ logon2(username, password, dbname, attach_mode)
153
+ end
154
+
155
+ if stmt_cache_size
156
+ # set statement cache size
157
+ attr_set_ub4(176, stmt_cache_size) # 176: OCI_ATTR_STMTCACHESIZE
158
+ end
159
+
160
+ @prefetch_rows = nil
161
+ @username = nil
162
+ end
163
+
164
+ # Returns a prepared SQL handle.
165
+ #
166
+ # @param [String] sql SQL statement
167
+ # @return [OCI8::Cursor]
168
+ def parse(sql)
169
+ @last_error = nil
170
+ parse_internal(sql)
171
+ end
172
+
173
+ # same with OCI8#parse except that this doesn't reset OCI8#last_error.
174
+ #
175
+ # @private
176
+ def parse_internal(sql)
177
+ cursor = OCI8::Cursor.new(self, sql)
178
+ cursor.prefetch_rows = @prefetch_rows if @prefetch_rows
179
+ cursor
180
+ end
181
+
182
+ # Executes the sql statement. The type of return value depends on
183
+ # the type of sql statement: select; insert, update and delete;
184
+ # create, alter and drop; and PL/SQL.
185
+ #
186
+ # When bindvars are specified, they are bound as bind variables
187
+ # before execution.
188
+ #
189
+ # == select statements without block
190
+ # It returns the instance of OCI8::Cursor.
191
+ #
192
+ # example:
193
+ # conn = OCI8.new('scott', 'tiger')
194
+ # cursor = conn.exec('SELECT * FROM emp')
195
+ # while r = cursor.fetch()
196
+ # puts r.join(',')
197
+ # end
198
+ # cursor.close
199
+ # conn.logoff
200
+ #
201
+ # == select statements with a block
202
+ # It acts as iterator and returns the processed row counts. Fetched
203
+ # data is passed to the block as array. NULL value becomes nil in ruby.
204
+ #
205
+ # example:
206
+ # conn = OCI8.new('scott', 'tiger')
207
+ # num_rows = conn.exec('SELECT * FROM emp') do |r|
208
+ # puts r.join(',')
209
+ # end
210
+ # puts num_rows.to_s + ' rows were processed.'
211
+ # conn.logoff
212
+ #
213
+ # == PL/SQL block (ruby-oci8 1.0)
214
+ # It returns the array of bind variables' values.
215
+ #
216
+ # example:
217
+ # conn = OCI8.new('scott', 'tiger')
218
+ # conn.exec("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;", 'ABCD', 123)
219
+ # # => ["0123", 123]
220
+ # conn.logoff
221
+ #
222
+ # Above example uses two bind variables which names are :str
223
+ # and :num. These initial values are "the string whose width
224
+ # is 4 and whose value is 'ABCD'" and "the number whose value is
225
+ # 123". This method returns the array of these bind variables,
226
+ # which may modified by PL/SQL statement. The order of array is
227
+ # same with that of bind variables.
228
+ #
229
+ # If a block is given, it is ignored.
230
+ #
231
+ # == PL/SQL block (ruby-oci8 2.0)
232
+ # It returns the number of processed rows.
233
+ #
234
+ # example:
235
+ # conn = OCI8.new('scott', 'tiger')
236
+ # conn.exec("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;", 'ABCD', 123)
237
+ # # => 1
238
+ # conn.logoff
239
+ #
240
+ # If a block is given, the bind variables' values are passed to the block after
241
+ # executed.
242
+ #
243
+ # conn = OCI8.new('scott', 'tiger')
244
+ # conn.exec("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;", 'ABCD', 123) do |str, num|
245
+ # puts str # => '0123'
246
+ # puts num # => 123
247
+ # end
248
+ # conn.logoff
249
+ #
250
+ # FYI, the following code do same on ruby-oci8 1.0 and ruby-oci8 2.0.
251
+ # conn.exec(sql, *bindvars) { |*outvars| outvars }
252
+ #
253
+ # == Other SQL statements
254
+ # It returns the number of processed rows.
255
+ #
256
+ # example:
257
+ # conn = OCI8.new('scott', 'tiger')
258
+ # num_rows = conn.exec('UPDATE emp SET sal = sal * 1.1')
259
+ # puts num_rows.to_s + ' rows were updated.'
260
+ # conn.logoff
261
+ #
262
+ # example:
263
+ # conn = OCI8.new('scott', 'tiger')
264
+ # conn.exec('CREATE TABLE test (col1 CHAR(6))') # => 0
265
+ # conn.logoff
266
+ #
267
+ def exec(sql, *bindvars, &block)
268
+ @last_error = nil
269
+ exec_internal(sql, *bindvars, &block)
270
+ end
271
+
272
+ # same with OCI8#exec except that this doesn't reset OCI8#last_error.
273
+ #
274
+ # @private
275
+ def exec_internal(sql, *bindvars)
276
+ begin
277
+ cursor = parse(sql)
278
+ ret = cursor.exec(*bindvars)
279
+ case cursor.type
280
+ when :select_stmt
281
+ if block_given?
282
+ cursor.fetch { |row| yield(row) } # for each row
283
+ ret = cursor.row_count()
284
+ else
285
+ ret = cursor
286
+ cursor = nil # unset cursor to skip cursor.close in ensure block
287
+ ret
288
+ end
289
+ when :begin_stmt, :declare_stmt # PL/SQL block
290
+ if block_given?
291
+ ary = []
292
+ cursor.keys.sort.each do |key|
293
+ ary << cursor[key]
294
+ end
295
+ yield(*ary)
296
+ else
297
+ ret
298
+ end
299
+ else
300
+ ret # number of rows processed
301
+ end
302
+ ensure
303
+ cursor.nil? || cursor.close
304
+ end
305
+ end # exec
306
+
307
+ # Executes a SQL statement and fetches the first one row.
308
+ #
309
+ # @param [String] sql SQL statement
310
+ # @param [Object] bindvars bind variables
311
+ # @return [Array] an array of first row.
312
+ def select_one(sql, *bindvars)
313
+ cursor = self.parse(sql)
314
+ begin
315
+ cursor.exec(*bindvars)
316
+ row = cursor.fetch
317
+ ensure
318
+ cursor.close
319
+ end
320
+ return row
321
+ end
322
+
323
+ def username
324
+ @username || begin
325
+ exec('select user from dual') do |row|
326
+ @username = row[0]
327
+ end
328
+ @username
329
+ end
330
+ end
331
+
332
+ # Sets the prefetch rows size. The default value is one.
333
+ # When a select statement is executed, the OCI library allocate
334
+ # prefetch buffer to reduce the number of network round trips by
335
+ # retrieving specified number of rows in one round trip.
336
+ #
337
+ # Note: Active record adaptors set 100 by default.
338
+ def prefetch_rows=(num)
339
+ @prefetch_rows = num
340
+ end
341
+
342
+ # @private
343
+ def inspect
344
+ "#<OCI8:#{username}>"
345
+ end
346
+
347
+ # Returns the Oracle server version.
348
+ #
349
+ # @see OCI8.oracle_client_version
350
+ # @return [OCI8::OracleVersion]
351
+ def oracle_server_version
352
+ unless defined? @oracle_server_version
353
+ if vernum = oracle_server_vernum
354
+ # If the Oracle client is Oracle 9i or upper,
355
+ # get the server version from the OCI function OCIServerRelease.
356
+ @oracle_server_version = OCI8::OracleVersion.new(vernum)
357
+ else
358
+ # Otherwise, get it from v$version.
359
+ self.exec('select banner from v$version') do |row|
360
+ if /^Oracle.*?(\d+\.\d+\.\d+\.\d+\.\d+)/ =~ row[0]
361
+ @oracle_server_version = OCI8::OracleVersion.new($1)
362
+ break
363
+ end
364
+ end
365
+ end
366
+ end
367
+ @oracle_server_version
368
+ end
369
+
370
+ # Returns the Oracle database character set name such as AL32UTF8.
371
+ #
372
+ # @since 2.1.0
373
+ # @return [String] Oracle database character set name
374
+ def database_charset_name
375
+ charset_id2name(@server_handle.send(:attr_get_ub2, OCI_ATTR_CHARSET_ID))
376
+ end
377
+
378
+ # Returns the client-side Oracle character set name such as AL32UTF8.
379
+ #
380
+ # @since 2.1.0
381
+ # @return [String] client-side character set name
382
+ # @private
383
+ # @see OCI8.encoding
384
+ def self.client_charset_name
385
+ @@client_charset_name
386
+ end
387
+ end
388
+
389
+ class OCIError
390
+
391
+ # @overload initialize(message, error_code = nil, sql_stmt = nil, parse_error_offset = nil)
392
+ # Creates a new OCIError object with specified parameters.
393
+ #
394
+ # @param [String] message error message
395
+ # @param [Integer] error_code Oracle error code
396
+ # @param [String] sql_stmt SQL statement
397
+ # @param [Integer] parse_error_offset
398
+ #
399
+ # @example
400
+ # OCIError.new("ORA-00001: unique constraint (%s.%s) violated", 1, 'insert into table_name values (1)', )
401
+ # # => #<OCIError: ORA-00001: unique constraint (%s.%s) violated>
402
+ # #<OCIError: ORA-00923: FROM keyword not found where expected>
403
+ # "select sysdate"
404
+ # 923
405
+ # 14
406
+ #
407
+ # @overload initialize(error_code, *params)
408
+ # Creates a new OCIError object with the error message which corresponds to the specified
409
+ # Oracle error code.
410
+ #
411
+ # @param [Integer] error_code Oracle error code
412
+ # @param [String, ...] params parameters which replace '%s'
413
+ #
414
+ # @example
415
+ # # without parameters
416
+ # OCIError.new(4043)
417
+ # # When NLS_LANG=american_america.AL32UTF8
418
+ # # => #<OCIError: ORA-04043: object %s does not exist>
419
+ # # When NLS_LANG=german_germany.AL32UTF8
420
+ # # => #<OCIError: ORA-04043: Objekt %s ist nicht vorhanden>
421
+ #
422
+ # # with one parameter
423
+ # OCIError.new(4043, 'table_name')
424
+ # # When NLS_LANG=american_america.AL32UTF8
425
+ # # => #<OCIError: ORA-04043: object table_name does not exist>
426
+ # # When NLS_LANG=german_germany.AL32UTF8
427
+ # # => #<OCIError: ORA-04043: Objekt table_name ist nicht vorhanden>
428
+ #
429
+ def initialize(*args)
430
+ if args.length > 0
431
+ if args[0].is_a? Fixnum
432
+ @code = args.shift
433
+ super(OCI8.error_message(@code).gsub('%s') {|s| args.empty? ? '%s' : args.shift})
434
+ @sql = nil
435
+ @parse_error_offset = nil
436
+ else
437
+ msg, @code, @sql, @parse_error_offset = args
438
+ super(msg)
439
+ end
440
+ else
441
+ super()
442
+ end
443
+ end
444
+ end
445
+
446
+ class OraDate
447
+
448
+ # Returns a Time object which denotes self.
449
+ def to_time
450
+ begin
451
+ Time.local(year, month, day, hour, minute, second)
452
+ rescue ArgumentError
453
+ 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)
454
+ raise RangeError.new(msg)
455
+ end
456
+ end
457
+
458
+ # Returns a Date object which denotes self.
459
+ def to_date
460
+ Date.new(year, month, day)
461
+ end
462
+
463
+ if defined? DateTime # ruby 1.8.0 or upper
464
+
465
+ # timezone offset of the time the command started
466
+ # @private
467
+ @@tz_offset = Time.now.utc_offset.to_r/86400
468
+
469
+ # Returns a DateTime object which denotes self.
470
+ #
471
+ # Note that this is not daylight saving time aware.
472
+ # The Time zone offset is that of the time the command started.
473
+ def to_datetime
474
+ DateTime.new(year, month, day, hour, minute, second, @@tz_offset)
475
+ end
476
+ end
477
+
478
+ # @private
479
+ def yaml_initialize(type, val)
480
+ initialize(*val.split(/[ -\/:]+/).collect do |i| i.to_i end)
481
+ end
482
+
483
+ # @private
484
+ def to_yaml(opts = {})
485
+ YAML.quick_emit(object_id, opts) do |out|
486
+ out.scalar(taguri, self.to_s, :plain)
487
+ end
488
+ end
489
+
490
+ # @private
491
+ def to_json(options=nil)
492
+ to_datetime.to_json(options)
493
+ end
494
+ end
495
+
496
+ class OraNumber
497
+
498
+ if defined? Psych and YAML == Psych
499
+
500
+ yaml_tag '!ruby/object:OraNumber'
501
+
502
+ # @private
503
+ def encode_with coder
504
+ coder.scalar = self.to_s
505
+ end
506
+
507
+ # @private
508
+ def init_with coder
509
+ initialize(coder.scalar)
510
+ end
511
+
512
+ else
513
+
514
+ # @private
515
+ def yaml_initialize(type, val)
516
+ initialize(val)
517
+ end
518
+
519
+ # @private
520
+ def to_yaml(opts = {})
521
+ YAML.quick_emit(object_id, opts) do |out|
522
+ out.scalar(taguri, self.to_s, :plain)
523
+ end
524
+ end
525
+ end
526
+
527
+ # @private
528
+ def to_json(options=nil)
529
+ to_s
530
+ end
531
+ end
532
+
533
+ class Numeric
534
+ # Converts +self+ to {OraNumber}.
535
+ #
536
+ # @return [OraNumber]
537
+ def to_onum
538
+ OraNumber.new(self)
539
+ end
540
+ end
541
+
542
+ class String # :nodoc:
543
+
544
+ # Converts +self+ to {OraNumber}.
545
+ # Optional <i>format</i> and <i>nls_params</i> is used as
546
+ # {http://docs.oracle.com/cd/E11882_01/server.112/e17118/functions211.htm Oracle SQL function TO_NUMBER}
547
+ # does.
548
+ #
549
+ # @example
550
+ # '123456.789'.to_onum # => #<OraNumber:123456.789>
551
+ # '123,456.789'.to_onum('999,999,999.999') # => #<OraNumber:123456.789>
552
+ # '123.456,789'.to_onum('999G999G999D999', "NLS_NUMERIC_CHARACTERS = ',.'") # => #<OraNumber:123456.789>
553
+ #
554
+ # @param [String] format
555
+ # @param [String] nls_params
556
+ # @return [OraNumber]
557
+ def to_onum(format = nil, nls_params = nil)
558
+ OraNumber.new(self, format, nls_params)
559
+ end
560
+ end