ruby-oci8 2.2.10-x64-mingw-ucrt

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 (78) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +14 -0
  3. data/COPYING +30 -0
  4. data/COPYING_old +64 -0
  5. data/ChangeLog +3826 -0
  6. data/Makefile +92 -0
  7. data/NEWS +1209 -0
  8. data/README.md +66 -0
  9. data/dist-files +112 -0
  10. data/docs/bind-array-to-in_cond.md +38 -0
  11. data/docs/conflicts-local-connections-and-processes.md +98 -0
  12. data/docs/hanging-after-inactivity.md +63 -0
  13. data/docs/install-binary-package.md +44 -0
  14. data/docs/install-full-client.md +111 -0
  15. data/docs/install-instant-client.md +194 -0
  16. data/docs/install-on-osx.md +46 -0
  17. data/docs/ldap-auth-and-function-interposition.md +123 -0
  18. data/docs/number-type-mapping.md +79 -0
  19. data/docs/platform-specific-issues.md +164 -0
  20. data/docs/report-installation-issue.md +50 -0
  21. data/docs/timeout-parameters.md +94 -0
  22. data/lib/.document +1 -0
  23. data/lib/dbd/OCI8.rb +591 -0
  24. data/lib/oci8/.document +8 -0
  25. data/lib/oci8/bindtype.rb +333 -0
  26. data/lib/oci8/check_load_error.rb +146 -0
  27. data/lib/oci8/compat.rb +117 -0
  28. data/lib/oci8/connection_pool.rb +179 -0
  29. data/lib/oci8/cursor.rb +605 -0
  30. data/lib/oci8/datetime.rb +605 -0
  31. data/lib/oci8/encoding-init.rb +45 -0
  32. data/lib/oci8/encoding.yml +537 -0
  33. data/lib/oci8/metadata.rb +2148 -0
  34. data/lib/oci8/object.rb +641 -0
  35. data/lib/oci8/oci8.rb +756 -0
  36. data/lib/oci8/ocihandle.rb +591 -0
  37. data/lib/oci8/oracle_version.rb +153 -0
  38. data/lib/oci8/properties.rb +196 -0
  39. data/lib/oci8/version.rb +3 -0
  40. data/lib/oci8.rb +190 -0
  41. data/lib/oci8lib_310.so +0 -0
  42. data/lib/ruby-oci8.rb +1 -0
  43. data/metaconfig +142 -0
  44. data/pre-distclean.rb +7 -0
  45. data/ruby-oci8.gemspec +85 -0
  46. data/setup.rb +1342 -0
  47. data/test/README.md +37 -0
  48. data/test/config.rb +201 -0
  49. data/test/setup_test_object.sql +199 -0
  50. data/test/setup_test_package.sql +59 -0
  51. data/test/test_all.rb +56 -0
  52. data/test/test_appinfo.rb +62 -0
  53. data/test/test_array_dml.rb +332 -0
  54. data/test/test_bind_array.rb +70 -0
  55. data/test/test_bind_boolean.rb +99 -0
  56. data/test/test_bind_integer.rb +47 -0
  57. data/test/test_bind_raw.rb +45 -0
  58. data/test/test_bind_string.rb +105 -0
  59. data/test/test_bind_time.rb +177 -0
  60. data/test/test_break.rb +125 -0
  61. data/test/test_clob.rb +85 -0
  62. data/test/test_connection_pool.rb +124 -0
  63. data/test/test_connstr.rb +220 -0
  64. data/test/test_datetime.rb +585 -0
  65. data/test/test_dbi.rb +365 -0
  66. data/test/test_dbi_clob.rb +53 -0
  67. data/test/test_encoding.rb +103 -0
  68. data/test/test_error.rb +87 -0
  69. data/test/test_metadata.rb +2674 -0
  70. data/test/test_object.rb +546 -0
  71. data/test/test_oci8.rb +624 -0
  72. data/test/test_oracle_version.rb +68 -0
  73. data/test/test_oradate.rb +255 -0
  74. data/test/test_oranumber.rb +792 -0
  75. data/test/test_package_type.rb +981 -0
  76. data/test/test_properties.rb +17 -0
  77. data/test/test_rowid.rb +32 -0
  78. metadata +123 -0
data/lib/oci8/oci8.rb ADDED
@@ -0,0 +1,756 @@
1
+ # oci8.rb -- OCI8
2
+ #
3
+ # Copyright (C) 2002-2015 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, :SYSOPER, :SYSASM, :SYSBACKUP, :SYSDG or :SYSKM
67
+ # to +privilege+, otherwise "username/password as sysdba",
68
+ # "username/password as sysoper", etc. 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, privilege = parse_connect_string(args[0])
100
+ else
101
+ username, password, dbname, privilege = args
102
+ end
103
+
104
+ if username.nil? and password.nil?
105
+ cred = OCI_CRED_EXT
106
+ end
107
+ auth_mode = to_auth_mode(privilege)
108
+
109
+ stmt_cache_size = OCI8.properties[:statement_cache_size]
110
+ stmt_cache_size = nil if stmt_cache_size == 0
111
+
112
+ attach_mode = 0
113
+ if dbname.is_a? OCI8::ConnectionPool
114
+ @pool = dbname # to prevent GC from freeing the connection pool.
115
+ dbname = dbname.send(:pool_name)
116
+ attach_mode |= 0x0200 # OCI_CPOOL
117
+ else
118
+ tcp_connect_timeout = OCI8::properties[:tcp_connect_timeout]
119
+ connect_timeout = OCI8::properties[:connect_timeout]
120
+ tcp_keepalive = OCI8::properties[:tcp_keepalive]
121
+ if tcp_connect_timeout || connect_timeout || tcp_keepalive
122
+ dbname = to_connect_descriptor(dbname, tcp_connect_timeout, connect_timeout, tcp_keepalive)
123
+ end
124
+ end
125
+ if stmt_cache_size
126
+ # enable statement caching
127
+ attach_mode |= 0x0004 # OCI_STMT_CACHE
128
+ end
129
+
130
+ # logon by the OCI function OCISessionBegin().
131
+ allocate_handles()
132
+ @session_handle.send(:attr_set_string, OCI_ATTR_USERNAME, username) if username
133
+ @session_handle.send(:attr_set_string, OCI_ATTR_PASSWORD, password) if password
134
+ if @@oracle_client_version >= ORAVER_11_1
135
+ # Sets the driver name displayed in V$SESSION_CONNECT_INFO.CLIENT_DRIVER
136
+ # if both the client and the server are Oracle 11g or upper.
137
+ # Only the first 8 chracters "ruby-oci" are displayed when the Oracle
138
+ # server version is lower than 12.0.1.2.
139
+ # 424: OCI_ATTR_DRIVER_NAME
140
+ @session_handle.send(:attr_set_string, 424, "ruby-oci8 : #{OCI8::VERSION}")
141
+ end
142
+ server_attach(dbname, attach_mode)
143
+ if OCI8.oracle_client_version >= OCI8::ORAVER_11_1
144
+ self.send_timeout = OCI8::properties[:send_timeout] if OCI8::properties[:send_timeout]
145
+ self.recv_timeout = OCI8::properties[:recv_timeout] if OCI8::properties[:recv_timeout]
146
+ end
147
+ session_begin(cred ? cred : OCI_CRED_RDBMS, auth_mode)
148
+
149
+ if stmt_cache_size
150
+ # set statement cache size
151
+ attr_set_ub4(176, stmt_cache_size) # 176: OCI_ATTR_STMTCACHESIZE
152
+ end
153
+
154
+ @prefetch_rows = 100
155
+ @username = nil
156
+ end
157
+
158
+ # Returns a prepared SQL handle.
159
+ #
160
+ # @param [String] sql SQL statement
161
+ # @return [OCI8::Cursor]
162
+ def parse(sql)
163
+ @last_error = nil
164
+ parse_internal(sql)
165
+ end
166
+
167
+ # same with OCI8#parse except that this doesn't reset OCI8#last_error.
168
+ #
169
+ # @private
170
+ def parse_internal(sql)
171
+ cursor = OCI8::Cursor.new(self, sql)
172
+ cursor
173
+ end
174
+
175
+ # Executes the sql statement. The type of return value depends on
176
+ # the type of sql statement: select; insert, update and delete;
177
+ # create, alter and drop; and PL/SQL.
178
+ #
179
+ # When bindvars are specified, they are bound as bind variables
180
+ # before execution.
181
+ #
182
+ # == select statements without block
183
+ # It returns the instance of OCI8::Cursor.
184
+ #
185
+ # example:
186
+ # conn = OCI8.new('scott', 'tiger')
187
+ # cursor = conn.exec('SELECT * FROM emp')
188
+ # while r = cursor.fetch()
189
+ # puts r.join(',')
190
+ # end
191
+ # cursor.close
192
+ # conn.logoff
193
+ #
194
+ # == select statements with a block
195
+ # It acts as iterator and returns the processed row counts. Fetched
196
+ # data is passed to the block as array. NULL value becomes nil in ruby.
197
+ #
198
+ # example:
199
+ # conn = OCI8.new('scott', 'tiger')
200
+ # num_rows = conn.exec('SELECT * FROM emp') do |r|
201
+ # puts r.join(',')
202
+ # end
203
+ # puts num_rows.to_s + ' rows were processed.'
204
+ # conn.logoff
205
+ #
206
+ # == PL/SQL block (ruby-oci8 1.0)
207
+ # It returns the array of bind variables' values.
208
+ #
209
+ # example:
210
+ # conn = OCI8.new('scott', 'tiger')
211
+ # conn.exec("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;", 'ABCD', 123)
212
+ # # => ["0123", 123]
213
+ # conn.logoff
214
+ #
215
+ # Above example uses two bind variables which names are :str
216
+ # and :num. These initial values are "the string whose width
217
+ # is 4 and whose value is 'ABCD'" and "the number whose value is
218
+ # 123". This method returns the array of these bind variables,
219
+ # which may modified by PL/SQL statement. The order of array is
220
+ # same with that of bind variables.
221
+ #
222
+ # If a block is given, it is ignored.
223
+ #
224
+ # == PL/SQL block (ruby-oci8 2.0)
225
+ # It returns the number of processed rows.
226
+ #
227
+ # example:
228
+ # conn = OCI8.new('scott', 'tiger')
229
+ # conn.exec("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;", 'ABCD', 123)
230
+ # # => 1
231
+ # conn.logoff
232
+ #
233
+ # If a block is given, the bind variables' values are passed to the block after
234
+ # executed.
235
+ #
236
+ # conn = OCI8.new('scott', 'tiger')
237
+ # conn.exec("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;", 'ABCD', 123) do |str, num|
238
+ # puts str # => '0123'
239
+ # puts num # => 123
240
+ # end
241
+ # conn.logoff
242
+ #
243
+ # FYI, the following code do same on ruby-oci8 1.0 and ruby-oci8 2.0.
244
+ # conn.exec(sql, *bindvars) { |*outvars| outvars }
245
+ #
246
+ # == Other SQL statements
247
+ # It returns the number of processed rows.
248
+ #
249
+ # example:
250
+ # conn = OCI8.new('scott', 'tiger')
251
+ # num_rows = conn.exec('UPDATE emp SET sal = sal * 1.1')
252
+ # puts num_rows.to_s + ' rows were updated.'
253
+ # conn.logoff
254
+ #
255
+ # example:
256
+ # conn = OCI8.new('scott', 'tiger')
257
+ # conn.exec('CREATE TABLE test (col1 CHAR(6))') # => 0
258
+ # conn.logoff
259
+ #
260
+ def exec(sql, *bindvars, &block)
261
+ @last_error = nil
262
+ exec_internal(sql, *bindvars, &block)
263
+ end
264
+
265
+ # same with OCI8#exec except that this doesn't reset OCI8#last_error.
266
+ #
267
+ # @private
268
+ def exec_internal(sql, *bindvars)
269
+ begin
270
+ cursor = parse(sql)
271
+ ret = cursor.exec(*bindvars)
272
+ case cursor.type
273
+ when :select_stmt
274
+ if block_given?
275
+ cursor.fetch { |row| yield(row) } # for each row
276
+ ret = cursor.row_count()
277
+ else
278
+ ret = cursor
279
+ cursor = nil # unset cursor to skip cursor.close in ensure block
280
+ ret
281
+ end
282
+ when :begin_stmt, :declare_stmt # PL/SQL block
283
+ if block_given?
284
+ ary = []
285
+ cursor.keys.sort.each do |key|
286
+ ary << cursor[key]
287
+ end
288
+ yield(*ary)
289
+ else
290
+ ret
291
+ end
292
+ else
293
+ ret # number of rows processed
294
+ end
295
+ ensure
296
+ cursor.nil? || cursor.close
297
+ end
298
+ end # exec
299
+
300
+ # Executes a SQL statement and fetches the first one row.
301
+ #
302
+ # @param [String] sql SQL statement
303
+ # @param [Object] bindvars bind variables
304
+ # @return [Array] an array of first row.
305
+ def select_one(sql, *bindvars)
306
+ cursor = self.parse(sql)
307
+ cursor.prefetch_rows = 1
308
+ begin
309
+ cursor.exec(*bindvars)
310
+ row = cursor.fetch
311
+ ensure
312
+ cursor.close
313
+ end
314
+ return row
315
+ end
316
+
317
+ def username
318
+ @username || begin
319
+ exec('select user from dual') do |row|
320
+ @username = row[0]
321
+ end
322
+ @username
323
+ end
324
+ end
325
+
326
+ # Sets the prefetch rows size. The default value is 100.
327
+ # When a select statement is executed, the OCI library allocate
328
+ # prefetch buffer to reduce the number of network round trips by
329
+ # retrieving specified number of rows in one round trip.
330
+ #
331
+ # Note: The default value had been 1 before ruby-oci8 2.2.0.
332
+ def prefetch_rows=(num)
333
+ @prefetch_rows = num
334
+ end
335
+
336
+ # @private
337
+ def inspect
338
+ "#<OCI8:#{username}>"
339
+ end
340
+
341
+ # Returns the Oracle server version.
342
+ #
343
+ # When the Oracle client version is 12c or earlier and
344
+ # the Oracle server version is 18c or later, this method
345
+ # doesn't return *full* version number such as '18.3.0.0.0'.
346
+ # It returns version number whose number components after
347
+ # the first dot are zeros such as '18.0.0.0.0'.
348
+ #
349
+ # @see OCI8.oracle_client_version
350
+ # @return [OCI8::OracleVersion]
351
+ def oracle_server_version
352
+ @oracle_server_version ||= OCI8::OracleVersion.new(oracle_server_vernum)
353
+ end
354
+
355
+ # Returns the Oracle database character set name such as AL32UTF8.
356
+ #
357
+ # @since 2.1.0
358
+ # @return [String] Oracle database character set name
359
+ def database_charset_name
360
+ charset_id2name(@server_handle.send(:attr_get_ub2, OCI_ATTR_CHARSET_ID))
361
+ end
362
+
363
+ # Returns the client-side Oracle character set name such as AL32UTF8.
364
+ #
365
+ # @since 2.1.0
366
+ # @return [String] client-side character set name
367
+ # @private
368
+ # @see OCI8.encoding
369
+ def self.client_charset_name
370
+ @@client_charset_name
371
+ end
372
+
373
+ if OCI8.oracle_client_version >= OCI8::ORAVER_11_1
374
+ # Returns send timeout in seconds.
375
+ # Zero means no timeout.
376
+ # This is equivalent to {http://docs.oracle.com/database/121/NETRF/sqlnet.htm#NETRF228 SQLNET.SEND_TIMEOUT} in client-side sqlnet.ora.
377
+ #
378
+ # @return [Float] seconds
379
+ # @see #recv_timeout
380
+ # @since 2.1.8 and Oracle 11.1
381
+ def send_timeout
382
+ # OCI_ATTR_SEND_TIMEOUT = 435
383
+ @server_handle.send(:attr_get_ub4, 435).to_f / 1000
384
+ end
385
+
386
+ # Sets send timeout in seconds.
387
+ # Zero means no timeout.
388
+ # This is equivalent to {http://docs.oracle.com/database/121/NETRF/sqlnet.htm#NETRF228 SQLNET.SEND_TIMEOUT} in client-side sqlnet.ora.
389
+ #
390
+ # If you need to set send timeout while establishing a connection, use {file:docs/timeout-parameters.md timeout parameters in OCI8::properties} instead.
391
+ #
392
+ # Note that the connection becomes unusable on timeout.
393
+ #
394
+ # If you have trouble by setting this, don't use it because it uses
395
+ # {http://blog.jiubao.org/2015/01/undocumented-oci-handle-attributes.html an undocumented OCI handle attribute}.
396
+ #
397
+ # @param [Float] timeout
398
+ # @return [void]
399
+ # @see #recv_timeout=
400
+ # @since 2.1.8 and Oracle 11.1
401
+ def send_timeout=(timeout)
402
+ # OCI_ATTR_SEND_TIMEOUT = 435
403
+ @server_handle.send(:attr_set_ub4, 435, timeout * 1000)
404
+ end
405
+
406
+ # Returns receive timeout in seconds.
407
+ # Zero means no timeout.
408
+ # This is equivalent to {http://docs.oracle.com/database/121/NETRF/sqlnet.htm#NETRF227 SQLNET.RECV_TIMEOUT} in client-side sqlnet.ora.
409
+ #
410
+ # @return [Float] seconds
411
+ # @see #send_timeout
412
+ # @since 2.1.8 and Oracle 11.1
413
+ def recv_timeout
414
+ # OCI_ATTR_RECEIVE_TIMEOUT = 436
415
+ @server_handle.send(:attr_get_ub4, 436).to_f / 1000
416
+ end
417
+
418
+ # Sets receive timeout in seconds.
419
+ # Zero means no timeout.
420
+ # This is equivalent to {http://docs.oracle.com/database/121/NETRF/sqlnet.htm#NETRF227 SQLNET.RECV_TIMEOUT} in client-side sqlnet.ora.
421
+ #
422
+ # If you need to set receive timeout while establishing a connection, use {file:docs/timeout-parameters.md timeout parameters in OCI8::properties} instead.
423
+ #
424
+ # Note that the connection becomes unusable on timeout.
425
+ #
426
+ # If you have trouble by setting this, don't use it because it uses
427
+ # {http://blog.jiubao.org/2015/01/undocumented-oci-handle-attributes.html an undocumented OCI handle attribute}.
428
+ #
429
+ # @param [Float] timeout
430
+ # @return [void]
431
+ # @see #send_timeout=
432
+ # @since 2.1.8 and Oracle 11.1
433
+ def recv_timeout=(timeout)
434
+ # OCI_ATTR_RECEIVE_TIMEOUT = 436
435
+ @server_handle.send(:attr_set_ub4, 436, timeout * 1000)
436
+ end
437
+ else
438
+ def send_timeout
439
+ raise NotImplementedError, 'send_timeout is unimplemented in this Oracle version'
440
+ end
441
+ def send_timeout=(timeout)
442
+ raise NotImplementedError, 'send_timeout= is unimplemented in this Oracle version'
443
+ end
444
+ def recv_timeout
445
+ raise NotImplementedError, 'recv_timeout is unimplemented in this Oracle version'
446
+ end
447
+ def recv_timeout=(timeout)
448
+ raise NotImplementedError, 'revc_timeout= is unimplemented in this Oracle version'
449
+ end
450
+ end
451
+
452
+ # A helper class to bind an array to paramters in IN-condition.
453
+ #
454
+ # See {file:docs/bind-array-to-in_cond.md Bind an Array to IN-condition}
455
+ class InCondBindHelper
456
+ def initialize(bind_name_prefix, array, type = nil, length = nil)
457
+ bind_name_prefix = bind_name_prefix.to_s
458
+ if bind_name_prefix !~ /^\w+$/
459
+ raise ArgumentError, "The first argument doesn't consist of alphanumeric characters and underscores."
460
+ end
461
+ if array.empty?
462
+ # This doesn't match anything.
463
+ # However in-condition requires at least one value.
464
+ @bind_names = ":#{bind_name_prefix}_0"
465
+ @bind_values = [[nil, type.nil? ? String : type, length]]
466
+ else
467
+ @bind_names = Array.new(array.length) do |index|
468
+ ":#{bind_name_prefix}_#{index}"
469
+ end.join(', ')
470
+ first_non_nil = array.find do |e|
471
+ !e.nil?
472
+ end
473
+ first_non_nil = '' if first_non_nil.nil?
474
+ @bind_values = array.collect do |elem|
475
+ if elem.nil? and type.nil?
476
+ [elem, first_non_nil.class]
477
+ else
478
+ [elem, type, length]
479
+ end
480
+ end
481
+ end
482
+ end
483
+
484
+ def names
485
+ @bind_names
486
+ end
487
+
488
+ def values
489
+ @bind_values
490
+ end
491
+ end
492
+
493
+ # Creates a helper object to bind an array to paramters in IN-condition.
494
+ #
495
+ # See {file:docs/bind-array-to-in_cond.md Bind an Array to IN-condition}
496
+ #
497
+ # @param [Symbol] bind_name_prefix prefix of the place holder name
498
+ # @param [Object] array an array of values to be bound.
499
+ # @param [Class] type data type. This is used as the third argument of {OCI8::Cursor#bind_param}.
500
+ # @param [Integer] length maximum bind length for string values. This is used as the fourth argument of {OCI8::Cursor#bind_param}.
501
+ # @return [OCI8::InCondBindHelper]
502
+ def self.in_cond(bind_name_prefix, array, type = nil, length = nil)
503
+ InCondBindHelper.new(bind_name_prefix, array, type, length)
504
+ end
505
+
506
+ private
507
+
508
+ # Converts the specified privilege name to the value passed to the
509
+ # fifth argument of OCISessionBegin().
510
+ #
511
+ # @private
512
+ def to_auth_mode(privilege)
513
+ case privilege
514
+ when :SYSDBA
515
+ 0x00000002 # OCI_SYSDBA in oci.h
516
+ when :SYSOPER
517
+ 0x00000004 # OCI_SYSOPER in oci.h
518
+ when :SYSASM
519
+ if OCI8.oracle_client_version < OCI8::ORAVER_11_1
520
+ raise "SYSASM is not supported on Oracle version #{OCI8.oracle_client_version}"
521
+ end
522
+ 0x00008000 # OCI_SYSASM in oci.h
523
+ when :SYSBACKUP
524
+ if OCI8.oracle_client_version < OCI8::ORAVER_12_1
525
+ raise "SYSBACKUP is not supported on Oracle version #{OCI8.oracle_client_version}"
526
+ end
527
+ 0x00020000 # OCI_SYSBKP in oci.h
528
+ when :SYSDG
529
+ if OCI8.oracle_client_version < OCI8::ORAVER_12_1
530
+ raise "SYSDG is not supported on Oracle version #{OCI8.oracle_client_version}"
531
+ end
532
+ 0x00040000 # OCI_SYSDGD in oci.h
533
+ when :SYSKM
534
+ if OCI8.oracle_client_version < OCI8::ORAVER_12_1
535
+ raise "SYSKM is not supported on Oracle version #{OCI8.oracle_client_version}"
536
+ end
537
+ 0x00080000 # OCI_SYSKMT in oci.h
538
+ when nil
539
+ 0 # OCI_DEFAULT
540
+ else
541
+ raise "unknown privilege type #{privilege}"
542
+ end
543
+ end
544
+
545
+ @@easy_connect_naming_regex = %r{
546
+ ^
547
+ (//)? # preceding double-slash($1)
548
+ (?:\[([\h:]+)\]|([^\s:/]+)) # IPv6 enclosed by square brackets($2) or hostname($3)
549
+ (?::(\d+))? # port($4)
550
+ (?:
551
+ /
552
+ ([^\s:/]+)? # service name($5)
553
+ (?::([^\s:/]+))? # server($6)
554
+ (?:/([^\s:/]+))? # instance name($7)
555
+ )?
556
+ $
557
+ }x
558
+
559
+ # Parse easy connect string as described in https://docs.oracle.com/database/121/NETAG/naming.htm
560
+ # and add TRANSPORT_CONNECT_TIMEOUT or CONNECT_TIMEOUT.
561
+ #
562
+ # @private
563
+ def to_connect_descriptor(database, tcp_connect_timeout, connect_timeout, tcp_keepalive)
564
+ if @@easy_connect_naming_regex =~ database && ($1 || $2 || $4 || $5 || $6 || $7)
565
+ connect_data = []
566
+ connect_data << "(SERVICE_NAME=#$5)"
567
+ connect_data << "(SERVER=#$6)" if $6
568
+ connect_data << "(INSTANCE_NAME=#$7)" if $7
569
+ desc = []
570
+ desc << "(CONNECT_DATA=#{connect_data.join})"
571
+ desc << "(ADDRESS=(PROTOCOL=TCP)(HOST=#{$2 || $3})(PORT=#{$4 || 1521}))"
572
+ if tcp_connect_timeout
573
+ desc << "(TRANSPORT_CONNECT_TIMEOUT=#{tcp_connect_timeout})"
574
+ end
575
+ if connect_timeout
576
+ desc << "(CONNECT_TIMEOUT=#{connect_timeout})"
577
+ end
578
+ if tcp_keepalive
579
+ desc << "(ENABLE=BROKEN)"
580
+ end
581
+ "(DESCRIPTION=#{desc.join})"
582
+ else
583
+ database
584
+ end
585
+ end
586
+ end
587
+
588
+ class OCIError
589
+
590
+ # @overload initialize(message, error_code = nil, sql_stmt = nil, parse_error_offset = nil)
591
+ # Creates a new OCIError object with specified parameters.
592
+ #
593
+ # @param [String] message error message
594
+ # @param [Integer] error_code Oracle error code
595
+ # @param [String] sql_stmt SQL statement
596
+ # @param [Integer] parse_error_offset
597
+ #
598
+ # @example
599
+ # OCIError.new("ORA-00001: unique constraint (%s.%s) violated", 1, 'insert into table_name values (1)', )
600
+ # # => #<OCIError: ORA-00001: unique constraint (%s.%s) violated>
601
+ # #<OCIError: ORA-00923: FROM keyword not found where expected>
602
+ # "select sysdate"
603
+ # 923
604
+ # 14
605
+ #
606
+ # @overload initialize(error_code, *params)
607
+ # Creates a new OCIError object with the error message which corresponds to the specified
608
+ # Oracle error code.
609
+ #
610
+ # @param [Integer] error_code Oracle error code
611
+ # @param [String, ...] params parameters which replace '%s'
612
+ #
613
+ # @example
614
+ # # without parameters
615
+ # OCIError.new(4043)
616
+ # # When NLS_LANG=american_america.AL32UTF8
617
+ # # => #<OCIError: ORA-04043: object %s does not exist>
618
+ # # When NLS_LANG=german_germany.AL32UTF8
619
+ # # => #<OCIError: ORA-04043: Objekt %s ist nicht vorhanden>
620
+ #
621
+ # # with one parameter
622
+ # OCIError.new(4043, 'table_name')
623
+ # # When NLS_LANG=american_america.AL32UTF8
624
+ # # => #<OCIError: ORA-04043: object table_name does not exist>
625
+ # # When NLS_LANG=german_germany.AL32UTF8
626
+ # # => #<OCIError: ORA-04043: Objekt table_name ist nicht vorhanden>
627
+ #
628
+ def initialize(*args)
629
+ if args.length > 0
630
+ if args[0].is_a? Integer
631
+ @code = args.shift
632
+ super(OCI8.error_message(@code).gsub('%s') {|s| args.empty? ? '%s' : args.shift})
633
+ @sql = nil
634
+ @parse_error_offset = nil
635
+ else
636
+ msg, @code, @sql, @parse_error_offset = args
637
+ super(msg)
638
+ end
639
+ else
640
+ super()
641
+ end
642
+ end
643
+ end
644
+
645
+ class OraDate
646
+
647
+ # Returns a Time object which denotes self.
648
+ def to_time
649
+ begin
650
+ Time.local(year, month, day, hour, minute, second)
651
+ rescue ArgumentError
652
+ 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)
653
+ raise RangeError.new(msg)
654
+ end
655
+ end
656
+
657
+ # Returns a Date object which denotes self.
658
+ def to_date
659
+ Date.new(year, month, day)
660
+ end
661
+
662
+ # timezone offset of the time the command started
663
+ # @private
664
+ @@tz_offset = Time.now.utc_offset.to_r/86400
665
+
666
+ # Returns a DateTime object which denotes self.
667
+ #
668
+ # Note that this is not daylight saving time aware.
669
+ # The Time zone offset is that of the time the command started.
670
+ def to_datetime
671
+ DateTime.new(year, month, day, hour, minute, second, @@tz_offset)
672
+ end
673
+
674
+ # @private
675
+ def yaml_initialize(type, val)
676
+ initialize(*val.split(/[ -\/:]+/).collect do |i| i.to_i end)
677
+ end
678
+
679
+ # @private
680
+ def to_yaml(opts = {})
681
+ YAML.quick_emit(object_id, opts) do |out|
682
+ out.scalar(taguri, self.to_s, :plain)
683
+ end
684
+ end
685
+
686
+ # @private
687
+ def to_json(options=nil)
688
+ to_datetime.to_json(options)
689
+ end
690
+ end
691
+
692
+ class OraNumber
693
+
694
+ if defined? Psych and YAML == Psych
695
+
696
+ yaml_tag '!ruby/object:OraNumber'
697
+
698
+ # @private
699
+ def encode_with coder
700
+ coder.scalar = self.to_s
701
+ end
702
+
703
+ # @private
704
+ def init_with coder
705
+ initialize(coder.scalar)
706
+ end
707
+
708
+ else
709
+
710
+ # @private
711
+ def yaml_initialize(type, val)
712
+ initialize(val)
713
+ end
714
+
715
+ # @private
716
+ def to_yaml(opts = {})
717
+ YAML.quick_emit(object_id, opts) do |out|
718
+ out.scalar(taguri, self.to_s, :plain)
719
+ end
720
+ end
721
+ end
722
+
723
+ # @private
724
+ def to_json(options=nil)
725
+ to_s
726
+ end
727
+ end
728
+
729
+ class Numeric
730
+ # Converts +self+ to {OraNumber}.
731
+ #
732
+ # @return [OraNumber]
733
+ def to_onum
734
+ OraNumber.new(self)
735
+ end
736
+ end
737
+
738
+ class String # :nodoc:
739
+
740
+ # Converts +self+ to {OraNumber}.
741
+ # Optional <i>format</i> and <i>nls_params</i> is used as
742
+ # {http://docs.oracle.com/cd/E11882_01/server.112/e17118/functions211.htm Oracle SQL function TO_NUMBER}
743
+ # does.
744
+ #
745
+ # @example
746
+ # '123456.789'.to_onum # => #<OraNumber:123456.789>
747
+ # '123,456.789'.to_onum('999,999,999.999') # => #<OraNumber:123456.789>
748
+ # '123.456,789'.to_onum('999G999G999D999', "NLS_NUMERIC_CHARACTERS = ',.'") # => #<OraNumber:123456.789>
749
+ #
750
+ # @param [String] format
751
+ # @param [String] nls_params
752
+ # @return [OraNumber]
753
+ def to_onum(format = nil, nls_params = nil)
754
+ OraNumber.new(self, format, nls_params)
755
+ end
756
+ end