ruby-oci8 2.2.1-x86-mingw32 → 2.2.2-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
data/.yardopts CHANGED
@@ -11,9 +11,4 @@
11
11
  NEWS
12
12
  COPYING
13
13
  COPYING_old
14
- docs/install-full-client.md
15
- docs/install-instant-client.md
16
- docs/install-binary-package.md
17
- docs/install-on-osx.md
18
- docs/platform-specific-issues.md
19
- docs/report-installation-issue.md
14
+ docs/*.md
data/ChangeLog CHANGED
@@ -1,3 +1,101 @@
1
+ 2016-04-24 Kubo Takehiro <kubo@jiubao.org>
2
+ * mkpkg-win32.rb: Added to compile mingw32 packages.
3
+ * dist-files: Updated to include docs/report-installation-issue.md.
4
+
5
+ 2016-04-24 Kubo Takehiro <kubo@jiubao.org>
6
+ * NEWS: Add changes between 2.2.1 and 2.2.2.
7
+ * lib/oci8/version.rb: update to 2.2.2.
8
+
9
+ 2016-04-24 Kubo Takehiro <kubo@jiubao.org>
10
+ * docs/report-installation-issue.md: Use RbConfig::CONFIG instead of
11
+ deprecated Config::CONFIG.
12
+
13
+ 2016-04-24 Kubo Takehiro <kubo@jiubao.org>
14
+ * lib/oci8/oci8.rb: Add OCI8::in_cond and OCI8:InCondBindHelper.
15
+ * test/test_all.rb, test/test_bind_array.rb: Add test of OCI8::in_cond.
16
+ * README.md, docs/bind-array-to-in_cond.md: Add document of OCI8::in_cond.
17
+
18
+ 2016-04-10 Kubo Takehiro <kubo@jiubao.org>
19
+ * lib/oci8/connection_pool.rb: update document.
20
+
21
+ 2016-03-27 Kubo Takehiro <kubo@jiubao.org>
22
+ * lib/oci8/object.rb: Suppress warning: instance variable
23
+ @name_to_tdo not initialized.
24
+
25
+ 2016-03-27 Kubo Takehiro <kubo@jiubao.org>
26
+ * ext/oci8/apiwrap.yml, ext/oci8/metadata.c, ext/oci8/object.c,
27
+ ext/oci8/oci8.h, lib/oci8/object.rb, test/setup_test_object.sql,
28
+ test/test_object.rb: Check object type from each object instance
29
+ when an Oracle object is got from a bind parameter.
30
+ (github issue #119)
31
+
32
+ 2016-03-27 Kubo Takehiro <kubo@jiubao.org>
33
+ * lib/ruby-oci8.rb: Added for 'Bundler.require'.
34
+ (github issue #114)
35
+ * dist-files: Add lib/ruby-oci8.rb.
36
+
37
+ 2016-03-27 Kubo Takehiro <kubo@jiubao.org>
38
+ * README.md, docs/timeout-parameters.md, lib/oci8/oci8.rb:
39
+ Update documents about timeout parameters.
40
+
41
+ 2016-03-18 Kubo Takehiro <kubo@jiubao.org>
42
+ * ext/oci8/oraconf.rb: Fix for mswin64.
43
+
44
+ 2016-03-15 Kubo Takehiro <kubo@jiubao.org>
45
+ * docs/conflicts-local-connections-and-processes.md: Add a document
46
+ about conflicts between local connections and child process
47
+ handling on Unix.
48
+ * README.md: Add a link to a newly added file.
49
+
50
+ 2016-03-13 Kubo Takehiro <kubo@jiubao.org>
51
+ * ruby-oci8.gemspec: Change the license name in gemspec to suppress the
52
+ following warning.
53
+ WARNING: license value '2-clause BSD-style license' is invalid.
54
+ Use a license identifier from http://spdx.org/licenses or 'Nonstandard'
55
+ for a nonstandard license.
56
+
57
+ 2016-01-29 Kubo Takehiro <kubo@jiubao.org>
58
+ * lib/oci8/oci8.rb, lib/oci8/properties.rb: Rename outbound_connect_timeout in
59
+ OCI8::properties to connect_timeout.
60
+ * docs/timeout-parameters.md: Revise document.
61
+
62
+ 2015-12-20 Kubo Takehiro <kubo@jiubao.org>
63
+ * lib/oci8/cursor.rb: Use OCI_ATTR_UB8_ROW_COUNT to get the number of processed rows
64
+ if Oracle client version is 12c or upper.
65
+
66
+ 2015-12-20 Kubo Takehiro <kubo@jiubao.org>
67
+ * lib/oci8/oci8.rb, lib/oci8/properties.rb, test/test_connstr.rb:
68
+ Support tcp_connect_timeout, connect_timeout, send_timeout and
69
+ recv_timeout in OCI8::properties.
70
+ * .yardopts, dist-files, docs/timeout-parameters.md: Add document
71
+ about timeout parameters.
72
+
73
+ 2015-12-19 Kubo Takehiro <kubo@jiubao.org>
74
+ * lib/oci8/oci8.rb, lib/oci8/ocihandle.rb: Support SYSBACKUP, SYSDG
75
+ and SYSKM privileges.
76
+ (github issue #110)
77
+
78
+ 2015-12-19 Kubo Takehiro <kubo@jiubao.org>
79
+ * ext/oci8/plthook_win32.c: Fix bug introduced by the previous commit
80
+ for mingw32 64-bit compiler.
81
+ (github issue #113)
82
+
83
+ 2015-12-18 Kubo Takehiro <kubo@jiubao.org>
84
+ * ext/oci8/plthook_win32.c, ext/oci8/extconf.rb: Import the latest
85
+ plthook_win32.c for cygwin. Ruby-oci8 had not been compiled on
86
+ cygwin since 2.1.8.
87
+ (github issue #113)
88
+
89
+ 2015-12-18 Kubo Takehiro <kubo@jiubao.org>
90
+ * ext/oci8/oraconf.rb: Fix a linkage error on cygwin and mingw32
91
+ when installing without `--with-runtime-check`.
92
+ This bug was introduced in ruby-oci8 2.2.1.
93
+ (github issue #113)
94
+
95
+ 2015-11-28 Kubo Takehiro <kubo@jiubao.org>
96
+ * ext/oci8/oraconf.rb: Check the default value of DYLD_FALLBACK_LIBRARY_PATH
97
+ after checking OCI_DIR. (OS X only)
98
+
1
99
  2015-11-01 Kubo Takehiro <kubo@jiubao.org>
2
100
  * NEWS: Add changes between 2.2.0.2 and 2.2.1.
3
101
  * lib/oci8/version.rb: update to 2.2.1.
data/NEWS CHANGED
@@ -1,5 +1,52 @@
1
1
  # @markup markdown
2
2
 
3
+ 2.2.2
4
+ =====
5
+
6
+ New Features
7
+ ------------
8
+
9
+ ### Add OCI8::in_cond
10
+
11
+ This is a helper method to bind an array to parameters in IN-conditions.
12
+ See {file:docs/bind-array-to-in_cond.md Bind an Array to IN-condition}
13
+
14
+ ### Add timeout parameters in OCI8::properties
15
+
16
+ See {file:docs/timeout-parameters.md Timeout Parameters}
17
+
18
+ ### Support SYSBACKUP, SYSDG and SYSKM privileges.
19
+
20
+ For example:
21
+
22
+ OCI8.new(username, password, database, :SYSBACKUP)
23
+
24
+ (github issue #110)
25
+
26
+ ### Support {OCI8::Cursor#row_count} over 4G (Oracle 12c client only)
27
+
28
+ Fixed Issues
29
+ ------------
30
+
31
+ ### Fix type mapping of subtypes of Oracle object
32
+
33
+ github issue #119
34
+
35
+ ### Fix compile error on cygwin since ruby-oci8 2.1.8.
36
+
37
+ github issue #113
38
+
39
+ ### Fix compile error when the ruby was compiled by Visual Studio 64bit.
40
+
41
+ Other Changes
42
+ -------------
43
+
44
+ - Suppress warning: instance variable @name_to_tdo not initialized.
45
+
46
+
47
+ - Check the default value of DYLD_FALLBACK_LIBRARY_PATH after checking OCI_DIR on installation. (OS X only)
48
+
49
+
3
50
  2.2.1
4
51
  =====
5
52
 
@@ -9,7 +56,7 @@ New Features
9
56
  ### Add OCI8::Metadata::Boolean
10
57
 
11
58
  Support boolean type binding. This feature requires Oracle 12c client and server.
12
- This doens't work when either Oracle server or client is 11g or lower.
59
+ Binding a boolean value fails when either Oracle server or client is 11g or lower.
13
60
 
14
61
  Fixed Issues
15
62
  ------------
data/README.md CHANGED
@@ -41,6 +41,13 @@ Report issues
41
41
  * {file:docs/report-installation-issue.md Report Installation Issues}
42
42
  * [The issues page on github](https://github.com/kubo/ruby-oci8/issues)
43
43
 
44
+ Other documents
45
+ ===============
46
+
47
+ * {file:docs/timeout-parameters.md Timeout Parameters}
48
+ * {file:docs/conflicts-local-connections-and-processes.md Conflicts between Local Connections and Child Process Handling on Unix}
49
+ * {file:docs/bind-array-to-in_cond.md Bind an Array to IN-condition}
50
+
44
51
  License
45
52
  =======
46
53
 
data/dist-files CHANGED
@@ -10,13 +10,16 @@ metaconfig
10
10
  pre-distclean.rb
11
11
  ruby-oci8.gemspec
12
12
  setup.rb
13
+ docs/bind-array-to-in_cond.md
13
14
  docs/install-binary-package.md
14
15
  docs/install-full-client.md
15
16
  docs/install-instant-client.md
16
17
  docs/install-on-osx.md
18
+ docs/conflicts-local-connections-and-processes.md
17
19
  docs/osx-install-dev-tools.png
18
20
  docs/platform-specific-issues.md
19
21
  docs/report-installation-issue.md
22
+ docs/timeout-parameters.md
20
23
  ext/oci8/.document
21
24
  ext/oci8/MANIFEST
22
25
  ext/oci8/apiwrap.c.tmpl
@@ -73,6 +76,7 @@ lib/oci8/ocihandle.rb
73
76
  lib/oci8/oracle_version.rb
74
77
  lib/oci8/properties.rb
75
78
  lib/oci8/version.rb
79
+ lib/ruby-oci8.rb
76
80
  test/README
77
81
  test/config.rb
78
82
  test/setup_test_object.sql
@@ -0,0 +1,38 @@
1
+ @ Bind an Array to IN-condition
2
+
3
+ Bind an Array to IN-condition
4
+ =============================
5
+
6
+ Binding an arbitrary-length array to IN-condition is not simple.
7
+ You need to create an SQL statement containing a comma-separated
8
+ list whose length is same with the input data.
9
+
10
+ Example:
11
+
12
+ ids = [ ... ] # an arbitrary-length array containing user IDs.
13
+
14
+ place_holder_string = Array.new(ids.length) {|index| ":id_#{index}"}.join(', ')
15
+ # place_holder_string is:
16
+ # ":id_0" if ids.length == 1
17
+ # ":id_0, :id_1" if ids.length == 2
18
+ # ...
19
+ cursor = conn.parse("select * from users where id in (#{place_holder_string})")
20
+ ids.each_with_index do |id, index|
21
+ cursor.bind_param("id#{index}", id) # bind each element
22
+ end
23
+ cursor.exec()
24
+
25
+ However this is awkward. So {OCI8.in_cond} was added in ruby-oci8 2.2.2.
26
+ The above code is rewritten as follows:
27
+
28
+ ids = [ ... ] # an arbitrary-length array containing user IDs.
29
+
30
+ in_cond = OCI8::in_cond(:id, ids)]
31
+ cursor = conn.exec("select * from users where id in (#{in_cond.names})", *in_cond.values)
32
+
33
+ or
34
+
35
+ ids = [ ... ] # an arbitrary-length array containing user IDs.
36
+
37
+ in_cond = OCI8::in_cond(:id, ids, Integer) # set the data type explicitly
38
+ cursor = conn.exec("select * from users where id in (#{in_cond.names})", *in_cond.values)
@@ -0,0 +1,95 @@
1
+ # @title Conflicts between Local Connections and Child Process Handling on Unix
2
+
3
+ Background
4
+ ==========
5
+
6
+ When a local (not-TCP) Oracle connection is established on Unix,
7
+ Oracle client library changes signal handlers in the process to reap
8
+ all dead child processes. However it conflicts with child process
9
+ handling in ruby.
10
+
11
+ Problem 1: It trashes child process handling of Open3::popen.
12
+ ==========
13
+
14
+ require 'oci8'
15
+ require 'open3'
16
+
17
+ Open3::popen3('true') do |i, o, e, w|
18
+ p w.value
19
+ end
20
+
21
+ conn = OCI8.new(username, password)
22
+ puts "establish a local connection"
23
+
24
+ Open3::popen3('true') do |i, o, e, w|
25
+ p w.value
26
+ end
27
+
28
+ The above code outputs the following result:
29
+
30
+ #<Process::Status: pid 19236 exit 0>
31
+ establish a local connection
32
+ nil
33
+
34
+ `w.value` after a local connection doesn't work because Oracle reaps
35
+ the child process on the process termination before ruby detects it.
36
+
37
+ Problem 2: It creates defunct processes after disconnection if signal handlers are reset.
38
+ ==========
39
+
40
+ The `system` function overwrites signal handlers.
41
+ It fixes the problem 1 as follows.
42
+
43
+ require 'oci8'
44
+ require 'open3'
45
+
46
+ Open3::popen3('true') do |i, o, e, w|
47
+ p w.value
48
+ end
49
+
50
+ conn = OCI8.new(username, password) # Signal handlers are changed here.
51
+ puts "establish a local connection"
52
+ system('true') # Signal handlers are reset here.
53
+
54
+ Open3::popen3('true') do |i, o, e, w|
55
+ p w.value
56
+ end
57
+
58
+ The above code outputs the following result:
59
+
60
+ #<Process::Status: pid 19652 exit 0>
61
+ establish a local connection
62
+ #<Process::Status: pid 19656 exit 0>
63
+
64
+ `w.value` after a local connection works.
65
+
66
+ However it makes another problem.
67
+
68
+ require 'oci8'
69
+
70
+ conn = OCI8.new(username, password) # Signal handlers are changed here.
71
+ # An Oracle server process is created here.
72
+ puts "establish a local connection"
73
+ system('true') # Signal handlers are reset here.
74
+
75
+ conn.logoff # The Oracle server process exits and become defunct.
76
+
77
+ # ... do other stuffs...
78
+
79
+ If a program repeatedly creates a local connection and disconnects it,
80
+ the number of defunct processes increases gradually.
81
+
82
+ Solution: BEQUEATH_DETACH=YES
83
+ ==========
84
+
85
+ By setting [BEQUEATH_DETACH=YES][] in `sqlnet.ora`, Oracle client library
86
+ doesn't change signal handlers. The above two problems are fixed.
87
+
88
+ Oracle client library reads `sqlnet.ora` in the following locations:
89
+
90
+ * `$TNS_ADMIN/sqlnet.ora` if the environment variable `TNS_ADMIN`
91
+ is set and `$TNS_ADMIN/sqlnet.ora` exists.
92
+ Otherwise, `$ORACLE_HOME/network/admin/sqlnet.ora`.
93
+ * `$HOME/.sqlnet.ora`
94
+
95
+ [BEQUEATH_DETACH=YES]: https://docs.oracle.com/database/121/NETRF/sqlnet.htm#NETRF183
@@ -20,14 +20,14 @@ If it is a new one, post the following information to [github][].
20
20
 
21
21
  file `which ruby`
22
22
  ruby --version
23
- ruby -r rbconfig -e "p Config::CONFIG['host']"
24
- ruby -r rbconfig -e "p Config::CONFIG['CC']"
25
- ruby -r rbconfig -e "p Config::CONFIG['CFLAGS']"
26
- ruby -r rbconfig -e "p Config::CONFIG['LDSHARED']"
27
- ruby -r rbconfig -e "p Config::CONFIG['LDFLAGS']"
28
- ruby -r rbconfig -e "p Config::CONFIG['DLDLAGS']"
29
- ruby -r rbconfig -e "p Config::CONFIG['LIBS']"
30
- ruby -r rbconfig -e "p Config::CONFIG['GNU_LD']"
23
+ ruby -r rbconfig -e "p RbConfig::CONFIG['host']"
24
+ ruby -r rbconfig -e "p RbConfig::CONFIG['CC']"
25
+ ruby -r rbconfig -e "p RbConfig::CONFIG['CFLAGS']"
26
+ ruby -r rbconfig -e "p RbConfig::CONFIG['LDSHARED']"
27
+ ruby -r rbconfig -e "p RbConfig::CONFIG['LDFLAGS']"
28
+ ruby -r rbconfig -e "p RbConfig::CONFIG['DLDLAGS']"
29
+ ruby -r rbconfig -e "p RbConfig::CONFIG['LIBS']"
30
+ ruby -r rbconfig -e "p RbConfig::CONFIG['GNU_LD']"
31
31
 
32
32
  # if you use gcc,
33
33
  gcc --print-prog-name=ld
@@ -0,0 +1,91 @@
1
+ # @title Timeout Parameters
2
+
3
+ Timeout Parameters
4
+ ==================
5
+
6
+ The following timeout parameters are available since ruby-oci8 2.2.2.
7
+
8
+ * tcp_connect_timeout
9
+ * connect_timeout
10
+ * send_timeout
11
+ * recv_timeout
12
+
13
+ For example:
14
+
15
+ OCI8.properties[:tcp_connect_timeout] = 10
16
+ OCI8.properties[:connect_timeout] = 15
17
+ OCI8.properties[:send_timeout] = 60
18
+ OCI8.properties[:recv_timeout] = 60
19
+
20
+ These parameters are applied only to TCP/IP connections.
21
+
22
+ The first two parameters `tcp_connect_timeout` and `connect_timeout`
23
+ are applied only to [connect descriptors][connect descriptor] using [Easy Connect Naming Method][EZCONNECT].
24
+ If you use a net service name, you should set [TRANSPORT_CONNECT_TIMEOUT][] and/or
25
+ [CONNECT_TIMEOUT][] in the address descriptor in `tnsnames.ora` instead of these parameters.
26
+ If you use easy connect naming method without any of `port`, `service_name`, `server` and `instance_name`,
27
+ you need to use `//host` to distinguish it from a net service name.
28
+
29
+ The next two parameters `send_timeout` and `recv_timeout` are available on Oracle 11g client
30
+ or upper. Use these parameters to prevent a ruby process from being blocked by poor quality network.
31
+ Otherwise, the ruby process may be blocked until TCP keepalive time (2 hours).
32
+
33
+ tcp_connect_timeout
34
+ -------------------
35
+
36
+ `tcp_connect_timeout` is equivalent to [TCP.CONNECT_TIMEOUT][] in the client-side `sqlnet.ora` and
37
+ [TRANSPORT_CONNECT_TIMEOUT][] in the address descriptor.
38
+ See description about [TCP.CONNECT_TIMEOUT][] and [TRANSPORT_CONNECT_TIMEOUT][].
39
+
40
+ connect_timeout
41
+ ---------------
42
+
43
+ `connect_timeout` is equivalent to [SQLNET.OUTBOUND_CONNECT_TIMEOUT][] in the client-side `sqlnet.ora`
44
+ and [CONNECT_TIMEOUT][] in the address description.
45
+ See description about [SQLNET.OUTBOUND_CONNECT_TIMEOUT][] and [CONNECT_TIMEOUT][].
46
+
47
+ Note: this parameter isn't equivalent to login timeout. It needs the following three
48
+ steps to establish a database connection.
49
+
50
+ 1. Establish a TCP/IP connection.
51
+ 2. Establish an [Oracle Net][] connection on the TCP/IP connection.
52
+ 3. Authenticate and authorize the database user.
53
+
54
+ `tcp_connect_timeout` sets the timeout of the first step.
55
+ `connect_timeout` sets the total timeout of the first and the second steps.
56
+ There is no timeout parameter to limit the maximum time of all three steps.
57
+
58
+ Use `send_timeout` and `recv_timeout` in case that a TCP/IP connection stalls
59
+ in the third step.
60
+
61
+ send_timeout
62
+ ------------
63
+
64
+ `send_timeout` is equivalent to [SQLNET.SEND_TIMEOUT][] in the client-side `sqlnet.ora`.
65
+ See description about [SQLNET.SEND_TIMEOUT][].
66
+
67
+ Note that the connection becomes unusable on timeout.
68
+
69
+ See also {OCI8#send_timeout=}.
70
+
71
+ recv_timeout
72
+ ------------
73
+
74
+ `recv_timeout` is equivalent to [SQLNET.RECV_TIMEOUT][] in the client-side `sqlnet.ora`.
75
+ See description about [SQLNET.RECV_TIMEOUT][].
76
+
77
+ Note that the connection becomes unusable on timeout.
78
+
79
+ See also {OCI8#recv_timeout=}.
80
+
81
+ Note: This parameter must be larger than the longest SQL execution time in your applications.
82
+
83
+ [TCP.CONNECT_TIMEOUT]: http://docs.oracle.com/database/121/NETRF/sqlnet.htm#BIIDDACA
84
+ [SQLNET.OUTBOUND_CONNECT_TIMEOUT]: https://docs.oracle.com/database/121/NETRF/sqlnet.htm#NETRF427
85
+ [SQLNET.SEND_TIMEOUT]: http://docs.oracle.com/database/121/NETRF/sqlnet.htm#NETRF228
86
+ [SQLNET.RECV_TIMEOUT]: http://docs.oracle.com/database/121/NETRF/sqlnet.htm#NETRF227
87
+ [connect descriptor]: https://docs.oracle.com/database/121/NETRF/glossary.htm#BGBEDFBF
88
+ [EZCONNECT]: https://docs.oracle.com/database/121/NETAG/naming.htm#NETAG255
89
+ [CONNECT_TIMEOUT]: https://docs.oracle.com/database/121/NETRF/tnsnames.htm#NETRF666
90
+ [TRANSPORT_CONNECT_TIMEOUT]: https://docs.oracle.com/database/121/NETRF/tnsnames.htm#NETRF1982
91
+ [Oracle Net]: https://en.wikipedia.org/wiki/Oracle_Net_Services#Oracle_Net
@@ -13,17 +13,88 @@ class OCI8
13
13
  #
14
14
  # This is equivalent to Oracle JDBC Driver {OCI Connection Pooling}[http://docs.oracle.com/cd/E11882_01/java.112/e16548/ociconpl.htm#JJDBC28789].
15
15
  #
16
- # Usage:
16
+ # Note that this is different with generally called connection pooling.
17
+ # Generally connection pooling caches connections in a pool.
18
+ # When an application needs a new connection, a connection is got from
19
+ # the pool. So that the amount of time to establish a connection is
20
+ # reduced. However connection pooling in ruby-oci8 is different with
21
+ # above.
22
+ #
23
+ # One Oracle connection is devided into two layers: One is physical
24
+ # connection such as TCP/IP. The other is logical connection which
25
+ # is used by an application. The connection pooling in ruby-oci8
26
+ # caches physical connections in a pool, not logical connections.
27
+ # When an application needs a new connection, a logical connection
28
+ # is created via a physical connection, which needs time to
29
+ # establish a connection unlike generally called connection pooling.
30
+ # When an application sends a query via a logical connection, a
31
+ # physical connection is got from the pool. The physical connection
32
+ # returns to the pool automatically when the query finishes.
33
+ # As long as logical connections are used sequentially, only one
34
+ # physical connection is used. When an application sends
35
+ # queries at a time, it needs more than one physical connection
36
+ # because one physical connection cannot transmit more then one
37
+ # query at a time.
38
+ #
39
+ # Example:
17
40
  # # Create a connection pool.
41
+ # # The number of initial physical connections: 1
42
+ # # The number of maximum physical connections: 5
43
+ # # the connection increment parameter: 2
18
44
  # # username and password are required to establish an implicit primary session.
19
45
  # cpool = OCI8::ConnectionPool.new(1, 5, 2, username, password, database)
20
46
  #
21
- # # Get a session from the pool.
47
+ # # The number of physical connections: 1
48
+ # # The number of logical connections: 0
49
+ #
50
+ # # Create a session.
22
51
  # # Pass the connection pool to the third argument.
23
52
  # conn1 = OCI8.new(username, password, cpool)
24
53
  #
25
- # # Get another session.
54
+ # # One logical connection was created.
55
+ # # The number of physical connections: 1
56
+ # # The number of logical connections: 1
57
+ #
58
+ # # Create another session.
26
59
  # conn2 = OCI8.new(username, password, cpool)
60
+ #
61
+ # # Another logical connection was created.
62
+ # # The number of physical connections: 1
63
+ # # The number of logical connections: 2
64
+ #
65
+ # # Use conn1 and conn2 sequentially
66
+ # conn1.exec('...')
67
+ # conn2.exec('...')
68
+ #
69
+ # # Both logical connections use one physical connection.
70
+ # # The number of physical connections: 1
71
+ # # The number of logical connections: 2
72
+ #
73
+ # thr1 = Thread.new do
74
+ # conn1.exec('...')
75
+ # end
76
+ # thr2 = Thread.new do
77
+ # conn2.exec('...')
78
+ # end
79
+ # thr1.join
80
+ # thr2.join
81
+ #
82
+ # # Logical connections cannot use one physical connection at a time.
83
+ # # So that the number of physical connections is incremented.
84
+ # # The number of physical connections: 3
85
+ # # The number of logical connections: 2
86
+ #
87
+ # conn1.logoff
88
+ #
89
+ # # One logical connection was closed.
90
+ # # The number of physical connections: 3
91
+ # # The number of logical connections: 1
92
+ #
93
+ # conn2.logoff
94
+ #
95
+ # # All logical connections were closed.
96
+ # # The number of physical connections: 3
97
+ # # The number of logical connections: 0
27
98
  #
28
99
  class ConnectionPool
29
100
 
@@ -384,12 +384,19 @@ class OCI8
384
384
  attr_set_ub4(11, rows) # OCI_ATTR_PREFETCH_ROWS(11)
385
385
  end
386
386
 
387
- # Returns the number of processed rows.
388
- #
389
- # @return [Integer]
390
- def row_count
391
- # http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/ociaahan.htm#sthref5498
392
- attr_get_ub4(9) # OCI_ATTR_ROW_COUNT(9)
387
+ if OCI8::oracle_client_version >= ORAVER_12_1
388
+ # Returns the number of processed rows.
389
+ #
390
+ # @return [Integer]
391
+ def row_count
392
+ # https://docs.oracle.com/database/121/LNOCI/ociaahan.htm#sthref5774
393
+ attr_get_ub8(457) # OCI_ATTR_UB8_ROW_COUNT(457)
394
+ end
395
+ else
396
+ def row_count
397
+ # http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/ociaahan.htm#sthref5498
398
+ attr_get_ub4(9) # OCI_ATTR_ROW_COUNT(9)
399
+ end
393
400
  end
394
401
 
395
402
  # Returns the text of the SQL statement prepared in the cursor.
@@ -78,7 +78,8 @@ EOS
78
78
  #
79
79
  # @private
80
80
  def get_tdo_by_typename(typename)
81
- tdo = @name_to_tdo && @name_to_tdo[typename]
81
+ @name_to_tdo ||= {}
82
+ tdo = @name_to_tdo[typename]
82
83
  return tdo if tdo
83
84
 
84
85
  metadata = describe_any(typename)
@@ -383,8 +384,10 @@ EOS
383
384
 
384
385
  case metadata.typecode
385
386
  when :named_type
387
+ @is_final_type = metadata.is_final_type?
386
388
  initialize_named_type(con, metadata)
387
389
  when :named_collection
390
+ @is_final_type = true
388
391
  initialize_named_collection(con, metadata)
389
392
  end
390
393
  end
@@ -63,9 +63,9 @@ class OCI8
63
63
  #
64
64
  # === connecting as a privileged user
65
65
  #
66
- # Set :SYSDBA or :SYSOPER to +privilege+, otherwise
67
- # "username/password as sysdba" or "username/password as sysoper"
68
- # as a single argument.
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
69
  #
70
70
  # OCI8.new('sys', 'change_on_install', nil, :SYSDBA)
71
71
  # or
@@ -96,29 +96,15 @@ class OCI8
96
96
  #
97
97
  def initialize(*args)
98
98
  if args.length == 1
99
- username, password, dbname, mode = parse_connect_string(args[0])
99
+ username, password, dbname, privilege = parse_connect_string(args[0])
100
100
  else
101
- username, password, dbname, mode = args
101
+ username, password, dbname, privilege = args
102
102
  end
103
103
 
104
104
  if username.nil? and password.nil?
105
105
  cred = OCI_CRED_EXT
106
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
107
+ auth_mode = to_auth_mode(privilege)
122
108
 
123
109
  stmt_cache_size = OCI8.properties[:statement_cache_size]
124
110
  stmt_cache_size = nil if stmt_cache_size == 0
@@ -128,6 +114,12 @@ class OCI8
128
114
  @pool = dbname # to prevent GC from freeing the connection pool.
129
115
  dbname = dbname.send(:pool_name)
130
116
  attach_mode |= 0x0200 # OCI_CPOOL and OCI_LOGON2_CPOOL
117
+ else
118
+ tcp_connect_timeout = OCI8::properties[:tcp_connect_timeout]
119
+ connect_timeout = OCI8::properties[:connect_timeout]
120
+ if tcp_connect_timeout || connect_timeout
121
+ dbname = to_connect_descriptor(dbname, tcp_connect_timeout, connect_timeout)
122
+ end
131
123
  end
132
124
  if stmt_cache_size
133
125
  # enable statement caching
@@ -148,7 +140,11 @@ class OCI8
148
140
  @session_handle.send(:attr_set_string, 424, "ruby-oci8 : #{OCI8::VERSION}")
149
141
  end
150
142
  server_attach(dbname, attach_mode)
151
- session_begin(cred ? cred : OCI_CRED_RDBMS, mode ? mode : OCI_DEFAULT)
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)
152
148
  else
153
149
  # logon by the OCI function OCILogon2().
154
150
  logon2(username, password, dbname, attach_mode)
@@ -389,6 +385,10 @@ class OCI8
389
385
  # Zero means no timeout.
390
386
  # This is equivalent to {http://docs.oracle.com/database/121/NETRF/sqlnet.htm#NETRF228 SQLNET.SEND_TIMEOUT} in client-side sqlnet.ora.
391
387
  #
388
+ # If you need to set send timeout while establishing a connection, use {file:docs/timeout-parameters.md timeout parameters in OCI8::properties} instead.
389
+ #
390
+ # Note that the connection becomes unusable on timeout.
391
+ #
392
392
  # If you have trouble by setting this, don't use it because it uses
393
393
  # {http://blog.jiubao.org/2015/01/undocumented-oci-handle-attributes.html an undocumented OCI handle attribute}.
394
394
  #
@@ -417,6 +417,10 @@ class OCI8
417
417
  # Zero means no timeout.
418
418
  # This is equivalent to {http://docs.oracle.com/database/121/NETRF/sqlnet.htm#NETRF227 SQLNET.RECV_TIMEOUT} in client-side sqlnet.ora.
419
419
  #
420
+ # If you need to set receive timeout while establishing a connection, use {file:docs/timeout-parameters.md timeout parameters in OCI8::properties} instead.
421
+ #
422
+ # Note that the connection becomes unusable on timeout.
423
+ #
420
424
  # If you have trouble by setting this, don't use it because it uses
421
425
  # {http://blog.jiubao.org/2015/01/undocumented-oci-handle-attributes.html an undocumented OCI handle attribute}.
422
426
  #
@@ -442,6 +446,138 @@ class OCI8
442
446
  raise NotImplementedError, 'revc_timeout= is unimplemented in this Oracle version'
443
447
  end
444
448
  end
449
+
450
+ # A helper class to bind an array to paramters in IN-condition.
451
+ #
452
+ # See {file:docs/bind-array-to-in_cond.md Bind an Array to IN-condition}
453
+ class InCondBindHelper
454
+ def initialize(bind_name_prefix, array, type = nil, length = nil)
455
+ bind_name_prefix = bind_name_prefix.to_s
456
+ if bind_name_prefix !~ /^\w+$/
457
+ raise ArgumentError, "The first argument doesn't consist of alphanumeric characters and underscores."
458
+ end
459
+ if array.empty?
460
+ # This doesn't match anything.
461
+ # However in-condition requires at least one value.
462
+ @bind_names = ":#{bind_name_prefix}_0"
463
+ @bind_values = [[nil, type.nil? ? String : type, length]]
464
+ else
465
+ @bind_names = Array.new(array.length) do |index|
466
+ ":#{bind_name_prefix}_#{index}"
467
+ end.join(', ')
468
+ first_non_nil = array.find do |e|
469
+ !e.nil?
470
+ end
471
+ first_non_nil = '' if first_non_nil.nil?
472
+ @bind_values = array.collect do |elem|
473
+ if elem.nil? and type.nil?
474
+ [elem, first_non_nil.class]
475
+ else
476
+ [elem, type, length]
477
+ end
478
+ end
479
+ end
480
+ end
481
+
482
+ def names
483
+ @bind_names
484
+ end
485
+
486
+ def values
487
+ @bind_values
488
+ end
489
+ end
490
+
491
+ # Creates a helper object to bind an array to paramters in IN-condition.
492
+ #
493
+ # See {file:docs/bind-array-to-in_cond.md Bind an Array to IN-condition}
494
+ #
495
+ # @param [Symbol] bind_name_prefix prefix of the place holder name
496
+ # @param [Object] array an array of values to be bound.
497
+ # @param [Class] type data type. This is used as the third argument of {OCI8::Cursor#bind_param}.
498
+ # @param [Integer] length maximum bind length for string values. This is used as the fourth argument of {OCI8::Cursor#bind_param}.
499
+ # @return [OCI8::InCondBindHelper]
500
+ def self.in_cond(bind_name_prefix, array, type = nil, length = nil)
501
+ InCondBindHelper.new(bind_name_prefix, array, type, length)
502
+ end
503
+
504
+ private
505
+
506
+ # Converts the specified privilege name to the value passed to the
507
+ # fifth argument of OCISessionBegin().
508
+ #
509
+ # @private
510
+ def to_auth_mode(privilege)
511
+ case privilege
512
+ when :SYSDBA
513
+ 0x00000002 # OCI_SYSDBA in oci.h
514
+ when :SYSOPER
515
+ 0x00000004 # OCI_SYSOPER in oci.h
516
+ when :SYSASM
517
+ if OCI8.oracle_client_version < OCI8::ORAVER_11_1
518
+ raise "SYSASM is not supported on Oracle version #{OCI8.oracle_client_version}"
519
+ end
520
+ 0x00008000 # OCI_SYSASM in oci.h
521
+ when :SYSBACKUP
522
+ if OCI8.oracle_client_version < OCI8::ORAVER_12_1
523
+ raise "SYSBACKUP is not supported on Oracle version #{OCI8.oracle_client_version}"
524
+ end
525
+ 0x00020000 # OCI_SYSBKP in oci.h
526
+ when :SYSDG
527
+ if OCI8.oracle_client_version < OCI8::ORAVER_12_1
528
+ raise "SYSDG is not supported on Oracle version #{OCI8.oracle_client_version}"
529
+ end
530
+ 0x00040000 # OCI_SYSDGD in oci.h
531
+ when :SYSKM
532
+ if OCI8.oracle_client_version < OCI8::ORAVER_12_1
533
+ raise "SYSKM is not supported on Oracle version #{OCI8.oracle_client_version}"
534
+ end
535
+ 0x00080000 # OCI_SYSKMT in oci.h
536
+ when nil
537
+ 0 # OCI_DEFAULT
538
+ else
539
+ raise "unknown privilege type #{privilege}"
540
+ end
541
+ end
542
+
543
+ @@easy_connect_naming_regex = %r{
544
+ ^
545
+ (//)? # preceding double-slash($1)
546
+ (?:\[([\h:]+)\]|([^\s:/]+)) # IPv6 enclosed by square brackets($2) or hostname($3)
547
+ (?::(\d+))? # port($4)
548
+ (?:
549
+ /
550
+ ([^\s:/]+)? # service name($5)
551
+ (?::([^\s:/]+))? # server($6)
552
+ (?:/([^\s:/]+))? # instance name($7)
553
+ )?
554
+ $
555
+ }x
556
+
557
+ # Parse easy connect string as described in https://docs.oracle.com/database/121/NETAG/naming.htm
558
+ # and add TRANSPORT_CONNECT_TIMEOUT or CONNECT_TIMEOUT.
559
+ #
560
+ # @private
561
+ def to_connect_descriptor(database, tcp_connect_timeout, connect_timeout)
562
+ if @@easy_connect_naming_regex =~ database && ($1 || $2 || $4 || $5 || $6 || $7)
563
+ connect_data = []
564
+ connect_data << "(SERVICE_NAME=#$5)"
565
+ connect_data << "(SERVER=#$6)" if $6
566
+ connect_data << "(INSTANCE_NAME=#$7)" if $7
567
+ desc = []
568
+ desc << "(CONNECT_DATA=#{connect_data.join})"
569
+ desc << "(ADDRESS=(PROTOCOL=TCP)(HOST=#{$2 || $3})(PORT=#{$4 || 1521}))"
570
+ if tcp_connect_timeout
571
+ desc << "(TRANSPORT_CONNECT_TIMEOUT=#{tcp_connect_timeout})"
572
+ end
573
+ if connect_timeout
574
+ desc << "(CONNECT_TIMEOUT=#{connect_timeout})"
575
+ end
576
+ "(DESCRIPTION=#{desc.join})"
577
+ else
578
+ database
579
+ end
580
+ end
445
581
  end
446
582
 
447
583
  class OCIError
@@ -425,22 +425,6 @@ class OCIHandle
425
425
  # @private
426
426
  OCI_CRED_EXT = 2
427
427
 
428
- #################################
429
- #
430
- # Authentication Modes
431
- #
432
- #################################
433
-
434
- # for SYSDBA authorization
435
- # @private
436
- OCI_SYSDBA = 0x0002
437
- # for SYSOPER authorization
438
- # @private
439
- OCI_SYSOPER = 0x0004
440
- # for SYSASM authorization
441
- # @private
442
- OCI_SYSASM = 0x8000
443
-
444
428
  #################################
445
429
  #
446
430
  # OCI Parameter Types
@@ -13,6 +13,10 @@ class OCI8
13
13
  :statement_cache_size => 0,
14
14
  :events_mode => ((OCI8.__get_prop(2) & 4) != 0), # 4 <- OCI_EVENTS in oci.h
15
15
  :cancel_read_at_exit => false,
16
+ :tcp_connect_timeout => nil,
17
+ :connect_timeout => nil,
18
+ :send_timeout => nil,
19
+ :recv_timeout => nil,
16
20
  }
17
21
 
18
22
  # @private
@@ -53,6 +57,11 @@ class OCI8
53
57
  when :cancel_read_at_exit
54
58
  val = val ? true : false
55
59
  OCI8.__set_prop(3, val)
60
+ when :tcp_connect_timeout, :connect_timeout, :send_timeout, :recv_timeout
61
+ if !val.nil?
62
+ val = val.to_i
63
+ raise ArgumentError, "The property value for :#{name} must be nil or a positive integer." if val <= 0
64
+ end
56
65
  end
57
66
  super(name, val)
58
67
  end
@@ -132,6 +141,30 @@ class OCI8
132
141
  #
133
142
  # *Since:* 2.1.8
134
143
  #
144
+ # [:tcp_connect_timeout]
145
+ #
146
+ # See {file:docs/timeout-parameters.md}
147
+ #
148
+ # *Since:* 2.2.2
149
+ #
150
+ # [:connect_timeout]
151
+ #
152
+ # See {file:docs/timeout-parameters.md}
153
+ #
154
+ # *Since:* 2.2.2
155
+ #
156
+ # [:send_timeout]
157
+ #
158
+ # See {file:docs/timeout-parameters.md}
159
+ #
160
+ # *Since:* 2.2.2
161
+ #
162
+ # [:recv_timeout]
163
+ #
164
+ # See {file:docs/timeout-parameters.md}
165
+ #
166
+ # *Since:* 2.2.2
167
+ #
135
168
  # @return [a customized Hash]
136
169
  # @since 2.0.5
137
170
  #
@@ -1,3 +1,3 @@
1
1
  class OCI8
2
- VERSION = "2.2.1"
2
+ VERSION = "2.2.2"
3
3
  end
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,4 @@
1
+ if caller[0] !~ /\/bundler\/runtime\.rb:\d+:in `require'/
2
+ warn "Don't requie 'ruby-oci8'. Use \"require 'oci8'\" instead. 'ruby-oci8.rb' was added only for 'Bundler.require'."
3
+ end
4
+ require 'oci8'
@@ -37,7 +37,7 @@ EOS
37
37
  s.has_rdoc = 'yard'
38
38
  s.authors = ['Kubo Takehiro']
39
39
  s.platform = gem_platform
40
- s.license = '2-clause BSD-style license'
40
+ s.license = 'BSD-2-Clause'
41
41
  files = File.read('dist-files').split("\n")
42
42
  if gem_platform == Gem::Platform::RUBY
43
43
  s.extensions << 'ext/oci8/extconf.rb'
@@ -10,6 +10,10 @@ drop type rb_test_obj_elem_array
10
10
  /
11
11
  drop type rb_test_obj_elem
12
12
  /
13
+ drop type rb_test_obj_sub
14
+ /
15
+ drop type rb_test_obj_base
16
+ /
13
17
  create type rb_test_obj_elem as object (
14
18
  x integer,
15
19
  y integer
@@ -116,7 +120,7 @@ create or replace type body rb_test_obj is
116
120
 
117
121
  static function test_object_version return integer is
118
122
  begin
119
- return 2;
123
+ return 3;
120
124
  end;
121
125
 
122
126
  static function class_func(n number) return rb_test_obj is
@@ -167,5 +171,21 @@ begin
167
171
  end loop;
168
172
  end;
169
173
  /
170
- commit
174
+
175
+ create type rb_test_obj_base as object (
176
+ id varchar2(30)
177
+ ) not final
178
+ /
179
+ create type rb_test_obj_sub under rb_test_obj_base (
180
+ subid varchar2(30)
181
+ ) final
182
+ /
183
+ create or replace function rb_test_obj_get_object(get_base integer) return rb_test_obj_base is
184
+ begin
185
+ if get_base = 0 then
186
+ return rb_test_obj_base('base');
187
+ else
188
+ return rb_test_obj_sub('sub', 'subid');
189
+ end if;
190
+ end;
171
191
  /
@@ -5,6 +5,7 @@ require "#{srcdir}/config"
5
5
 
6
6
  require "#{srcdir}/test_oradate"
7
7
  require "#{srcdir}/test_oranumber"
8
+ require "#{srcdir}/test_bind_array.rb"
8
9
  require "#{srcdir}/test_bind_string"
9
10
  require "#{srcdir}/test_bind_time"
10
11
  require "#{srcdir}/test_bind_raw"
@@ -75,4 +75,130 @@ class TestConnStr < Minitest::Test
75
75
  end
76
76
  end
77
77
  end
78
+
79
+ # https://docs.oracle.com/database/121/NETAG/naming.htm#BABJBFHJ
80
+ DESC_TEST_CASE =
81
+ [
82
+ # Cannot distinguish net service names from easy connect strings in this case.
83
+ ["sales-server", nil, nil, "sales-server"],
84
+ # Easy Connect string with host.
85
+ ["//sales-server", nil, nil, <<EOS],
86
+ (DESCRIPTION=
87
+ (CONNECT_DATA=
88
+ (SERVICE_NAME=))
89
+ (ADDRESS=
90
+ (PROTOCOL=TCP)
91
+ (HOST=sales-server)
92
+ (PORT=1521)))
93
+ EOS
94
+ # Easy Connect string with host and port.
95
+ ["sales-server:3456", nil, nil, <<EOS],
96
+ (DESCRIPTION=
97
+ (CONNECT_DATA=
98
+ (SERVICE_NAME=))
99
+ (ADDRESS=
100
+ (PROTOCOL=TCP)
101
+ (HOST=sales-server)
102
+ (PORT=3456)))
103
+ EOS
104
+ # The host name is sales-server and the service name is sales.
105
+ ["sales-server/sales", nil, nil, <<EOS],
106
+ (DESCRIPTION=
107
+ (CONNECT_DATA=
108
+ (SERVICE_NAME=sales))
109
+ (ADDRESS=
110
+ (PROTOCOL=TCP)
111
+ (HOST=sales-server)
112
+ (PORT=1521)))
113
+ EOS
114
+ # Easy Connect string with IPv6 address.
115
+ ["[2001:0db8:0:0::200C:417A]:80/sales", nil, nil, <<EOS],
116
+ (DESCRIPTION=
117
+ (CONNECT_DATA=
118
+ (SERVICE_NAME=sales))
119
+ (ADDRESS=
120
+ (PROTOCOL=TCP)
121
+ (HOST=2001:0db8:0:0::200C:417A)
122
+ (PORT=80)))
123
+ EOS
124
+ # Easy Connect string with IPv6 host address.
125
+ ["sales-server:80/sales", nil, nil, <<EOS],
126
+ (DESCRIPTION=
127
+ (CONNECT_DATA=
128
+ (SERVICE_NAME=sales))
129
+ (ADDRESS=
130
+ (PROTOCOL=TCP)
131
+ (HOST=sales-server)
132
+ (PORT=80)))
133
+ EOS
134
+ # Easy Connect string with host, service name, and server.
135
+ ["sales-server/sales:dedicated/inst1", nil, nil, <<EOS],
136
+ (DESCRIPTION=
137
+ (CONNECT_DATA=
138
+ (SERVICE_NAME=sales)
139
+ (SERVER=dedicated)
140
+ (INSTANCE_NAME=inst1))
141
+ (ADDRESS=
142
+ (PROTOCOL=TCP)
143
+ (HOST=sales-server)
144
+ (PORT=1521)))
145
+ EOS
146
+ ["sales-server//inst1", nil, nil, <<EOS],
147
+ (DESCRIPTION=
148
+ (CONNECT_DATA=
149
+ (SERVICE_NAME=)
150
+ (INSTANCE_NAME=inst1))
151
+ (ADDRESS=
152
+ (PROTOCOL=TCP)
153
+ (HOST=sales-server)
154
+ (PORT=1521)))
155
+ EOS
156
+ #
157
+ ["sales-server/sales", 20, nil, <<EOS],
158
+ (DESCRIPTION=
159
+ (CONNECT_DATA=
160
+ (SERVICE_NAME=sales))
161
+ (ADDRESS=
162
+ (PROTOCOL=TCP)
163
+ (HOST=sales-server)
164
+ (PORT=1521))
165
+ (TRANSPORT_CONNECT_TIMEOUT=20))
166
+ EOS
167
+ #
168
+ ["sales-server/sales", nil, 30, <<EOS],
169
+ (DESCRIPTION=
170
+ (CONNECT_DATA=
171
+ (SERVICE_NAME=sales))
172
+ (ADDRESS=
173
+ (PROTOCOL=TCP)
174
+ (HOST=sales-server)
175
+ (PORT=1521))
176
+ (CONNECT_TIMEOUT=30))
177
+ EOS
178
+ #
179
+ ["sales-server/sales", 20, 30, <<EOS],
180
+ (DESCRIPTION=
181
+ (CONNECT_DATA=
182
+ (SERVICE_NAME=sales))
183
+ (ADDRESS=
184
+ (PROTOCOL=TCP)
185
+ (HOST=sales-server)
186
+ (PORT=1521))
187
+ (TRANSPORT_CONNECT_TIMEOUT=20)
188
+ (CONNECT_TIMEOUT=30))
189
+ EOS
190
+ ]
191
+
192
+ def test_connect_descriptor
193
+ obj = OCI8.allocate # create an uninitialized object.
194
+ DESC_TEST_CASE.each do |test_case|
195
+ easy_connect_string = test_case[0]
196
+ tcp_connnect_timeout= test_case[1]
197
+ outbound_connnect_timeout = test_case[2]
198
+ expected_result = test_case[3].gsub(/\s/, '')
199
+ # use instance_eval to call a private method to_connect_descriptor
200
+ result = obj.instance_eval { to_connect_descriptor(easy_connect_string, tcp_connnect_timeout, outbound_connnect_timeout) }
201
+ assert_equal(expected_result, result, easy_connect_string)
202
+ end
203
+ end
78
204
  end
@@ -22,7 +22,7 @@ begin
22
22
 
23
23
  begin
24
24
  version = RbTestObj.test_object_version(conn)
25
- error_message = "Invalid test object version" if version != 2
25
+ error_message = "Invalid test object version" if version != 3
26
26
  rescue NoMethodError
27
27
  raise unless $!.to_s.include?('test_object_version')
28
28
  error_message = "rb_test_obj.test_object_version is not declared."
@@ -48,6 +48,12 @@ EOS
48
48
  class RbTestIntArray < OCI8::Object::Base
49
49
  end
50
50
 
51
+ class RbTestObjBase < OCI8::Object::Base
52
+ end
53
+
54
+ class RbTestObjSub < RbTestObjBase
55
+ end
56
+
51
57
  class TestObj1 < Minitest::Test
52
58
  Delta = 0.00001
53
59
 
@@ -456,4 +462,23 @@ EOS
456
462
  assert_equal(ary ? ary[2] : nil, csr[:out3])
457
463
  end
458
464
  end
465
+
466
+ def test_get_subtype
467
+ csr = @conn.parse("BEGIN :result := rb_test_obj_get_object(:1); END;")
468
+ csr.bind_param(1, nil, RbTestObjBase)
469
+ csr.bind_param(2, nil, Integer)
470
+
471
+ csr[2] = 0
472
+ csr.exec
473
+ val = csr[1]
474
+ assert_instance_of(RbTestObjBase, val)
475
+ assert_equal(val.id, 'base')
476
+
477
+ csr[2] = 1
478
+ csr.exec
479
+ val = csr[1]
480
+ assert_instance_of(RbTestObjSub, val)
481
+ assert_equal(val.id, 'sub')
482
+ assert_equal(val.subid, 'subid')
483
+ end
459
484
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-oci8
3
3
  version: !ruby/object:Gem::Version
4
- hash: 5
4
+ hash: 3
5
5
  prerelease: false
6
6
  segments:
7
7
  - 2
8
8
  - 2
9
- - 1
10
- version: 2.2.1
9
+ - 2
10
+ version: 2.2.2
11
11
  platform: x86-mingw32
12
12
  authors:
13
13
  - Kubo Takehiro
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2015-11-01 00:00:00 +09:00
18
+ date: 2016-04-24 00:00:00 +09:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -42,13 +42,16 @@ files:
42
42
  - pre-distclean.rb
43
43
  - ruby-oci8.gemspec
44
44
  - setup.rb
45
+ - docs/bind-array-to-in_cond.md
45
46
  - docs/install-binary-package.md
46
47
  - docs/install-full-client.md
47
48
  - docs/install-instant-client.md
48
49
  - docs/install-on-osx.md
50
+ - docs/conflicts-local-connections-and-processes.md
49
51
  - docs/osx-install-dev-tools.png
50
52
  - docs/platform-specific-issues.md
51
53
  - docs/report-installation-issue.md
54
+ - docs/timeout-parameters.md
52
55
  - lib/.document
53
56
  - lib/oci8.rb
54
57
  - lib/dbd/OCI8.rb
@@ -68,6 +71,7 @@ files:
68
71
  - lib/oci8/oracle_version.rb
69
72
  - lib/oci8/properties.rb
70
73
  - lib/oci8/version.rb
74
+ - lib/ruby-oci8.rb
71
75
  - test/README
72
76
  - test/config.rb
73
77
  - test/setup_test_object.sql
@@ -96,12 +100,13 @@ files:
96
100
  - test/test_rowid.rb
97
101
  - lib/oci8lib_220.so
98
102
  - lib/oci8lib_191.so
103
+ - lib/oci8lib_230.so
99
104
  - lib/oci8lib_200.so
100
105
  - lib/oci8lib_210.so
101
106
  has_rdoc: true
102
107
  homepage: http://www.rubydoc.info/github/kubo/ruby-oci8
103
108
  licenses:
104
- - 2-clause BSD-style license
109
+ - BSD-2-Clause
105
110
  post_install_message:
106
111
  rdoc_options: []
107
112