ruby-oci8 2.2.0.2 → 2.2.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +1 -6
  3. data/ChangeLog +600 -0
  4. data/NEWS +426 -35
  5. data/README.md +27 -9
  6. data/dist-files +13 -2
  7. data/docs/bind-array-to-in_cond.md +38 -0
  8. data/docs/conflicts-local-connections-and-processes.md +98 -0
  9. data/docs/hanging-after-inactivity.md +63 -0
  10. data/docs/install-binary-package.md +15 -11
  11. data/docs/install-full-client.md +18 -21
  12. data/docs/install-instant-client.md +45 -27
  13. data/docs/install-on-osx.md +31 -117
  14. data/docs/ldap-auth-and-function-interposition.md +123 -0
  15. data/docs/number-type-mapping.md +79 -0
  16. data/docs/platform-specific-issues.md +17 -50
  17. data/docs/report-installation-issue.md +11 -8
  18. data/docs/timeout-parameters.md +94 -0
  19. data/ext/oci8/apiwrap.c.tmpl +2 -5
  20. data/ext/oci8/apiwrap.rb +6 -1
  21. data/ext/oci8/apiwrap.yml +39 -143
  22. data/ext/oci8/attr.c +4 -2
  23. data/ext/oci8/bind.c +421 -9
  24. data/ext/oci8/connection_pool.c +3 -3
  25. data/ext/oci8/encoding.c +5 -5
  26. data/ext/oci8/env.c +8 -2
  27. data/ext/oci8/error.c +24 -16
  28. data/ext/oci8/extconf.rb +35 -63
  29. data/ext/oci8/hook_funcs.c +274 -61
  30. data/ext/oci8/lob.c +31 -75
  31. data/ext/oci8/metadata.c +8 -6
  32. data/ext/oci8/object.c +119 -29
  33. data/ext/oci8/oci8.c +46 -133
  34. data/ext/oci8/oci8.h +40 -123
  35. data/ext/oci8/oci8lib.c +178 -46
  36. data/ext/oci8/ocihandle.c +37 -37
  37. data/ext/oci8/ocinumber.c +24 -35
  38. data/ext/oci8/oraconf.rb +168 -337
  39. data/ext/oci8/oradate.c +19 -19
  40. data/ext/oci8/plthook.h +10 -0
  41. data/ext/oci8/plthook_elf.c +433 -268
  42. data/ext/oci8/plthook_osx.c +40 -9
  43. data/ext/oci8/plthook_win32.c +16 -1
  44. data/ext/oci8/stmt.c +52 -17
  45. data/ext/oci8/win32.c +4 -22
  46. data/lib/oci8/bindtype.rb +10 -17
  47. data/lib/oci8/check_load_error.rb +57 -10
  48. data/lib/oci8/compat.rb +5 -1
  49. data/lib/oci8/connection_pool.rb +74 -3
  50. data/lib/oci8/cursor.rb +70 -31
  51. data/lib/oci8/metadata.rb +9 -1
  52. data/lib/oci8/object.rb +14 -1
  53. data/lib/oci8/oci8.rb +184 -58
  54. data/lib/oci8/ocihandle.rb +0 -16
  55. data/lib/oci8/oracle_version.rb +11 -1
  56. data/lib/oci8/properties.rb +55 -0
  57. data/lib/oci8/version.rb +1 -1
  58. data/lib/oci8.rb +48 -4
  59. data/lib/ruby-oci8.rb +1 -0
  60. data/pre-distclean.rb +1 -3
  61. data/ruby-oci8.gemspec +4 -9
  62. data/setup.rb +11 -2
  63. data/test/README.md +37 -0
  64. data/test/config.rb +8 -1
  65. data/test/setup_test_object.sql +42 -14
  66. data/test/setup_test_package.sql +59 -0
  67. data/test/test_all.rb +4 -0
  68. data/test/test_bind_array.rb +70 -0
  69. data/test/test_bind_boolean.rb +99 -0
  70. data/test/test_bind_integer.rb +47 -0
  71. data/test/test_break.rb +11 -9
  72. data/test/test_clob.rb +5 -17
  73. data/test/test_connstr.rb +142 -0
  74. data/test/test_datetime.rb +8 -3
  75. data/test/test_metadata.rb +2 -1
  76. data/test/test_object.rb +99 -18
  77. data/test/test_oci8.rb +170 -46
  78. data/test/test_oranumber.rb +12 -6
  79. data/test/test_package_type.rb +17 -3
  80. data/test/test_properties.rb +17 -0
  81. metadata +45 -55
  82. data/docs/osx-install-dev-tools.png +0 -0
  83. data/test/README +0 -42
@@ -0,0 +1,47 @@
1
+ require 'oci8'
2
+ require File.dirname(__FILE__) + '/config'
3
+
4
+ class TestBindInteger < Minitest::Test
5
+
6
+ def setup
7
+ @conn = get_oci8_connection
8
+ end
9
+
10
+ POSITIVE_INTS = [
11
+ 100,
12
+ 2**30,
13
+ 2**31,
14
+ 2**32,
15
+ 2**33,
16
+ 2**62,
17
+ 2**63,
18
+ 2**64,
19
+ ('9' * 38).to_i
20
+ ]
21
+
22
+ def bind_and_get(input_value, output_type)
23
+ cursor = @conn.parse("BEGIN :out := :in; END;")
24
+ cursor.bind_param(:out, output_type)
25
+ cursor.bind_param(:in, input_value)
26
+ cursor.exec
27
+ result = cursor[:out]
28
+ cursor.close
29
+ result
30
+ end
31
+
32
+ (POSITIVE_INTS + [0] + POSITIVE_INTS.map(&:-@)).each do |num|
33
+ define_method("test_bind_param_with_input_of '#{num}'") do
34
+ assert_equal(OraNumber.new(num.to_s), bind_and_get(num, OraNumber))
35
+ end
36
+
37
+ define_method("test_bind_param_with_output_of '#{num}'") do
38
+ result = bind_and_get(OraNumber.new(num.to_s), Integer)
39
+ assert_equal(num, result)
40
+ assert_kind_of(Integer, result)
41
+ end
42
+ end
43
+
44
+ def teardown
45
+ @conn.logoff
46
+ end
47
+ 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
@@ -67,7 +51,7 @@ class TestCLob < Minitest::Test
67
51
  # Though buf.size counts in byte,
68
52
  # offset and $lobreadnum count in character.
69
53
  end
70
- assert_equal(nil, buf)
54
+ assert_nil(buf)
71
55
  assert(f.eof?)
72
56
  assert(lob.eof?)
73
57
  end
@@ -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_connstr.rb CHANGED
@@ -75,4 +75,146 @@ 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, false, "sales-server"],
84
+ # Easy Connect string with host.
85
+ ["//sales-server", nil, nil, false, <<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, false, <<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, false, <<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, false, <<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, false, <<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, false, <<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, false, <<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, false, <<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, false, <<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, false, <<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
+ ["sales-server/sales", 20, 30, true, <<EOS],
191
+ (DESCRIPTION=
192
+ (CONNECT_DATA=
193
+ (SERVICE_NAME=sales)
194
+ )
195
+ (ADDRESS=
196
+ (PROTOCOL=TCP)
197
+ (HOST=sales-server)
198
+ (PORT=1521)
199
+ )
200
+ (TRANSPORT_CONNECT_TIMEOUT=20)
201
+ (CONNECT_TIMEOUT=30)
202
+ (ENABLE=BROKEN)
203
+ )
204
+ EOS
205
+ ]
206
+
207
+ def test_connect_descriptor
208
+ obj = OCI8.allocate # create an uninitialized object.
209
+ DESC_TEST_CASE.each do |test_case|
210
+ easy_connect_string = test_case[0]
211
+ tcp_connnect_timeout= test_case[1]
212
+ outbound_connnect_timeout = test_case[2]
213
+ tcp_keepalive = test_case[3]
214
+ expected_result = test_case[4].gsub(/\s/, '')
215
+ # use instance_eval to call a private method to_connect_descriptor
216
+ result = obj.instance_eval { to_connect_descriptor(easy_connect_string, tcp_connnect_timeout, outbound_connnect_timeout, tcp_keepalive) }
217
+ assert_equal(expected_result, result, easy_connect_string)
218
+ end
219
+ end
78
220
  end
@@ -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
@@ -42,6 +42,8 @@ class TestMetadata < Minitest::Test
42
42
  assert(expected_value.call(val), "#{msg} > #{method}")
43
43
  when Regexp
44
44
  assert_match(expected_value, val, "#{msg} > #{method}")
45
+ when nil
46
+ assert_nil(val, "#{msg} > #{method}")
45
47
  else
46
48
  assert_equal(expected_value, val, "#{msg} > #{method}")
47
49
  end
@@ -1335,7 +1337,6 @@ EOS
1335
1337
  drop_type('TEST_TYPE_NESTEAD_TABLE')
1336
1338
  drop_type('TEST_TYPE_CHILD')
1337
1339
  drop_type('TEST_TYPE_PARENT')
1338
- expected_values = []
1339
1340
  attrs_map = {}
1340
1341
 
1341
1342
  @conn.exec(<<-EOS)
data/test/test_object.rb CHANGED
@@ -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 != 4
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
 
@@ -94,7 +100,8 @@ class TestObj1 < Minitest::Test
94
100
  attr_reader :obj_array_val
95
101
  attr_reader :obj_ary_of_ary_val
96
102
  attr_reader :date_val
97
- # attr_reader :date_array_val
103
+ attr_reader :timestamp_val
104
+ attr_reader :timestamp_tz_val
98
105
 
99
106
  attr_accessor :assertions
100
107
 
@@ -103,16 +110,28 @@ class TestObj1 < Minitest::Test
103
110
  @assertions = 0
104
111
  end
105
112
 
106
- def to_test_date(n)
113
+ def to_test_datetime(n, type)
107
114
  year = (1990 + n).round
108
115
  month = (n.round * 5) % 12 + 1
109
116
  mday = (n.round * 7) % 27 + 1
110
117
  hour = (n.round * 9) % 24
111
118
  minute = (n.round * 11) % 60
112
119
  sec = (n.round * 13) % 60
113
- convert_to_time(year, month, mday, hour, minute, sec, 0, nil)
120
+ nsec = if type == :date
121
+ 0
122
+ else
123
+ ((n.round * 333_333_333) % 1_000_000_000).to_r / 1_000_000_000
124
+ end
125
+ tz = if type == :timestamp_tz
126
+ tzh = (n.round * 15) % 24 - 11
127
+ tzm = (n.round * 17) % 60
128
+ format('%+03d:%02d', tzh, tzm)
129
+ else
130
+ nil
131
+ end
132
+ convert_to_time(year, month, mday, hour, minute, sec, nsec, tz)
114
133
  end
115
- private :to_test_date
134
+ private :to_test_datetime
116
135
 
117
136
  def next
118
137
  @n += 1.2
@@ -129,7 +148,9 @@ class TestObj1 < Minitest::Test
129
148
  @nclob_val = @str_val
130
149
  @blob_val = @str_val
131
150
  @obj_val = ExpectedValObjElem.new(@int_val, @int_val + 1)
132
- @date_val = to_test_date(@n)
151
+ @date_val = to_test_datetime(@n, :date)
152
+ @timestamp_val = to_test_datetime(@n, :timestamp)
153
+ @timestamp_tz_val = to_test_datetime(@n, :timestamp_tz)
133
154
  if @int_val == 1
134
155
  @int_array_val = nil
135
156
  @flt_array_val = nil
@@ -193,7 +214,8 @@ class TestObj1 < Minitest::Test
193
214
  obj_array_val = val[18]
194
215
  obj_ary_of_ary_val = val[19]
195
216
  date_val = val[20]
196
- # date_array_val = val[18]
217
+ timestamp_val = val[21]
218
+ timestamp_tz_val = val[22]
197
219
  else
198
220
  assert_instance_of(RbTestObj, val)
199
221
  int_val = val.int_val
@@ -217,7 +239,8 @@ class TestObj1 < Minitest::Test
217
239
  obj_array_val = val.obj_array_val
218
240
  obj_ary_of_ary_val = val.obj_ary_of_ary_val
219
241
  date_val = val.date_val
220
- # date_array_val = val.date_array_val
242
+ timestamp_val = val.timestamp_val
243
+ timestamp_tz_val = val.timestamp_tz_val
221
244
  end
222
245
 
223
246
  assert_equal(@int_val, int_val)
@@ -231,17 +254,38 @@ class TestObj1 < Minitest::Test
231
254
  assert_equal(@nclob_val, nclob_val)
232
255
  assert_equal(@blob_val, blob_val)
233
256
  assert_equal(@obj_val, obj_val)
234
- assert_equal(@int_array_val, int_array_val && int_array_val.to_ary)
257
+ if @int_array_val
258
+ assert_equal(@int_array_val, int_array_val.to_ary)
259
+ else
260
+ assert_nil(@int_array_val, int_array_val)
261
+ end
235
262
  assert_array_in_delta(@flt_array_val, flt_array_val && flt_array_val.to_ary)
236
263
  assert_array_in_delta(@num_array_val, num_array_val && num_array_val.to_ary)
237
264
  assert_array_in_delta(@bdbl_array_val, bdbl_array_val && bdbl_array_val.to_ary)
238
265
  assert_array_in_delta(@bflt_array_val, bflt_array_val && bflt_array_val.to_ary)
239
- assert_equal(@str_array_val, str_array_val && str_array_val.to_ary)
240
- assert_equal(@raw_array_val, raw_array_val && raw_array_val.to_ary)
241
- assert_equal(@obj_array_val, obj_array_val && obj_array_val.to_ary)
242
- assert_equal(@obj_ary_of_ary_val, obj_ary_of_ary_val && obj_ary_of_ary_val.to_ary.collect { |elem| elem.to_ary })
266
+ if @str_array_val
267
+ assert_equal(@str_array_val, str_array_val.to_ary)
268
+ else
269
+ assert_nil(str_array_val)
270
+ end
271
+ if @raw_array_val
272
+ assert_equal(@raw_array_val, raw_array_val.to_ary)
273
+ else
274
+ assert_nil(raw_array_val)
275
+ end
276
+ if @obj_array_val
277
+ assert_equal(@obj_array_val, obj_array_val.to_ary)
278
+ else
279
+ assert_nil(obj_array_val)
280
+ end
281
+ if @obj_ary_of_ary_val
282
+ assert_equal(@obj_ary_of_ary_val, obj_ary_of_ary_val.to_ary.collect { |elem| elem.to_ary })
283
+ else
284
+ assert_nil(obj_ary_of_ary_val)
285
+ end
243
286
  assert_equal(@date_val, date_val)
244
- # assert_equal(@date_array_val, date_array_val && date_array_val.to_ary)
287
+ assert_equal(@timestamp_val, timestamp_val)
288
+ assert_equal(@timestamp_tz_val, timestamp_tz_val)
245
289
  end
246
290
 
247
291
  def assert_array_in_delta(exp, val)
@@ -250,6 +294,8 @@ class TestObj1 < Minitest::Test
250
294
  exp.each_with_index do |elem, idx|
251
295
  assert_in_delta(elem, val[idx], Delta)
252
296
  end
297
+ elsif exp.nil?
298
+ assert_nil(val)
253
299
  else
254
300
  assert_equal(exp, val)
255
301
  end
@@ -450,10 +496,45 @@ EOS
450
496
  csr.bind_param(:out2, nil, Integer)
451
497
  csr.bind_param(:out3, nil, Integer)
452
498
  csr.exec
453
- assert_equal(ary ? ary.length : -1, csr[:cnt])
454
- assert_equal(ary ? ary[0] : nil, csr[:out1])
455
- assert_equal(ary ? ary[1] : nil, csr[:out2])
456
- assert_equal(ary ? ary[2] : nil, csr[:out3])
499
+ if ary
500
+ assert_equal(ary.length, csr[:cnt])
501
+ else
502
+ assert_equal(-1, csr[:cnt])
503
+ end
504
+ if ary && ary[0]
505
+ assert_equal(ary[0], csr[:out1])
506
+ else
507
+ assert_nil(csr[:out1])
508
+ end
509
+ if ary && ary[1]
510
+ assert_equal(ary[1], csr[:out2])
511
+ else
512
+ assert_nil(csr[:out2])
513
+ end
514
+ if ary && ary[2]
515
+ assert_equal(ary[2], csr[:out3])
516
+ else
517
+ assert_nil(csr[:out3])
518
+ end
457
519
  end
458
520
  end
521
+
522
+ def test_get_subtype
523
+ csr = @conn.parse("BEGIN :result := rb_test_obj_get_object(:1); END;")
524
+ csr.bind_param(1, nil, RbTestObjBase)
525
+ csr.bind_param(2, nil, Integer)
526
+
527
+ csr[2] = 0
528
+ csr.exec
529
+ val = csr[1]
530
+ assert_instance_of(RbTestObjBase, val)
531
+ assert_equal(val.id, 'base')
532
+
533
+ csr[2] = 1
534
+ csr.exec
535
+ val = csr[1]
536
+ assert_instance_of(RbTestObjSub, val)
537
+ assert_equal(val.id, 'sub')
538
+ assert_equal(val.subid, 'subid')
539
+ end
459
540
  end