ruby-staci 2.2.9

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