ruby-oci8 2.2.10-x64-mingw-ucrt

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +14 -0
  3. data/COPYING +30 -0
  4. data/COPYING_old +64 -0
  5. data/ChangeLog +3826 -0
  6. data/Makefile +92 -0
  7. data/NEWS +1209 -0
  8. data/README.md +66 -0
  9. data/dist-files +112 -0
  10. data/docs/bind-array-to-in_cond.md +38 -0
  11. data/docs/conflicts-local-connections-and-processes.md +98 -0
  12. data/docs/hanging-after-inactivity.md +63 -0
  13. data/docs/install-binary-package.md +44 -0
  14. data/docs/install-full-client.md +111 -0
  15. data/docs/install-instant-client.md +194 -0
  16. data/docs/install-on-osx.md +46 -0
  17. data/docs/ldap-auth-and-function-interposition.md +123 -0
  18. data/docs/number-type-mapping.md +79 -0
  19. data/docs/platform-specific-issues.md +164 -0
  20. data/docs/report-installation-issue.md +50 -0
  21. data/docs/timeout-parameters.md +94 -0
  22. data/lib/.document +1 -0
  23. data/lib/dbd/OCI8.rb +591 -0
  24. data/lib/oci8/.document +8 -0
  25. data/lib/oci8/bindtype.rb +333 -0
  26. data/lib/oci8/check_load_error.rb +146 -0
  27. data/lib/oci8/compat.rb +117 -0
  28. data/lib/oci8/connection_pool.rb +179 -0
  29. data/lib/oci8/cursor.rb +605 -0
  30. data/lib/oci8/datetime.rb +605 -0
  31. data/lib/oci8/encoding-init.rb +45 -0
  32. data/lib/oci8/encoding.yml +537 -0
  33. data/lib/oci8/metadata.rb +2148 -0
  34. data/lib/oci8/object.rb +641 -0
  35. data/lib/oci8/oci8.rb +756 -0
  36. data/lib/oci8/ocihandle.rb +591 -0
  37. data/lib/oci8/oracle_version.rb +153 -0
  38. data/lib/oci8/properties.rb +196 -0
  39. data/lib/oci8/version.rb +3 -0
  40. data/lib/oci8.rb +190 -0
  41. data/lib/oci8lib_310.so +0 -0
  42. data/lib/ruby-oci8.rb +1 -0
  43. data/metaconfig +142 -0
  44. data/pre-distclean.rb +7 -0
  45. data/ruby-oci8.gemspec +85 -0
  46. data/setup.rb +1342 -0
  47. data/test/README.md +37 -0
  48. data/test/config.rb +201 -0
  49. data/test/setup_test_object.sql +199 -0
  50. data/test/setup_test_package.sql +59 -0
  51. data/test/test_all.rb +56 -0
  52. data/test/test_appinfo.rb +62 -0
  53. data/test/test_array_dml.rb +332 -0
  54. data/test/test_bind_array.rb +70 -0
  55. data/test/test_bind_boolean.rb +99 -0
  56. data/test/test_bind_integer.rb +47 -0
  57. data/test/test_bind_raw.rb +45 -0
  58. data/test/test_bind_string.rb +105 -0
  59. data/test/test_bind_time.rb +177 -0
  60. data/test/test_break.rb +125 -0
  61. data/test/test_clob.rb +85 -0
  62. data/test/test_connection_pool.rb +124 -0
  63. data/test/test_connstr.rb +220 -0
  64. data/test/test_datetime.rb +585 -0
  65. data/test/test_dbi.rb +365 -0
  66. data/test/test_dbi_clob.rb +53 -0
  67. data/test/test_encoding.rb +103 -0
  68. data/test/test_error.rb +87 -0
  69. data/test/test_metadata.rb +2674 -0
  70. data/test/test_object.rb +546 -0
  71. data/test/test_oci8.rb +624 -0
  72. data/test/test_oracle_version.rb +68 -0
  73. data/test/test_oradate.rb +255 -0
  74. data/test/test_oranumber.rb +792 -0
  75. data/test/test_package_type.rb +981 -0
  76. data/test/test_properties.rb +17 -0
  77. data/test/test_rowid.rb +32 -0
  78. metadata +123 -0
@@ -0,0 +1,792 @@
1
+ # Low-level API
2
+ require 'oci8'
3
+ require File.dirname(__FILE__) + '/config'
4
+ require 'yaml'
5
+ require 'bigdecimal'
6
+ require 'rational'
7
+
8
+ class TestOraNumber < Minitest::Test
9
+
10
+ LARGE_RANGE_VALUES = [
11
+ "12345678901234567890123456789012345678",
12
+ "1234567890123456789012345678901234567",
13
+ "1234567890123456789012345678901234567.8",
14
+ "12.345678901234567890123456789012345678",
15
+ "1.2345678901234567890123456789012345678",
16
+ "1.234567890123456789012345678901234567",
17
+ "0.0000000000000000000000000000000000001",
18
+ "0.000000000000000000000000000000000001",
19
+ "0",
20
+ "2147483647", # max of 32 bit signed value
21
+ "2147483648", # max of 32 bit signed value + 1
22
+ "-2147483648", # min of 32 bit signed value
23
+ "-2147483649", # min of 32 bit signed value - 1
24
+ "9223372036854775807", # max of 64 bit signed value
25
+ "9223372036854775808", # max of 64 bit signed value + 1
26
+ "-9223372036854775808", # min of 64 bit signed value
27
+ "-9223372036854775809", # min of 64 bit signed value - 1
28
+ "-12345678901234567890123456789012345678",
29
+ "-1234567890123456789012345678901234567",
30
+ "-123456789012345678901234567890123456",
31
+ "-1234567890123456789012345678901234567.8",
32
+ "-12.345678901234567890123456789012345678",
33
+ "-1.2345678901234567890123456789012345678",
34
+ "-0.0000000000000000000000000000000000001",
35
+ "-0.000000000000000000000000000000000001",
36
+ "-0.00000000000000000000000000000000001",
37
+ "1",
38
+ "20",
39
+ "300",
40
+ "-1",
41
+ "-20",
42
+ "-300",
43
+ "1.123",
44
+ "12.123",
45
+ "123.123",
46
+ "1.1",
47
+ "1.12",
48
+ "1.123",
49
+ "-1.123",
50
+ "-12.123",
51
+ "-123.123",
52
+ "-1.1",
53
+ "-1.12",
54
+ "-1.123",
55
+ ]
56
+
57
+ SMALL_RANGE_VALUES = [
58
+ "10",
59
+ "3",
60
+ "3.14159265358979323846", # PI
61
+ "2",
62
+ "1.57079632679489661923", # PI/2
63
+ "0.5",
64
+ "0.0000000001",
65
+ "0",
66
+ "-0.0000000001",
67
+ "-0.5",
68
+ "-1.57079632679489661923", # -PI/2
69
+ "-2",
70
+ "-3.14159265358979323846", # -PI
71
+ "-3",
72
+ "-10",
73
+ ]
74
+
75
+ def compare_with_float(values, rettype, proc1, proc2 = nil)
76
+ proc2 = proc1 if proc2.nil?
77
+ values.each do |x|
78
+ expected_val = proc1.call(x.to_f)
79
+ actual_val = proc2.call(OraNumber.new(x))
80
+ assert_kind_of(rettype, actual_val)
81
+ delta = [expected_val.abs * 1.0e-12, 1.0e-14].max
82
+ assert_in_delta(expected_val, actual_val, delta, x)
83
+ end
84
+ end
85
+
86
+ def compare_with_float2(values, proc_args, proc1, proc2 = nil)
87
+ proc2 = proc1 if proc2.nil?
88
+ values.each do |x|
89
+ proc_args.each do |y|
90
+ expected_val = proc1.call(x.to_f, y)
91
+ actual_val = proc2.call(OraNumber.new(x), y)
92
+ begin
93
+ delta = [expected_val.abs * 1.0e-12, 1.0e-14].max
94
+ rescue
95
+ puts '-----------'
96
+ p x
97
+ p y
98
+ p expected_val
99
+ puts '-----------'
100
+ raise $!
101
+ end
102
+ # explicity convert actual_val to a Float to prevent
103
+ # SEGV in OCINumberSub() if the Oracle client vesion
104
+ # is less than 10.2.0.4.
105
+ if OCI8.oracle_client_version < OCI8::OracleVersion.new('10.2.0.4')
106
+ actual_val = actual_val.to_f
107
+ end
108
+ assert_in_delta(expected_val, actual_val, delta, x)
109
+ end
110
+ end
111
+ end
112
+
113
+ def test_in_bind
114
+ conn = get_oci8_connection
115
+ begin
116
+ conn.exec("alter session set nls_numeric_characters = '.,'")
117
+ cursor = conn.parse("BEGIN :out := TO_CHAR(:in); END;")
118
+ cursor.bind_param(:out, nil, String, 40)
119
+ cursor.bind_param(:in, OraNumber)
120
+ LARGE_RANGE_VALUES.each do |val|
121
+ cursor[:in] = OraNumber.new(val)
122
+ cursor.exec
123
+ # convert 0.0001 and -0.0001 to .0001 and -.0001 respectively
124
+ val = $1+'.'+$2 if /(-?)0\.(.*)/ =~ val
125
+ assert_equal(val, cursor[:out])
126
+ end
127
+ # Infinity and -Infinity
128
+ ['~', '-~'].each do |val|
129
+ cursor[:in] = OraNumber.new(val)
130
+ cursor.exec
131
+ assert_equal(val, cursor[:out])
132
+ end
133
+ if OCI8::oracle_client_version >= OCI8::ORAVER_10_1
134
+ cursor = conn.parse(<<EOS)
135
+ BEGIN
136
+ IF (:in_oranum = CAST(:in_binary_double AS NUMBER)) THEN
137
+ :result := 'match';
138
+ ELSE
139
+ :result := 'unmatch';
140
+ END IF;
141
+ END;
142
+ EOS
143
+ cursor.bind_param(:in_oranum, nil, OraNumber)
144
+ cursor.bind_param(:in_binary_double, nil, :binary_double)
145
+ cursor.bind_param(:result, nil, String, 7)
146
+ [['~', 1.0/0.0], ['-~', -1.0/0.0]].each do |val|
147
+ cursor[:in_oranum] = OraNumber.new(val[0])
148
+ cursor[:in_binary_double] = val[1]
149
+ cursor.exec
150
+ assert_equal(cursor[:result], 'match')
151
+ end
152
+ end
153
+
154
+ ensure
155
+ conn.logoff
156
+ end
157
+ end
158
+
159
+ def test_out_bind
160
+ conn = get_oci8_connection
161
+ begin
162
+ conn.exec("alter session set nls_numeric_characters = '.,'")
163
+ cursor = conn.parse("BEGIN :out := TO_NUMBER(:in); END;")
164
+ cursor.bind_param(:out, OraNumber)
165
+ cursor.bind_param(:in, nil, String, 40)
166
+ LARGE_RANGE_VALUES.each do |val|
167
+ cursor[:in] = val
168
+ cursor.exec
169
+ assert_equal(OraNumber.new(val), cursor[:out])
170
+ end
171
+ # Infinity and -Infinity
172
+ if OCI8::oracle_client_version >= OCI8::ORAVER_10_1
173
+ cursor = conn.parse("BEGIN :out := CAST(:in AS NUMBER); END;")
174
+ cursor.bind_param(:out, OraNumber)
175
+ cursor.bind_param(:in, nil, :binary_double)
176
+ [['~', 1.0/0.0], ['-~', -1.0/0.0]].each do |val|
177
+ cursor[:in] = val[1]
178
+ cursor.exec
179
+ assert_equal(OraNumber.new(val[0]), cursor[:out])
180
+ end
181
+ end
182
+ ensure
183
+ conn.logoff
184
+ end
185
+ end
186
+
187
+ def test_bind_basic_number_type
188
+ conn = get_oci8_connection
189
+ bind_type = OCI8::BindType::Mapping[:number]
190
+ begin
191
+ OCI8::BindType::Mapping[:number] = OCI8::BindType::BasicNumberType
192
+ assert_kind_of(NilClass, conn.select_one('select CAST(NULL AS NUMBER) from dual')[0])
193
+ assert_kind_of(Integer, conn.select_one('select 0.0 from dual')[0])
194
+ assert_kind_of(Integer, conn.select_one('select 10.0 from dual')[0])
195
+ assert_kind_of(Float, conn.select_one('select 10.1 from dual')[0])
196
+ ensure
197
+ conn.logoff
198
+ OCI8::BindType::Mapping[:number] = bind_type
199
+ end
200
+ end
201
+
202
+ def test_dup
203
+ (LARGE_RANGE_VALUES + ['~', '-~']).each do |x|
204
+ n = OraNumber.new(x)
205
+ assert_equal(n, n.dup)
206
+ assert_equal(n, n.clone)
207
+ end
208
+ end
209
+
210
+ def test_marshal
211
+ (LARGE_RANGE_VALUES + ['~', '-~']).each do |x|
212
+ n = OraNumber.new(x)
213
+ assert_equal(n, Marshal.load(Marshal.dump(n)))
214
+ end
215
+ end
216
+
217
+ def test_yaml
218
+ # Use the permitted_classes keyword parameter if it is supported by YAML.load
219
+ keyword_params = if YAML.method(:load).parameters.any? { |key, value| value == :permitted_symbols }
220
+ {permitted_classes: [OraNumber]}
221
+ else
222
+ {}
223
+ end
224
+ (LARGE_RANGE_VALUES + ['~', '-~']).each do |x|
225
+ n = OraNumber.new(x)
226
+ assert_equal(n, YAML.load(YAML.dump(n), **keyword_params))
227
+ end
228
+ end
229
+
230
+ # OCI8::Math.acos(x) -> ocinumber
231
+ def test_math_acos
232
+ test_values = []
233
+ -1.0.step(1.0, 0.01) do |n|
234
+ test_values << n
235
+ end
236
+ compare_with_float(test_values, OraNumber,
237
+ Proc.new {|n| Math::acos(n)},
238
+ Proc.new {|n| OCI8::Math::acos(n)})
239
+ end
240
+
241
+ # OCI8::Math.asin(x) -> ocinumber
242
+ def test_math_asin
243
+ test_values = []
244
+ -1.0.step(1.0, 0.01) do |n|
245
+ test_values << n
246
+ end
247
+ compare_with_float(test_values, OraNumber,
248
+ Proc.new {|n| Math::asin(n)},
249
+ Proc.new {|n| OCI8::Math::asin(n)})
250
+ end
251
+
252
+ # OCI8::Math.atan(x) -> ocinumber
253
+ def test_math_atan
254
+ compare_with_float(SMALL_RANGE_VALUES, OraNumber,
255
+ Proc.new {|n| Math::atan(n)},
256
+ Proc.new {|n| OCI8::Math::atan(n)})
257
+ end
258
+
259
+ # OCI8::Math.atan2(y, x) -> ocinumber
260
+ def test_math_atan2
261
+ # Prior to ruby 1.9.2:
262
+ # Following method calls' return values depend on the underneath C library
263
+ # implementation.
264
+ #
265
+ # Math::atan2(+0.0, +0.0)
266
+ # Math::atan2(-0.0, +0.0)
267
+ # Math::atan2(+0.0, -0.0)
268
+ # Math::atan2(-0.0, -0.0)
269
+ #
270
+ # They are +0.0, -0.0, +PI and -PI respectively as far as I checked them on
271
+ # Windows and Linux.
272
+ #
273
+ # After ruby 1.9.2:
274
+ # They all raise a Math::DomainError exception.
275
+ #
276
+ # In contrast to Math::atan2, OCI8::Math::atan2(0, 0) allways returns 0 because
277
+ # OraNumber doesn't have the difference between +0 and -0.
278
+ compare_with_float2(SMALL_RANGE_VALUES, SMALL_RANGE_VALUES,
279
+ Proc.new {|x, y| (x.to_f == 0 && y.to_f == 0) ? 0 : Math::atan2(x, y.to_f)},
280
+ Proc.new {|x, y| OCI8::Math::atan2(x, y.to_f)})
281
+ compare_with_float2(SMALL_RANGE_VALUES, SMALL_RANGE_VALUES,
282
+ Proc.new {|x, y| (x.to_f == 0 && y.to_f == 0) ? 0 : Math::atan2(y.to_f, x)},
283
+ Proc.new {|x, y| OCI8::Math::atan2(y.to_f, x)})
284
+ end
285
+
286
+ # OCI8::Math.cos(x) -> ocinumber
287
+ def test_math_cos
288
+ compare_with_float(SMALL_RANGE_VALUES, OraNumber,
289
+ Proc.new {|n| Math::cos(n)},
290
+ Proc.new {|n| OCI8::Math::cos(n)})
291
+ end
292
+
293
+ # OCI8::Math.cosh(x) -> ocinumber
294
+ def test_math_cosh
295
+ compare_with_float(SMALL_RANGE_VALUES, OraNumber,
296
+ Proc.new {|n| Math::cosh(n)},
297
+ Proc.new {|n| OCI8::Math::cosh(n)})
298
+ end
299
+
300
+ # OCI8::Math.exp(x) -> ocinumber
301
+ def test_exp
302
+ compare_with_float(SMALL_RANGE_VALUES, OraNumber,
303
+ Proc.new {|n| Math::exp(n)},
304
+ Proc.new {|n| OCI8::Math::exp(n)})
305
+ end
306
+
307
+ # OCI8::Math.log(numeric) -> ocinumber
308
+ # OCI8::Math.log(numeric, base_num) -> ocinumber
309
+ def test_log
310
+ test_values = LARGE_RANGE_VALUES.reject do |x|
311
+ # reject minus and zero values
312
+ x[0,1] == '-' || x == '0'
313
+ end
314
+ compare_with_float(test_values, OraNumber,
315
+ Proc.new {|n| Math::log(n)},
316
+ Proc.new {|n| OCI8::Math::log(n)})
317
+ compare_with_float(test_values, OraNumber,
318
+ Proc.new {|n| Math::log(n)/Math::log(3)},
319
+ Proc.new {|n| OCI8::Math::log(n, 3)})
320
+ end
321
+
322
+ # OCI8::Math.log10(numeric) -> ocinumber
323
+ def test_log10
324
+ test_values = LARGE_RANGE_VALUES.reject do |x|
325
+ # reject minus and zero values
326
+ x[0,1] == '-' || x == '0'
327
+ end
328
+ compare_with_float(test_values, OraNumber,
329
+ Proc.new {|n| Math::log10(n)},
330
+ Proc.new {|n| OCI8::Math::log10(n)})
331
+ end
332
+
333
+ # OCI8::Math.sin(x) -> ocinumber
334
+ def test_math_sin
335
+ compare_with_float(SMALL_RANGE_VALUES, OraNumber,
336
+ Proc.new {|n| Math::sin(n)},
337
+ Proc.new {|n| OCI8::Math::sin(n)})
338
+ end
339
+
340
+ # OCI8::Math.sinh(x) -> ocinumber
341
+ def test_math_sinh
342
+ compare_with_float(SMALL_RANGE_VALUES, OraNumber,
343
+ Proc.new {|n| Math::sinh(n)},
344
+ Proc.new {|n| OCI8::Math::sinh(n)})
345
+ end
346
+
347
+ # OCI8::Math.sqrt(numeric) -> ocinumber
348
+ def test_sqrt
349
+ test_values = LARGE_RANGE_VALUES.reject do |x|
350
+ # reject minus values
351
+ x[0,1] == '-'
352
+ end
353
+ compare_with_float(test_values, OraNumber,
354
+ Proc.new {|n| Math::sqrt(n)},
355
+ Proc.new {|n| OCI8::Math::sqrt(n)})
356
+ end
357
+
358
+ # OCI8::Math.tan(x) -> ocinumber
359
+ def test_math_tan
360
+ test_values = SMALL_RANGE_VALUES.reject do |x|
361
+ # reject PI/2 and -PI/2.
362
+ # Those values are +inf and -info
363
+ radian = x.to_f
364
+ (radian.abs - Math::PI/2).abs < 0.000001
365
+ end
366
+ compare_with_float(test_values, OraNumber,
367
+ Proc.new {|n| Math::tan(n)},
368
+ Proc.new {|n| OCI8::Math::tan(n)})
369
+ end
370
+
371
+ # OCI8::Math.tanh() -> ocinumber
372
+ def test_math_tanh
373
+ compare_with_float(SMALL_RANGE_VALUES, OraNumber,
374
+ Proc.new {|n| Math::tanh(n)},
375
+ Proc.new {|n| OCI8::Math::tanh(n)})
376
+ end
377
+
378
+ # onum % other -> onum
379
+ # def test_mod
380
+
381
+ # onum * other -> onum
382
+ def test_mul
383
+ compare_with_float2(SMALL_RANGE_VALUES, SMALL_RANGE_VALUES,
384
+ Proc.new {|x, y| x * y.to_f})
385
+ compare_with_float2(SMALL_RANGE_VALUES, SMALL_RANGE_VALUES,
386
+ Proc.new {|x, y| y.to_f * x})
387
+ end
388
+
389
+ # onum ** other -> onum
390
+ def test_pow
391
+ base_values = SMALL_RANGE_VALUES.reject do |x|
392
+ # reject minus and zero values
393
+ x[0,1] == '-' || x == '0'
394
+ end
395
+ compare_with_float2(base_values, SMALL_RANGE_VALUES,
396
+ Proc.new {|x, y| x ** y.to_f})
397
+ compare_with_float2(SMALL_RANGE_VALUES, base_values,
398
+ Proc.new {|x, y| y.to_f ** x})
399
+ end
400
+
401
+ # onum + other -> onum
402
+ def test_add
403
+ compare_with_float2(SMALL_RANGE_VALUES, SMALL_RANGE_VALUES,
404
+ Proc.new {|x, y| x + y.to_f})
405
+ compare_with_float2(SMALL_RANGE_VALUES, SMALL_RANGE_VALUES,
406
+ Proc.new {|x, y| y.to_f + x})
407
+ end
408
+
409
+ # onum - other -> onum
410
+ def test_minus
411
+ compare_with_float2(SMALL_RANGE_VALUES, SMALL_RANGE_VALUES,
412
+ Proc.new {|x, y| x - y.to_f})
413
+ compare_with_float2(SMALL_RANGE_VALUES, SMALL_RANGE_VALUES,
414
+ Proc.new {|x, y| y.to_f - x})
415
+ end
416
+
417
+ # -ocinumber -> ocinumber
418
+ def test_uminus
419
+ compare_with_float(LARGE_RANGE_VALUES, OraNumber, Proc.new {|n| -n})
420
+ end
421
+
422
+ # onum / other -> onum
423
+ # TODO: test_div
424
+
425
+ # onum <=> other -> -1, 0, +1
426
+ def test_cmp
427
+ assert_equal(-1, 1 <=> OraNumber(2))
428
+ assert_equal(-1, 1.0 <=> OraNumber(2))
429
+ assert_equal(-1, BigDecimal("1") <=> OraNumber(2))
430
+ assert_equal(-1, Rational(1) <=> OraNumber(2))
431
+ assert_equal(0, 2 <=> OraNumber(2))
432
+ assert_equal(0, 2.0 <=> OraNumber(2))
433
+ assert_equal(0, BigDecimal("2") <=> OraNumber(2))
434
+ assert_equal(0, Rational(2) <=> OraNumber(2))
435
+ assert_equal(1, 3 <=> OraNumber(2))
436
+ assert_equal(1, 3.0 <=> OraNumber(2))
437
+ assert_equal(1, BigDecimal("3") <=> OraNumber(2))
438
+ assert_equal(1, Rational(3) <=> OraNumber(2))
439
+ end
440
+
441
+ # onum.abs -> ocinumber
442
+ def test_abs
443
+ compare_with_float(LARGE_RANGE_VALUES, OraNumber, Proc.new {|n| n.abs})
444
+ end
445
+
446
+ # onum.ceil -> integer
447
+ def test_ceil
448
+ compare_with_float(LARGE_RANGE_VALUES, Integer, Proc.new {|n| n.ceil})
449
+ end
450
+
451
+ # onum.floor -> integer
452
+ def test_floor
453
+ compare_with_float(LARGE_RANGE_VALUES, Integer, Proc.new {|n| n.floor})
454
+ end
455
+
456
+ # onum.round -> integer
457
+ # onum.round(decplace) -> onum
458
+ def test_round
459
+ compare_with_float(LARGE_RANGE_VALUES, Integer, Proc.new {|n| n.round})
460
+ compare_with_float(LARGE_RANGE_VALUES, OraNumber,
461
+ Proc.new {|n| (n * 10).round * 0.1},
462
+ Proc.new {|n| n.round(1)})
463
+ compare_with_float(LARGE_RANGE_VALUES, OraNumber,
464
+ Proc.new {|n| (n * 100).round * 0.01},
465
+ Proc.new {|n| n.round(2)})
466
+ compare_with_float(LARGE_RANGE_VALUES, OraNumber,
467
+ Proc.new {|n| (n * 0.1).round * 10},
468
+ Proc.new {|n| n.round(-1)})
469
+ end
470
+
471
+ # onum.round_prec(digits) -> ocinumber
472
+ def test_round_prec
473
+ if OCI8::oracle_client_version >= OCI8::ORAVER_8_1
474
+ # Oracle 8.1 client or upper
475
+ compare_with_float2(LARGE_RANGE_VALUES, [1, 2, 3, 5, 10, 20],
476
+ Proc.new {|x, y|
477
+ return 0.0 if x == 0.0
478
+ factor = 10 ** (Math::log10(x.abs).to_i - y + 1)
479
+ (x / factor).round * factor
480
+ },
481
+ Proc.new {|x, y| x.round_prec(y)})
482
+ else
483
+ # Oracle 8.0 client
484
+ assert_raises NoMethodError do
485
+ OraNumber.new(1).round_prec(1)
486
+ end
487
+ end
488
+ end
489
+
490
+ # onum.shift(fixnum) -> ocinumber
491
+ def test_shift
492
+ if OCI8::oracle_client_version >= OCI8::ORAVER_8_1
493
+ # Oracle 8.1 client or upper
494
+ compare_with_float2(LARGE_RANGE_VALUES, [-5, -4, -3, -1, 0, 1, 2, 3, 4, 5],
495
+ Proc.new {|x, y| x * (10 ** y)},
496
+ Proc.new {|x, y| x.shift(y)})
497
+ else
498
+ # Oracle 8.0 client
499
+ assert_raises NoMethodError do
500
+ OraNumber.new(1).shift(1)
501
+ end
502
+ end
503
+ end
504
+
505
+ # onum.to_char(fmt = nil, nls_params = nil) -> string
506
+ def test_to_char
507
+ onum = OraNumber.new(123.45)
508
+ assert_equal(' 123.4500', onum.to_char('99999.9999'))
509
+ assert_equal(' 0123.4500', onum.to_char('90000.0009'))
510
+ assert_equal(' 00123.4500', onum.to_char('00000.0000'))
511
+ assert_equal('123.45', onum.to_char('FM99999.9999'))
512
+ assert_equal('0123.450', onum.to_char('FM90000.0009'))
513
+ assert_equal('00123.4500', onum.to_char('FM00000.0000'))
514
+ assert_equal(' -123.4500',(-onum).to_char('99999.9999'))
515
+ assert_equal(' -0123.4500',(-onum).to_char('90000.0009'))
516
+ assert_equal('-00123.4500',(-onum).to_char('00000.0000'))
517
+ assert_equal('-123.45', (-onum).to_char('FM99999.9999'))
518
+ assert_equal('-0123.450', (-onum).to_char('FM90000.0009'))
519
+ assert_equal('-00123.4500',(-onum).to_char('FM00000.0000'))
520
+ assert_equal(' 0,123.4500', onum.to_char('0G000D0000', "NLS_NUMERIC_CHARACTERS = '.,'"))
521
+ assert_equal(' 0.123,4500', onum.to_char('0G000D0000', "NLS_NUMERIC_CHARACTERS = ',.'"))
522
+ assert_equal('Ducat123.45', onum.to_char('FML9999.999', "NLS_CURRENCY = 'Ducat'"))
523
+ end
524
+
525
+ # onum.to_f -> float
526
+ def test_to_f
527
+ LARGE_RANGE_VALUES.each do |x|
528
+ expected_val = x.to_f
529
+ actual_val = OraNumber.new(x).to_f
530
+ delta = [expected_val.abs * 1.0e-12, 1.0e-14].max
531
+ assert_in_delta(expected_val, actual_val, delta, x)
532
+ end
533
+ end
534
+
535
+ # onum.to_i -> integer
536
+ def test_to_i
537
+ LARGE_RANGE_VALUES.each do |x|
538
+ expected_val = x.to_i
539
+ actual_val = OraNumber.new(x).to_i
540
+ assert_equal(expected_val, actual_val, x)
541
+ end
542
+ end
543
+
544
+ # onum.to_s -> string
545
+ def test_to_s
546
+ LARGE_RANGE_VALUES.each do |x|
547
+ expected_val = x
548
+ actual_val = OraNumber.new(x).to_s
549
+ assert_equal(expected_val, actual_val, x)
550
+ end
551
+
552
+ conn = get_oci8_connection()
553
+ begin
554
+ cursor = conn.parse('select to_number(:1) from dual')
555
+ cursor.define(1, OraNumber)
556
+ cursor.bind_param(1, nil, String, 200)
557
+ [
558
+ "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", # 1E125
559
+ "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", # 1E124
560
+ "234567890234567890234567890234567890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
561
+ "23456789023456789023456789023456789000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
562
+ "2345678902345678902345678902345678900",
563
+ "234567890234567890234567890234567890",
564
+ "23456789023456789023456789023456789",
565
+ "2345678902345678902345678902345678.9",
566
+ "234567890234567890234567890234567.89",
567
+ "23.456789023456789023456789023456789",
568
+ "2.3456789023456789023456789023456789",
569
+ "0.23456789023456789023456789023456789", # 2.34..snip..E-1
570
+ "0.023456789023456789023456789023456789", # 2.34..snip..E-2
571
+ "0.0023456789023456789023456789023456789", # 2.34..snip..E-3
572
+ "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000023456789023456789023456789023456789", # 2.34..snip..E-130
573
+ "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", # 1E-129
574
+ "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", # 1E-130
575
+ ].each do |str|
576
+ cursor[1] = str
577
+ cursor.exec
578
+ onum = cursor.fetch[0]
579
+ assert_equal(str, onum.to_s, "test data: " + str)
580
+
581
+ str = '-' + str
582
+ cursor[1] = str
583
+ cursor.exec
584
+ onum = cursor.fetch[0]
585
+ assert_equal(str, onum.to_s, "test data: " + str)
586
+ end
587
+ ensure
588
+ conn.logoff
589
+ end
590
+ end
591
+
592
+ # onum.truncate -> integer
593
+ # onum.truncate(decplace) -> ocinumber
594
+ # TODO: test_truncate
595
+
596
+ # onum.zero? -> true or false
597
+ def test_zero_p
598
+ LARGE_RANGE_VALUES.each do |x|
599
+ expected_val = x.to_f.zero?
600
+ actual_val = OraNumber.new(x).zero?
601
+ assert_equal(expected_val, actual_val, x)
602
+ end
603
+ end
604
+
605
+ def test_new_from_string
606
+ conn = get_oci8_connection()
607
+ begin
608
+ cursor = conn.parse('select to_number(:1) from dual')
609
+ cursor.define(1, OraNumber)
610
+ cursor.bind_param(1, nil, String, 200)
611
+ [
612
+ "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", # 1E125
613
+ "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", # 1E124
614
+ "234567890234567890234567890234567890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
615
+ "23456789023456789023456789023456789000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
616
+ "2345678902345678902345678902345678900",
617
+ "234567890234567890234567890234567890",
618
+ "23456789023456789023456789023456789",
619
+ "2345678902345678902345678902345678.9",
620
+ "234567890234567890234567890234567.89",
621
+ "23.456789023456789023456789023456789",
622
+ "2.3456789023456789023456789023456789",
623
+ "0.23456789023456789023456789023456789", # 2.34..snip..E-1
624
+ "0.023456789023456789023456789023456789", # 2.34..snip..E-2
625
+ "0.0023456789023456789023456789023456789", # 2.34..snip..E-3
626
+ "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000023456789023456789023456789023456789", # 2.34..snip..E-130
627
+ "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", # 1E-129
628
+ "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", # 1E-130
629
+
630
+ # leading spaces
631
+ " 123",
632
+ # trailing spaces
633
+ "123 ",
634
+ "123.456 ",
635
+ "123E10 ",
636
+ "123.456E10 ",
637
+ # scientific notation
638
+ "1234567890000e-9",
639
+ "123456789000e-8",
640
+ "123456789e-5",
641
+ "12345.6789e-1",
642
+ "12.3456789e+1",
643
+ "0.0000123456789E7",
644
+ # round to zero
645
+ "1E-131",
646
+ # overflow
647
+ "1E126",
648
+ "10E125",
649
+ "100000000000E115",
650
+ "1E+126",
651
+ # invalid number
652
+ "",
653
+ " ",
654
+ "abc",
655
+ "1E10a",
656
+ "11E10a",
657
+ "1.1.1",
658
+ # round down
659
+ "444444444444444444444444444444444444444444444444440000",
660
+ "44444444444444444444444444444444444444444444444444000",
661
+ "44444444444444444444444444.444444444444444444444444",
662
+ "4444444444444444444444444.4444444444444444444444444",
663
+ "0.000000044444444444444444444444444444444444444444444444444",
664
+ "0.00000044444444444444444444444444444444444444444444444444",
665
+ # round up
666
+ "555555555555555555555555555555555555555555555555550000",
667
+ "55555555555555555555555555555555555555555555555555000",
668
+ "55555555555555555555555555.555555555555555555555555",
669
+ "5555555555555555555555555.5555555555555555555555555",
670
+ "0.000000055555555555555555555555555555555555555555555555555",
671
+ "0.00000055555555555555555555555555555555555555555555555555",
672
+ "999999999999999999999999999999999999999999999999990000",
673
+ "99999999999999999999999999999999999999999999999999000",
674
+ "99999999999999999999999999.999999999999999999999999",
675
+ "9999999999999999999999999.9999999999999999999999999",
676
+ "0.000000099999999999999999999999999999999999999999999999999",
677
+ "0.00000099999999999999999999999999999999999999999999999999",
678
+ # overflow by round up
679
+ "999999999999999999999999999999999999999999999999999999999900000000000000000000000000000000000000000000000000000000000000000000",
680
+ ].each do |str|
681
+ run_test_new_from_string(cursor, str)
682
+ run_test_new_from_string(cursor, '-' + str)
683
+ end
684
+ ensure
685
+ conn.logoff
686
+ end
687
+ end
688
+
689
+ def run_test_new_from_string(cursor, str)
690
+ cursor[1] = str
691
+ onum = nil
692
+ begin
693
+ cursor.exec
694
+ onum = cursor.fetch[0]
695
+ rescue OCIError => oraerr
696
+ begin
697
+ OraNumber.new(str)
698
+ flunk("exception expected but none was thrown. test data: " + str)
699
+ rescue
700
+ assert_equal(oraerr.to_s, $!.to_s, "test data: " + str)
701
+ end
702
+ end
703
+ if onum
704
+ assert_equal(onum.dump, OraNumber.new(str).dump, "test data: " + str)
705
+ end
706
+ end
707
+
708
+ def test_new_from_bigdecimal
709
+ ["+Infinity", "-Infinity", "NaN"].each do |n|
710
+ assert_raises TypeError do
711
+ OraNumber.new(BigDecimal(n))
712
+ end
713
+ end
714
+
715
+ LARGE_RANGE_VALUES.each do |val|
716
+ assert_equal(val, OraNumber.new(BigDecimal(val)).to_s)
717
+ end
718
+ end
719
+
720
+ def test_new_from_rational
721
+ [
722
+ [Rational(1, 2), "0.5"],
723
+ [Rational(3, 5), "0.6"],
724
+ [Rational(10, 3), "3.33333333333333333333333333333333333333"],
725
+ [Rational(20, 3), "6.66666666666666666666666666666666666667"],
726
+ ].each do |ary|
727
+ assert_equal(ary[1], OraNumber.new(ary[0]).to_s)
728
+ end
729
+ end
730
+
731
+ def test_dump
732
+ conn = get_oci8_connection
733
+ begin
734
+ cursor = conn.parse("select dump(to_number(:1)) from dual")
735
+ cursor.bind_param(1, nil, String, 40)
736
+ LARGE_RANGE_VALUES.each do |val|
737
+ cursor[1] = val
738
+ cursor.exec
739
+ assert_equal(cursor.fetch[0], OraNumber.new(val).dump)
740
+ end
741
+ ensure
742
+ conn.logoff
743
+ end
744
+ LARGE_RANGE_VALUES
745
+ end
746
+
747
+ def test_has_fractional_part
748
+ assert_equal(false, OraNumber(10.0).has_fractional_part?)
749
+ assert_equal(true, OraNumber(10.1).has_fractional_part?)
750
+ end
751
+
752
+ def test_float_conversion_type_ruby
753
+ orig = OCI8.properties[:float_conversion_type]
754
+ conn = get_oci8_connection
755
+ begin
756
+ OCI8.properties[:float_conversion_type] = :ruby
757
+ # Oracle Number -> Ruby Float
758
+ cursor = conn.parse('begin :out := :in; end;')
759
+ cursor.bind_param(:in, nil, String, 50)
760
+ cursor.bind_param(:out, nil, Float)
761
+ LARGE_RANGE_VALUES.each do |n|
762
+ cursor[:in] = n
763
+ cursor.exec
764
+ assert_equal(n.to_f, cursor[:out])
765
+ end
766
+ cursor.close
767
+ # Ruby Float -> Oracle Number
768
+ LARGE_RANGE_VALUES.each do |n|
769
+ float_val = n.to_f
770
+ expected_val = float_val.to_s
771
+ # convert
772
+ if /(-?)(\d).(\d+)e([+-]?\d+)/ =~ expected_val
773
+ sign = $1
774
+ int = $2
775
+ frac = $3
776
+ shift = $4.to_i
777
+ if frac.length <= shift
778
+ expected_val = sign + int + frac + '0' * (shift - frac.length)
779
+ elsif shift < 0
780
+ expected_val = sign + '0.' + '0' * (-shift - 1) + int + frac
781
+ expected_val.gsub!(/0+$/, '')
782
+ end
783
+ end
784
+ expected_val.gsub!(/\.0$/, '')
785
+ assert_equal(expected_val, OraNumber(float_val).to_s, "n = #{n}, float_val.to_s = #{float_val.to_s}")
786
+ end
787
+ ensure
788
+ OCI8.properties[:float_conversion_type] = orig
789
+ conn.logoff
790
+ end
791
+ end
792
+ end