ruby-oci8 2.2.4.1 → 2.2.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ChangeLog +311 -1
- data/NEWS +278 -46
- data/README.md +5 -2
- data/dist-files +8 -4
- data/docs/bind-array-to-in_cond.md +1 -1
- data/docs/install-instant-client.md +2 -1
- data/docs/install-on-osx.md +29 -116
- data/docs/ldap-auth-and-function-interposition.md +123 -0
- data/docs/number-type-mapping.md +79 -0
- data/ext/oci8/apiwrap.c.tmpl +2 -5
- data/ext/oci8/apiwrap.rb +6 -1
- data/ext/oci8/apiwrap.yml +34 -22
- data/ext/oci8/attr.c +4 -2
- data/ext/oci8/bind.c +366 -6
- data/ext/oci8/connection_pool.c +3 -3
- data/ext/oci8/error.c +18 -33
- data/ext/oci8/extconf.rb +7 -4
- data/ext/oci8/hook_funcs.c +128 -51
- data/ext/oci8/lob.c +31 -75
- data/ext/oci8/metadata.c +2 -2
- data/ext/oci8/object.c +72 -27
- data/ext/oci8/oci8.c +27 -119
- data/ext/oci8/oci8.h +21 -3
- data/ext/oci8/oci8lib.c +50 -37
- data/ext/oci8/ocihandle.c +2 -2
- data/ext/oci8/ocinumber.c +22 -16
- data/ext/oci8/oraconf.rb +130 -257
- data/ext/oci8/oradate.c +1 -1
- data/ext/oci8/plthook_elf.c +384 -300
- data/ext/oci8/plthook_osx.c +10 -10
- data/ext/oci8/stmt.c +51 -16
- data/ext/oci8/win32.c +4 -22
- data/lib/oci8/bindtype.rb +1 -15
- data/lib/oci8/check_load_error.rb +57 -10
- data/lib/oci8/cursor.rb +48 -17
- data/lib/oci8/metadata.rb +9 -1
- data/lib/oci8/object.rb +10 -0
- data/lib/oci8/oci8.rb +26 -25
- data/lib/oci8/oracle_version.rb +11 -1
- data/lib/oci8/version.rb +1 -1
- data/lib/oci8.rb +11 -4
- data/lib/ruby-oci8.rb +0 -3
- data/ruby-oci8.gemspec +2 -3
- data/setup.rb +11 -2
- data/test/README.md +37 -0
- data/test/config.rb +1 -1
- data/test/setup_test_object.sql +21 -13
- data/test/setup_test_package.sql +59 -0
- data/test/test_all.rb +1 -0
- data/test/test_bind_boolean.rb +99 -0
- data/test/test_break.rb +11 -9
- data/test/test_clob.rb +4 -16
- data/test/test_datetime.rb +8 -3
- data/test/test_object.rb +33 -9
- data/test/test_oci8.rb +169 -45
- data/test/test_oranumber.rb +12 -6
- data/test/test_package_type.rb +15 -3
- data/test/test_properties.rb +17 -0
- metadata +40 -57
- data/docs/osx-install-dev-tools.png +0 -0
- data/test/README +0 -42
data/lib/oci8/oracle_version.rb
CHANGED
@@ -66,6 +66,12 @@ class OCI8
|
|
66
66
|
major, minor, update, patch, port_update = arg.split('.').collect do |v|
|
67
67
|
v.to_i
|
68
68
|
end
|
69
|
+
elsif arg >= 0x12000000
|
70
|
+
major = (arg & 0xFF000000) >> 24
|
71
|
+
minor = (arg & 0x00FF0000) >> 16
|
72
|
+
update = (arg & 0x0000F000) >> 12
|
73
|
+
patch = (arg & 0x00000FF0) >> 4
|
74
|
+
port_update = (arg & 0x0000000F)
|
69
75
|
elsif arg >= 0x08000000
|
70
76
|
major = (arg & 0xFF000000) >> 24
|
71
77
|
minor = (arg & 0x00F00000) >> 20
|
@@ -80,7 +86,11 @@ class OCI8
|
|
80
86
|
@update = update || 0
|
81
87
|
@patch = patch || 0
|
82
88
|
@port_update = port_update || 0
|
83
|
-
@vernum =
|
89
|
+
@vernum = if @major >= 18
|
90
|
+
(@major << 24) | (@minor << 16) | (@update << 12) | (@patch << 4) | @port_update
|
91
|
+
else
|
92
|
+
(@major << 24) | (@minor << 20) | (@update << 12) | (@patch << 8) | @port_update
|
93
|
+
end
|
84
94
|
end
|
85
95
|
|
86
96
|
# Compares +self+ and +other+.
|
data/lib/oci8/version.rb
CHANGED
data/lib/oci8.rb
CHANGED
@@ -11,8 +11,11 @@ if RUBY_PLATFORM =~ /cygwin/
|
|
11
11
|
# Cygwin manages environment variables by itself.
|
12
12
|
# They don't synchroize with Win32's ones.
|
13
13
|
# This set some Oracle's environment variables to win32's enviroment.
|
14
|
-
require '
|
15
|
-
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
|
+
|
16
19
|
['NLS_LANG', 'TNS_ADMIN', 'LOCAL'].each do |name|
|
17
20
|
val = ENV[name]
|
18
21
|
win32setenv.call(name, val && val.dup)
|
@@ -63,6 +66,8 @@ when 'rbx'
|
|
63
66
|
so_basename += 'rbx'
|
64
67
|
when 'jruby'
|
65
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'
|
66
71
|
else
|
67
72
|
raise 'unsupported ruby engine: ' + RUBY_ENGINE
|
68
73
|
end
|
@@ -95,7 +100,7 @@ begin
|
|
95
100
|
|
96
101
|
ruby_arch = [nil].pack('P').size == 8 ? :x64 : :x86
|
97
102
|
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
98
|
-
if dll_arch.call(File.join(path, 'OCI.DLL')) == ruby_arch
|
103
|
+
if !path.empty? && dll_arch.call(File.join(path, 'OCI.DLL')) == ruby_arch
|
99
104
|
dll_dir = RubyInstaller::Runtime.add_dll_directory(path)
|
100
105
|
break
|
101
106
|
end
|
@@ -105,7 +110,7 @@ end
|
|
105
110
|
|
106
111
|
begin
|
107
112
|
require so_basename
|
108
|
-
rescue LoadError
|
113
|
+
rescue LoadError
|
109
114
|
require 'oci8/check_load_error'
|
110
115
|
OCI8::Util::check_load_error($!)
|
111
116
|
raise
|
@@ -140,6 +145,8 @@ class OCI8
|
|
140
145
|
ORAVER_11_1 = OCI8::OracleVersion.new(11, 1)
|
141
146
|
# @private
|
142
147
|
ORAVER_12_1 = OCI8::OracleVersion.new(12, 1)
|
148
|
+
# @private
|
149
|
+
ORAVER_18 = OCI8::OracleVersion.new(18)
|
143
150
|
|
144
151
|
# @private
|
145
152
|
@@oracle_client_version = OCI8::OracleVersion.new(self.oracle_client_vernum)
|
data/lib/ruby-oci8.rb
CHANGED
data/ruby-oci8.gemspec
CHANGED
@@ -34,7 +34,6 @@ 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
39
|
s.license = 'BSD-2-Clause'
|
@@ -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
|
@@ -79,7 +78,7 @@ EOS
|
|
79
78
|
end
|
80
79
|
files << 'lib/oci8.rb'
|
81
80
|
end
|
82
|
-
s.require_paths = ['lib'
|
81
|
+
s.require_paths = ['lib']
|
83
82
|
s.files = files
|
84
83
|
s.test_files = 'test/test_all.rb'
|
85
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
@@ -134,7 +134,7 @@ class Minitest::Test
|
|
134
134
|
|
135
135
|
def get_oci8_connection()
|
136
136
|
OCI8.new($dbuser, $dbpass, $dbname)
|
137
|
-
|
137
|
+
rescue OCIError
|
138
138
|
raise if $!.code != 12516 && $!.code != 12520
|
139
139
|
# sleep a few second and try again if
|
140
140
|
# the error code is ORA-12516 or ORA-12520.
|
data/test/setup_test_object.sql
CHANGED
@@ -61,6 +61,8 @@ create type rb_test_obj as object (
|
|
61
61
|
obj_array_val rb_test_obj_elem_array,
|
62
62
|
obj_ary_of_ary_val rb_test_obj_elem_ary_of_ary,
|
63
63
|
date_val date,
|
64
|
+
timestamp_val timestamp(9),
|
65
|
+
timestamp_tz_val timestamp(9) with time zone,
|
64
66
|
-- date_array_val rb_test_date_array,
|
65
67
|
|
66
68
|
constructor function rb_test_obj(n number) return self as result,
|
@@ -72,19 +74,23 @@ create type rb_test_obj as object (
|
|
72
74
|
member procedure member_proc(n in integer)
|
73
75
|
)
|
74
76
|
/
|
75
|
-
create
|
76
|
-
|
77
|
+
create type body rb_test_obj is
|
77
78
|
constructor function rb_test_obj(n number) return self as result is
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
to_char(mod(round(n) * 5, 12) + 1, 'FM00') ||
|
82
|
-
to_char(mod(round(n) * 7, 27) + 1, 'FM00') ||
|
83
|
-
to_char(mod(round(n) * 9, 24), 'FM00') ||
|
84
|
-
to_char(mod(round(n) * 11, 60), 'FM00') ||
|
85
|
-
to_char(mod(round(n) * 13, 60), 'FM00'), 'yyyymmddhh24miss');
|
86
|
-
end;
|
79
|
+
str varchar(28);
|
80
|
+
ts timestamp(9);
|
81
|
+
ts_tz timestamp(9) with time zone;
|
87
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');
|
88
94
|
self.int_val := n;
|
89
95
|
self.flt_val := n;
|
90
96
|
self.num_val := n;
|
@@ -96,7 +102,9 @@ create or replace type body rb_test_obj is
|
|
96
102
|
self.nclob_val := to_clob(n);
|
97
103
|
self.blob_val := to_blob(utl_raw.cast_to_raw(to_char(n)));
|
98
104
|
self.obj_val := rb_test_obj_elem(n, n + 1);
|
99
|
-
self.date_val :=
|
105
|
+
self.date_val := ts;
|
106
|
+
self.timestamp_val := ts;
|
107
|
+
self.timestamp_tz_val := ts_tz;
|
100
108
|
if self.int_val != 1 then
|
101
109
|
self.int_array_val := rb_test_int_array(n, n + 1, n + 2);
|
102
110
|
self.flt_array_val := rb_test_flt_array(n, n + 1, n + 2);
|
@@ -120,7 +128,7 @@ create or replace type body rb_test_obj is
|
|
120
128
|
|
121
129
|
static function test_object_version return integer is
|
122
130
|
begin
|
123
|
-
return
|
131
|
+
return 4;
|
124
132
|
end;
|
125
133
|
|
126
134
|
static function class_func(n number) return rb_test_obj is
|
@@ -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
@@ -26,6 +26,7 @@ require "#{srcdir}/test_oracle_version"
|
|
26
26
|
require "#{srcdir}/test_error"
|
27
27
|
require "#{srcdir}/test_connection_pool"
|
28
28
|
require "#{srcdir}/test_object"
|
29
|
+
require "#{srcdir}/test_properties.rb"
|
29
30
|
|
30
31
|
if OCI8.respond_to? :encoding
|
31
32
|
require "#{srcdir}/test_encoding"
|
@@ -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
|
data/test/test_break.rb
CHANGED
@@ -7,10 +7,12 @@ class TestBreak < Minitest::Test
|
|
7
7
|
|
8
8
|
def setup
|
9
9
|
@conn = get_oci8_connection
|
10
|
+
Thread.report_on_exception, @original_report_on_exception = false, Thread.report_on_exception if Thread.respond_to?(:report_on_exception)
|
10
11
|
end
|
11
12
|
|
12
13
|
def teardown
|
13
14
|
@conn.logoff
|
15
|
+
Thread.report_on_exception = @original_report_on_exception if Thread.respond_to?(:report_on_exception)
|
14
16
|
end
|
15
17
|
|
16
18
|
def report(str)
|
@@ -20,9 +22,8 @@ class TestBreak < Minitest::Test
|
|
20
22
|
@@server_is_runing_on_windows = nil
|
21
23
|
def server_is_runing_on_windows?
|
22
24
|
if @@server_is_runing_on_windows.nil?
|
23
|
-
|
24
|
-
|
25
|
-
@@server_is_runing_on_windows = true if row[0].include? 'Windows'
|
25
|
+
@conn.exec('select dbms_utility.port_string from dual') do |row|
|
26
|
+
@@server_is_runing_on_windows = row[0].include? '/WIN'
|
26
27
|
end
|
27
28
|
end
|
28
29
|
@@server_is_runing_on_windows
|
@@ -61,7 +62,7 @@ class TestBreak < Minitest::Test
|
|
61
62
|
expect = []
|
62
63
|
expect[PLSQL_DONE] = TIME_IN_PLSQL
|
63
64
|
expect[OCIBREAK] = "Invalid status"
|
64
|
-
if defined? Rubinius and Rubinius::VERSION >= "2.0"
|
65
|
+
if (defined? Rubinius and Rubinius::VERSION >= "2.0") || (defined? RUBY_ENGINE and RUBY_ENGINE == "truffleruby")
|
65
66
|
# Rubinius 2.0.0.
|
66
67
|
# DBMS_LOCK.SLEEP blocks ruby threads which try to call C-API.
|
67
68
|
expect[SEND_BREAK] = TIME_TO_BREAK
|
@@ -98,6 +99,11 @@ class TestBreak < Minitest::Test
|
|
98
99
|
def test_timeout
|
99
100
|
@conn.non_blocking = true
|
100
101
|
start_time = Time.now
|
102
|
+
if server_is_runing_on_windows?
|
103
|
+
end_time = start_time + 5
|
104
|
+
else
|
105
|
+
end_time = start_time + 1
|
106
|
+
end
|
101
107
|
|
102
108
|
if defined? Rubinius and Rubinius::VERSION < "2.0"
|
103
109
|
# Rubinius 1.2.4
|
@@ -111,12 +117,8 @@ class TestBreak < Minitest::Test
|
|
111
117
|
@conn.exec("BEGIN DBMS_LOCK.SLEEP(5); END;")
|
112
118
|
end
|
113
119
|
end
|
114
|
-
if server_is_runing_on_windows?
|
115
|
-
end_time = start_time + 5
|
116
|
-
else
|
117
|
-
end_time = start_time + 1
|
118
|
-
end
|
119
120
|
assert_in_delta(Time.now, end_time, 1)
|
121
|
+
sleep(0.01) # for truffleruby. Is truffleruby too fast?
|
120
122
|
@conn.exec("BEGIN NULL; END;")
|
121
123
|
assert_in_delta(Time.now, end_time, 1)
|
122
124
|
end
|
data/test/test_clob.rb
CHANGED
@@ -24,22 +24,6 @@ class TestCLob < Minitest::Test
|
|
24
24
|
lob.close
|
25
25
|
end
|
26
26
|
|
27
|
-
def test_insert_with_flush
|
28
|
-
filename = File.basename($lobfile)
|
29
|
-
@conn.exec("DELETE FROM test_table WHERE filename = :1", filename)
|
30
|
-
@conn.exec("INSERT INTO test_table(filename, content) VALUES (:1, EMPTY_CLOB())", filename)
|
31
|
-
cursor = @conn.exec("SELECT content FROM test_table WHERE filename = :1 FOR UPDATE", filename)
|
32
|
-
lob = cursor.fetch[0]
|
33
|
-
lob.sync = false
|
34
|
-
open($lobfile) do |f|
|
35
|
-
while s = f.read(1000)
|
36
|
-
lob.write(s)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
lob.flush
|
40
|
-
lob.close
|
41
|
-
end
|
42
|
-
|
43
27
|
def test_insert_symbol
|
44
28
|
filename = 'test_symbol'
|
45
29
|
value = :foo_bar
|
@@ -76,7 +60,11 @@ class TestCLob < Minitest::Test
|
|
76
60
|
|
77
61
|
# https://github.com/kubo/ruby-oci8/issues/20
|
78
62
|
def test_github_issue_20
|
63
|
+
# Skip this test if FULLTEST isn't set because it takes 4 minutes in my Linux box.
|
64
|
+
return if ENV['FULLTEST']
|
65
|
+
|
79
66
|
lob1 = OCI8::CLOB.new(@conn, ' ' * (1024 * 1024))
|
67
|
+
lob1.read(1) # to suppress `warning: assigned but unused variable - lob1`
|
80
68
|
begin
|
81
69
|
lob2 = OCI8::CLOB.new(@conn, ' ' * (128 * 1024 * 1024))
|
82
70
|
rescue OCIError
|
data/test/test_datetime.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'oci8'
|
2
2
|
require File.dirname(__FILE__) + '/config'
|
3
|
-
require 'scanf'
|
4
3
|
|
5
4
|
class TestDateTime < Minitest::Test
|
6
5
|
|
@@ -28,6 +27,12 @@ class TestDateTime < Minitest::Test
|
|
28
27
|
convert_to_datetime($1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, subsec, $8)
|
29
28
|
end
|
30
29
|
|
30
|
+
# 'YYYY-MM-DD HH24:MI:SS' or 'YYYY-MM-DD HH24:MI:SS.FF6' to array
|
31
|
+
def string_to_array(str)
|
32
|
+
/(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)(?:\.(\d+))?/ =~ str
|
33
|
+
[$1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, $7 ? $7.to_i / 1000 : 0]
|
34
|
+
end
|
35
|
+
|
31
36
|
def setup
|
32
37
|
@conn = get_oci8_connection
|
33
38
|
end
|
@@ -43,7 +48,7 @@ class TestDateTime < Minitest::Test
|
|
43
48
|
@conn.exec(<<-EOS) do |row|
|
44
49
|
SELECT TO_DATE('#{date}', 'YYYY-MM-DD HH24:MI:SS') FROM dual
|
45
50
|
EOS
|
46
|
-
assert_equal(Time.local(*date
|
51
|
+
assert_equal(Time.local(*string_to_array(date)), row[0])
|
47
52
|
end
|
48
53
|
end
|
49
54
|
end
|
@@ -94,7 +99,7 @@ EOS
|
|
94
99
|
@conn.exec(<<-EOS) do |row|
|
95
100
|
SELECT TO_TIMESTAMP('#{date}', 'YYYY-MM-DD HH24:MI:SS.FF') FROM dual
|
96
101
|
EOS
|
97
|
-
assert_equal(Time.local(*date
|
102
|
+
assert_equal(Time.local(*string_to_array(date)), row[0])
|
98
103
|
end
|
99
104
|
end
|
100
105
|
end
|
data/test/test_object.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
require 'oci8'
|
2
2
|
require File.dirname(__FILE__) + '/config'
|
3
3
|
|
4
|
+
class Time
|
5
|
+
def inspect
|
6
|
+
self.strftime("%Y-%m-%d %H:%M:%S.%N %:z")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
4
10
|
conn = OCI8.new($dbuser, $dbpass, $dbname)
|
5
11
|
error_message = nil
|
6
12
|
begin
|
@@ -22,7 +28,7 @@ begin
|
|
22
28
|
|
23
29
|
begin
|
24
30
|
version = RbTestObj.test_object_version(conn)
|
25
|
-
error_message = "Invalid test object version" if version !=
|
31
|
+
error_message = "Invalid test object version" if version != 4
|
26
32
|
rescue NoMethodError
|
27
33
|
raise unless $!.to_s.include?('test_object_version')
|
28
34
|
error_message = "rb_test_obj.test_object_version is not declared."
|
@@ -100,7 +106,8 @@ class TestObj1 < Minitest::Test
|
|
100
106
|
attr_reader :obj_array_val
|
101
107
|
attr_reader :obj_ary_of_ary_val
|
102
108
|
attr_reader :date_val
|
103
|
-
|
109
|
+
attr_reader :timestamp_val
|
110
|
+
attr_reader :timestamp_tz_val
|
104
111
|
|
105
112
|
attr_accessor :assertions
|
106
113
|
|
@@ -109,16 +116,28 @@ class TestObj1 < Minitest::Test
|
|
109
116
|
@assertions = 0
|
110
117
|
end
|
111
118
|
|
112
|
-
def
|
119
|
+
def to_test_datetime(n, type)
|
113
120
|
year = (1990 + n).round
|
114
121
|
month = (n.round * 5) % 12 + 1
|
115
122
|
mday = (n.round * 7) % 27 + 1
|
116
123
|
hour = (n.round * 9) % 24
|
117
124
|
minute = (n.round * 11) % 60
|
118
125
|
sec = (n.round * 13) % 60
|
119
|
-
|
126
|
+
nsec = if type == :date
|
127
|
+
0
|
128
|
+
else
|
129
|
+
((n.round * 333_333_333) % 1_000_000_000).to_r / 1_000_000_000
|
130
|
+
end
|
131
|
+
tz = if type == :timestamp_tz
|
132
|
+
tzh = (n.round * 15) % 24 - 11
|
133
|
+
tzm = (n.round * 17) % 60
|
134
|
+
format('%+03d:%02d', tzh, tzm)
|
135
|
+
else
|
136
|
+
nil
|
137
|
+
end
|
138
|
+
convert_to_time(year, month, mday, hour, minute, sec, nsec, tz)
|
120
139
|
end
|
121
|
-
private :
|
140
|
+
private :to_test_datetime
|
122
141
|
|
123
142
|
def next
|
124
143
|
@n += 1.2
|
@@ -135,7 +154,9 @@ class TestObj1 < Minitest::Test
|
|
135
154
|
@nclob_val = @str_val
|
136
155
|
@blob_val = @str_val
|
137
156
|
@obj_val = ExpectedValObjElem.new(@int_val, @int_val + 1)
|
138
|
-
@date_val =
|
157
|
+
@date_val = to_test_datetime(@n, :date)
|
158
|
+
@timestamp_val = to_test_datetime(@n, :timestamp)
|
159
|
+
@timestamp_tz_val = to_test_datetime(@n, :timestamp_tz)
|
139
160
|
if @int_val == 1
|
140
161
|
@int_array_val = nil
|
141
162
|
@flt_array_val = nil
|
@@ -199,7 +220,8 @@ class TestObj1 < Minitest::Test
|
|
199
220
|
obj_array_val = val[18]
|
200
221
|
obj_ary_of_ary_val = val[19]
|
201
222
|
date_val = val[20]
|
202
|
-
|
223
|
+
timestamp_val = val[21]
|
224
|
+
timestamp_tz_val = val[22]
|
203
225
|
else
|
204
226
|
assert_instance_of(RbTestObj, val)
|
205
227
|
int_val = val.int_val
|
@@ -223,7 +245,8 @@ class TestObj1 < Minitest::Test
|
|
223
245
|
obj_array_val = val.obj_array_val
|
224
246
|
obj_ary_of_ary_val = val.obj_ary_of_ary_val
|
225
247
|
date_val = val.date_val
|
226
|
-
|
248
|
+
timestamp_val = val.timestamp_val
|
249
|
+
timestamp_tz_val = val.timestamp_tz_val
|
227
250
|
end
|
228
251
|
|
229
252
|
assert_equal(@int_val, int_val)
|
@@ -267,7 +290,8 @@ class TestObj1 < Minitest::Test
|
|
267
290
|
assert_nil(obj_ary_of_ary_val)
|
268
291
|
end
|
269
292
|
assert_equal(@date_val, date_val)
|
270
|
-
|
293
|
+
assert_equal(@timestamp_val, timestamp_val)
|
294
|
+
assert_equal(@timestamp_tz_val, timestamp_tz_val)
|
271
295
|
end
|
272
296
|
|
273
297
|
def assert_array_in_delta(exp, val)
|