ruby-oci8 1.0.7 → 2.0.0

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 (89) hide show
  1. data/ChangeLog +1254 -390
  2. data/Makefile +10 -13
  3. data/README +56 -385
  4. data/VERSION +1 -1
  5. data/dist-files +26 -27
  6. data/ext/oci8/.document +1 -0
  7. data/ext/oci8/MANIFEST +0 -4
  8. data/ext/oci8/apiwrap.c.tmpl +172 -0
  9. data/ext/oci8/apiwrap.h.tmpl +61 -0
  10. data/ext/oci8/apiwrap.rb +91 -0
  11. data/ext/oci8/apiwrap.yml +1243 -0
  12. data/ext/oci8/attr.c +124 -384
  13. data/ext/oci8/bind.c +472 -164
  14. data/ext/oci8/encoding.c +196 -0
  15. data/ext/oci8/env.c +84 -253
  16. data/ext/oci8/error.c +196 -127
  17. data/ext/oci8/extconf.rb +82 -59
  18. data/ext/oci8/lob.c +710 -370
  19. data/ext/oci8/metadata.c +359 -0
  20. data/ext/oci8/object.c +622 -0
  21. data/ext/oci8/oci8.c +577 -161
  22. data/ext/oci8/oci8.h +354 -258
  23. data/ext/oci8/oci8lib.c +493 -0
  24. data/ext/oci8/ocidatetime.c +473 -0
  25. data/ext/oci8/ocinumber.c +1123 -24
  26. data/ext/oci8/oraconf.rb +72 -106
  27. data/ext/oci8/oradate.c +511 -321
  28. data/ext/oci8/stmt.c +752 -572
  29. data/ext/oci8/win32.c +131 -0
  30. data/ext/oci8/xmldb.c +383 -0
  31. data/lib/.document +2 -0
  32. data/lib/dbd/OCI8.rb +2 -17
  33. data/lib/oci8.rb.in +41 -1622
  34. data/lib/oci8/.document +5 -0
  35. data/lib/oci8/compat.rb +108 -0
  36. data/lib/oci8/datetime.rb +489 -0
  37. data/lib/oci8/encoding-init.rb +40 -0
  38. data/lib/oci8/encoding.yml +537 -0
  39. data/lib/oci8/metadata.rb +2077 -0
  40. data/lib/oci8/object.rb +548 -0
  41. data/lib/oci8/oci8.rb +773 -0
  42. data/lib/oci8/oracle_version.rb +144 -0
  43. data/metaconfig +3 -3
  44. data/ruby-oci8.gemspec +5 -5
  45. data/setup.rb +4 -4
  46. data/test/config.rb +64 -84
  47. data/test/test_all.rb +14 -21
  48. data/test/test_array_dml.rb +317 -0
  49. data/test/test_bind_raw.rb +18 -25
  50. data/test/test_bind_time.rb +78 -91
  51. data/test/test_break.rb +37 -35
  52. data/test/test_clob.rb +33 -89
  53. data/test/test_connstr.rb +5 -4
  54. data/test/test_datetime.rb +469 -0
  55. data/test/test_dbi.rb +99 -60
  56. data/test/test_dbi_clob.rb +3 -8
  57. data/test/test_metadata.rb +65 -51
  58. data/test/test_oci8.rb +151 -55
  59. data/test/test_oracle_version.rb +70 -0
  60. data/test/test_oradate.rb +76 -83
  61. data/test/test_oranumber.rb +405 -71
  62. data/test/test_rowid.rb +6 -11
  63. metadata +31 -32
  64. data/NEWS +0 -420
  65. data/ext/oci8/const.c +0 -165
  66. data/ext/oci8/define.c +0 -53
  67. data/ext/oci8/describe.c +0 -81
  68. data/ext/oci8/descriptor.c +0 -39
  69. data/ext/oci8/handle.c +0 -273
  70. data/ext/oci8/oranumber.c +0 -445
  71. data/ext/oci8/param.c +0 -37
  72. data/ext/oci8/server.c +0 -182
  73. data/ext/oci8/session.c +0 -99
  74. data/ext/oci8/svcctx.c +0 -238
  75. data/ruby-oci8.spec +0 -62
  76. data/support/README +0 -4
  77. data/support/runit/assert.rb +0 -281
  78. data/support/runit/cui/testrunner.rb +0 -101
  79. data/support/runit/error.rb +0 -4
  80. data/support/runit/method_mappable.rb +0 -20
  81. data/support/runit/robserver.rb +0 -25
  82. data/support/runit/setuppable.rb +0 -15
  83. data/support/runit/teardownable.rb +0 -16
  84. data/support/runit/testcase.rb +0 -113
  85. data/support/runit/testfailure.rb +0 -25
  86. data/support/runit/testresult.rb +0 -121
  87. data/support/runit/testsuite.rb +0 -43
  88. data/support/runit/version.rb +0 -3
  89. data/test/test_describe.rb +0 -137
@@ -1,19 +1,42 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
1
2
  /*
2
- ocinumber.c - part of ruby-oci8
3
- copy from ocinumber.c in ruby-oci8 0.2.
4
- */
5
-
3
+ * ocinumber.c
4
+ *
5
+ * $Author: kubo $
6
+ * $Date: 2009-01-12 00:11:09 +0900 (Mon, 12 Jan 2009) $
7
+ *
8
+ * Copyright (C) 2005-2008 KUBO Takehiro <kubo@jiubao.org>
9
+ *
10
+ */
6
11
  #include "oci8.h"
7
12
  #include <orl.h>
13
+ #include <errno.h>
14
+
15
+ #ifndef RUBY_VM
16
+ /* ruby 1.8 */
17
+ #define rb_num_coerce_cmp(x, y, id) rb_num_coerce_cmp((x), (y))
18
+ #define rb_num_coerce_bin(x, y, id) rb_num_coerce_bin((x), (y))
19
+ #endif
8
20
 
9
- /* use for local call */
10
- #define oci_lc(rv) do { \
11
- sword __rv = (rv); \
12
- if (__rv != OCI_SUCCESS) { \
13
- oci8_raise(errhp, __rv, NULL); \
14
- } \
15
- } while(0)
21
+ static ID id_power; /* rb_intern("**") */
22
+ static ID id_cmp; /* rb_intern("<=>") */
16
23
 
24
+ static VALUE cOCINumber;
25
+ static OCINumber const_p1; /* +1 */
26
+ static OCINumber const_p10; /* +10 */
27
+ static OCINumber const_m1; /* -1 */
28
+ static OCINumber const_PI2; /* +PI/2 */
29
+ static OCINumber const_mPI2; /* -PI/2 */
30
+
31
+ #define SHRESHOLD_FMT_STR "00000000000000000000000000"
32
+ #define SHRESHOLD_FMT (OraText*)SHRESHOLD_FMT_STR
33
+ #define SHRESHOLD_FMT_LEN (sizeof(SHRESHOLD_FMT_STR) - 1)
34
+ #define SHRESHOLD_VAL_STR "10000000000000000000000000"
35
+ #define SHRESHOLD_VAL (OraText*)SHRESHOLD_VAL_STR
36
+ #define SHRESHOLD_VAL_LEN (sizeof(SHRESHOLD_VAL_STR) - 1)
37
+ static OCINumber const_shreshold;
38
+
39
+ /* TODO: scale: -84 - 127 */
17
40
  #define NUMBER_FORMAT1_STR "FM9999999999999999999999990.9999999999999999999999999999999999999"
18
41
  #define NUMBER_FORMAT1 (OraText*)NUMBER_FORMAT1_STR
19
42
  #define NUMBER_FORMAT1_LEN (sizeof(NUMBER_FORMAT1_STR) - 1)
@@ -25,12 +48,53 @@
25
48
  #define NUMBER_FORMAT_INT (OraText*)NUMBER_FORMAT_INT_STR
26
49
  #define NUMBER_FORMAT_INT_LEN (sizeof(NUMBER_FORMAT_INT_STR) - 1)
27
50
 
28
- #ifndef StringValue
29
- #define StringValue(s) ((s) = (TYPE(s) == T_STRING) ? (s) : rb_str_to_str(s))
30
- #endif
51
+ #define _NUMBER(val) ((OCINumber *)DATA_PTR(val)) /* dangerous macro */
52
+
53
+ static VALUE onum_s_alloc(VALUE klass)
54
+ {
55
+ VALUE obj;
56
+ OCINumber *d;
57
+
58
+ obj = Data_Make_Struct(klass, OCINumber, NULL, xfree, d);
59
+ OCINumberSetZero(oci8_errhp, d);
60
+ return obj;
61
+ }
62
+
63
+ /* construct an ruby object(OCI::Number) from C structure (OCINumber). */
64
+ VALUE oci8_make_ocinumber(OCINumber *s)
65
+ {
66
+ VALUE obj;
67
+ OCINumber *d;
68
+
69
+ obj = Data_Make_Struct(cOCINumber, OCINumber, NULL, xfree, d);
70
+ oci_lc(OCINumberAssign(oci8_errhp, s, d));
71
+ return obj;
72
+ }
73
+
74
+ VALUE oci8_make_integer(OCINumber *s)
75
+ {
76
+ signed long sl;
77
+ char buf[512];
78
+ ub4 buf_size = sizeof(buf);
79
+
80
+ if (OCINumberToInt(oci8_errhp, s, sizeof(sl), OCI_NUMBER_SIGNED, &sl) == OCI_SUCCESS) {
81
+ return LONG2NUM(sl);
82
+ }
83
+ oci_lc(OCINumberToText(oci8_errhp, s, NUMBER_FORMAT2, NUMBER_FORMAT2_LEN,
84
+ NULL, 0, &buf_size, TO_ORATEXT(buf)));
85
+ return rb_cstr2inum(buf, 10);
86
+ }
87
+
88
+ VALUE oci8_make_float(OCINumber *s)
89
+ {
90
+ double dbl;
91
+
92
+ oci_lc(OCINumberToReal(oci8_errhp, s, sizeof(double), &dbl));
93
+ return rb_float_new(dbl);
94
+ }
31
95
 
32
96
  /* fill C structure (OCINumber) from a string. */
33
- static void set_oci_number_from_str(OCINumber *result, VALUE str, VALUE fmt, VALUE nls_params, OCIError *errhp)
97
+ static void set_oci_number_from_str(OCINumber *result, VALUE str, VALUE fmt, VALUE nls_params)
34
98
  {
35
99
  oratext *fmt_ptr;
36
100
  oratext *nls_params_ptr;
@@ -71,7 +135,7 @@ static void set_oci_number_from_str(OCINumber *result, VALUE str, VALUE fmt, VAL
71
135
  nls_params_ptr = RSTRING_ORATEXT(nls_params);
72
136
  nls_params_len = RSTRING_LEN(nls_params);
73
137
  }
74
- oci_lc(OCINumberFromText(errhp,
138
+ oci_lc(OCINumberFromText(oci8_errhp,
75
139
  RSTRING_ORATEXT(str), RSTRING_LEN(str),
76
140
  fmt_ptr, fmt_len, nls_params_ptr, nls_params_len,
77
141
  result));
@@ -79,7 +143,7 @@ static void set_oci_number_from_str(OCINumber *result, VALUE str, VALUE fmt, VAL
79
143
 
80
144
  /* fill C structure (OCINumber) from a numeric object. */
81
145
  /* 1 - success, 0 - error */
82
- static int set_oci_number_from_num(OCINumber *result, VALUE num, OCIError *errhp)
146
+ static int set_oci_number_from_num(OCINumber *result, VALUE num, int force)
83
147
  {
84
148
  signed long sl;
85
149
  double dbl;
@@ -90,28 +154,1063 @@ static int set_oci_number_from_num(OCINumber *result, VALUE num, OCIError *errhp
90
154
  case T_FIXNUM:
91
155
  /* set from long. */
92
156
  sl = NUM2LONG(num);
93
- oci_lc(OCINumberFromInt(errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, result));
157
+ oci_lc(OCINumberFromInt(oci8_errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, result));
94
158
  return 1;
95
159
  case T_FLOAT:
96
160
  /* set from double. */
97
161
  dbl = NUM2DBL(num);
98
- oci_lc(OCINumberFromReal(errhp, &dbl, sizeof(dbl), result));
162
+ oci_lc(OCINumberFromReal(oci8_errhp, &dbl, sizeof(dbl), result));
99
163
  return 1;
100
164
  case T_BIGNUM:
101
165
  /* change via string. */
102
166
  num = rb_big2str(num, 10);
103
- set_oci_number_from_str(result, num, Qnil, Qnil, errhp);
167
+ set_oci_number_from_str(result, num, Qnil, Qnil);
104
168
  return 1;
105
169
  }
106
- if (RTEST(rb_obj_is_instance_of(num, cOraNumber))) {
170
+ if (RTEST(rb_obj_is_instance_of(num, cOCINumber))) {
107
171
  /* OCI::Number */
108
- oci_lc(OCINumberAssign(errhp, DATA_PTR(num), result));
172
+ oci_lc(OCINumberAssign(oci8_errhp, DATA_PTR(num), result));
173
+ return 1;
174
+ }
175
+ if (force) {
176
+ /* change via string as a last resort. */
177
+ /* TODO: if error, raise TypeError instead of OCI::Error */
178
+ set_oci_number_from_str(result, num, Qnil, Qnil);
109
179
  return 1;
110
180
  }
111
181
  return 0;
112
182
  }
113
183
 
114
- int set_oci_vnumber(ora_vnumber_t *result, VALUE num, OCIError *errhp)
184
+ OCINumber *oci8_set_ocinumber(OCINumber *result, VALUE self)
185
+ {
186
+ set_oci_number_from_num(result, self, 1);
187
+ return result;
188
+ }
189
+ #define TO_OCINUM(on, val) oci8_set_ocinumber((on), (val))
190
+
191
+ OCINumber *oci8_set_integer(OCINumber *result, VALUE self)
192
+ {
193
+ OCINumber work;
194
+ set_oci_number_from_num(&work, self, 1);
195
+ oci_lc(OCINumberTrunc(oci8_errhp, &work, 0, result));
196
+ return result;
197
+ }
198
+
199
+ /*
200
+ * call-seq:
201
+ * OCI8::Math.atan2(y, x) -> oranumber
202
+ *
203
+ * Computes the arc tangent given <i>y</i> and <i>x</i>. Returns
204
+ * -PI..PI.
205
+ */
206
+ static VALUE omath_atan2(VALUE self, VALUE Ycoordinate, VALUE Xcoordinate)
207
+ {
208
+ OCINumber nY;
209
+ OCINumber nX;
210
+ OCINumber rv;
211
+ boolean is_zero;
212
+ sword sign;
213
+
214
+ set_oci_number_from_num(&nX, Xcoordinate, 1);
215
+ set_oci_number_from_num(&nY, Ycoordinate, 1);
216
+ /* check zero */
217
+ oci_lc(OCINumberIsZero(oci8_errhp, &nX, &is_zero));
218
+ if (is_zero) {
219
+ oci_lc(OCINumberSign(oci8_errhp, &nY, &sign));
220
+ switch (sign) {
221
+ case 0:
222
+ return INT2FIX(0); /* atan2(0, 0) => 0 or ERROR? */
223
+ case 1:
224
+ return oci8_make_ocinumber(&const_PI2); /* atan2(positive, 0) => PI/2 */
225
+ case -1:
226
+ return oci8_make_ocinumber(&const_mPI2); /* atan2(negative, 0) => -PI/2 */
227
+ }
228
+ }
229
+ /* atan2 */
230
+ oci_lc(OCINumberArcTan2(oci8_errhp, &nY, &nX, &rv));
231
+ return oci8_make_ocinumber(&rv);
232
+ }
233
+
234
+ /*
235
+ * call-seq:
236
+ * OCI8::Math.cos(x) -> oranumber
237
+ *
238
+ * Computes the cosine of <i>x</i> (expressed in radians). Returns
239
+ * -1..1.
240
+ */
241
+ static VALUE omath_cos(VALUE obj, VALUE radian)
242
+ {
243
+ OCINumber r;
244
+ OCINumber rv;
245
+
246
+ oci_lc(OCINumberCos(oci8_errhp, TO_OCINUM(&r, radian), &rv));
247
+ return oci8_make_ocinumber(&rv);
248
+ }
249
+
250
+ /*
251
+ * call-seq:
252
+ * OCI8::Math.sin(x) -> oranumber
253
+ *
254
+ * Computes the sine of <i>x</i> (expressed in radians). Returns
255
+ * -1..1.
256
+ */
257
+ static VALUE omath_sin(VALUE obj, VALUE radian)
258
+ {
259
+ OCINumber r;
260
+ OCINumber rv;
261
+
262
+ oci_lc(OCINumberSin(oci8_errhp, TO_OCINUM(&r, radian), &rv));
263
+ return oci8_make_ocinumber(&rv);
264
+ }
265
+
266
+ /*
267
+ * call-seq:
268
+ * OCI8::Math.tan(x) -> oranumber
269
+ *
270
+ * Returns the tangent of <i>x</i> (expressed in radians).
271
+ */
272
+ static VALUE omath_tan(VALUE obj, VALUE radian)
273
+ {
274
+ OCINumber r;
275
+ OCINumber rv;
276
+
277
+ oci_lc(OCINumberTan(oci8_errhp, TO_OCINUM(&r, radian), &rv));
278
+ return oci8_make_ocinumber(&rv);
279
+ }
280
+
281
+ /*
282
+ * call-seq:
283
+ * OCI8::Math.acos(x) -> oranumber
284
+ *
285
+ * Computes the arc cosine of <i>x</i>. Returns 0..PI.
286
+ */
287
+ static VALUE omath_acos(VALUE obj, VALUE num)
288
+ {
289
+ OCINumber n;
290
+ OCINumber r;
291
+ sword sign;
292
+
293
+ set_oci_number_from_num(&n, num, 1);
294
+ /* check upper bound */
295
+ oci_lc(OCINumberCmp(oci8_errhp, &n, &const_p1, &sign));
296
+ if (sign > 0)
297
+ rb_raise(rb_eRangeError, "out of range for acos");
298
+ /* check lower bound */
299
+ oci_lc(OCINumberCmp(oci8_errhp, &n, &const_m1, &sign));
300
+ if (sign < 0)
301
+ rb_raise(rb_eRangeError, "out of range for acos");
302
+ /* acos */
303
+ oci_lc(OCINumberArcCos(oci8_errhp, &n, &r));
304
+ return oci8_make_ocinumber(&r);
305
+ }
306
+
307
+ /*
308
+ * call-seq:
309
+ * OCI8::Math.asin(x) -> oranumber
310
+ *
311
+ * Computes the arc sine of <i>x</i>. Returns 0..PI.
312
+ */
313
+ static VALUE omath_asin(VALUE obj, VALUE num)
314
+ {
315
+ OCINumber n;
316
+ OCINumber r;
317
+ sword sign;
318
+
319
+ set_oci_number_from_num(&n, num, 1);
320
+ /* check upper bound */
321
+ oci_lc(OCINumberCmp(oci8_errhp, &n, &const_p1, &sign));
322
+ if (sign > 0)
323
+ rb_raise(rb_eRangeError, "out of range for asin");
324
+ /* check lower bound */
325
+ oci_lc(OCINumberCmp(oci8_errhp, &n, &const_m1, &sign));
326
+ if (sign < 0)
327
+ rb_raise(rb_eRangeError, "out of range for asin");
328
+ /* asin */
329
+ oci_lc(OCINumberArcSin(oci8_errhp, &n, &r));
330
+ return oci8_make_ocinumber(&r);
331
+ }
332
+
333
+ /*
334
+ * call-seq:
335
+ * OCI8::Math.atan(x) -> oranumber
336
+ *
337
+ * Computes the arc tangent of <i>x</i>. Returns -{PI/2} .. {PI/2}.
338
+ */
339
+ static VALUE omath_atan(VALUE obj, VALUE num)
340
+ {
341
+ OCINumber n;
342
+ OCINumber r;
343
+
344
+ oci_lc(OCINumberArcTan(oci8_errhp, TO_OCINUM(&n, num), &r));
345
+ return oci8_make_ocinumber(&r);
346
+ }
347
+
348
+ /*
349
+ * call-seq:
350
+ * OCI8::Math.cosh(x) -> oranumber
351
+ *
352
+ * Computes the hyperbolic cosine of <i>x</i> (expressed in radians).
353
+ */
354
+ static VALUE omath_cosh(VALUE obj, VALUE num)
355
+ {
356
+ OCINumber n;
357
+ OCINumber r;
358
+
359
+ oci_lc(OCINumberHypCos(oci8_errhp, TO_OCINUM(&n, num), &r));
360
+ return oci8_make_ocinumber(&r);
361
+ }
362
+
363
+ /*
364
+ * call-seq:
365
+ * OCI8::Math.sinh(x) -> oranumber
366
+ *
367
+ * Computes the hyperbolic sine of <i>x</i> (expressed in
368
+ * radians).
369
+ */
370
+ static VALUE omath_sinh(VALUE obj, VALUE num)
371
+ {
372
+ OCINumber n;
373
+ OCINumber r;
374
+
375
+ oci_lc(OCINumberHypSin(oci8_errhp, TO_OCINUM(&n, num), &r));
376
+ return oci8_make_ocinumber(&r);
377
+ }
378
+
379
+ /*
380
+ * call-seq:
381
+ * OCI8::Math.tanh() -> oranumber
382
+ *
383
+ * Computes the hyperbolic tangent of <i>x</i> (expressed in
384
+ * radians).
385
+ */
386
+ static VALUE omath_tanh(VALUE obj, VALUE num)
387
+ {
388
+ OCINumber n;
389
+ OCINumber r;
390
+
391
+ oci_lc(OCINumberHypTan(oci8_errhp, TO_OCINUM(&n, num), &r));
392
+ return oci8_make_ocinumber(&r);
393
+ }
394
+
395
+ /*
396
+ * call-seq:
397
+ * OCI8::Math.exp(x) -> oranumber
398
+ *
399
+ * Returns e**x.
400
+ */
401
+ static VALUE omath_exp(VALUE obj, VALUE num)
402
+ {
403
+ OCINumber n;
404
+ OCINumber r;
405
+
406
+ oci_lc(OCINumberExp(oci8_errhp, TO_OCINUM(&n, num), &r));
407
+ return oci8_make_ocinumber(&r);
408
+ }
409
+
410
+ /*
411
+ * call-seq:
412
+ * OCI8::Math.log(numeric) -> oranumber
413
+ * OCI8::Math.log(numeric, base_num) -> oranumber
414
+ *
415
+ * Returns the natural logarithm of <i>numeric</i> for one argument.
416
+ * Returns the base <i>base_num</i> logarithm of <i>numeric</i> for two arguments.
417
+ */
418
+ static VALUE omath_log(int argc, VALUE *argv, VALUE obj)
419
+ {
420
+ VALUE num, base;
421
+ OCINumber n;
422
+ OCINumber b;
423
+ OCINumber r;
424
+ sword sign;
425
+
426
+ rb_scan_args(argc, argv, "11", &num, &base);
427
+ set_oci_number_from_num(&n, num, 1);
428
+ oci_lc(OCINumberSign(oci8_errhp, &n, &sign));
429
+ if (sign <= 0)
430
+ rb_raise(rb_eRangeError, "nonpositive value for log");
431
+ if (NIL_P(base)) {
432
+ oci_lc(OCINumberLn(oci8_errhp, &n, &r));
433
+ } else {
434
+ set_oci_number_from_num(&b, base, 1);
435
+ oci_lc(OCINumberSign(oci8_errhp, &b, &sign));
436
+ if (sign <= 0)
437
+ rb_raise(rb_eRangeError, "nonpositive value for the base of log");
438
+ oci_lc(OCINumberCmp(oci8_errhp, &b, &const_p1, &sign));
439
+ if (sign == 0)
440
+ rb_raise(rb_eRangeError, "base 1 for log");
441
+ oci_lc(OCINumberLog(oci8_errhp, &b, &n, &r));
442
+ }
443
+ return oci8_make_ocinumber(&r);
444
+ }
445
+
446
+ /*
447
+ * call-seq:
448
+ * OCI8::Math.log10(numeric) -> oranumber
449
+ *
450
+ * Returns the base 10 logarithm of <i>numeric</i>.
451
+ */
452
+ static VALUE omath_log10(VALUE obj, VALUE num)
453
+ {
454
+ OCINumber n;
455
+ OCINumber r;
456
+ sword sign;
457
+
458
+ set_oci_number_from_num(&n, num, 1);
459
+ oci_lc(OCINumberSign(oci8_errhp, &n, &sign));
460
+ if (sign <= 0)
461
+ rb_raise(rb_eRangeError, "nonpositive value for log10");
462
+ oci_lc(OCINumberLog(oci8_errhp, &const_p10, &n, &r));
463
+ return oci8_make_ocinumber(&r);
464
+ }
465
+
466
+ /*
467
+ * call-seq:
468
+ * OCI8::Math.sqrt(numeric) -> oranumber
469
+ *
470
+ * Returns the non-negative square root of <i>numeric</i>.
471
+ */
472
+ static VALUE omath_sqrt(VALUE obj, VALUE num)
473
+ {
474
+ OCINumber n;
475
+ OCINumber r;
476
+ sword sign;
477
+
478
+ set_oci_number_from_num(&n, num, 1);
479
+ /* check whether num is negative */
480
+ oci_lc(OCINumberSign(oci8_errhp, &n, &sign));
481
+ if (sign < 0) {
482
+ errno = EDOM;
483
+ rb_sys_fail("sqrt");
484
+ }
485
+ oci_lc(OCINumberSqrt(oci8_errhp, &n, &r));
486
+ return oci8_make_ocinumber(&r);
487
+ }
488
+
489
+ static VALUE onum_initialize(int argc, VALUE *argv, VALUE self)
490
+ {
491
+ VALUE val;
492
+ VALUE fmt;
493
+ VALUE nls_params;
494
+
495
+ if (rb_scan_args(argc, argv, "03", &val /* 0 */, &fmt /* nil */, &nls_params /* nil */) == 0) {
496
+ OCINumberSetZero(oci8_errhp, _NUMBER(self));
497
+ } else if (RTEST(rb_obj_is_kind_of(val, rb_cNumeric))) {
498
+ set_oci_number_from_num(_NUMBER(self), val, 1);
499
+ } else {
500
+ set_oci_number_from_str(_NUMBER(self), val, fmt, nls_params);
501
+ }
502
+ return Qnil;
503
+ }
504
+
505
+ static VALUE onum_initialize_copy(VALUE lhs, VALUE rhs)
506
+ {
507
+ if (!RTEST(rb_obj_is_instance_of(rhs, CLASS_OF(lhs)))) {
508
+ rb_raise(rb_eTypeError, "invalid type: expected %s but %s",
509
+ rb_class2name(CLASS_OF(lhs)), rb_class2name(CLASS_OF(rhs)));
510
+ }
511
+ oci_lc(OCINumberAssign(oci8_errhp, _NUMBER(rhs), _NUMBER(lhs)));
512
+ return lhs;
513
+ }
514
+
515
+ static VALUE onum_coerce(VALUE self, VALUE other)
516
+ {
517
+ OCINumber n;
518
+
519
+ if (RTEST(rb_obj_is_kind_of(other, rb_cNumeric)))
520
+ if (set_oci_number_from_num(&n, other, 0))
521
+ return rb_assoc_new(oci8_make_ocinumber(&n), self);
522
+ rb_raise(rb_eTypeError, "Can't coerce %s to %s",
523
+ rb_class2name(CLASS_OF(other)), rb_class2name(cOCINumber));
524
+ }
525
+
526
+ /*
527
+ * call-seq:
528
+ * -onum -> oranumber
529
+ *
530
+ * Returns an <code>OraNumber</code>, negated.
531
+ */
532
+ static VALUE onum_neg(VALUE self)
533
+ {
534
+ OCINumber r;
535
+
536
+ oci_lc(OCINumberNeg(oci8_errhp, _NUMBER(self), &r));
537
+ return oci8_make_ocinumber(&r);
538
+ }
539
+
540
+ /*
541
+ * call-seq:
542
+ * onum + other -> oranumber
543
+ *
544
+ * Returns a new <code>OraNumber</code> which is the sum of <i>onum</i>
545
+ * and <i>other</i>.
546
+ */
547
+ static VALUE onum_add(VALUE lhs, VALUE rhs)
115
548
  {
116
- return set_oci_number_from_num((OCINumber*)result, num, errhp);
549
+ OCINumber n;
550
+ OCINumber r;
551
+
552
+ /* change to OCINumber */
553
+ if (!set_oci_number_from_num(&n, rhs, 0))
554
+ return rb_num_coerce_bin(lhs, rhs, '+');
555
+ /* add */
556
+ oci_lc(OCINumberAdd(oci8_errhp, _NUMBER(lhs), &n, &r));
557
+ return oci8_make_ocinumber(&r);
558
+ }
559
+
560
+ /*
561
+ * call-seq:
562
+ * onum - other -> oranumber
563
+ *
564
+ * Returns a new <code>OraNumber</code> which is the difference of <i>onum</i>
565
+ * and <i>other</i>.
566
+ */
567
+ static VALUE onum_sub(VALUE lhs, VALUE rhs)
568
+ {
569
+ OCINumber n;
570
+ OCINumber r;
571
+
572
+ /* change to OCINumber */
573
+ if (!set_oci_number_from_num(&n, rhs, 0))
574
+ return rb_num_coerce_bin(lhs, rhs, '-');
575
+ /* subtracting */
576
+ oci_lc(OCINumberSub(oci8_errhp, _NUMBER(lhs), &n, &r));
577
+ return oci8_make_ocinumber(&r);
578
+ }
579
+
580
+ /*
581
+ * call-seq:
582
+ * onum * other -> oranumber
583
+ *
584
+ * Returns a new <code>OraNumber</code> which is the product of <i>onum</i>
585
+ * and <i>other</i>.
586
+ */
587
+ static VALUE onum_mul(VALUE lhs, VALUE rhs)
588
+ {
589
+ OCINumber n;
590
+ OCINumber r;
591
+
592
+ /* change to OCINumber */
593
+ if (!set_oci_number_from_num(&n, rhs, 0))
594
+ return rb_num_coerce_bin(lhs, rhs, '*');
595
+ /* multiply */
596
+ oci_lc(OCINumberMul(oci8_errhp, _NUMBER(lhs), &n, &r));
597
+ return oci8_make_ocinumber(&r);
598
+ }
599
+
600
+ /*
601
+ * call-seq:
602
+ * onum / other -> oranumber
603
+ *
604
+ * Returns a new <code>OraNumber</code> which is the result of dividing
605
+ * <i>onum</i> by <i>other</i>.
606
+ */
607
+ static VALUE onum_div(VALUE lhs, VALUE rhs)
608
+ {
609
+ OCINumber n;
610
+ OCINumber r;
611
+ boolean is_zero;
612
+
613
+ /* change to OCINumber */
614
+ if (!set_oci_number_from_num(&n, rhs, 0))
615
+ return rb_num_coerce_bin(lhs, rhs, '/');
616
+ /* check whether argument is not zero. */
617
+ oci_lc(OCINumberIsZero(oci8_errhp, &n, &is_zero));
618
+ if (is_zero)
619
+ rb_num_zerodiv();
620
+ /* division */
621
+ oci_lc(OCINumberDiv(oci8_errhp, _NUMBER(lhs), &n, &r));
622
+ return oci8_make_ocinumber(&r);
623
+ }
624
+
625
+ /*
626
+ * call-seq:
627
+ * onum % other -> oranumber
628
+ *
629
+ * Returns the modulo after division of <i>onum</i> by <i>other</i>.
630
+ */
631
+ static VALUE onum_mod(VALUE lhs, VALUE rhs)
632
+ {
633
+ OCINumber n;
634
+ OCINumber r;
635
+ boolean is_zero;
636
+
637
+ /* change to OCINumber */
638
+ if (!set_oci_number_from_num(&n, rhs, 0))
639
+ return rb_num_coerce_bin(lhs, rhs, '%');
640
+ /* check whether argument is not zero. */
641
+ oci_lc(OCINumberIsZero(oci8_errhp, &n, &is_zero));
642
+ if (is_zero)
643
+ rb_num_zerodiv();
644
+ /* modulo */
645
+ oci_lc(OCINumberMod(oci8_errhp, _NUMBER(lhs), &n, &r));
646
+ return oci8_make_ocinumber(&r);
647
+ }
648
+
649
+ /*
650
+ * call-seq:
651
+ * onum ** other -> oranumber
652
+ *
653
+ * Raises <i>onum</i> the <i>other</i> power.
654
+ */
655
+ static VALUE onum_power(VALUE lhs, VALUE rhs)
656
+ {
657
+ OCINumber n;
658
+ OCINumber r;
659
+
660
+ if (FIXNUM_P(rhs)) {
661
+ oci_lc(OCINumberIntPower(oci8_errhp, _NUMBER(lhs), FIX2INT(rhs), &r));
662
+ } else {
663
+ /* change to OCINumber */
664
+ if (!set_oci_number_from_num(&n, rhs, 0))
665
+ return rb_num_coerce_bin(lhs, rhs, id_power);
666
+ oci_lc(OCINumberPower(oci8_errhp, _NUMBER(lhs), &n, &r));
667
+ }
668
+ return oci8_make_ocinumber(&r);
669
+ }
670
+
671
+ /*
672
+ * call-seq:
673
+ * onum <=> other -> -1, 0, +1
674
+ *
675
+ * Returns -1, 0, or +1 depending on whether <i>onum</i> is less than,
676
+ * equal to, or greater than <i>other</i>. This is the basis for the
677
+ * tests in <code>Comparable</code>.
678
+ */
679
+ static VALUE onum_cmp(VALUE lhs, VALUE rhs)
680
+ {
681
+ OCINumber n;
682
+ sword r;
683
+
684
+ /* change to OCINumber */
685
+ if (!set_oci_number_from_num(&n, rhs, 0))
686
+ return rb_num_coerce_cmp(lhs, rhs, id_cmp);
687
+ /* compare */
688
+ oci_lc(OCINumberCmp(oci8_errhp, _NUMBER(lhs), &n, &r));
689
+ if (r > 0) {
690
+ return INT2FIX(1);
691
+ } else if (r == 0) {
692
+ return INT2FIX(0);
693
+ } else {
694
+ return INT2FIX(-1);
695
+ }
696
+ }
697
+
698
+ /*
699
+ * call-seq:
700
+ * onum.floor -> integer
701
+ *
702
+ * Returns the largest <code>Integer</code> less than or equal to <i>onum</i>.
703
+ */
704
+ static VALUE onum_floor(VALUE self)
705
+ {
706
+ OCINumber r;
707
+
708
+ oci_lc(OCINumberFloor(oci8_errhp, _NUMBER(self), &r));
709
+ return oci8_make_integer(&r);
710
+ }
711
+
712
+ /*
713
+ * call-seq:
714
+ * onum.ceil -> integer
715
+ *
716
+ * Returns the smallest <code>Integer</code> greater than or equal to
717
+ * <i>onum</i>.
718
+ */
719
+ static VALUE onum_ceil(VALUE self)
720
+ {
721
+ OCINumber r;
722
+
723
+ oci_lc(OCINumberCeil(oci8_errhp, _NUMBER(self), &r));
724
+ return oci8_make_integer(&r);
725
+ }
726
+
727
+ /*
728
+ * call-seq:
729
+ * onum.round -> integer
730
+ * onum.round(decplace) -> oranumber
731
+ *
732
+ * Rounds <i>onum</i> to the nearest <code>Integer</code> when no argument.
733
+ * Rounds <i>onum</i> to a specified decimal place <i>decplace</i> when one argument.
734
+ *
735
+ * OraNumber.new(1.234).round(1) #=> 1.2
736
+ * OraNumber.new(1.234).round(2) #=> 1.23
737
+ * OraNumber.new(1.234).round(3) #=> 1.234
738
+ */
739
+ static VALUE onum_round(int argc, VALUE *argv, VALUE self)
740
+ {
741
+ VALUE decplace;
742
+ OCINumber r;
743
+
744
+ rb_scan_args(argc, argv, "01", &decplace /* 0 */);
745
+ oci_lc(OCINumberRound(oci8_errhp, _NUMBER(self), NIL_P(decplace) ? 0 : NUM2INT(decplace), &r));
746
+ if (argc == 0) {
747
+ return oci8_make_integer(&r);
748
+ } else {
749
+ return oci8_make_ocinumber(&r);
750
+ }
751
+ }
752
+
753
+ /*
754
+ * call-seq:
755
+ * onum.truncate -> integer
756
+ * onum.truncate(decplace) -> oranumber
757
+ *
758
+ * Truncates <i>onum</i> to the <code>Integer</code> when no argument.
759
+ * Truncates <i>onum</i> to a specified decimal place <i>decplace</i> when one argument.
760
+ */
761
+ static VALUE onum_trunc(int argc, VALUE *argv, VALUE self)
762
+ {
763
+ VALUE decplace;
764
+ OCINumber r;
765
+
766
+ rb_scan_args(argc, argv, "01", &decplace /* 0 */);
767
+ oci_lc(OCINumberTrunc(oci8_errhp, _NUMBER(self), NIL_P(decplace) ? 0 : NUM2INT(decplace), &r));
768
+ return oci8_make_ocinumber(&r);
769
+ }
770
+
771
+ /*
772
+ * call-seq:
773
+ * onum.round_prec(digits) -> oranumber
774
+ *
775
+ * Rounds <i>onum</i> to a specified number of decimal digits.
776
+ * This method is available on Oracle 8.1 client or upper.
777
+ *
778
+ * OraNumber.new(1.234).round_prec(2) #=> 1.2
779
+ * OraNumber.new(12.34).round_prec(2) #=> 12
780
+ * OraNumber.new(123.4).round_prec(2) #=> 120
781
+ */
782
+ static VALUE onum_round_prec(VALUE self, VALUE ndigs)
783
+ {
784
+ OCINumber r;
785
+
786
+ oci_lc(OCINumberPrec(oci8_errhp, _NUMBER(self), NUM2INT(ndigs), &r));
787
+ return oci8_make_ocinumber(&r);
788
+ }
789
+
790
+ /*
791
+ * call-seq:
792
+ * onum.to_char(fmt = nil, nls_params = nil) -> string
793
+ *
794
+ * Returns a string containing a representation of self.
795
+ * <i>fmt</i> and <i>nls_params</i> are same meanings with
796
+ * <code>TO_CHAR</code> of Oracle function.
797
+ */
798
+ static VALUE onum_to_char(int argc, VALUE *argv, VALUE self)
799
+ {
800
+ VALUE fmt;
801
+ VALUE nls_params;
802
+ char buf[512];
803
+ ub4 buf_size = sizeof(buf);
804
+ oratext *fmt_ptr;
805
+ oratext *nls_params_ptr;
806
+ ub4 fmt_len;
807
+ ub4 nls_params_len;
808
+ sword rv;
809
+
810
+ rb_scan_args(argc, argv, "02", &fmt /* nil */, &nls_params /* nil */);
811
+ if (NIL_P(fmt)) {
812
+ OCINumber absval;
813
+ sword sign;
814
+ boolean is_int;
815
+
816
+ oci_lc(OCINumberIsInt(oci8_errhp, _NUMBER(self), &is_int));
817
+ if (is_int) {
818
+ fmt_ptr = NUMBER_FORMAT_INT;
819
+ fmt_len = NUMBER_FORMAT_INT_LEN;
820
+ } else {
821
+ oci_lc(OCINumberAbs(oci8_errhp, _NUMBER(self), &absval));
822
+ oci_lc(OCINumberCmp(oci8_errhp, &absval, &const_shreshold, &sign));
823
+ if (sign >= 0) {
824
+ fmt_ptr = NUMBER_FORMAT2;
825
+ fmt_len = NUMBER_FORMAT2_LEN;
826
+ } else {
827
+ fmt_ptr = NUMBER_FORMAT1;
828
+ fmt_len = NUMBER_FORMAT1_LEN;
829
+ }
830
+ }
831
+ } else {
832
+ StringValue(fmt);
833
+ fmt_ptr = RSTRING_ORATEXT(fmt);
834
+ fmt_len = RSTRING_LEN(fmt);
835
+ }
836
+ if (NIL_P(nls_params)) {
837
+ nls_params_ptr = NULL;
838
+ nls_params_len = 0;
839
+ } else {
840
+ StringValue(nls_params);
841
+ nls_params_ptr = RSTRING_ORATEXT(nls_params);
842
+ nls_params_len = RSTRING_LEN(nls_params);
843
+ }
844
+ rv = OCINumberToText(oci8_errhp, _NUMBER(self),
845
+ fmt_ptr, fmt_len, nls_params_ptr, nls_params_len,
846
+ &buf_size, TO_ORATEXT(buf));
847
+ if (rv == OCI_ERROR) {
848
+ sb4 errcode;
849
+ OCIErrorGet(oci8_errhp, 1, NULL, &errcode, NULL, 0, OCI_HTYPE_ERROR);
850
+ if (errcode == 22065) {
851
+ /* OCI-22065: number to text translation for the given format causes overflow */
852
+ if (NIL_P(fmt)) /* implicit conversion */
853
+ return rb_usascii_str_new_cstr("overflow");
854
+ }
855
+ oci8_raise(oci8_errhp, rv, NULL);
856
+ }
857
+ return rb_usascii_str_new(buf, buf_size);
858
+ }
859
+
860
+ /*
861
+ * call-seq:
862
+ * onum.to_s -> string
863
+ *
864
+ * Returns a string containing a representation of self.
865
+ */
866
+ static VALUE onum_to_s(VALUE self)
867
+ {
868
+ return onum_to_char(0, NULL, self);
869
+ }
870
+
871
+ /*
872
+ * call-seq:
873
+ * onum.to_i -> integer
874
+ *
875
+ * Returns <i>onm</i> truncated to an <code>Integer</code>.
876
+ */
877
+ static VALUE onum_to_i(VALUE self)
878
+ {
879
+ OCINumber num;
880
+
881
+ oci_lc(OCINumberTrunc(oci8_errhp, _NUMBER(self), 0, &num));
882
+ return oci8_make_integer(&num);
883
+ }
884
+
885
+ /*
886
+ * call-seq:
887
+ * onum.to_f -> float
888
+ *
889
+ * Converts <i>onum</i> to a <code>Float</code>.
890
+ *
891
+ */
892
+ static VALUE onum_to_f(VALUE self)
893
+ {
894
+ double dbl;
895
+
896
+ oci_lc(OCINumberToReal(oci8_errhp, _NUMBER(self), sizeof(dbl), &dbl));
897
+ return rb_float_new(dbl);
898
+ }
899
+
900
+ /*
901
+ * call-seq:
902
+ * onum.to_onum -> oranumber
903
+ *
904
+ */
905
+ static VALUE onum_to_onum(VALUE self)
906
+ {
907
+ return self;
908
+ }
909
+
910
+ /*
911
+ * call-seq:
912
+ * onum.zero? -> true or false
913
+ *
914
+ * Returns <code>true</code> if <i>onum</i> is zero.
915
+ *
916
+ */
917
+ static VALUE onum_zero_p(VALUE self)
918
+ {
919
+ boolean result;
920
+
921
+ oci_lc(OCINumberIsZero(oci8_errhp, _NUMBER(self), &result));
922
+ return result ? Qtrue : Qfalse;
923
+ }
924
+
925
+ /*
926
+ * call-seq:
927
+ * onum.abs -> oranumber
928
+ *
929
+ * Returns the absolute value of <i>onum</i>.
930
+ *
931
+ */
932
+ static VALUE onum_abs(VALUE self)
933
+ {
934
+ OCINumber result;
935
+
936
+ oci_lc(OCINumberAbs(oci8_errhp, _NUMBER(self), &result));
937
+ return oci8_make_ocinumber(&result);
938
+ }
939
+
940
+ /*
941
+ * call-seq:
942
+ * onum.shift(fixnum) -> oranumber
943
+ *
944
+ * Returns <i>onum</i> * 10**<i>fixnum</i>
945
+ * This method is available on Oracle 8.1 client or upper.
946
+ */
947
+ static VALUE onum_shift(VALUE self, VALUE exp)
948
+ {
949
+ OCINumber result;
950
+
951
+ oci_lc(OCINumberShift(oci8_errhp, _NUMBER(self), NUM2INT(exp), &result));
952
+ return oci8_make_ocinumber(&result);
953
+ }
954
+
955
+ static VALUE onum_hash(VALUE self)
956
+ {
957
+ char *c = DATA_PTR(self);
958
+ int size = c[0] + 1;
959
+ int i, hash;
960
+
961
+ /* assert(size <= 22); ?*/
962
+ if (size > 22)
963
+ size = 22;
964
+
965
+ for (hash = 0, i = 1; i< size; i++) {
966
+ hash += c[i] * 971;
967
+ }
968
+ if (hash < 0) hash = -hash;
969
+ return INT2FIX(hash);
970
+ }
971
+
972
+ static VALUE onum_inspect(VALUE self)
973
+ {
974
+ const char *name = rb_class2name(CLASS_OF(self));
975
+ volatile VALUE s = onum_to_s(self);
976
+ size_t len = strlen(name) + RSTRING_LEN(s) + 5;
977
+ char *str = ALLOCA_N(char, len);
978
+
979
+ snprintf(str, len, "#<%s:%s>", name, RSTRING_PTR(s));
980
+ str[len - 1] = '\0';
981
+ return rb_usascii_str_new_cstr(str);
982
+ }
983
+
984
+ /*
985
+ * call-seq:
986
+ * onum._dump -> string
987
+ *
988
+ * Dump <i>onum</i> for marshaling.
989
+ */
990
+ static VALUE onum_dump(int argc, VALUE *argv, VALUE self)
991
+ {
992
+ char *c = DATA_PTR(self);
993
+ int size = c[0] + 1;
994
+ VALUE dummy;
995
+
996
+ rb_scan_args(argc, argv, "01", &dummy);
997
+ return rb_str_new(c, size);
998
+ }
999
+
1000
+ /*
1001
+ * call-seq:
1002
+ * OraNumber._load(string) -> oranumber
1003
+ *
1004
+ * Unmarshal a dumped <code>OraNumber</code> object.
1005
+ */
1006
+ static VALUE
1007
+ onum_s_load(VALUE klass, VALUE str)
1008
+ {
1009
+ unsigned char *c;
1010
+ int size;
1011
+ OCINumber num;
1012
+
1013
+ Check_Type(str, T_STRING);
1014
+ c = RSTRING_ORATEXT(str);
1015
+ size = RSTRING_LEN(str);
1016
+ if (size == 0 || size != c[0] + 1 || size > sizeof(num)) {
1017
+ rb_raise(rb_eTypeError, "marshaled OCI::Number format differ");
1018
+ }
1019
+ memset(&num, 0, sizeof(num));
1020
+ memcpy(&num, c, size);
1021
+ return oci8_make_ocinumber(&num);
1022
+ }
1023
+
1024
+ /*
1025
+ * bind_ocinumber
1026
+ */
1027
+ static VALUE bind_ocinumber_get(oci8_bind_t *obind, void *data, void *null_struct)
1028
+ {
1029
+ return oci8_make_ocinumber((OCINumber*)data);
1030
+ }
1031
+
1032
+ static VALUE bind_integer_get(oci8_bind_t *obind, void *data, void *null_struct)
1033
+ {
1034
+ return oci8_make_integer((OCINumber*)data);
1035
+ }
1036
+
1037
+ static void bind_ocinumber_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
1038
+ {
1039
+ set_oci_number_from_num((OCINumber*)data, val, 1);
1040
+ }
1041
+
1042
+ static void bind_integer_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
1043
+ {
1044
+ OCINumber num;
1045
+
1046
+ set_oci_number_from_num(&num, val, 1);
1047
+ oci_lc(OCINumberTrunc(oci8_errhp, &num, 0, (OCINumber*)data));
1048
+ }
1049
+
1050
+ static void bind_ocinumber_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
1051
+ {
1052
+ obind->value_sz = sizeof(OCINumber);
1053
+ obind->alloc_sz = sizeof(OCINumber);
1054
+ }
1055
+
1056
+ static void bind_ocinumber_init_elem(oci8_bind_t *obind, VALUE svc)
1057
+ {
1058
+ ub4 idx = 0;
1059
+
1060
+ do {
1061
+ OCINumberSetZero(oci8_errhp, (OCINumber*)obind->valuep + idx);
1062
+ } while (++idx < obind->maxar_sz);
1063
+ }
1064
+
1065
+ static const oci8_bind_class_t bind_ocinumber_class = {
1066
+ {
1067
+ NULL,
1068
+ oci8_bind_free,
1069
+ sizeof(oci8_bind_t)
1070
+ },
1071
+ bind_ocinumber_get,
1072
+ bind_ocinumber_set,
1073
+ bind_ocinumber_init,
1074
+ bind_ocinumber_init_elem,
1075
+ NULL,
1076
+ NULL,
1077
+ NULL,
1078
+ SQLT_VNU,
1079
+ };
1080
+
1081
+ static const oci8_bind_class_t bind_integer_class = {
1082
+ {
1083
+ NULL,
1084
+ oci8_bind_free,
1085
+ sizeof(oci8_bind_t)
1086
+ },
1087
+ bind_integer_get,
1088
+ bind_integer_set,
1089
+ bind_ocinumber_init,
1090
+ bind_ocinumber_init_elem,
1091
+ NULL,
1092
+ NULL,
1093
+ NULL,
1094
+ SQLT_VNU,
1095
+ };
1096
+
1097
+ void
1098
+ Init_oci_number(VALUE cOCI8)
1099
+ {
1100
+ VALUE mMath;
1101
+ OCINumber num1, num2;
1102
+ VALUE obj_PI;
1103
+ signed long sl;
1104
+
1105
+ id_power = rb_intern("**");
1106
+ id_cmp = rb_intern("<=>");
1107
+
1108
+ cOCINumber = rb_define_class("OraNumber", rb_cNumeric);
1109
+ mMath = rb_define_module_under(cOCI8, "Math");
1110
+
1111
+ /* constants for internal use. */
1112
+ /* set const_p1 */
1113
+ sl = 1;
1114
+ OCINumberFromInt(oci8_errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &const_p1);
1115
+ /* set const_p10 */
1116
+ sl = 10;
1117
+ OCINumberFromInt(oci8_errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &const_p10);
1118
+ /* set const_m1 */
1119
+ sl = -1;
1120
+ OCINumberFromInt(oci8_errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &const_m1);
1121
+ /* set const_PI2 */
1122
+ sl = 2;
1123
+ OCINumberSetPi(oci8_errhp, &num1);
1124
+ OCINumberFromInt(oci8_errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &num2);
1125
+ OCINumberDiv(oci8_errhp, &num1 /* PI */, &num2 /* 2 */, &const_PI2);
1126
+ /* set const_mPI2 */
1127
+ OCINumberNeg(oci8_errhp, &const_PI2 /* PI/2 */, &const_mPI2);
1128
+ /* set const_shreshold */
1129
+ OCINumberFromText(oci8_errhp, SHRESHOLD_VAL, SHRESHOLD_VAL_LEN, SHRESHOLD_FMT, SHRESHOLD_FMT_LEN,
1130
+ NULL, 0, &const_shreshold);
1131
+
1132
+ /* PI */
1133
+ OCINumberSetPi(oci8_errhp, &num1);
1134
+ obj_PI = oci8_make_ocinumber(&num1);
1135
+
1136
+ /* The ratio of the circumference of a circle to its diameter. */
1137
+ rb_define_const(mMath, "PI", obj_PI);
1138
+
1139
+ /*
1140
+ * module functions of OCI::Math.
1141
+ */
1142
+ rb_define_module_function(mMath, "atan2", omath_atan2, 2);
1143
+
1144
+ rb_define_module_function(mMath, "cos", omath_cos, 1);
1145
+ rb_define_module_function(mMath, "sin", omath_sin, 1);
1146
+ rb_define_module_function(mMath, "tan", omath_tan, 1);
1147
+
1148
+ rb_define_module_function(mMath, "acos", omath_acos, 1);
1149
+ rb_define_module_function(mMath, "asin", omath_asin, 1);
1150
+ rb_define_module_function(mMath, "atan", omath_atan, 1);
1151
+
1152
+ rb_define_module_function(mMath, "cosh", omath_cosh, 1);
1153
+ rb_define_module_function(mMath, "sinh", omath_sinh, 1);
1154
+ rb_define_module_function(mMath, "tanh", omath_tanh, 1);
1155
+
1156
+ rb_define_module_function(mMath, "exp", omath_exp, 1);
1157
+ rb_define_module_function(mMath, "log", omath_log, -1);
1158
+ rb_define_module_function(mMath, "log10", omath_log10, 1);
1159
+ rb_define_module_function(mMath, "sqrt", omath_sqrt, 1);
1160
+
1161
+ rb_define_alloc_func(cOCINumber, onum_s_alloc);
1162
+
1163
+ /* methods of OCI::Number */
1164
+ rb_define_method_nodoc(cOCINumber, "initialize", onum_initialize, -1);
1165
+ rb_define_method_nodoc(cOCINumber, "initialize_copy", onum_initialize_copy, 1);
1166
+ rb_define_method_nodoc(cOCINumber, "coerce", onum_coerce, 1);
1167
+
1168
+ rb_include_module(cOCINumber, rb_mComparable);
1169
+
1170
+ rb_define_method(cOCINumber, "-@", onum_neg, 0);
1171
+ rb_define_method(cOCINumber, "+", onum_add, 1);
1172
+ rb_define_method(cOCINumber, "-", onum_sub, 1);
1173
+ rb_define_method(cOCINumber, "*", onum_mul, 1);
1174
+ rb_define_method(cOCINumber, "/", onum_div, 1);
1175
+ rb_define_method(cOCINumber, "%", onum_mod, 1);
1176
+ rb_define_method(cOCINumber, "**", onum_power, 1);
1177
+ rb_define_method(cOCINumber, "<=>", onum_cmp, 1);
1178
+
1179
+ rb_define_method(cOCINumber, "floor", onum_floor, 0);
1180
+ rb_define_method(cOCINumber, "ceil", onum_ceil, 0);
1181
+ rb_define_method(cOCINumber, "round", onum_round, -1);
1182
+ rb_define_method(cOCINumber, "truncate", onum_trunc, -1);
1183
+ if (have_OCINumberPrec) {
1184
+ rb_define_method(cOCINumber, "round_prec", onum_round_prec, 1);
1185
+ }
1186
+
1187
+ rb_define_method(cOCINumber, "to_s", onum_to_s, 0);
1188
+ rb_define_method(cOCINumber, "to_char", onum_to_char, -1);
1189
+ rb_define_method(cOCINumber, "to_i", onum_to_i, 0);
1190
+ rb_define_method(cOCINumber, "to_f", onum_to_f, 0);
1191
+ rb_define_method_nodoc(cOCINumber, "to_onum", onum_to_onum, 0);
1192
+
1193
+ rb_define_method(cOCINumber, "zero?", onum_zero_p, 0);
1194
+ rb_define_method(cOCINumber, "abs", onum_abs, 0);
1195
+ if (have_OCINumberShift) {
1196
+ rb_define_method(cOCINumber, "shift", onum_shift, 1);
1197
+ }
1198
+
1199
+ rb_define_method_nodoc(cOCINumber, "hash", onum_hash, 0);
1200
+ rb_define_method_nodoc(cOCINumber, "inspect", onum_inspect, 0);
1201
+
1202
+ /* methods for marshaling */
1203
+ rb_define_method(cOCINumber, "_dump", onum_dump, -1);
1204
+ rb_define_singleton_method(cOCINumber, "_load", onum_s_load, 1);
1205
+
1206
+ oci8_define_bind_class("OraNumber", &bind_ocinumber_class);
1207
+ oci8_define_bind_class("Integer", &bind_integer_class);
1208
+ }
1209
+
1210
+ OCINumber *oci8_get_ocinumber(VALUE num)
1211
+ {
1212
+ if (!rb_obj_is_kind_of(num, cOCINumber)) {
1213
+ rb_raise(rb_eTypeError, "invalid argument %s (expect a subclass of %s)", rb_class2name(CLASS_OF(num)), rb_class2name(cOCINumber));
1214
+ }
1215
+ return _NUMBER(num);
117
1216
  }