ruby-oci8 1.0.7 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
  }