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.
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