ruby-oci8 2.1.5.1-x64-mingw32

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