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.
- data/ChangeLog +1254 -390
- data/Makefile +10 -13
- data/README +56 -385
- data/VERSION +1 -1
- data/dist-files +26 -27
- data/ext/oci8/.document +1 -0
- data/ext/oci8/MANIFEST +0 -4
- data/ext/oci8/apiwrap.c.tmpl +172 -0
- data/ext/oci8/apiwrap.h.tmpl +61 -0
- data/ext/oci8/apiwrap.rb +91 -0
- data/ext/oci8/apiwrap.yml +1243 -0
- data/ext/oci8/attr.c +124 -384
- data/ext/oci8/bind.c +472 -164
- data/ext/oci8/encoding.c +196 -0
- data/ext/oci8/env.c +84 -253
- data/ext/oci8/error.c +196 -127
- data/ext/oci8/extconf.rb +82 -59
- data/ext/oci8/lob.c +710 -370
- data/ext/oci8/metadata.c +359 -0
- data/ext/oci8/object.c +622 -0
- data/ext/oci8/oci8.c +577 -161
- data/ext/oci8/oci8.h +354 -258
- data/ext/oci8/oci8lib.c +493 -0
- data/ext/oci8/ocidatetime.c +473 -0
- data/ext/oci8/ocinumber.c +1123 -24
- data/ext/oci8/oraconf.rb +72 -106
- data/ext/oci8/oradate.c +511 -321
- data/ext/oci8/stmt.c +752 -572
- data/ext/oci8/win32.c +131 -0
- data/ext/oci8/xmldb.c +383 -0
- data/lib/.document +2 -0
- data/lib/dbd/OCI8.rb +2 -17
- data/lib/oci8.rb.in +41 -1622
- data/lib/oci8/.document +5 -0
- data/lib/oci8/compat.rb +108 -0
- data/lib/oci8/datetime.rb +489 -0
- data/lib/oci8/encoding-init.rb +40 -0
- data/lib/oci8/encoding.yml +537 -0
- data/lib/oci8/metadata.rb +2077 -0
- data/lib/oci8/object.rb +548 -0
- data/lib/oci8/oci8.rb +773 -0
- data/lib/oci8/oracle_version.rb +144 -0
- data/metaconfig +3 -3
- data/ruby-oci8.gemspec +5 -5
- data/setup.rb +4 -4
- data/test/config.rb +64 -84
- data/test/test_all.rb +14 -21
- data/test/test_array_dml.rb +317 -0
- data/test/test_bind_raw.rb +18 -25
- data/test/test_bind_time.rb +78 -91
- data/test/test_break.rb +37 -35
- data/test/test_clob.rb +33 -89
- data/test/test_connstr.rb +5 -4
- data/test/test_datetime.rb +469 -0
- data/test/test_dbi.rb +99 -60
- data/test/test_dbi_clob.rb +3 -8
- data/test/test_metadata.rb +65 -51
- data/test/test_oci8.rb +151 -55
- data/test/test_oracle_version.rb +70 -0
- data/test/test_oradate.rb +76 -83
- data/test/test_oranumber.rb +405 -71
- data/test/test_rowid.rb +6 -11
- metadata +31 -32
- data/NEWS +0 -420
- data/ext/oci8/const.c +0 -165
- data/ext/oci8/define.c +0 -53
- data/ext/oci8/describe.c +0 -81
- data/ext/oci8/descriptor.c +0 -39
- data/ext/oci8/handle.c +0 -273
- data/ext/oci8/oranumber.c +0 -445
- data/ext/oci8/param.c +0 -37
- data/ext/oci8/server.c +0 -182
- data/ext/oci8/session.c +0 -99
- data/ext/oci8/svcctx.c +0 -238
- data/ruby-oci8.spec +0 -62
- data/support/README +0 -4
- data/support/runit/assert.rb +0 -281
- data/support/runit/cui/testrunner.rb +0 -101
- data/support/runit/error.rb +0 -4
- data/support/runit/method_mappable.rb +0 -20
- data/support/runit/robserver.rb +0 -25
- data/support/runit/setuppable.rb +0 -15
- data/support/runit/teardownable.rb +0 -16
- data/support/runit/testcase.rb +0 -113
- data/support/runit/testfailure.rb +0 -25
- data/support/runit/testresult.rb +0 -121
- data/support/runit/testsuite.rb +0 -43
- data/support/runit/version.rb +0 -3
- data/test/test_describe.rb +0 -137
data/ext/oci8/ocinumber.c
CHANGED
@@ -1,19 +1,42 @@
|
|
1
|
+
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
1
2
|
/*
|
2
|
-
ocinumber.c
|
3
|
-
|
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
|
-
|
10
|
-
|
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
|
-
#
|
29
|
-
|
30
|
-
|
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
|
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(
|
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,
|
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(
|
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(
|
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
|
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,
|
170
|
+
if (RTEST(rb_obj_is_instance_of(num, cOCINumber))) {
|
107
171
|
/* OCI::Number */
|
108
|
-
oci_lc(OCINumberAssign(
|
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
|
-
|
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
|
-
|
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
|
}
|