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.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/ChangeLog +311 -1
  3. data/NEWS +278 -46
  4. data/README.md +5 -2
  5. data/dist-files +8 -4
  6. data/docs/bind-array-to-in_cond.md +1 -1
  7. data/docs/install-instant-client.md +2 -1
  8. data/docs/install-on-osx.md +29 -116
  9. data/docs/ldap-auth-and-function-interposition.md +123 -0
  10. data/docs/number-type-mapping.md +79 -0
  11. data/ext/oci8/apiwrap.c.tmpl +2 -5
  12. data/ext/oci8/apiwrap.rb +6 -1
  13. data/ext/oci8/apiwrap.yml +34 -22
  14. data/ext/oci8/attr.c +4 -2
  15. data/ext/oci8/bind.c +366 -6
  16. data/ext/oci8/connection_pool.c +3 -3
  17. data/ext/oci8/error.c +18 -33
  18. data/ext/oci8/extconf.rb +7 -4
  19. data/ext/oci8/hook_funcs.c +128 -51
  20. data/ext/oci8/lob.c +31 -75
  21. data/ext/oci8/metadata.c +2 -2
  22. data/ext/oci8/object.c +72 -27
  23. data/ext/oci8/oci8.c +27 -119
  24. data/ext/oci8/oci8.h +21 -3
  25. data/ext/oci8/oci8lib.c +50 -37
  26. data/ext/oci8/ocihandle.c +2 -2
  27. data/ext/oci8/ocinumber.c +22 -16
  28. data/ext/oci8/oraconf.rb +130 -257
  29. data/ext/oci8/oradate.c +1 -1
  30. data/ext/oci8/plthook_elf.c +384 -300
  31. data/ext/oci8/plthook_osx.c +10 -10
  32. data/ext/oci8/stmt.c +51 -16
  33. data/ext/oci8/win32.c +4 -22
  34. data/lib/oci8/bindtype.rb +1 -15
  35. data/lib/oci8/check_load_error.rb +57 -10
  36. data/lib/oci8/cursor.rb +48 -17
  37. data/lib/oci8/metadata.rb +9 -1
  38. data/lib/oci8/object.rb +10 -0
  39. data/lib/oci8/oci8.rb +26 -25
  40. data/lib/oci8/oracle_version.rb +11 -1
  41. data/lib/oci8/version.rb +1 -1
  42. data/lib/oci8.rb +11 -4
  43. data/lib/ruby-oci8.rb +0 -3
  44. data/ruby-oci8.gemspec +2 -3
  45. data/setup.rb +11 -2
  46. data/test/README.md +37 -0
  47. data/test/config.rb +1 -1
  48. data/test/setup_test_object.sql +21 -13
  49. data/test/setup_test_package.sql +59 -0
  50. data/test/test_all.rb +1 -0
  51. data/test/test_bind_boolean.rb +99 -0
  52. data/test/test_break.rb +11 -9
  53. data/test/test_clob.rb +4 -16
  54. data/test/test_datetime.rb +8 -3
  55. data/test/test_object.rb +33 -9
  56. data/test/test_oci8.rb +169 -45
  57. data/test/test_oranumber.rb +12 -6
  58. data/test/test_package_type.rb +15 -3
  59. data/test/test_properties.rb +17 -0
  60. metadata +40 -57
  61. data/docs/osx-install-dev-tools.png +0 -0
  62. data/test/README +0 -42
@@ -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 = (@major << 24) | (@minor << 20) | (@update << 12) | (@patch << 8) | @port_update
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
@@ -1,3 +1,3 @@
1
1
  class OCI8
2
- VERSION = "2.2.4.1"
2
+ VERSION = "2.2.11"
3
3
  end
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 'Win32API'
15
- win32setenv = Win32API.new('Kernel32.dll', 'SetEnvironmentVariableA', 'PP', 'I')
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, OCIError
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
@@ -1,4 +1 @@
1
- if caller[0] !~ /\/bundler\/runtime\.rb:\d+:in `require'/
2
- warn "Don't require 'ruby-oci8'. Use \"require 'oci8'\" instead. 'ruby-oci8.rb' was added only for 'Bundler.require'."
3
- end
4
1
  require 'oci8'
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.exists? map_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', 'ext/oci8']
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, vname, desc, default2)|
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
- rescue OCIError
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.
@@ -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 or replace type body rb_test_obj is
76
-
77
+ create type body rb_test_obj is
77
78
  constructor function rb_test_obj(n number) return self as result is
78
- function to_test_date(n number) return date is
79
- begin
80
- return to_date(to_char(1990 + n, 'FM0000') ||
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 := to_test_date(n);
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 3;
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
- @@server_is_runing_on_windows = false
24
- @conn.exec('select banner from v$version') do |row|
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
@@ -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.scanf("%d-%d-%d %d:%d:%d.%06d")), row[0])
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.scanf("%d-%d-%d %d:%d:%d.%06d")), row[0])
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 != 3
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
- # attr_reader :date_array_val
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 to_test_date(n)
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
- convert_to_time(year, month, mday, hour, minute, sec, 0, nil)
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 :to_test_date
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 = to_test_date(@n)
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
- # date_array_val = val[18]
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
- # date_array_val = val.date_array_val
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
- # assert_equal(@date_array_val, date_array_val && date_array_val.to_ary)
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)