ruby-oci8 2.2.0.2 → 2.2.12
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.
- checksums.yaml +7 -0
- data/.yardopts +1 -6
- data/ChangeLog +600 -0
- data/NEWS +426 -35
- data/README.md +27 -9
- data/dist-files +13 -2
- data/docs/bind-array-to-in_cond.md +38 -0
- data/docs/conflicts-local-connections-and-processes.md +98 -0
- data/docs/hanging-after-inactivity.md +63 -0
- data/docs/install-binary-package.md +15 -11
- data/docs/install-full-client.md +18 -21
- data/docs/install-instant-client.md +45 -27
- data/docs/install-on-osx.md +31 -117
- data/docs/ldap-auth-and-function-interposition.md +123 -0
- data/docs/number-type-mapping.md +79 -0
- data/docs/platform-specific-issues.md +17 -50
- data/docs/report-installation-issue.md +11 -8
- data/docs/timeout-parameters.md +94 -0
- data/ext/oci8/apiwrap.c.tmpl +2 -5
- data/ext/oci8/apiwrap.rb +6 -1
- data/ext/oci8/apiwrap.yml +39 -143
- data/ext/oci8/attr.c +4 -2
- data/ext/oci8/bind.c +421 -9
- data/ext/oci8/connection_pool.c +3 -3
- data/ext/oci8/encoding.c +5 -5
- data/ext/oci8/env.c +8 -2
- data/ext/oci8/error.c +24 -16
- data/ext/oci8/extconf.rb +35 -63
- data/ext/oci8/hook_funcs.c +274 -61
- data/ext/oci8/lob.c +31 -75
- data/ext/oci8/metadata.c +8 -6
- data/ext/oci8/object.c +119 -29
- data/ext/oci8/oci8.c +46 -133
- data/ext/oci8/oci8.h +40 -123
- data/ext/oci8/oci8lib.c +178 -46
- data/ext/oci8/ocihandle.c +37 -37
- data/ext/oci8/ocinumber.c +24 -35
- data/ext/oci8/oraconf.rb +168 -337
- data/ext/oci8/oradate.c +19 -19
- data/ext/oci8/plthook.h +10 -0
- data/ext/oci8/plthook_elf.c +433 -268
- data/ext/oci8/plthook_osx.c +40 -9
- data/ext/oci8/plthook_win32.c +16 -1
- data/ext/oci8/stmt.c +52 -17
- data/ext/oci8/win32.c +4 -22
- data/lib/oci8/bindtype.rb +10 -17
- data/lib/oci8/check_load_error.rb +57 -10
- data/lib/oci8/compat.rb +5 -1
- data/lib/oci8/connection_pool.rb +74 -3
- data/lib/oci8/cursor.rb +70 -31
- data/lib/oci8/metadata.rb +9 -1
- data/lib/oci8/object.rb +14 -1
- data/lib/oci8/oci8.rb +184 -58
- data/lib/oci8/ocihandle.rb +0 -16
- data/lib/oci8/oracle_version.rb +11 -1
- data/lib/oci8/properties.rb +55 -0
- data/lib/oci8/version.rb +1 -1
- data/lib/oci8.rb +48 -4
- data/lib/ruby-oci8.rb +1 -0
- data/pre-distclean.rb +1 -3
- data/ruby-oci8.gemspec +4 -9
- data/setup.rb +11 -2
- data/test/README.md +37 -0
- data/test/config.rb +8 -1
- data/test/setup_test_object.sql +42 -14
- data/test/setup_test_package.sql +59 -0
- data/test/test_all.rb +4 -0
- data/test/test_bind_array.rb +70 -0
- data/test/test_bind_boolean.rb +99 -0
- data/test/test_bind_integer.rb +47 -0
- data/test/test_break.rb +11 -9
- data/test/test_clob.rb +5 -17
- data/test/test_connstr.rb +142 -0
- data/test/test_datetime.rb +8 -3
- data/test/test_metadata.rb +2 -1
- data/test/test_object.rb +99 -18
- data/test/test_oci8.rb +170 -46
- data/test/test_oranumber.rb +12 -6
- data/test/test_package_type.rb +17 -3
- data/test/test_properties.rb +17 -0
- metadata +45 -55
- data/docs/osx-install-dev-tools.png +0 -0
- data/test/README +0 -42
data/lib/oci8/properties.rb
CHANGED
@@ -13,6 +13,12 @@ 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,
|
20
|
+
:tcp_keepalive => false,
|
21
|
+
:tcp_keepalive_time => nil,
|
16
22
|
}
|
17
23
|
|
18
24
|
# @private
|
@@ -53,6 +59,19 @@ class OCI8
|
|
53
59
|
when :cancel_read_at_exit
|
54
60
|
val = val ? true : false
|
55
61
|
OCI8.__set_prop(3, val)
|
62
|
+
when :tcp_connect_timeout, :connect_timeout, :send_timeout, :recv_timeout
|
63
|
+
if !val.nil?
|
64
|
+
val = val.to_i
|
65
|
+
raise ArgumentError, "The property value for :#{name} must be nil or a positive integer." if val <= 0
|
66
|
+
end
|
67
|
+
when :tcp_keepalive
|
68
|
+
val = val ? true : false
|
69
|
+
when :tcp_keepalive_time
|
70
|
+
if !val.nil?
|
71
|
+
val = val.to_i
|
72
|
+
raise ArgumentError, "The property value for :#{name} must be nil or a positive integer." if val <= 0
|
73
|
+
end
|
74
|
+
OCI8.__set_prop(4, val)
|
56
75
|
end
|
57
76
|
super(name, val)
|
58
77
|
end
|
@@ -132,6 +151,42 @@ class OCI8
|
|
132
151
|
#
|
133
152
|
# *Since:* 2.1.8
|
134
153
|
#
|
154
|
+
# [:tcp_connect_timeout]
|
155
|
+
#
|
156
|
+
# See {file:docs/timeout-parameters.md}
|
157
|
+
#
|
158
|
+
# *Since:* 2.2.2
|
159
|
+
#
|
160
|
+
# [:connect_timeout]
|
161
|
+
#
|
162
|
+
# See {file:docs/timeout-parameters.md}
|
163
|
+
#
|
164
|
+
# *Since:* 2.2.2
|
165
|
+
#
|
166
|
+
# [:send_timeout]
|
167
|
+
#
|
168
|
+
# See {file:docs/timeout-parameters.md}
|
169
|
+
#
|
170
|
+
# *Since:* 2.2.2
|
171
|
+
#
|
172
|
+
# [:recv_timeout]
|
173
|
+
#
|
174
|
+
# See {file:docs/timeout-parameters.md}
|
175
|
+
#
|
176
|
+
# *Since:* 2.2.2
|
177
|
+
#
|
178
|
+
# [:tcp_keepalive]
|
179
|
+
#
|
180
|
+
# See {file:docs/hanging-after-inactivity.md}
|
181
|
+
#
|
182
|
+
# *Since:* 2.2.4
|
183
|
+
#
|
184
|
+
# [:tcp_keepalive_time]
|
185
|
+
#
|
186
|
+
# See {file:docs/hanging-after-inactivity.md}
|
187
|
+
#
|
188
|
+
# *Since:* 2.2.4
|
189
|
+
#
|
135
190
|
# @return [a customized Hash]
|
136
191
|
# @since 2.0.5
|
137
192
|
#
|
data/lib/oci8/version.rb
CHANGED
data/lib/oci8.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
# --*- ruby -*--
|
3
2
|
# This is based on yoshidam's oracle.rb.
|
4
3
|
#
|
@@ -12,8 +11,11 @@ if RUBY_PLATFORM =~ /cygwin/
|
|
12
11
|
# Cygwin manages environment variables by itself.
|
13
12
|
# They don't synchroize with Win32's ones.
|
14
13
|
# This set some Oracle's environment variables to win32's enviroment.
|
15
|
-
require '
|
16
|
-
win32setenv =
|
14
|
+
require 'fiddle'
|
15
|
+
win32setenv = Fiddle::Function.new( Fiddle.dlopen('Kernel32.dll')['SetEnvironmentVariableA'],
|
16
|
+
[Fiddle::TYPE_VOIDP,Fiddle::TYPE_VOIDP],
|
17
|
+
Fiddle::TYPE_INT )
|
18
|
+
|
17
19
|
['NLS_LANG', 'TNS_ADMIN', 'LOCAL'].each do |name|
|
18
20
|
val = ENV[name]
|
19
21
|
win32setenv.call(name, val && val.dup)
|
@@ -64,16 +66,56 @@ when 'rbx'
|
|
64
66
|
so_basename += 'rbx'
|
65
67
|
when 'jruby'
|
66
68
|
raise "Ruby-oci8 doesn't support jruby because its C extension support is in development in jruby 1.6 and deprecated in jruby 1.7."
|
69
|
+
when 'truffleruby'
|
70
|
+
so_basename += 'truffleruby'
|
67
71
|
else
|
68
72
|
raise 'unsupported ruby engine: ' + RUBY_ENGINE
|
69
73
|
end
|
70
74
|
|
75
|
+
dll_dir = nil
|
76
|
+
begin
|
77
|
+
require 'ruby_installer/runtime' # RubyInstaller2 for Windows
|
78
|
+
|
79
|
+
dll_arch = proc do |file|
|
80
|
+
begin
|
81
|
+
File.open(file, 'rb') do |f|
|
82
|
+
if f.read(2) == 'MZ' # IMAGE_DOS_HEADER.e_magic
|
83
|
+
f.seek(60, IO::SEEK_SET)
|
84
|
+
pe_offset = f.read(4).unpack('V')[0] # IMAGE_DOS_HEADER.e_lfanew
|
85
|
+
f.seek(pe_offset)
|
86
|
+
if f.read(4) == "PE\000\000" # IMAGE_NT_HEADERS.Signature
|
87
|
+
case f.read(2).unpack('v')[0] # IMAGE_FILE_HEADER.Machine
|
88
|
+
when 0x014c # IMAGE_FILE_MACHINE_I386
|
89
|
+
:x86
|
90
|
+
when 0x8664 # IMAGE_FILE_MACHINE_AMD64
|
91
|
+
:x64
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
rescue
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
ruby_arch = [nil].pack('P').size == 8 ? :x64 : :x86
|
102
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
103
|
+
if !path.empty? && dll_arch.call(File.join(path, 'OCI.DLL')) == ruby_arch
|
104
|
+
dll_dir = RubyInstaller::Runtime.add_dll_directory(path)
|
105
|
+
break
|
106
|
+
end
|
107
|
+
end
|
108
|
+
rescue LoadError
|
109
|
+
end
|
110
|
+
|
71
111
|
begin
|
72
112
|
require so_basename
|
73
|
-
rescue LoadError
|
113
|
+
rescue LoadError
|
74
114
|
require 'oci8/check_load_error'
|
75
115
|
OCI8::Util::check_load_error($!)
|
76
116
|
raise
|
117
|
+
ensure
|
118
|
+
dll_dir.remove if dll_dir
|
77
119
|
end
|
78
120
|
|
79
121
|
require 'oci8/version.rb'
|
@@ -103,6 +145,8 @@ class OCI8
|
|
103
145
|
ORAVER_11_1 = OCI8::OracleVersion.new(11, 1)
|
104
146
|
# @private
|
105
147
|
ORAVER_12_1 = OCI8::OracleVersion.new(12, 1)
|
148
|
+
# @private
|
149
|
+
ORAVER_18 = OCI8::OracleVersion.new(18)
|
106
150
|
|
107
151
|
# @private
|
108
152
|
@@oracle_client_version = OCI8::OracleVersion.new(self.oracle_client_vernum)
|
data/lib/ruby-oci8.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'oci8'
|
data/pre-distclean.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
rm_f "#{curr_objdir}/
|
2
|
-
rm_f "#{curr_objdir}/ext/oci8/oci8lib_18.map"
|
3
|
-
rm_f "#{curr_objdir}/ext/oci8/oci8lib_191.map"
|
1
|
+
rm_f "#{curr_objdir}/ext/oci8/oci8lib_*.map"
|
4
2
|
if RUBY_PLATFORM =~ /cygwin/
|
5
3
|
rm_f "#{curr_objdir}/ext/oci8/OCI.def"
|
6
4
|
rm_f "#{curr_objdir}/ext/oci8/libOCI.a"
|
data/ruby-oci8.gemspec
CHANGED
@@ -34,10 +34,9 @@ spec = Gem::Specification.new do |s|
|
|
34
34
|
s.description = <<EOS
|
35
35
|
ruby-oci8 is a ruby interface for Oracle using OCI8 API. It is available with Oracle 10g or later including Oracle Instant Client.
|
36
36
|
EOS
|
37
|
-
s.has_rdoc = 'yard'
|
38
37
|
s.authors = ['Kubo Takehiro']
|
39
38
|
s.platform = gem_platform
|
40
|
-
s.license = '2-
|
39
|
+
s.license = 'BSD-2-Clause'
|
41
40
|
files = File.read('dist-files').split("\n")
|
42
41
|
if gem_platform == Gem::Platform::RUBY
|
43
42
|
s.extensions << 'ext/oci8/extconf.rb'
|
@@ -51,7 +50,7 @@ EOS
|
|
51
50
|
# add map files to analyze a core (minidump) file.
|
52
51
|
so_vers.each do |ver|
|
53
52
|
map_file = 'ext/oci8/oci8lib_#{ver}.map'
|
54
|
-
so_files << map_file if File.
|
53
|
+
so_files << map_file if File.exist? map_file
|
55
54
|
end
|
56
55
|
|
57
56
|
# least version in so_vers
|
@@ -64,11 +63,7 @@ EOS
|
|
64
63
|
raise "No compiled binary are found. Run make in advance."
|
65
64
|
when 1
|
66
65
|
puts "Binary gem for ruby #{so_vers.first}"
|
67
|
-
|
68
|
-
s.required_ruby_version = "~> #{so_vermin}"
|
69
|
-
else
|
70
|
-
s.required_ruby_version = "~> #{so_vermin}.0"
|
71
|
-
end
|
66
|
+
s.required_ruby_version = "~> #{so_vermin}"
|
72
67
|
else
|
73
68
|
puts "Binary gem for ruby #{so_vers.join(', ')}"
|
74
69
|
s.required_ruby_version = ">= #{so_vermin}"
|
@@ -83,7 +78,7 @@ EOS
|
|
83
78
|
end
|
84
79
|
files << 'lib/oci8.rb'
|
85
80
|
end
|
86
|
-
s.require_paths = ['lib'
|
81
|
+
s.require_paths = ['lib']
|
87
82
|
s.files = files
|
88
83
|
s.test_files = 'test/test_all.rb'
|
89
84
|
s.extra_rdoc_files = ['README.md']
|
data/setup.rb
CHANGED
@@ -189,7 +189,16 @@ class ConfigTable
|
|
189
189
|
'the make program to compile ruby extentions' ] ],
|
190
190
|
[ 'without-ext', [ 'no',
|
191
191
|
'yes/no',
|
192
|
-
'does not compile/install ruby extentions' ] ]
|
192
|
+
'does not compile/install ruby extentions' ] ],
|
193
|
+
[ 'with-instant-client-dir', ['',
|
194
|
+
'path',
|
195
|
+
'path to the Oracle instant client directory'] ],
|
196
|
+
[ 'with-instant-client-lib', ['',
|
197
|
+
'path',
|
198
|
+
'path to the Oracle instant client libraries'] ],
|
199
|
+
[ 'with-instant-client-include', ['',
|
200
|
+
'path',
|
201
|
+
'path to the Oracle instant client header files'] ]
|
193
202
|
]
|
194
203
|
multipackage_descripters = [
|
195
204
|
[ 'with', [ '',
|
@@ -277,7 +286,7 @@ class ConfigTable
|
|
277
286
|
|
278
287
|
def initialize_from_table
|
279
288
|
@table = {}
|
280
|
-
DESCRIPTER.each do |k, (default,
|
289
|
+
DESCRIPTER.each do |k, (default, *)|
|
281
290
|
@table[k] = default
|
282
291
|
end
|
283
292
|
end
|
data/test/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
Before running unit test:
|
2
|
+
|
3
|
+
1. Connect to Oracle as sys
|
4
|
+
```shell
|
5
|
+
$ sqlplus sys/<password_of_sys> as sysdba
|
6
|
+
SQL>
|
7
|
+
```
|
8
|
+
2. Create user ruby
|
9
|
+
```sql
|
10
|
+
SQL> CREATE USER ruby IDENTIFIED BY oci8 DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp;
|
11
|
+
SQL> alter user ruby quota unlimited on users;
|
12
|
+
```
|
13
|
+
3. Grant the privilege to connect and execute.
|
14
|
+
```sql
|
15
|
+
SQL> GRANT connect, resource, create view, create synonym TO ruby;
|
16
|
+
SQL> GRANT execute ON dbms_lock TO ruby;
|
17
|
+
```
|
18
|
+
4. Connect as ruby user.
|
19
|
+
```shell
|
20
|
+
$ sqlplus ruby/oci8
|
21
|
+
SQL>
|
22
|
+
```
|
23
|
+
5. Create object types
|
24
|
+
```sql
|
25
|
+
SQL> @test/setup_test_object.sql
|
26
|
+
SQL> @test/setup_test_package.sql
|
27
|
+
```
|
28
|
+
6. change $dbname in test/config.rb.
|
29
|
+
|
30
|
+
Then run the following command:
|
31
|
+
```shell
|
32
|
+
$ make check
|
33
|
+
```
|
34
|
+
or
|
35
|
+
```
|
36
|
+
$ nmake check (If your compiler is MS Visual C++.)
|
37
|
+
````
|
data/test/config.rb
CHANGED
@@ -125,9 +125,16 @@ end
|
|
125
125
|
|
126
126
|
class Minitest::Test
|
127
127
|
|
128
|
+
# @!visibility private
|
129
|
+
# dirty hack to suppress "warning: constant ::Fixnum is deprecated"
|
130
|
+
Fixnum = (0.class == ::Integer) ? ::Integer : ::Fixnum
|
131
|
+
# @!visibility private
|
132
|
+
# dirty hack to suppress "warning: constant ::Bignum is deprecated"
|
133
|
+
Bignum = (0.class == ::Integer) ? ::Integer : ::Bignum
|
134
|
+
|
128
135
|
def get_oci8_connection()
|
129
136
|
OCI8.new($dbuser, $dbpass, $dbname)
|
130
|
-
|
137
|
+
rescue OCIError
|
131
138
|
raise if $!.code != 12516 && $!.code != 12520
|
132
139
|
# sleep a few second and try again if
|
133
140
|
# the error code is ORA-12516 or ORA-12520.
|
data/test/setup_test_object.sql
CHANGED
@@ -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
|
@@ -57,6 +61,8 @@ create type rb_test_obj as object (
|
|
57
61
|
obj_array_val rb_test_obj_elem_array,
|
58
62
|
obj_ary_of_ary_val rb_test_obj_elem_ary_of_ary,
|
59
63
|
date_val date,
|
64
|
+
timestamp_val timestamp(9),
|
65
|
+
timestamp_tz_val timestamp(9) with time zone,
|
60
66
|
-- date_array_val rb_test_date_array,
|
61
67
|
|
62
68
|
constructor function rb_test_obj(n number) return self as result,
|
@@ -68,19 +74,23 @@ create type rb_test_obj as object (
|
|
68
74
|
member procedure member_proc(n in integer)
|
69
75
|
)
|
70
76
|
/
|
71
|
-
create
|
72
|
-
|
77
|
+
create type body rb_test_obj is
|
73
78
|
constructor function rb_test_obj(n number) return self as result is
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
to_char(mod(round(n) * 5, 12) + 1, 'FM00') ||
|
78
|
-
to_char(mod(round(n) * 7, 27) + 1, 'FM00') ||
|
79
|
-
to_char(mod(round(n) * 9, 24), 'FM00') ||
|
80
|
-
to_char(mod(round(n) * 11, 60), 'FM00') ||
|
81
|
-
to_char(mod(round(n) * 13, 60), 'FM00'), 'yyyymmddhh24miss');
|
82
|
-
end;
|
79
|
+
str varchar(28);
|
80
|
+
ts timestamp(9);
|
81
|
+
ts_tz timestamp(9) with time zone;
|
83
82
|
begin
|
83
|
+
str := to_char(1990 + n, 'FM0000') ||
|
84
|
+
to_char(mod(round(n) * 5, 12) + 1, 'FM00') ||
|
85
|
+
to_char(mod(round(n) * 7, 27) + 1, 'FM00') ||
|
86
|
+
to_char(mod(round(n) * 9, 24), 'FM00') ||
|
87
|
+
to_char(mod(round(n) * 11, 60), 'FM00') ||
|
88
|
+
to_char(mod(round(n) * 13, 60), 'FM00') ||
|
89
|
+
to_char(mod(round(n) * 333333333, 1000000000), 'FM000000000');
|
90
|
+
ts := to_timestamp(str, 'yyyymmddhh24missff9');
|
91
|
+
str := str || to_char(mod(round(n) * 15, 24) - 11, 'FMS00') ||
|
92
|
+
to_char(mod(round(n) * 17, 60), 'FM00');
|
93
|
+
ts_tz := to_timestamp_tz(str, 'yyyymmddhh24missff9tzhtzm');
|
84
94
|
self.int_val := n;
|
85
95
|
self.flt_val := n;
|
86
96
|
self.num_val := n;
|
@@ -92,7 +102,9 @@ create or replace type body rb_test_obj is
|
|
92
102
|
self.nclob_val := to_clob(n);
|
93
103
|
self.blob_val := to_blob(utl_raw.cast_to_raw(to_char(n)));
|
94
104
|
self.obj_val := rb_test_obj_elem(n, n + 1);
|
95
|
-
self.date_val :=
|
105
|
+
self.date_val := ts;
|
106
|
+
self.timestamp_val := ts;
|
107
|
+
self.timestamp_tz_val := ts_tz;
|
96
108
|
if self.int_val != 1 then
|
97
109
|
self.int_array_val := rb_test_int_array(n, n + 1, n + 2);
|
98
110
|
self.flt_array_val := rb_test_flt_array(n, n + 1, n + 2);
|
@@ -116,7 +128,7 @@ create or replace type body rb_test_obj is
|
|
116
128
|
|
117
129
|
static function test_object_version return integer is
|
118
130
|
begin
|
119
|
-
return
|
131
|
+
return 4;
|
120
132
|
end;
|
121
133
|
|
122
134
|
static function class_func(n number) return rb_test_obj is
|
@@ -167,5 +179,21 @@ begin
|
|
167
179
|
end loop;
|
168
180
|
end;
|
169
181
|
/
|
170
|
-
|
182
|
+
|
183
|
+
create type rb_test_obj_base as object (
|
184
|
+
id varchar2(30)
|
185
|
+
) not final
|
186
|
+
/
|
187
|
+
create type rb_test_obj_sub under rb_test_obj_base (
|
188
|
+
subid varchar2(30)
|
189
|
+
) final
|
190
|
+
/
|
191
|
+
create or replace function rb_test_obj_get_object(get_base integer) return rb_test_obj_base is
|
192
|
+
begin
|
193
|
+
if get_base = 0 then
|
194
|
+
return rb_test_obj_base('base');
|
195
|
+
else
|
196
|
+
return rb_test_obj_sub('sub', 'subid');
|
197
|
+
end if;
|
198
|
+
end;
|
171
199
|
/
|
@@ -0,0 +1,59 @@
|
|
1
|
+
create or replace package rb_test_pkg is
|
2
|
+
package_version pls_integer := 1;
|
3
|
+
|
4
|
+
type array_of_integer is array(50) of integer;
|
5
|
+
type table_of_pls_integer is table of pls_integer;
|
6
|
+
type table_of_boolean is table of boolean;
|
7
|
+
type indexed_table_of_varchar2 is table of varchar2(10) index by varchar2(5);
|
8
|
+
type rec1 is record (i pls_integer, j integer);
|
9
|
+
type rec2 is record (b boolean, it indexed_table_of_varchar2, rec rec1);
|
10
|
+
type table_of_rec1 is table of rec1;
|
11
|
+
type table_of_rec2 is table of rec2;
|
12
|
+
|
13
|
+
function sum_table_of_pls_integer(tbl in table_of_pls_integer) return pls_integer;
|
14
|
+
function add_rec1_values(tbl in table_of_rec1) return pls_integer;
|
15
|
+
procedure out_rec1_values(tbl out table_of_rec1);
|
16
|
+
end;
|
17
|
+
/
|
18
|
+
create or replace package body rb_test_pkg is
|
19
|
+
function sum_table_of_pls_integer(tbl in table_of_pls_integer) return pls_integer is
|
20
|
+
i pls_integer;
|
21
|
+
ret pls_integer := 0;
|
22
|
+
begin
|
23
|
+
for i in tbl.first..tbl.last loop
|
24
|
+
ret := ret + tbl(i);
|
25
|
+
end loop;
|
26
|
+
return ret;
|
27
|
+
end;
|
28
|
+
|
29
|
+
function add_rec1_values(tbl in table_of_rec1) return pls_integer is
|
30
|
+
i pls_integer;
|
31
|
+
ret pls_integer := 0;
|
32
|
+
begin
|
33
|
+
for i in tbl.first..tbl.last loop
|
34
|
+
ret := ret + nvl(tbl(i).i, 0) + nvl(tbl(i).j, 0);
|
35
|
+
end loop;
|
36
|
+
return ret;
|
37
|
+
end;
|
38
|
+
|
39
|
+
procedure out_rec1_values(tbl out table_of_rec1) is
|
40
|
+
i pls_integer;
|
41
|
+
rec1val rec1;
|
42
|
+
begin
|
43
|
+
tbl := table_of_rec1();
|
44
|
+
for i in 1..20 loop
|
45
|
+
tbl.extend;
|
46
|
+
if i mod 6 != 0 then
|
47
|
+
if i mod 3 != 0 then
|
48
|
+
rec1val.i := i;
|
49
|
+
rec1val.j := i;
|
50
|
+
else
|
51
|
+
rec1val.i := null;
|
52
|
+
rec1val.j := null;
|
53
|
+
end if;
|
54
|
+
tbl(i) := rec1val;
|
55
|
+
end if;
|
56
|
+
end loop;
|
57
|
+
end;
|
58
|
+
end;
|
59
|
+
/
|
data/test/test_all.rb
CHANGED
@@ -5,9 +5,11 @@ 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"
|
12
|
+
require "#{srcdir}/test_bind_integer"
|
11
13
|
if $test_clob
|
12
14
|
require "#{srcdir}/test_clob"
|
13
15
|
end
|
@@ -24,6 +26,7 @@ require "#{srcdir}/test_oracle_version"
|
|
24
26
|
require "#{srcdir}/test_error"
|
25
27
|
require "#{srcdir}/test_connection_pool"
|
26
28
|
require "#{srcdir}/test_object"
|
29
|
+
require "#{srcdir}/test_properties.rb"
|
27
30
|
|
28
31
|
if OCI8.respond_to? :encoding
|
29
32
|
require "#{srcdir}/test_encoding"
|
@@ -31,6 +34,7 @@ end
|
|
31
34
|
|
32
35
|
if $oracle_version >= OCI8::ORAVER_12_1
|
33
36
|
require "#{srcdir}/test_package_type"
|
37
|
+
require "#{srcdir}/test_bind_boolean.rb"
|
34
38
|
end
|
35
39
|
|
36
40
|
# Ruby/DBI
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'oci8'
|
2
|
+
require File.dirname(__FILE__) + '/config'
|
3
|
+
|
4
|
+
class TestBindArray < Minitest::Test
|
5
|
+
|
6
|
+
def test_bind_array_names
|
7
|
+
assert_equal(":id_0", OCI8::in_cond(:id, []).names)
|
8
|
+
assert_equal(":id_0", OCI8::in_cond(:id, [1]).names)
|
9
|
+
assert_equal(":id_0, :id_1", OCI8::in_cond(:id, [1, 2]).names)
|
10
|
+
assert_equal(":id_0, :id_1, :id_2", OCI8::in_cond(:id, [1, 2, 3]).names)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_bind_array_values
|
14
|
+
assert_equal([[nil, String, nil]], OCI8::in_cond(:id, []).values)
|
15
|
+
assert_equal([[1, nil, nil]], OCI8::in_cond(:id, [1]).values)
|
16
|
+
assert_equal([[1, nil, nil], [2, nil, nil]], OCI8::in_cond(:id, [1, 2]).values)
|
17
|
+
assert_equal([[1, nil, nil], [2, nil, nil], [3, nil, nil]], OCI8::in_cond(:id, [1, 2, 3]).values)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_bind_array_values_containg_nil
|
21
|
+
assert_equal([[nil, String]], OCI8::in_cond(:id, [nil]).values)
|
22
|
+
assert_equal([[nil, Fixnum], [2, nil, nil], [3, nil, nil]], OCI8::in_cond(:id, [nil, 2, 3]).values)
|
23
|
+
assert_equal([[1, nil, nil], [nil, Fixnum], [3, nil, nil]], OCI8::in_cond(:id, [1, nil, 3]).values)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_bind_array_values_with_type
|
27
|
+
assert_equal([[nil, Integer, nil]], OCI8::in_cond(:id, [], Integer).values)
|
28
|
+
assert_equal([[1, Integer, nil]], OCI8::in_cond(:id, [1], Integer).values)
|
29
|
+
assert_equal([[1, Integer, nil], [2, Integer, nil]], OCI8::in_cond(:id, [1, 2], Integer).values)
|
30
|
+
assert_equal([[1, Integer, nil], [2, Integer, nil], [3, Integer, nil]], OCI8::in_cond(:id, [1, 2, 3], Integer).values)
|
31
|
+
assert_equal([[nil, Integer, nil], [2, Integer, nil], [3, Integer, nil]], OCI8::in_cond(:id, [nil, 2, 3], Integer).values)
|
32
|
+
assert_equal([[1, Integer, nil], [nil, Integer, nil], [3, Integer, nil]], OCI8::in_cond(:id, [1, nil, 3], Integer).values)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_select
|
36
|
+
@conn = get_oci8_connection
|
37
|
+
begin
|
38
|
+
drop_table('test_table')
|
39
|
+
@conn.exec(<<EOS)
|
40
|
+
CREATE TABLE test_table (ID NUMBER(38))
|
41
|
+
EOS
|
42
|
+
cursor = @conn.parse('insert into test_table values(:1)')
|
43
|
+
cursor.bind_param(1, nil, Integer)
|
44
|
+
[1, 3, 5].each do |id|
|
45
|
+
cursor.exec(id)
|
46
|
+
end
|
47
|
+
cursor.close
|
48
|
+
|
49
|
+
[
|
50
|
+
[],
|
51
|
+
[1],
|
52
|
+
[1, 2],
|
53
|
+
[1, 2, 3],
|
54
|
+
[nil],
|
55
|
+
[nil, 2, 3],
|
56
|
+
[1, nil, 3],
|
57
|
+
].each do |ids|
|
58
|
+
in_cond = OCI8::in_cond(:id, ids)
|
59
|
+
cursor = @conn.exec("select * from test_table where id in (#{in_cond.names}) order by id", *in_cond.values)
|
60
|
+
([1, 3, 5] & ids).each do |id|
|
61
|
+
assert_equal(id, cursor.fetch[0])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
drop_table('test_table')
|
66
|
+
ensure
|
67
|
+
@conn.logoff
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# Low-level API
|
2
|
+
require 'oci8'
|
3
|
+
require File.dirname(__FILE__) + '/config'
|
4
|
+
|
5
|
+
class TestBindBoolean < Minitest::Test
|
6
|
+
def setup
|
7
|
+
@conn = get_oci8_connection()
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_set_raw
|
11
|
+
stmt = <<EOS
|
12
|
+
DECLARE
|
13
|
+
bool_val boolean;
|
14
|
+
int_val pls_integer;
|
15
|
+
BEGIN
|
16
|
+
bool_val := :in;
|
17
|
+
IF bool_val THEN
|
18
|
+
int_val := 1;
|
19
|
+
ELSE
|
20
|
+
int_val := 0;
|
21
|
+
END IF;
|
22
|
+
:out := int_val;
|
23
|
+
END;
|
24
|
+
EOS
|
25
|
+
# explicit bind
|
26
|
+
cursor = @conn.parse(stmt)
|
27
|
+
cursor.bind_param(:in, nil, TrueClass)
|
28
|
+
cursor.bind_param(:out, nil, Integer)
|
29
|
+
|
30
|
+
cursor[:in] = true
|
31
|
+
cursor.exec
|
32
|
+
assert_equal(1, cursor[:out])
|
33
|
+
|
34
|
+
cursor[:in] = false
|
35
|
+
cursor.exec
|
36
|
+
assert_equal(0, cursor[:out])
|
37
|
+
|
38
|
+
# implicit bind
|
39
|
+
do_block_cnt = 0
|
40
|
+
@conn.exec(stmt, true, 0) do |in_val, out_val|
|
41
|
+
assert_equal(true, in_val)
|
42
|
+
assert_equal(1, out_val)
|
43
|
+
do_block_cnt += 1
|
44
|
+
end
|
45
|
+
|
46
|
+
@conn.exec(stmt, false, 0) do |in_val, out_val|
|
47
|
+
assert_equal(false, in_val)
|
48
|
+
assert_equal(0, out_val)
|
49
|
+
do_block_cnt += 1
|
50
|
+
end
|
51
|
+
assert_equal(2, do_block_cnt)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_get_raw
|
55
|
+
stmt = <<EOS
|
56
|
+
DECLARE
|
57
|
+
int_val pls_integer;
|
58
|
+
bool_val boolean;
|
59
|
+
BEGIN
|
60
|
+
int_val := :in;
|
61
|
+
IF int_val <> 0 THEN
|
62
|
+
bool_val := TRUE;
|
63
|
+
ELSE
|
64
|
+
bool_val := FALSE;
|
65
|
+
END IF;
|
66
|
+
:out := bool_val;
|
67
|
+
END;
|
68
|
+
EOS
|
69
|
+
cursor = @conn.parse(stmt)
|
70
|
+
cursor.bind_param(:in, nil, Integer)
|
71
|
+
cursor.bind_param(:out, nil, TrueClass)
|
72
|
+
|
73
|
+
cursor[:in] = 1
|
74
|
+
cursor.exec
|
75
|
+
assert_equal(true, cursor[:out])
|
76
|
+
|
77
|
+
cursor[:in] = 0
|
78
|
+
cursor.exec
|
79
|
+
assert_equal(false, cursor[:out])
|
80
|
+
|
81
|
+
do_block_cnt = 0
|
82
|
+
@conn.exec(stmt, 1, true) do |in_val, out_val|
|
83
|
+
assert_equal(1, in_val)
|
84
|
+
assert_equal(true, out_val)
|
85
|
+
do_block_cnt += 1
|
86
|
+
end
|
87
|
+
|
88
|
+
@conn.exec(stmt, 0, true) do |in_val, out_val|
|
89
|
+
assert_equal(0, in_val)
|
90
|
+
assert_equal(false, out_val)
|
91
|
+
do_block_cnt += 1
|
92
|
+
end
|
93
|
+
assert_equal(2, do_block_cnt)
|
94
|
+
end
|
95
|
+
|
96
|
+
def teardown
|
97
|
+
@conn.logoff
|
98
|
+
end
|
99
|
+
end
|