From nobody at rubyforge.org Sun Oct 4 09:55:02 2009 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Sun, 4 Oct 2009 09:55:02 -0400 (EDT) Subject: [ruby-oci8-commit] [360] trunk/ruby-oci8: * ext/oci8/oci8.c: Add constants missing in Oracle client prior to 10g. Message-ID: <20091004135502.7870316782AD@rubyforge.org> Revision: 360 Author: kubo Date: 2009-10-04 09:55:01 -0400 (Sun, 04 Oct 2009) Log Message: ----------- * ext/oci8/oci8.c: Add constants missing in Oracle client prior to 10g. * ext/oci8/oraconf.rb: 1. Fix for ruby 1.8.5 with Oracle 8.x which needs some object files to link with. 2. Revise the error message under the sudo environemnt. 3. Print not only error message but also the error backtrace when oraconf.rb fails. * lib/oci8/object.rb: Fix to accept nil attribute in object type's constructors. This works only for simple data types such as number, string. But it doesn't for complex types such as object types. (requested by Remi Gagnon) * spec/object_type_spec.rb: Add a test for object type's constructors. Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/ext/oci8/oci8.c trunk/ruby-oci8/ext/oci8/oraconf.rb trunk/ruby-oci8/lib/oci8/object.rb Added Paths: ----------- trunk/ruby-oci8/spec/object_type_spec.rb Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2009-09-22 10:46:31 UTC (rev 359) +++ trunk/ruby-oci8/ChangeLog 2009-10-04 13:55:01 UTC (rev 360) @@ -1,3 +1,17 @@ +2009-10-04 KUBO Takehiro + * ext/oci8/oci8.c: Add constants missing in Oracle client prior to 10g. + * ext/oci8/oraconf.rb: + 1. Fix for ruby 1.8.5 with Oracle 8.x which needs some object + files to link with. + 2. Revise the error message under the sudo environemnt. + 3. Print not only error message but also the error backtrace when + oraconf.rb fails. + * lib/oci8/object.rb: Fix to accept nil attribute in object type's + constructors. This works only for simple data types such as number, + string. But it doesn't for complex types such as object types. + (requested by Remi Gagnon) + * spec/object_type_spec.rb: Add a test for object type's constructors. + 2009-09-22 KUBO Takehiro * lib/oci8/.document, lib/oci8/datetime.rb: 1. Add OCI8::BindType.default_timezone and OCI8::BindType.default_timezone=. Modified: trunk/ruby-oci8/ext/oci8/oci8.c =================================================================== --- trunk/ruby-oci8/ext/oci8/oci8.c 2009-09-22 10:46:31 UTC (rev 359) +++ trunk/ruby-oci8/ext/oci8/oci8.c 2009-10-04 13:55:01 UTC (rev 360) @@ -20,6 +20,15 @@ #ifndef OCI_ATTR_CLIENT_IDENTIFIER #define OCI_ATTR_CLIENT_IDENTIFIER 278 #endif +#ifndef OCI_ATTR_MODULE +#define OCI_ATTR_MODULE 366 +#endif +#ifndef OCI_ATTR_ACTION +#define OCI_ATTR_ACTION 367 +#endif +#ifndef OCI_ATTR_CLIENT_INFO +#define OCI_ATTR_CLIENT_INFO 368 +#endif static VALUE cOCI8; Modified: trunk/ruby-oci8/ext/oci8/oraconf.rb =================================================================== --- trunk/ruby-oci8/ext/oci8/oraconf.rb 2009-09-22 10:46:31 UTC (rev 359) +++ trunk/ruby-oci8/ext/oci8/oraconf.rb 2009-10-04 13:55:01 UTC (rev 360) @@ -353,8 +353,10 @@ end print < Revision: 361 Author: kubo Date: 2009-10-04 10:01:58 -0400 (Sun, 04 Oct 2009) Log Message: ----------- Modified Paths: -------------- trunk/ruby-oci8/ChangeLog Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2009-10-04 13:55:01 UTC (rev 360) +++ trunk/ruby-oci8/ChangeLog 2009-10-04 14:01:58 UTC (rev 361) @@ -3,6 +3,7 @@ * ext/oci8/oraconf.rb: 1. Fix for ruby 1.8.5 with Oracle 8.x which needs some object files to link with. + (reported by Jayson Cena) 2. Revise the error message under the sudo environemnt. 3. Print not only error message but also the error backtrace when oraconf.rb fails. From nobody at rubyforge.org Sun Oct 4 10:04:01 2009 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Sun, 4 Oct 2009 10:04:01 -0400 (EDT) Subject: [ruby-oci8-commit] [362] branches/ruby-oci8-1.0: * ext/oci8/oraconf.rb: Message-ID: <20091004140401.50F9B16782AD@rubyforge.org> Revision: 362 Author: kubo Date: 2009-10-04 10:04:01 -0400 (Sun, 04 Oct 2009) Log Message: ----------- * ext/oci8/oraconf.rb: 1. Fix for ruby 1.8.5 with Oracle 8.x which needs some object files to link with. (reported by Jayson Cena) 2. Add additional error message if under the sudo environemnt. 3. Print not only error message but also the error backtrace when oraconf.rb fails. Modified Paths: -------------- branches/ruby-oci8-1.0/ChangeLog branches/ruby-oci8-1.0/ext/oci8/oraconf.rb Modified: branches/ruby-oci8-1.0/ChangeLog =================================================================== --- branches/ruby-oci8-1.0/ChangeLog 2009-10-04 14:01:58 UTC (rev 361) +++ branches/ruby-oci8-1.0/ChangeLog 2009-10-04 14:04:01 UTC (rev 362) @@ -1,3 +1,12 @@ +2009-10-04 KUBO Takehiro + * ext/oci8/oraconf.rb: + 1. Fix for ruby 1.8.5 with Oracle 8.x which needs some object + files to link with. + (reported by Jayson Cena) + 2. Add additional error message if under the sudo environemnt. + 3. Print not only error message but also the error backtrace when + oraconf.rb fails. + 2009-09-13 KUBO Takehiro * ext/oci8/lob.c, ext/oci8/oci8.h, test/test_clob.rb: Change OCI8::LOB#write to accept an object which is not a String and Modified: branches/ruby-oci8-1.0/ext/oci8/oraconf.rb =================================================================== --- branches/ruby-oci8-1.0/ext/oci8/oraconf.rb 2009-10-04 14:01:58 UTC (rev 361) +++ branches/ruby-oci8-1.0/ext/oci8/oraconf.rb 2009-10-04 14:04:01 UTC (rev 362) @@ -353,8 +353,10 @@ end print < Revision: 363 Author: kubo Date: 2009-10-06 09:46:41 -0400 (Tue, 06 Oct 2009) Log Message: ----------- * ext/oci8/ocinumber.c: Add a global function OraNumber(obj) as a shortcut of OraNumber.new(obj) as Rational and BigDecimal do. Changes the return type of the four rules of arithmetic; addition, subtraction, multiplication and division. It was OraNumber, but now it depends on the operand. * lib/oci8/bindtype.rb: Add OCI8::BindType::BigDecimal and OCI8::BindType::Rational. Change the default data type for number column which fit neither Integer nor Float from OraNumber to BigDecimal. * lib/oci8/oci8.rb: Fix for OCI8::BindType::Mapping to accept a class name instead of the class object to support OCI8::BindType::BigDecimal and OCI8::BindType::Rational without requiring 'bigdecimal' and 'rational'. * spec/oranumber_spec.rb: Add a spec file for OraNumber arithmetic. * test/test_oci8.rb: Add tests for OCI8::BindType::BigDecimal and OCI8::BindType::Rational. Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/ext/oci8/ocinumber.c trunk/ruby-oci8/lib/oci8/bindtype.rb trunk/ruby-oci8/lib/oci8/oci8.rb trunk/ruby-oci8/test/test_oci8.rb Added Paths: ----------- trunk/ruby-oci8/spec/oranumber_spec.rb Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2009-10-04 14:04:01 UTC (rev 362) +++ trunk/ruby-oci8/ChangeLog 2009-10-06 13:46:41 UTC (rev 363) @@ -1,3 +1,21 @@ +2009-10-06 KUBO Takehiro + * ext/oci8/ocinumber.c: Add a global function OraNumber(obj) as a + shortcut of OraNumber.new(obj) as Rational and BigDecimal do. + Changes the return type of the four rules of arithmetic; + addition, subtraction, multiplication and division. It was + OraNumber, but now it depends on the operand. + * lib/oci8/bindtype.rb: Add OCI8::BindType::BigDecimal and + OCI8::BindType::Rational. Change the default data type for + number column which fit neither Integer nor Float from + OraNumber to BigDecimal. + * lib/oci8/oci8.rb: Fix for OCI8::BindType::Mapping to accept + a class name instead of the class object to support + OCI8::BindType::BigDecimal and OCI8::BindType::Rational without + requiring 'bigdecimal' and 'rational'. + * spec/oranumber_spec.rb: Add a spec file for OraNumber arithmetic. + * test/test_oci8.rb: Add tests for OCI8::BindType::BigDecimal and + OCI8::BindType::Rational. + 2009-10-04 KUBO Takehiro * ext/oci8/oci8.c: Add constants missing in Oracle client prior to 10g. * ext/oci8/oraconf.rb: Modified: trunk/ruby-oci8/ext/oci8/ocinumber.c =================================================================== --- trunk/ruby-oci8/ext/oci8/ocinumber.c 2009-10-04 14:04:01 UTC (rev 362) +++ trunk/ruby-oci8/ext/oci8/ocinumber.c 2009-10-06 13:46:41 UTC (rev 363) @@ -21,7 +21,14 @@ static ID id_split; static ID id_numerator; static ID id_denominator; +static ID id_Rational; +static ID id_BigDecimal; +#ifndef T_RATIONAL +static VALUE cRational; +#endif +static VALUE cBigDecimal; + static VALUE cOCINumber; static OCINumber const_p1; /* +1 */ static OCINumber const_p10; /* +10 */ @@ -51,6 +58,58 @@ #define _NUMBER(val) ((OCINumber *)DATA_PTR(val)) /* dangerous macro */ +#define RBOCI8_T_ORANUMBER (T_MASK + 1) +#define RBOCI8_T_BIGDECIMAL (T_MASK + 2) +#ifdef T_RATIONAL +#define RBOCI8_T_RATIONAL T_RATIONAL +#else +#define RBOCI8_T_RATIONAL (T_MASK + 3) +#endif + +static int rboci8_type(VALUE obj) +{ + int type = TYPE(obj); + VALUE klass; + + switch (type) { +#ifndef T_RATIONAL + case T_OBJECT: + klass = CLASS_OF(obj); + if (cRational != 0) { + if (klass == cRational) { + return RBOCI8_T_RATIONAL; + } + } else { + if (strcmp(rb_class2name(klass), "Rational") == 0) { + cRational = rb_const_get(rb_cObject, id_Rational); + return RBOCI8_T_RATIONAL; + } + } + break; +#endif + case T_DATA: + klass = CLASS_OF(obj); + if (klass == cOCINumber) { + return RBOCI8_T_ORANUMBER; + } + if (cBigDecimal != 0) { + if (klass == cBigDecimal) { + return RBOCI8_T_BIGDECIMAL; + } + } else { + if (strcmp(rb_class2name(klass), "BigDecimal") == 0) { + cBigDecimal = rb_const_get(rb_cObject, id_BigDecimal); + return RBOCI8_T_BIGDECIMAL; + } + } + } + return type; +} + +static VALUE onum_to_f(VALUE self); +static VALUE onum_to_r(VALUE self); +static VALUE onum_to_d(VALUE self); + static VALUE onum_s_alloc(VALUE klass) { VALUE obj; @@ -573,6 +632,20 @@ return oci8_make_ocinumber(&r, errhp); } + +/* + * call-seq: + * OraNumber(obj) -> oranumber + * + * Returns a new OraNumber. + */ +static VALUE onum_f_new(int argc, VALUE *argv, VALUE self) +{ + VALUE obj = rb_obj_alloc(cOCINumber); + rb_obj_call_init(obj, argc, argv); + return obj; +} + static VALUE onum_initialize(int argc, VALUE *argv, VALUE self) { OCIError *errhp = oci8_errhp; @@ -602,12 +675,26 @@ static VALUE onum_coerce(VALUE self, VALUE other) { - OCIError *errhp = oci8_errhp; + signed long sl; OCINumber n; - if (RTEST(rb_obj_is_kind_of(other, rb_cNumeric))) - if (set_oci_number_from_num(&n, other, 0, errhp)) - return rb_assoc_new(oci8_make_ocinumber(&n, errhp), self); + switch(rboci8_type(other)) { + case T_FIXNUM: + sl = NUM2LONG(other); + oci_lc(OCINumberFromInt(oci8_errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &n)); + return rb_assoc_new(oci8_make_ocinumber(&n, oci8_errhp), self); + case T_BIGNUM: + /* change via string. */ + other = rb_big2str(other, 10); + set_oci_number_from_str(&n, other, Qnil, Qnil, oci8_errhp); + return rb_assoc_new(oci8_make_ocinumber(&n, oci8_errhp), self); + case T_FLOAT: + return rb_assoc_new(other, onum_to_f(self)); + case RBOCI8_T_RATIONAL: + return rb_assoc_new(other, onum_to_r(self)); + case RBOCI8_T_BIGDECIMAL: + return rb_assoc_new(other, onum_to_d(self)); + } rb_raise(rb_eTypeError, "Can't coerce %s to %s", rb_class2name(CLASS_OF(other)), rb_class2name(cOCINumber)); } @@ -616,7 +703,7 @@ * call-seq: * -onum -> oranumber * - * Returns an OraNumber, negated. + * Returns a negated OraNumber. */ static VALUE onum_neg(VALUE self) { @@ -627,12 +714,12 @@ return oci8_make_ocinumber(&r, errhp); } + /* * call-seq: - * onum + other -> oranumber + * onum + other -> number * - * Returns a new OraNumber which is the sum of onum - * and other. + * Returns the sum of onum and other. */ static VALUE onum_add(VALUE lhs, VALUE rhs) { @@ -640,20 +727,33 @@ OCINumber n; OCINumber r; - /* change to OCINumber */ - if (!set_oci_number_from_num(&n, rhs, 0, errhp)) - return rb_num_coerce_bin(lhs, rhs, '+'); - /* add */ - oci_lc(OCINumberAdd(errhp, _NUMBER(lhs), &n, &r)); - return oci8_make_ocinumber(&r, errhp); + switch (rboci8_type(rhs)) { + case T_FIXNUM: + case T_BIGNUM: + if (set_oci_number_from_num(&n, rhs, 0, errhp)) { + oci_lc(OCINumberAdd(errhp, _NUMBER(lhs), &n, &r)); + return oci8_make_ocinumber(&r, errhp); + } + break; + case RBOCI8_T_ORANUMBER: + oci_lc(OCINumberAdd(errhp, _NUMBER(lhs), _NUMBER(rhs), &r)); + return oci8_make_ocinumber(&r, errhp); + case T_FLOAT: + return rb_funcall(onum_to_f(lhs), '+', 1, rhs); + case RBOCI8_T_RATIONAL: + return rb_funcall(onum_to_r(lhs), '+', 1, rhs); + case RBOCI8_T_BIGDECIMAL: + return rb_funcall(onum_to_d(lhs), '+', 1, rhs); + } + return rb_num_coerce_bin(lhs, rhs, '+'); } /* * call-seq: - * onum - other -> oranumber + * onum - integer -> oranumber + * onum - numeric -> numeric * - * Returns a new OraNumber which is the difference of onum - * and other. + * Returns the difference of onum and other. */ static VALUE onum_sub(VALUE lhs, VALUE rhs) { @@ -661,20 +761,32 @@ OCINumber n; OCINumber r; - /* change to OCINumber */ - if (!set_oci_number_from_num(&n, rhs, 0, errhp)) - return rb_num_coerce_bin(lhs, rhs, '-'); - /* subtracting */ - oci_lc(OCINumberSub(errhp, _NUMBER(lhs), &n, &r)); - return oci8_make_ocinumber(&r, errhp); + switch (rboci8_type(rhs)) { + case T_FIXNUM: + case T_BIGNUM: + if (set_oci_number_from_num(&n, rhs, 0, errhp)) { + oci_lc(OCINumberSub(errhp, _NUMBER(lhs), &n, &r)); + return oci8_make_ocinumber(&r, errhp); + } + break; + case RBOCI8_T_ORANUMBER: + oci_lc(OCINumberSub(errhp, _NUMBER(lhs), _NUMBER(rhs), &r)); + return oci8_make_ocinumber(&r, errhp); + case T_FLOAT: + return rb_funcall(onum_to_f(lhs), '-', 1, rhs); + case RBOCI8_T_RATIONAL: + return rb_funcall(onum_to_r(lhs), '-', 1, rhs); + case RBOCI8_T_BIGDECIMAL: + return rb_funcall(onum_to_d(lhs), '-', 1, rhs); + } + return rb_num_coerce_bin(lhs, rhs, '-'); } /* * call-seq: - * onum * other -> oranumber + * onum * other -> number * - * Returns a new OraNumber which is the product of onum - * and other. + * Returns the product of onum and other. */ static VALUE onum_mul(VALUE lhs, VALUE rhs) { @@ -682,20 +794,33 @@ OCINumber n; OCINumber r; - /* change to OCINumber */ - if (!set_oci_number_from_num(&n, rhs, 0, errhp)) - return rb_num_coerce_bin(lhs, rhs, '*'); - /* multiply */ - oci_lc(OCINumberMul(errhp, _NUMBER(lhs), &n, &r)); - return oci8_make_ocinumber(&r, errhp); + switch (rboci8_type(rhs)) { + case T_FIXNUM: + case T_BIGNUM: + if (set_oci_number_from_num(&n, rhs, 0, errhp)) { + oci_lc(OCINumberMul(errhp, _NUMBER(lhs), &n, &r)); + return oci8_make_ocinumber(&r, errhp); + } + break; + case RBOCI8_T_ORANUMBER: + oci_lc(OCINumberMul(errhp, _NUMBER(lhs), _NUMBER(rhs), &r)); + return oci8_make_ocinumber(&r, errhp); + case T_FLOAT: + return rb_funcall(onum_to_f(lhs), '*', 1, rhs); + case RBOCI8_T_RATIONAL: + return rb_funcall(onum_to_r(lhs), '*', 1, rhs); + case RBOCI8_T_BIGDECIMAL: + return rb_funcall(onum_to_d(lhs), '*', 1, rhs); + } + return rb_num_coerce_bin(lhs, rhs, '*'); } /* * call-seq: - * onum / other -> oranumber + * onum / integer -> oranumber + * onum / numeric -> numeric * - * Returns a new OraNumber which is the result of dividing - * onum by other. + * Returns the result of dividing onum by other. */ static VALUE onum_div(VALUE lhs, VALUE rhs) { @@ -704,16 +829,32 @@ OCINumber r; boolean is_zero; - /* change to OCINumber */ - if (!set_oci_number_from_num(&n, rhs, 0, errhp)) - return rb_num_coerce_bin(lhs, rhs, '/'); - /* check whether argument is not zero. */ - oci_lc(OCINumberIsZero(errhp, &n, &is_zero)); - if (is_zero) - rb_num_zerodiv(); - /* division */ - oci_lc(OCINumberDiv(errhp, _NUMBER(lhs), &n, &r)); - return oci8_make_ocinumber(&r, errhp); + switch (rboci8_type(rhs)) { + case T_FIXNUM: + if (rhs == INT2FIX(0)) { + rb_num_zerodiv(); + } + case T_BIGNUM: + if (set_oci_number_from_num(&n, rhs, 0, errhp)) { + oci_lc(OCINumberDiv(errhp, _NUMBER(lhs), &n, &r)); + return oci8_make_ocinumber(&r, errhp); + } + break; + case RBOCI8_T_ORANUMBER: + oci_lc(OCINumberIsZero(errhp, _NUMBER(rhs), &is_zero)); + if (is_zero) { + rb_num_zerodiv(); + } + oci_lc(OCINumberDiv(errhp, _NUMBER(lhs), _NUMBER(rhs), &r)); + return oci8_make_ocinumber(&r, errhp); + case T_FLOAT: + return rb_funcall(onum_to_f(lhs), '/', 1, rhs); + case RBOCI8_T_RATIONAL: + return rb_funcall(onum_to_r(lhs), '/', 1, rhs); + case RBOCI8_T_BIGDECIMAL: + return rb_funcall(onum_to_d(lhs), '/', 1, rhs); + } + return rb_num_coerce_bin(lhs, rhs, '/'); } /* @@ -975,7 +1116,7 @@ * call-seq: * onum.to_i -> integer * - * Returns onm truncated to an Integer. + * Returns onum truncated to an Integer. */ static VALUE onum_to_i(VALUE self) { @@ -990,7 +1131,7 @@ * call-seq: * onum.to_f -> float * - * Converts onum to a Float. + * Return the value as a Float. * */ static VALUE onum_to_f(VALUE self) @@ -1004,8 +1145,69 @@ /* * call-seq: + * onum.to_r -> rational + * + * Return the value as a Rational. + * + */ +static VALUE onum_to_r(VALUE self) +{ + VALUE x, y; + int nshift = 0; + OCINumber onum[2]; + int current = 0; + boolean is_int; + + oci_lc(OCINumberAssign(oci8_errhp, _NUMBER(self), &onum[0])); + + for (;;) { + oci_lc(OCINumberIsInt(oci8_errhp, &onum[current], &is_int)); + if (is_int) { + break; + } + nshift++; + oci_lc(OCINumberShift(oci8_errhp, &onum[current], 1, &onum[1 - current])); + current = 1 - current; + } + x = oci8_make_integer(&onum[current], oci8_errhp); + if (nshift == 0) { + y = INT2FIX(1); + } else { + y = rb_funcall(INT2FIX(10), rb_intern("**"), 1, INT2FIX(nshift)); + } +#ifdef T_RATIONAL + return rb_Rational(x, y); +#else + if (!cRational) { + rb_require("rational"); + cRational = rb_const_get(rb_cObject, id_Rational); + } + return rb_funcall(rb_cObject, id_Rational, 2, x, y); +#endif +} + +/* + * call-seq: + * onum.to_d -> bigdecimal + * + * Return the value as a BigDecimal. + * + */ +static VALUE onum_to_d(VALUE self) +{ + if (!cBigDecimal) { + rb_require("bigdecimal"); + cBigDecimal = rb_const_get(rb_cObject, id_BigDecimal); + } + return rb_funcall(rb_cObject, id_BigDecimal, 1, onum_to_s(self)); +} + +/* + * call-seq: * onum.to_onum -> oranumber * + * Returns self. + * */ static VALUE onum_to_onum(VALUE self) { @@ -1218,6 +1420,8 @@ id_split = rb_intern("split"); id_numerator = rb_intern("numerator"); id_denominator = rb_intern("denominator"); + id_Rational = rb_intern("Rational"); + id_BigDecimal = rb_intern("BigDecimal"); cOCINumber = rb_define_class("OraNumber", rb_cNumeric); mMath = rb_define_module_under(cOCI8, "Math"); @@ -1275,6 +1479,7 @@ rb_define_alloc_func(cOCINumber, onum_s_alloc); /* methods of OCI::Number */ + rb_define_method(rb_cObject, "OraNumber", onum_f_new, -1); rb_define_method_nodoc(cOCINumber, "initialize", onum_initialize, -1); rb_define_method_nodoc(cOCINumber, "initialize_copy", onum_initialize_copy, 1); rb_define_method_nodoc(cOCINumber, "coerce", onum_coerce, 1); @@ -1302,6 +1507,8 @@ rb_define_method(cOCINumber, "to_char", onum_to_char, -1); rb_define_method(cOCINumber, "to_i", onum_to_i, 0); rb_define_method(cOCINumber, "to_f", onum_to_f, 0); + rb_define_method(cOCINumber, "to_r", onum_to_r, 0); + rb_define_method(cOCINumber, "to_d", onum_to_d, 0); rb_define_method_nodoc(cOCINumber, "to_onum", onum_to_onum, 0); rb_define_method(cOCINumber, "zero?", onum_zero_p, 0); Modified: trunk/ruby-oci8/lib/oci8/bindtype.rb =================================================================== --- trunk/ruby-oci8/lib/oci8/bindtype.rb 2009-10-04 14:04:01 UTC (rev 362) +++ trunk/ruby-oci8/lib/oci8/bindtype.rb 2009-10-06 13:46:41 UTC (rev 363) @@ -24,6 +24,28 @@ end end + class BigDecimal < OCI8::BindType::OraNumber + @@bigdecimal_is_required = false + def get() + unless @@bigdecimal_is_required + require 'bigdecimal' + @@bigdecimal_is_required = true + end + (val = super()) && val.to_d + end + end + + class Rational < OCI8::BindType::OraNumber + @@rational_is_required = false + def get() + unless @@rational_is_required + require 'rational' + @@rational_is_required = true + end + (val = super()) && val.to_r + end + end + # get/set Number (for OCI8::SQLT_NUM) class Number def self.create(con, val, param, max_array_size) @@ -54,8 +76,8 @@ if precision < 15 # the precision of double. klass = OCI8::BindType::Float else - # use BigDecimal instead? - klass = OCI8::BindType::OraNumber + # use BigDecimal instead + klass = OCI8::BindType::BigDecimal end end klass.new(con, val, nil, max_array_size) @@ -156,6 +178,8 @@ # bind or explicitly define OCI8::BindType::Mapping[String] = OCI8::BindType::String OCI8::BindType::Mapping[OraNumber] = OCI8::BindType::OraNumber +OCI8::BindType::Mapping['BigDecimal'] = OCI8::BindType::BigDecimal +OCI8::BindType::Mapping['Rational'] = OCI8::BindType::Rational OCI8::BindType::Mapping[Fixnum] = OCI8::BindType::Integer OCI8::BindType::Mapping[Float] = OCI8::BindType::Float OCI8::BindType::Mapping[Integer] = OCI8::BindType::Integer @@ -263,9 +287,9 @@ # datatypes that have no explicit setting of their precision # and scale. # -# The default mapping is Float for ruby-oci8 1.0. It is OraNumber -# for ruby-oci8 2.0. -OCI8::BindType::Mapping[:number_unknown_prec] = OCI8::BindType::OraNumber +# The default mapping is Float for ruby-oci8 1.0, OraNumber for 2.0.0 ~ 2.0.2, +# BigDecimal for 2.0.3 ~. +OCI8::BindType::Mapping[:number_unknown_prec] = OCI8::BindType::BigDecimal # mapping for number without precision and scale. # @@ -276,9 +300,9 @@ # note: This is available only on Oracle 9.2.0.3 or above. # see: Oracle 9.2.0.x Patch Set Notes. # -# The default mapping is Float for ruby-oci8 1.0. It is OraNumber -# for ruby-oci8 2.0. -OCI8::BindType::Mapping[:number_no_prec_setting] = OCI8::BindType::OraNumber +# The default mapping is Float for ruby-oci8 1.0, OraNumber for 2.0.0 ~ 2.0.2, +# BigDecimal for 2.0.3 ~. +OCI8::BindType::Mapping[:number_no_prec_setting] = OCI8::BindType::BigDecimal if defined? OCI8::BindType::BinaryDouble OCI8::BindType::Mapping[:binary_float] = OCI8::BindType::BinaryDouble Modified: trunk/ruby-oci8/lib/oci8/oci8.rb =================================================================== --- trunk/ruby-oci8/lib/oci8/oci8.rb 2009-10-04 14:04:01 UTC (rev 362) +++ trunk/ruby-oci8/lib/oci8/oci8.rb 2009-10-06 13:46:41 UTC (rev 363) @@ -343,6 +343,10 @@ end bindclass = OCI8::BindType::Mapping[type] + if bindclass.nil? and type.is_a? Class + bindclass = OCI8::BindType::Mapping[type.to_s] + OCI8::BindType::Mapping[type] = bindclass if bindclass + end raise "unsupported dataType: #{type}" if bindclass.nil? bindobj = bindclass.create(@con, var_array, param, @max_array_size) __bind(key, bindobj) @@ -452,6 +456,10 @@ end bindclass = OCI8::BindType::Mapping[key] + if bindclass.nil? and key.is_a? Class + bindclass = OCI8::BindType::Mapping[key.to_s] + OCI8::BindType::Mapping[key] = bindclass if bindclass + end raise "unsupported datatype: #{key}" if bindclass.nil? bindclass.create(@con, val, param, max_array_size) end Added: trunk/ruby-oci8/spec/oranumber_spec.rb =================================================================== --- trunk/ruby-oci8/spec/oranumber_spec.rb (rev 0) +++ trunk/ruby-oci8/spec/oranumber_spec.rb 2009-10-06 13:46:41 UTC (rev 363) @@ -0,0 +1,167 @@ +require 'bigdecimal' +require 'rational' +require File.join(File.dirname(__FILE__), 'spec_helper.rb') + +describe OraNumber do + + it "should be converted to Flaot by to_f" do + OraNumber("0.25").to_f.should eql(0.25) + end + + it "should be converted to Integer by to_i" do + OraNumber("7.25").to_i.should eql(7) + OraNumber("7.75").to_i.should eql(7) + end + + it "should be converted to Rational by to_r" do + OraNumber("100000000000000.1").to_r.should eql(Rational(1000000000000001, 10)) + end + + it "should be converted to BigDecimal by to_d" do + OraNumber("100000000000000.1").to_d.should eql(BigDecimal("100000000000000.1")) + end + + # OraNumber bin_op OraNumber + it "+ OraNumber should be an OraNumber" do + (OraNumber(2) + OraNumber(1)).should eql(OraNumber(3)) + end + + it "- OraNumber should be an OraNumber" do + (OraNumber(2) - OraNumber(1)).should eql(OraNumber(1)) + end + + it "* OraNumber should be an OraNumber" do + (OraNumber(2) * OraNumber(1)).should eql(OraNumber(2)) + end + + it "/ OraNumber should be an OraNumber" do + (OraNumber(2) / OraNumber(1)).should eql(OraNumber(2)) + end + + # OraNumber bin_op Fixnum + it "+ Fixnum should be an OraNumber" do + (OraNumber(2) + 1).should eql(OraNumber(3)) + end + + it "- Fixnum should be an OraNumber" do + (OraNumber(2) - 1).should eql(OraNumber(1)) + end + + it "* Fixnum should be an OraNumber" do + (OraNumber(2) * 1).should eql(OraNumber(2)) + end + + it "/ Fixnum should be an OraNumber" do + (OraNumber(2) / 1).should eql(OraNumber(2)) + end + + # OraNumber bin_op Bignum + it "+ Bignum should be an OraNumber" do + (OraNumber(2) + 100000000000000000000).should eql(OraNumber(100000000000000000002)) + end + + it "- Bignum should be an OraNumber" do + (OraNumber(2) - 100000000000000000000).should eql(OraNumber(-99999999999999999998)) + end + + it "* Bignum should be an OraNumber" do + (OraNumber(2) * 100000000000000000000).should eql(OraNumber(200000000000000000000)) + end + + it "/ Bignum should be an OraNumber" do + (OraNumber(2) / 100000000000000000000).should eql(OraNumber("0.00000000000000000002")) + end + + # OraNumber bin_op Float + it "+ Float should be a Float" do + (OraNumber(2) + 1.0).should eql(3.0) + end + + it "- Float should be a Float" do + (OraNumber(2) - 1.0).should eql(1.0) + end + + it "* Float should be a Float" do + (OraNumber(2) * 1.0).should eql(2.0) + end + + it "/ Float should be a Float" do + (OraNumber(2) / 1.0).should eql(2.0) + end + + # OraNumber bin_op BigDecimal + it "+ BigDecimal should be a BigDecimal" do + (OraNumber(2) + BigDecimal("1")).should eql(BigDecimal("3")) + end + + it "- BigDecimal should be a BigDecimal" do + (OraNumber(2) - BigDecimal("1")).should eql(BigDecimal("1")) + end + + it "* BigDecimal should be a BigDecimal" do + (OraNumber(2) * BigDecimal("1")).should eql(BigDecimal("2")) + end + + it "/ BigDecimal should be a BigDecimal" do + (OraNumber(2) / BigDecimal("1")).should eql(BigDecimal("2")) + end + + # OraNumber bin_op Rational + it "+ Rational should be a Rational" do + (OraNumber(2) + Rational(1)).should eql(Rational(3)) + end + + it "- Rational should be a Rational" do + (OraNumber(2) - Rational(1)).should eql(Rational(1)) + end + + it "* Rational should be a Rational" do + (OraNumber(2) * Rational(1)).should eql(Rational(2)) + end + + it "/ Rational should be a Rational" do + (OraNumber(2) / Rational(1)).should eql(Rational(2)) + end +end + +describe Fixnum do + it "+ OraNumber should be an OraNumber" do + (2 + OraNumber(1)).should eql(OraNumber(3)) + end + + it "- OraNumber should be an OraNumber" do + (2 - OraNumber(1)).should eql(OraNumber(1)) + end + + it "* OraNumber should be an OraNumber" do + (2 * OraNumber(1)).should eql(OraNumber(2)) + end + + it "/ OraNumber should be an OraNumber" do + (2 / OraNumber(1)).should eql(OraNumber(2)) + end +end + +describe Bignum do + it "+ OraNumber should be an OraNumber" do + (100000000000000000000 + OraNumber(1)).should eql(OraNumber(100000000000000000001)) + end +end + +describe Float do + it "+ OraNumber should be a Float" do + (1.0 + OraNumber(1)).should eql(2.0) + end +end + +describe BigDecimal do + it "+ OraNumber should be a BigDecimal" do + (BigDecimal("1") + OraNumber(1)).should eql(BigDecimal("2")) + end +end + +describe Rational do + it "+ OraNumber should be a Rational" do + (Rational(1) + OraNumber(1)).should eql(Rational(2)) + end +end Modified: trunk/ruby-oci8/test/test_oci8.rb =================================================================== --- trunk/ruby-oci8/test/test_oci8.rb 2009-10-04 14:04:01 UTC (rev 362) +++ trunk/ruby-oci8/test/test_oci8.rb 2009-10-06 13:46:41 UTC (rev 363) @@ -359,10 +359,10 @@ assert_equal(row[2], 123456789012.34) assert_equal(row[3], 1234567890123.45) assert_equal(row[4], 1234.5) - assert_instance_of(OraNumber, row[0]) + assert_instance_of(BigDecimal, row[0]) assert_instance_of(Bignum, row[1]) assert_instance_of(Float, row[2]) - assert_instance_of(OraNumber, row[3]) + assert_instance_of(BigDecimal, row[3]) assert_instance_of(Float, row[4]) end drop_table('test_table') @@ -372,6 +372,8 @@ src = [1, 1.2, BigDecimal("1.2"), Rational(12, 10)] int = [1, 1, 1, 1] flt = [1, 1.2, 1.2, 1.2] + dec = [BigDecimal("1"), BigDecimal("1.2"), BigDecimal("1.2"), BigDecimal("1.2")] + rat = [Rational(1), Rational(12, 10), Rational(12, 10), Rational(12, 10)] cursor = @conn.parse("begin :1 := :2; end;") @@ -382,6 +384,7 @@ cursor[2] = s cursor.exec assert_equal(cursor[1], flt[idx]) + assert_kind_of(Float, cursor[1]) end # Fixnum @@ -391,6 +394,7 @@ cursor[2] = s cursor.exec assert_equal(cursor[1], int[idx]) + assert_kind_of(Fixnum, cursor[1]) end # Integer @@ -400,7 +404,28 @@ cursor[2] = s cursor.exec assert_equal(cursor[1], int[idx]) + assert_kind_of(Integer, cursor[1]) end + + # BigDecimal + cursor.bind_param(1, nil, BigDecimal) + cursor.bind_param(2, nil, BigDecimal) + src.each_with_index do |s, idx| + cursor[2] = s + cursor.exec + assert_equal(cursor[1], dec[idx]) + assert_kind_of(BigDecimal, cursor[1]) + end + + # Rational + cursor.bind_param(1, nil, Rational) + cursor.bind_param(2, nil, Rational) + src.each_with_index do |s, idx| + cursor[2] = s + cursor.exec + assert_equal(cursor[1], rat[idx]) + assert_kind_of(Rational, cursor[1]) + end end end # TestOCI8 From nobody at rubyforge.org Sat Oct 17 10:23:14 2009 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Sat, 17 Oct 2009 10:23:14 -0400 (EDT) Subject: [ruby-oci8-commit] [364] trunk/ruby-oci8: * ext/oci8/oci8.c: Add a workaround for Oracle 9.2.0 .1 when clearing Message-ID: <20091017142314.323851858282@rubyforge.org> Revision: 364 Author: kubo Date: 2009-10-17 10:23:12 -0400 (Sat, 17 Oct 2009) Log Message: ----------- * ext/oci8/oci8.c: Add a workaround for Oracle 9.2.0.1 when clearing a client identifier. * ext/oci8/oci8lib.c: Fix a segv when canceling a non-blocking execution. * test_appinfo.rb: Fix temporarily to prevent a segmentation fault under Oracle 9.2.0.1. * test/test_oci8.rb: Fix temporarily to prevent a segmentation fault under Oracle 9.2.0.1. Fix for BigDecimal bundled in ruby 1.8.5. * test/test_oranumber.rb: Fix for Oracle 9.2. Comparing float values by <=> is too sensitive to use it in tests. Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/ext/oci8/oci8.c trunk/ruby-oci8/ext/oci8/oci8lib.c trunk/ruby-oci8/test/test_appinfo.rb trunk/ruby-oci8/test/test_oci8.rb trunk/ruby-oci8/test/test_oranumber.rb Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2009-10-06 13:46:41 UTC (rev 363) +++ trunk/ruby-oci8/ChangeLog 2009-10-17 14:23:12 UTC (rev 364) @@ -1,3 +1,15 @@ +2009-10-17 KUBO Takehiro + * ext/oci8/oci8.c: Add a workaround for Oracle 9.2.0.1 when clearing + a client identifier. + * ext/oci8/oci8lib.c: Fix a segv when canceling a non-blocking + execution. + * test_appinfo.rb: Fix temporarily to prevent a segmentation fault + under Oracle 9.2.0.1. + * test/test_oci8.rb: Fix temporarily to prevent a segmentation fault + under Oracle 9.2.0.1. Fix for BigDecimal bundled in ruby 1.8.5. + * test/test_oranumber.rb: Fix for Oracle 9.2. Comparing float values + by <=> is too sensitive to use it in tests. + 2009-10-06 KUBO Takehiro * ext/oci8/ocinumber.c: Add a global function OraNumber(obj) as a shortcut of OraNumber.new(obj) as Rational and BigDecimal do. Modified: trunk/ruby-oci8/ext/oci8/oci8.c =================================================================== --- trunk/ruby-oci8/ext/oci8/oci8.c 2009-10-06 13:46:41 UTC (rev 363) +++ trunk/ruby-oci8/ext/oci8/oci8.c 2009-10-17 14:23:12 UTC (rev 364) @@ -673,6 +673,7 @@ { char *ptr; ub4 size; + int use_attr_set = 1; if (!NIL_P(val)) { OCI8SafeStringValue(val); @@ -682,7 +683,15 @@ ptr = ""; size = 0; } - if (oracle_client_version >= ORAVER_9_0) { + + if (oracle_client_version < ORAVER_9_0) { + use_attr_set = 0; + } else if (oracle_client_version < ORAVERNUM(9, 2, 0, 3, 0) && size == 0) { + /* Workaround for Bug 2449486 */ + use_attr_set = 0; + } + + if (use_attr_set) { if (size > 0 && ptr[0] == ':') { rb_raise(rb_eArgError, "client identifier should not start with ':'."); } Modified: trunk/ruby-oci8/ext/oci8/oci8lib.c =================================================================== --- trunk/ruby-oci8/ext/oci8/oci8lib.c 2009-10-06 13:46:41 UTC (rev 363) +++ trunk/ruby-oci8/ext/oci8/oci8lib.c 2009-10-17 14:23:12 UTC (rev 364) @@ -263,6 +263,8 @@ } #ifdef RUBY_VM + +#if 0 typedef struct { dvoid *hndlp; OCIError *errhp; @@ -285,6 +287,13 @@ rb_thread_blocking_region(call_OCIBreak, &arg, NULL, NULL); } } +#else +static void oci8_unblock_func(void *user_data) +{ + oci8_svcctx_t *svcctx = (oci8_svcctx_t *)user_data; + OCIBreak(svcctx->base.hp.ptr, oci8_errhp); +} +#endif /* ruby 1.9 */ sword oci8_blocking_region(oci8_svcctx_t *svcctx, rb_blocking_function_t func, void *data) Modified: trunk/ruby-oci8/test/test_appinfo.rb =================================================================== --- trunk/ruby-oci8/test/test_appinfo.rb 2009-10-06 13:46:41 UTC (rev 363) +++ trunk/ruby-oci8/test/test_appinfo.rb 2009-10-17 14:23:12 UTC (rev 364) @@ -24,6 +24,9 @@ end def test_set_module + # FIXME: check again after upgrading Oracle 9.2 to 9.2.0.4. + return if @conn.oracle_server_version < OCI8::ORAVER_10_1 + # set module @conn.module = 'ruby-oci8' assert_equal('ruby-oci8', @conn.select_one("SELECT SYS_CONTEXT('USERENV', 'MODULE') FROM DUAL")[0]); @@ -33,6 +36,9 @@ end def test_set_action + # FIXME: check again after upgrading Oracle 9.2 to 9.2.0.4. + return if @conn.oracle_server_version < OCI8::ORAVER_10_1 + # set action @conn.action = 'test_set_action' assert_equal('test_set_action', @conn.select_one("SELECT SYS_CONTEXT('USERENV', 'ACTION') FROM DUAL")[0]); Modified: trunk/ruby-oci8/test/test_oci8.rb =================================================================== --- trunk/ruby-oci8/test/test_oci8.rb 2009-10-06 13:46:41 UTC (rev 363) +++ trunk/ruby-oci8/test/test_oci8.rb 2009-10-17 14:23:12 UTC (rev 364) @@ -167,6 +167,9 @@ end def test_bind_cursor + # FIXME: check again after upgrading Oracle 9.2 to 9.2.0.4. + return if $oracle_version < OCI8::ORAVER_10_1 + drop_table('test_table') sql = <<-EOS CREATE TABLE test_table @@ -357,7 +360,7 @@ assert_equal(row[0], 12345678901234) assert_equal(row[1], 12345678901234567890) assert_equal(row[2], 123456789012.34) - assert_equal(row[3], 1234567890123.45) + assert_equal(row[3], BigDecimal("1234567890123.45")) assert_equal(row[4], 1234.5) assert_instance_of(BigDecimal, row[0]) assert_instance_of(Bignum, row[1]) Modified: trunk/ruby-oci8/test/test_oranumber.rb =================================================================== --- trunk/ruby-oci8/test/test_oranumber.rb 2009-10-06 13:46:41 UTC (rev 363) +++ trunk/ruby-oci8/test/test_oranumber.rb 2009-10-17 14:23:12 UTC (rev 364) @@ -349,13 +349,18 @@ # onum <=> other -> -1, 0, +1 def test_cmp - test_values = SMALL_RANGE_VALUES.collect do |x| - x[0,15] # donw the precision to pass this test. - end - compare_with_float2(test_values, test_values, - Proc.new {|x, y| x <=> y.to_f}) - compare_with_float2(test_values, test_values, - Proc.new {|x, y| y.to_f <=> x}) + assert_equal(-1, 1 <=> OraNumber(2)) + assert_equal(-1, 1.0 <=> OraNumber(2)) + assert_equal(-1, BigDecimal("1") <=> OraNumber(2)) + assert_equal(-1, Rational(1) <=> OraNumber(2)) + assert_equal(0, 2 <=> OraNumber(2)) + assert_equal(0, 2.0 <=> OraNumber(2)) + assert_equal(0, BigDecimal("2") <=> OraNumber(2)) + assert_equal(0, Rational(2) <=> OraNumber(2)) + assert_equal(1, 3 <=> OraNumber(2)) + assert_equal(1, 3.0 <=> OraNumber(2)) + assert_equal(1, BigDecimal("3") <=> OraNumber(2)) + assert_equal(1, Rational(3) <=> OraNumber(2)) end # onum.abs -> ocinumber From nobody at rubyforge.org Sun Oct 18 09:46:49 2009 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Sun, 18 Oct 2009 09:46:49 -0400 (EDT) Subject: [ruby-oci8-commit] [365] trunk/ruby-oci8: * ext/oci8/ocidatetime.c: Add workarounds for Oracle 9.2.0.1. Message-ID: <20091018134649.54FCF158805C@rubyforge.org> Revision: 365 Author: kubo Date: 2009-10-18 09:46:48 -0400 (Sun, 18 Oct 2009) Log Message: ----------- * ext/oci8/ocidatetime.c: Add workarounds for Oracle 9.2.0.1. * lib/oci8/datetime.rb: Change the unit of OCI8::BindType::IntervalDS from day to second. Add OCI8::BindType::IntervalDS.unit and OCI8::BindType::IntervalDS.unit. * test/test_datetime.rb: Fix tests for the above changes. Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/ext/oci8/ocidatetime.c trunk/ruby-oci8/lib/oci8/datetime.rb trunk/ruby-oci8/test/test_datetime.rb Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2009-10-17 14:23:12 UTC (rev 364) +++ trunk/ruby-oci8/ChangeLog 2009-10-18 13:46:48 UTC (rev 365) @@ -1,3 +1,10 @@ +2009-10-18 KUBO Takehiro + * ext/oci8/ocidatetime.c: Add workarounds for Oracle 9.2.0.1. + * lib/oci8/datetime.rb: Change the unit of OCI8::BindType::IntervalDS + from day to second. Add OCI8::BindType::IntervalDS.unit and + OCI8::BindType::IntervalDS.unit. + * test/test_datetime.rb: Fix tests for the above changes. + 2009-10-17 KUBO Takehiro * ext/oci8/oci8.c: Add a workaround for Oracle 9.2.0.1 when clearing a client identifier. Modified: trunk/ruby-oci8/ext/oci8/ocidatetime.c =================================================================== --- trunk/ruby-oci8/ext/oci8/ocidatetime.c 2009-10-17 14:23:12 UTC (rev 364) +++ trunk/ruby-oci8/ext/oci8/ocidatetime.c 2009-10-18 13:46:48 UTC (rev 365) @@ -320,8 +320,26 @@ } year = NUM2INT(RARRAY_PTR(val)[0]); month = NUM2INT(RARRAY_PTR(val)[1]); - oci_lc(OCIIntervalSetYearMonth(oci8_envhp, oci8_errhp, - year, month, intvl)); + if (oracle_client_version >= ORAVERNUM(9, 2, 0, 3, 0)) { + oci_lc(OCIIntervalSetYearMonth(oci8_envhp, oci8_errhp, + year, month, intvl)); + } else { + /* Workaround for Bug 2227982 */ + char buf[64]; + char *sign = ""; + + if (year < 0 && month != 0) { + year += 1; + month -= 12; + } + if (year < 0 || month < 0) { + sign = "-"; + year = -year; + month = -month; + } + sprintf(buf, "%s%d-%d", sign, year, month); + oci_lc(OCIIntervalFromText(oci8_envhp, oci8_errhp, (text*)buf, strlen(buf), intvl)); + } return intvl; } @@ -357,8 +375,32 @@ minute = NUM2INT(RARRAY_PTR(val)[2]); sec = NUM2INT(RARRAY_PTR(val)[3]); fsec = NUM2INT(RARRAY_PTR(val)[4]); - oci_lc(OCIIntervalSetDaySecond(oci8_envhp, oci8_errhp, - day, hour, minute, sec, fsec, intvl)); + if (oracle_client_version >= ORAVERNUM(9, 2, 0, 3, 0)) { + oci_lc(OCIIntervalSetDaySecond(oci8_envhp, oci8_errhp, + day, hour, minute, sec, fsec, intvl)); + } else { + /* Workaround for Bug 2227982 */ + char buf[64]; + char *sign = ""; + + if (day == 0) { + if (hour < 0) { + sign = "-"; + hour = -hour; + } else if (minute < 0) { + sign = "-"; + minute = -minute; + } else if (sec < 0) { + sign = "-"; + sec = -sec; + } else if (fsec < 0) { + sign = "-"; + fsec = -fsec; + } + } + sprintf(buf, "%s%d %02d:%02d:%02d.%09d", sign, day, hour, minute, sec, fsec); + oci_lc(OCIIntervalFromText(oci8_envhp, oci8_errhp, (text*)buf, strlen(buf), intvl)); + } return intvl; } Modified: trunk/ruby-oci8/lib/oci8/datetime.rb =================================================================== --- trunk/ruby-oci8/lib/oci8/datetime.rb 2009-10-17 14:23:12 UTC (rev 364) +++ trunk/ruby-oci8/lib/oci8/datetime.rb 2009-10-18 13:46:48 UTC (rev 365) @@ -427,21 +427,27 @@ # OCI8::BindType::IntervalYM #++ # - # This is a helper class to bind ruby's - # Integer[http://www.ruby-doc.org/core/classes/Integer.html] - # object as Oracle's INTERVAL YEAR TO MONTH datatype. + # This is a helper class to select or bind Oracle data type + # INTERVAL YEAR TO MONTH. The retrieved value is + # the number of months between two timestamps. # - # == Select + # The value can be applied to \DateTime#>> to shift months. + # It can be applied to \Time#months_since if activisupport has + # been loaded. # - # The fetched value for a INTERVAL YEAR TO MONTH column - # is an Integer[http://www.ruby-doc.org/core/classes/Integer.html] - # which means the months between two timestamps. + # === How to select INTERVAL YEAR TO MONTH # - # == Bind + # INTERVAL YEAR TO MONTH is selected as an Integer. # - # You cannot bind as INTERVAL YEAR TO MONTH implicitly. - # It must be bound explicitly with :interval_ym. + # conn.exec("select (current_timestamp - hiredate) year to month from emp") do |hired_months| + # puts "hired_months = #{hired_months}" + # end # + # == How to bind INTERVAL YEAR TO MONTH + # + # You cannot bind a bind variable as INTERVAL YEAR TO MONTH implicitly. + # It must be bound explicitly by OCI8::Cursor#bind_param. + # # # output bind variable # cursor = conn.parse(<<-EOS) # BEGIN @@ -487,51 +493,43 @@ # OCI8::BindType::IntervalDS #++ # - # This is a helper class to bind ruby's - # Rational[http://www.ruby-doc.org/core/classes/Rational.html] - # object as Oracle's INTERVAL DAY TO SECOND datatype. + # (new in 2.0) # - # == Select + # This is a helper class to select or bind Oracle data type + # INTERVAL DAY TO SECOND. The retrieved value is + # the number of seconds between two typestamps as a \Float. # - # The fetched value for a INTERVAL DAY TO SECOND column - # is a Rational[http://www.ruby-doc.org/core/classes/Rational.html] - # or an Integer[http://www.ruby-doc.org/core/classes/Integer.html]. - # The value is usable to apply to - # DateTime[http://www.ruby-doc.org/core/classes/DateTime.html]#+ and - # DateTime[http://www.ruby-doc.org/core/classes/DateTime.html]#-. + # Note that it is the number days as a \Rational if + # OCI8::BindType::IntervalDS.unit is :day or the ruby-oci8 + # version is prior to 2.0.3. # - # == Bind + # == How to bind INTERVAL DAY TO SECOND # - # You cannot bind as INTERVAL YEAR TO MONTH implicitly. - # It must be bound explicitly with :interval_ds. + # You cannot bind a bind variable as INTERVAL DAY TO SECOND + # implicitly. It must be bound explicitly by OCI8::Cursor#bind_param. # - # # output - # ts1 = DateTime.parse('1969-11-19 06:54:35 00:00') - # ts2 = DateTime.parse('1969-07-20 20:17:40 00:00') + # # output bind variable # cursor = conn.parse(<<-EOS) # BEGIN - # :itv := (:ts1 - :ts2) DAY TO SECOND; + # :interval := (:ts1 - :ts2) DAY TO SECOND(9); # END; # EOS - # cursor.bind_param(:itv, nil, :interval_ds) - # cursor.bind_param(:ts1, ts1) - # cursor.bind_param(:ts2, ts2) + # cursor.bind_param(:interval, nil, :interval_ds) + # cursor.bind_param(:ts1, DateTime.parse('1969-11-19 06:54:35 00:00')) + # cursor.bind_param(:ts2, DateTime.parse('1969-07-20 20:17:40 00:00')) # cursor.exec - # cursor[:itv] # == ts1 - ts2 + # cursor[:interval] # => 10492615.0 seconds # cursor.close # - # # input - # ts2 = DateTime.parse('1969-07-20 20:17:40 00:00') - # itv = 121 + 10.to_r/24 + 36.to_r/(24*60) + 55.to_r/(24*60*60) - # # 121 days, 10 hours, 36 minutes, 55 seconds + # # input bind variable # cursor = conn.parse(<<-EOS) # BEGIN - # :ts1 := :ts2 + :itv; + # :ts1 := :ts2 + :interval; # END; # EOS # cursor.bind_param(:ts1, nil, DateTime) - # cursor.bind_param(:ts2, ts2) - # cursor.bind_param(:itv, itv, :interval_ds) + # cursor.bind_param(:ts2, DateTime.parse('1969-07-20 20:17:40 00:00')) + # cursor.bind_param(:interval, 10492615.0, :interval_ds) # cursor.exec # cursor[:ts1].strftime('%Y-%m-%d %H:%M:%S') # => 1969-11-19 06:54:35 # cursor.close @@ -541,7 +539,33 @@ @@minute = @@hour / 60 @@sec = @@minute / 60 @@fsec = @@sec / 1000000000 + @@unit = :second + # call-seq: + # OCI8::BindType::IntervalDS.unit -> :second or :day + # + # (new in 2.0.3) + # + # Retrieves the unit of interval. + def self.unit + @@unit + end + + # call-seq: + # OCI8::BindType::IntervalDS.unit = :second or :day + # + # (new in 2.0.3) + # + # Changes the unit of interval. :second is the default. + def self.unit=(val) + case val + when :second, :day + @@unit = val + else + raise 'unit should be :second or :day' + end + end + def set(val) # :nodoc: unless val.nil? if val < 0 @@ -550,10 +574,17 @@ else is_minus = false end - day, val = val.divmod 1 - hour, val = (val * 24).divmod 1 - minute, val = (val * 60).divmod 1 - sec, val = (val * 60).divmod 1 + if @@unit == :second + day, val = val.divmod 86400 + hour, val = val.divmod 3600 + minute, val = val.divmod 60 + sec, val = val.divmod 1 + else + day, val = val.divmod 1 + hour, val = (val * 24).divmod 1 + minute, val = (val * 60).divmod 1 + sec, val = (val * 60).divmod 1 + end fsec, val = (val * 1000000000).divmod 1 if is_minus day = - day @@ -571,7 +602,12 @@ val = super() return nil if val.nil? day, hour, minute, sec, fsec = val - day + (hour * @@hour) + (minute * @@minute) + (sec * @@sec) + (fsec * @@fsec) + if @@unit == :second + fsec = fsec / 1000000000.0 + day * 86400 + hour * 3600 + minute * 60 + sec + fsec + else + day + (hour * @@hour) + (minute * @@minute) + (sec * @@sec) + (fsec * @@fsec) + end end end # OCI8::BindType::IntervalDS end Modified: trunk/ruby-oci8/test/test_datetime.rb =================================================================== --- trunk/ruby-oci8/test/test_datetime.rb 2009-10-17 14:23:12 UTC (rev 364) +++ trunk/ruby-oci8/test/test_datetime.rb 2009-10-18 13:46:48 UTC (rev 365) @@ -13,6 +13,31 @@ end end + def string_to_time(str) + /(\d+)-(\d+)-(\d+) ?(?:(\d+):(\d+):(\d+))?(?:\.(\d+))? ?([+-]\d+:\d+)?/ =~ str + args = [] + args << $1.to_i # year + args << $2.to_i # month + args << $3.to_i # day + args << $4.to_i if $4 # hour + args << $5.to_i if $5 # minute + if $8 + args << $6.to_i + $7.to_i.to_r / ('1' + '0' * ($7.length)).to_i + args << $8 + Time.new(*args) + else + if $6 + args << $6.to_i + end + if $7 + args << $7.to_i.to_r * 1000000 / ('1' + '0' * ($7.length)).to_i + end + # no time zone + Time.local(*args) + end + #Time.local(*str.split(/[- :\.]/).collect do |n| n.to_i; end) + end + def setup @conn = get_oci8_connection @local_timezone = timezone_string(*((::Time.now.utc_offset / 60).divmod 60)) @@ -129,7 +154,12 @@ @conn.exec(<<-EOS) do |row| SELECT TO_TIMESTAMP_TZ('#{date}', 'YYYY-MM-DD HH24:MI:SS.FF TZH:TZM') FROM dual EOS - assert_equal(DateTime.parse(date), row[0]) + expected_val = begin + string_to_time(date) + rescue + DateTime.parse(date) + end + assert_equal(expected_val, row[0]) end end end @@ -274,6 +304,7 @@ when Time assert_equal(tz, timezone_string(*((dt.utc_offset / 60).divmod 60))) when DateTime + tz = tz.gsub(/:/, '') if RUBY_VERSION <= '1.8.5' assert_equal(tz, dt.zone) else flunk "unexpedted type #{dt.class}" @@ -352,9 +383,14 @@ cursor.bind_param(:out, nil, String, 36) cursor.bind_param(:in1, nil, String, 36) cursor.bind_param(:in2, nil, :interval_ym) - [['2006-01-01', -22], - ['2006-01-01', -10], + [['2006-01-01', -25], + ['2006-01-01', -24], + ['2006-01-01', -23], + ['2006-01-01', -13], + ['2006-01-01', -12], + ['2006-01-01', -11], ['2006-01-01', +2], + ['2006-01-01', -2], ['2006-01-01', +12] ].each do |date, interval| cursor[:in1] = date @@ -388,7 +424,7 @@ - TO_TIMESTAMP('#{date2}', 'YYYY-MM-DD HH24:MI:SS.FF')) DAY(3) TO SECOND FROM dual EOS - assert_equal(DateTime.parse(date1) - DateTime.parse(date2), row[0]) + assert_in_delta(string_to_time(date1) - string_to_time(date2), row[0], 0.0000000001) end end end @@ -427,7 +463,7 @@ cursor[:in1] = date1 cursor[:in2] = date2 cursor.exec - assert_equal(DateTime.parse(date1) - DateTime.parse(date2), cursor[:out]) + assert_in_delta(string_to_time(date1) - string_to_time(date2), cursor[:out], 0.0000000001) end cursor.close end @@ -440,7 +476,7 @@ ts1 TIMESTAMP; BEGIN ts1 := TO_TIMESTAMP(:in1, 'YYYY-MM-DD HH24:MI:SS.FF'); - :out := TO_CHAR(ts1 + :in2, 'YYYY-MM-DD HH24:MI:SS.FF'); + :out := TO_CHAR(ts1 + :in2, 'YYYY-MM-DD HH24:MI:SS.FF6'); END; EOS cursor.bind_param(:out, nil, String, 36) @@ -459,11 +495,128 @@ ['2006-01-01', +1.to_r / (24*60*60)], # one second ['2006-01-01', +999999.to_r / (24*60*60*1000000)] # 0.999999 seconds ].each do |date, interval| + interval *= 86400 cursor[:in1] = date cursor[:in2] = interval cursor.exec - assert_equal(DateTime.parse(date) + interval, DateTime.parse(cursor[:out])) + assert_equal(string_to_time(date) + interval, string_to_time(cursor[:out])) end cursor.close end + + def test_days_interval_ds_select + return if $oracle_version < OCI8::ORAVER_9_0 + + [['2006-01-01', '2004-03-01'], + ['2006-01-01', '2005-03-01'], + ['2006-01-01', '2006-03-01'], + ['2006-01-01', '2007-03-01'], + ['2006-01-01', '2006-01-01 23:00:00'], + ['2006-01-01', '2006-01-01 00:59:00'], + ['2006-01-01', '2006-01-01 00:00:59'], + ['2006-01-01', '2006-01-01 00:00:00.999999'], + ['2006-01-01', '2006-01-01 23:59:59.999999'], + ['2006-01-01', '2005-12-31 23:00:00'], + ['2006-01-01', '2005-12-31 00:59:00'], + ['2006-01-01', '2005-12-31 00:00:59'], + ['2006-01-01', '2005-12-31 00:00:00.999999'], + ['2006-01-01', '2005-12-31 23:59:59.999999'] + ].each do |date1, date2| + begin + OCI8::BindType::IntervalDS.unit = :day + @conn.exec(<<-EOS) do |row| +SELECT (TO_TIMESTAMP('#{date1}', 'YYYY-MM-DD HH24:MI:SS.FF') + - TO_TIMESTAMP('#{date2}', 'YYYY-MM-DD HH24:MI:SS.FF')) DAY(3) TO SECOND + FROM dual +EOS + assert_equal(DateTime.parse(date1) - DateTime.parse(date2), row[0]) + end + ensure + OCI8::BindType::IntervalDS.unit = :second + end + end + end + + def test_days_interval_ds_out_bind + return if $oracle_version < OCI8::ORAVER_9_0 + + cursor = @conn.parse(<<-EOS) +DECLARE + ts1 TIMESTAMP; + ts2 TIMESTAMP; +BEGIN + ts1 := TO_TIMESTAMP(:in1, 'YYYY-MM-DD HH24:MI:SS.FF'); + ts2 := TO_TIMESTAMP(:in2, 'YYYY-MM-DD HH24:MI:SS.FF'); + :out := (ts1 - ts2) DAY TO SECOND(9); +END; +EOS + cursor.bind_param(:out, nil, :interval_ds) + cursor.bind_param(:in1, nil, String, 36) + cursor.bind_param(:in2, nil, String, 36) + [['2006-01-01', '2004-03-01'], + ['2006-01-01', '2005-03-01'], + ['2006-01-01', '2006-03-01'], + ['2006-01-01', '2007-03-01'], + ['2006-01-01', '2006-01-01 23:00:00'], + ['2006-01-01', '2006-01-01 00:59:00'], + ['2006-01-01', '2006-01-01 00:00:59'], + ['2006-01-01', '2006-01-01 00:00:00.999999'], + ['2006-01-01', '2006-01-01 23:59:59.999999'], + ['2006-01-01', '2005-12-31 23:00:00'], + ['2006-01-01', '2005-12-31 00:59:00'], + ['2006-01-01', '2005-12-31 00:00:59'], + ['2006-01-01', '2005-12-31 00:00:00.999999'], + ['2006-01-01', '2005-12-31 23:59:59.999999'] + ].each do |date1, date2| + begin + OCI8::BindType::IntervalDS.unit = :day + cursor[:in1] = date1 + cursor[:in2] = date2 + cursor.exec + assert_equal(DateTime.parse(date1) - DateTime.parse(date2), cursor[:out]) + ensure + OCI8::BindType::IntervalDS.unit = :second + end + end + cursor.close + end + + def test_days_interval_ds_in_bind + return if $oracle_version < OCI8::ORAVER_9_0 + + cursor = @conn.parse(<<-EOS) +DECLARE + ts1 TIMESTAMP; +BEGIN + ts1 := TO_TIMESTAMP(:in1, 'YYYY-MM-DD'); + :out := TO_CHAR(ts1 + :in2, 'YYYY-MM-DD HH24:MI:SS.FF'); +END; +EOS + cursor.bind_param(:out, nil, String, 36) + cursor.bind_param(:in1, nil, String, 36) + cursor.bind_param(:in2, nil, :interval_ds) + [['2006-01-01', -22], + ['2006-01-01', -10], + ['2006-01-01', +2], + ['2006-01-01', +12], + ['2006-01-01', -1.to_r / 24], # one hour + ['2006-01-01', -1.to_r / (24*60)], # one minute + ['2006-01-01', -1.to_r / (24*60*60)], # one second + ['2006-01-01', -999999.to_r / (24*60*60*1000000)], # 0.999999 seconds + ['2006-01-01', +1.to_r / 24], # one hour + ['2006-01-01', +1.to_r / (24*60)], # one minute + ['2006-01-01', +1.to_r / (24*60*60)], # one second + ['2006-01-01', +999999.to_r / (24*60*60*1000000)] # 0.999999 seconds + ].each do |date, interval| + begin + OCI8::BindType::IntervalDS.unit = :day + cursor[:in1] = date + cursor[:in2] = interval + cursor.exec + assert_equal(DateTime.parse(date) + interval, DateTime.parse(cursor[:out])) + ensure + OCI8::BindType::IntervalDS.unit = :second + end + end + end end # TestOCI8 From nobody at rubyforge.org Wed Oct 21 09:45:05 2009 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Wed, 21 Oct 2009 09:45:05 -0400 (EDT) Subject: [ruby-oci8-commit] [366] trunk/ruby-oci8: * NEWS: add changes between 2.0.2 and 2.0.3. Message-ID: <20091021134505.7E065197827D@rubyforge.org> Revision: 366 Author: kubo Date: 2009-10-21 09:45:04 -0400 (Wed, 21 Oct 2009) Log Message: ----------- * NEWS: add changes between 2.0.2 and 2.0.3. * VERSION, Makefile: change the version to 2.0.3. * ext/oci8/oci8.c: fix typo. * ext/oci8/apiwrap.yml: add OCIIntervalFromText() prototype. Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/Makefile trunk/ruby-oci8/NEWS trunk/ruby-oci8/VERSION trunk/ruby-oci8/ext/oci8/apiwrap.yml trunk/ruby-oci8/ext/oci8/oci8.c Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2009-10-18 13:46:48 UTC (rev 365) +++ trunk/ruby-oci8/ChangeLog 2009-10-21 13:45:04 UTC (rev 366) @@ -1,3 +1,9 @@ +2009-10-21 KUBO Takehiro + * NEWS: add changes between 2.0.2 and 2.0.3. + * VERSION, Makefile: change the version to 2.0.3. + * ext/oci8/oci8.c: fix typo. + * ext/oci8/apiwrap.yml: add OCIIntervalFromText() prototype. + 2009-10-18 KUBO Takehiro * ext/oci8/ocidatetime.c: Add workarounds for Oracle 9.2.0.1. * lib/oci8/datetime.rb: Change the unit of OCI8::BindType::IntervalDS @@ -2,3 +8,3 @@ from day to second. Add OCI8::BindType::IntervalDS.unit and - OCI8::BindType::IntervalDS.unit. + OCI8::BindType::IntervalDS.unit=. * test/test_datetime.rb: Fix tests for the above changes. Modified: trunk/ruby-oci8/Makefile =================================================================== --- trunk/ruby-oci8/Makefile 2009-10-18 13:46:48 UTC (rev 365) +++ trunk/ruby-oci8/Makefile 2009-10-21 13:45:04 UTC (rev 366) @@ -59,7 +59,7 @@ # RUBY_18 = c:\ruby RUBY_191 = c:\ruby-1.9.1 -GEMPKG = ruby-oci8-2.0.2-x86-mswin32-60.gem +GEMPKG = ruby-oci8-2.0.3-x86-mswin32-60.gem ext\oci8\oci8lib_18.so: $(RUBY_18)\bin\ruby -r fileutils -e "FileUtils.rm_rf('ruby18')" Modified: trunk/ruby-oci8/NEWS =================================================================== --- trunk/ruby-oci8/NEWS 2009-10-18 13:46:48 UTC (rev 365) +++ trunk/ruby-oci8/NEWS 2009-10-21 13:45:04 UTC (rev 366) @@ -1,3 +1,129 @@ +2.0.3: + +* Imcompatible Changes + + - Number column in a SQL statement + + Changes the default data type for number column which fit neither + Integer nor Float from OraNumber to BigDecimal. + + conn.exec("select 1.0 from dual") do |row| + p row[0] # => BigDecimal("1") if the ruby-oci8 version is 2.0.3. + # => OraNumber(1) if the version is 2.0.2. + end + + - Priority of OraNumber within numerical types + + The return types of basic arithmetic operations with other numerical + types are changed. + + 2.0.3: + OraNumber + Integer => OraNumber (OraNumber wins.) + OraNumber + Float => Float (OraNumber loses.) + OraNumber + Rational => Rational (OraNumber loses.) + OraNumber + BigDecimal => BigDecimal (OraNumber loses.) + + 2.0.2: + OraNumber + Integer => OraNumber (OraNumber wins always.) + OraNumber + Float => OraNumber + OraNumber + Rational => OraNumber + OraNumber + BigDecimal => OraNumber + + - Interval day to second + + The retrived value of Oracle data type "interval day to second" + was changed from the number of days as a Rational to the number + of seconds as a Float by default. + Use OCI8::BindType::IntervalDS.unit = :day to make it compatible + with the previous versions. + + conn.exec("select to_dsinterval('0 00:00:01') from dual") do |row| + p row[0] # => 1.0 if the version is 2.0.3 and + # OCI8::BindType::IntervalDS.unit is :second. + # => (1/86400) if the version is 2.0.3 and + # OCI8::BindType::IntervalDS.unit is :day or + # the version is 2.0.2. + end + + - Date, timestamp, timestamp with time zone data types and ruby 1.9.2 + + These data types are retrived always as Time values when the + ruby version is 1.9.2 because the Time class is enhanced to + represent any time zone and is free from year 2038 problem. + + Prior to ruby 1.9.2, if the time cannot be represented by + Unix time or the time zone is neither utc nor local, they are + retrived as DateTime values. + + - Non-blocking mode and ruby 1.9 + + non-blocking mode is enabled by default when the ruby is 1.9. + +* New Features + + - BigDecimal and Rational are availabe as bind values. + + - New methods OCI8#module=, OCI8#action= and OCI8#client_info= are added. + + These methods change the module name, the action name and the client_info + in the current session respectively. + + After Oracle 10g client, these don't perform network round trips. + The change is reflected to the server by the next round trip such as + OCI8#exec, OCI8#ping, etc. + + Prior to Oracle 10g client, these call PL/SQL functions such as + DBMS_APPLICATION_INFO.SET_MODULE, DBMS_APPLICATION_INFO.SET_ACTION, + and DBMS_APPLICATION_INFO.SET_CLIENT_INFO internally. + The change is reflected immediately by a network round trip. + + - OCI8::BindType.default_timezone + + The default time zone of Time or DateTime values. + This parameter is used only when + (1) date values are fetched and the Oracle client version is 8.x + or + (2) object types have date data type attributes. + + Note that if the Oracle client version is 9i or upper, the time + zone is determined by the session time zone. The default value + is local time zone. You can change it to GMT by executing the + following SQL statement for each connection. + + alter session set time_zone = '00:00' + +* Other specification changes + + - Add a global function OraNumber(obj) as a shortcut of OraNumber.new(obj) + as Rational and BigDecimal do. + + - Fix to accept nil attribute in object type's + constructors. This works only for simple data types such as number, + string. But it doesn't for complex types such as object types. + (requested by Remi Gagnon) + + - add DATE datatype support in object types. + + - Change OCI8::LOB#write to accept an object which is not a String and + doesn't respond to 'to_str' as IO#write does. + (requested by Christopher Jones) + + - Change the initial polling interval of + non-blocking mode for ruby 1.8 from 100 msec to 10 msec, which + is same with ruby-oci8 1.0. + +* Fixed installation issues. + + - Fix oraconf.rb for ruby 1.8.5 with Oracle 8.x which needs some object + files to link with. + (reported by Jayson Cena) + + - Fix oraconf.rb for ruby 1.9.2 preview1. + (pointed by Raimonds Simanovskis) + + - Fix oraconf.rb to compile for AIX instant clients. + (reported by Kazuya Teramoto) + 2.0.2: * add new methods Modified: trunk/ruby-oci8/VERSION =================================================================== --- trunk/ruby-oci8/VERSION 2009-10-18 13:46:48 UTC (rev 365) +++ trunk/ruby-oci8/VERSION 2009-10-21 13:45:04 UTC (rev 366) @@ -1 +1 @@ -2.0.2 +2.0.3 Modified: trunk/ruby-oci8/ext/oci8/apiwrap.yml =================================================================== --- trunk/ruby-oci8/ext/oci8/apiwrap.yml 2009-10-18 13:46:48 UTC (rev 365) +++ trunk/ruby-oci8/ext/oci8/apiwrap.yml 2009-10-21 13:45:04 UTC (rev 366) @@ -1077,6 +1077,15 @@ - ub4 *fsec # round trip: 0 (not docmented. I guess.) +OCIIntervalFromText: + :version: 900 + :args: - dvoid *hndl + - OCIError *err + - CONST OraText *inpstr + - size_t str_len + - OCIInterval *result + +# round trip: 0 (not docmented. I guess.) OCIDateTimeGetTimeZoneOffset: :version: 900 :args: - dvoid *hndl Modified: trunk/ruby-oci8/ext/oci8/oci8.c =================================================================== --- trunk/ruby-oci8/ext/oci8/oci8.c 2009-10-18 13:46:48 UTC (rev 365) +++ trunk/ruby-oci8/ext/oci8/oci8.c 2009-10-21 13:45:04 UTC (rev 366) @@ -721,7 +721,7 @@ * * (new in 2.0.3) * - * Sets the name of the current current module. This information is + * Sets the name of the current module. This information is * stored in the V$SESSION view and is also stored in the V$SQL view * and the V$SQLAREA view when a SQL statement is executed and the SQL * statement is first parsed in the Oracle server. From nobody at rubyforge.org Wed Oct 21 09:53:18 2009 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Wed, 21 Oct 2009 09:53:18 -0400 (EDT) Subject: [ruby-oci8-commit] [368] branches/ruby-oci8-1.0: * NEWS: add changes between 1.0.6 and 1.0.7. Message-ID: <20091021135318.1D9B51D78851@rubyforge.org> Revision: 368 Author: kubo Date: 2009-10-21 09:53:17 -0400 (Wed, 21 Oct 2009) Log Message: ----------- * NEWS: add changes between 1.0.6 and 1.0.7. * VERSION: change version to 1.0.7. Modified Paths: -------------- branches/ruby-oci8-1.0/ChangeLog branches/ruby-oci8-1.0/NEWS branches/ruby-oci8-1.0/VERSION Modified: branches/ruby-oci8-1.0/ChangeLog =================================================================== --- branches/ruby-oci8-1.0/ChangeLog 2009-10-21 13:50:01 UTC (rev 367) +++ branches/ruby-oci8-1.0/ChangeLog 2009-10-21 13:53:17 UTC (rev 368) @@ -1,3 +1,7 @@ +2009-10-21 KUBO Takehiro + * NEWS: add changes between 1.0.6 and 1.0.7. + * VERSION: change version to 1.0.7. + 2009-10-04 KUBO Takehiro * ext/oci8/oraconf.rb: 1. Fix for ruby 1.8.5 with Oracle 8.x which needs some object Modified: branches/ruby-oci8-1.0/NEWS =================================================================== --- branches/ruby-oci8-1.0/NEWS 2009-10-21 13:50:01 UTC (rev 367) +++ branches/ruby-oci8-1.0/NEWS 2009-10-21 13:53:17 UTC (rev 368) @@ -1,3 +1,16 @@ +1.0.7: + +* change OCI8::LOB#write to accept an object which is not a String and + doesn't respond to 'to_str' as IO#write does. + (requested by Christopher Jones) + +* fix oraconf.rb for AIX instant clients. + (reported by Kazuya Teramoto) + +* fix oraconf.rb for ruby 1.8.5 with Oracle 8.x which needs some object + files to link with. + (reported by Jayson Cena) + 1.0.6: * fix a problem when compiling for Oracle 8.0. Modified: branches/ruby-oci8-1.0/VERSION =================================================================== --- branches/ruby-oci8-1.0/VERSION 2009-10-21 13:50:01 UTC (rev 367) +++ branches/ruby-oci8-1.0/VERSION 2009-10-21 13:53:17 UTC (rev 368) @@ -1 +1 @@ -1.0.6 \ No newline at end of file +1.0.7 \ No newline at end of file From nobody at rubyforge.org Fri Oct 23 03:24:50 2009 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Fri, 23 Oct 2009 03:24:50 -0400 (EDT) Subject: [ruby-oci8-commit] [370] trunk/ruby-oci8: * ext/oci8/extconf.rb, ext/oci8/oci8.h, ext/oci8/ oci8lib.c, Message-ID: <20091023072450.CE449185826A@rubyforge.org> Revision: 370 Author: kubo Date: 2009-10-23 03:24:50 -0400 (Fri, 23 Oct 2009) Log Message: ----------- * ext/oci8/extconf.rb, ext/oci8/oci8.h, ext/oci8/oci8lib.c, ext/oci8/ocihandle.c: add ocihandle.c and move OCIHandle definitions from oci8lib.c to the file. Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/ext/oci8/extconf.rb trunk/ruby-oci8/ext/oci8/oci8.h trunk/ruby-oci8/ext/oci8/oci8lib.c Added Paths: ----------- trunk/ruby-oci8/ext/oci8/ocihandle.c Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2009-10-21 13:57:34 UTC (rev 369) +++ trunk/ruby-oci8/ChangeLog 2009-10-23 07:24:50 UTC (rev 370) @@ -1,3 +1,8 @@ +2009-10-23 KUBO Takehiro + * ext/oci8/extconf.rb, ext/oci8/oci8.h, ext/oci8/oci8lib.c, + ext/oci8/ocihandle.c: add ocihandle.c and move OCIHandle + definitions from oci8lib.c to the file. + 2009-10-21 KUBO Takehiro * NEWS: add changes between 2.0.2 and 2.0.3. * VERSION, Makefile: change the version to 2.0.3. Modified: trunk/ruby-oci8/ext/oci8/extconf.rb =================================================================== --- trunk/ruby-oci8/ext/oci8/extconf.rb 2009-10-21 13:57:34 UTC (rev 369) +++ trunk/ruby-oci8/ext/oci8/extconf.rb 2009-10-23 07:24:50 UTC (rev 370) @@ -82,7 +82,7 @@ $libs = saved_libs end -$objs = ["oci8lib.o", "env.o", "error.o", "oci8.o", +$objs = ["oci8lib.o", "env.o", "error.o", "oci8.o", "ocihandle.o", "stmt.o", "bind.o", "metadata.o", "attr.o", "lob.o", "oradate.o", "ocinumber.o", "ocidatetime.o", "object.o", "apiwrap.o", Modified: trunk/ruby-oci8/ext/oci8/oci8.h =================================================================== --- trunk/ruby-oci8/ext/oci8/oci8.h 2009-10-21 13:57:34 UTC (rev 369) +++ trunk/ruby-oci8/ext/oci8/oci8.h 2009-10-23 07:24:50 UTC (rev 370) @@ -389,6 +389,7 @@ extern ID oci8_id_get; extern ID oci8_id_set; extern ID oci8_id_keys; +extern ID oci8_id_oci8_class; extern int oci8_in_finalizer; extern VALUE oci8_cOCIHandle; void oci8_base_free(oci8_base_t *base); @@ -412,6 +413,9 @@ NORETURN(void oci8_do_raise_init_error(const char *file, int line)); sb4 oci8_get_error_code(OCIError *errhp); +/* ocihandle.c */ +void Init_oci8_handle(void); + /* oci8.c */ VALUE Init_oci8(void); oci8_svcctx_t *oci8_get_svcctx(VALUE obj); Modified: trunk/ruby-oci8/ext/oci8/oci8lib.c =================================================================== --- trunk/ruby-oci8/ext/oci8/oci8lib.c 2009-10-21 13:57:34 UTC (rev 369) +++ trunk/ruby-oci8/ext/oci8/oci8lib.c 2009-10-23 07:24:50 UTC (rev 370) @@ -10,29 +10,18 @@ #include #endif -static oci8_base_class_t oci8_base_class = { - NULL, - NULL, - sizeof(oci8_base_t), -}; - ID oci8_id_new; ID oci8_id_get; ID oci8_id_set; ID oci8_id_keys; +ID oci8_id_oci8_class; int oci8_in_finalizer = 0; VALUE oci8_cOCIHandle; -static ID id_oci8_class; static VALUE mOCI8BindType; static VALUE cOCI8BindTypeBase; -static VALUE oci8_handle_initialize(VALUE self) -{ - rb_raise(rb_eNameError, "private method `new' called for %s:Class", rb_class2name(CLASS_OF(self))); -} - void oci8_base_free(oci8_base_t *base) { while (base->children != NULL) { @@ -49,55 +38,6 @@ base->hp.ptr = NULL; } -static VALUE oci8_handle_free(VALUE self) -{ - oci8_base_t *base = DATA_PTR(self); - - oci8_base_free(base); - return self; -} - -static void oci8_handle_mark(oci8_base_t *base) -{ - if (base->klass->mark != NULL) - base->klass->mark(base); -} - -static void oci8_handle_cleanup(oci8_base_t *base) -{ - oci8_base_free(base); - xfree(base); -} - -static VALUE oci8_s_allocate(VALUE klass) -{ - oci8_base_t *base; - const oci8_base_class_t *base_class; - VALUE superklass; - VALUE obj; - - superklass = klass; - while (!RTEST(rb_ivar_defined(superklass, id_oci8_class))) { - superklass = RCLASS_SUPER(superklass); - if (superklass == rb_cObject) - rb_raise(rb_eRuntimeError, "private method `new' called for %s:Class", rb_class2name(klass)); - } - obj = rb_ivar_get(superklass, id_oci8_class); - base_class = DATA_PTR(obj); - - base = xmalloc(base_class->size); - memset(base, 0, base_class->size); - - obj = Data_Wrap_Struct(klass, oci8_handle_mark, oci8_handle_cleanup, base); - base->self = obj; - base->klass = base_class; - base->parent = NULL; - base->next = base; - base->prev = base; - base->children = NULL; - return obj; -} - static void at_exit_func(VALUE val) { oci8_in_finalizer = 1; @@ -107,7 +47,6 @@ Init_oci8lib() { VALUE cOCI8; - VALUE obj; OCIEnv *envhp; OCIError *errhp; sword rv; @@ -121,23 +60,18 @@ } #endif - id_oci8_class = rb_intern("__oci8_class__"); oci8_id_new = rb_intern("new"); oci8_id_get = rb_intern("get"); oci8_id_set = rb_intern("set"); oci8_id_keys = rb_intern("keys"); + oci8_id_oci8_class = rb_intern("__oci8_class__"); rb_set_end_proc(at_exit_func, Qnil); Init_oci8_error(); Init_oci8_env(); /* OCIHandle class */ - oci8_cOCIHandle = rb_define_class("OCIHandle", rb_cObject); - rb_define_alloc_func(oci8_cOCIHandle, oci8_s_allocate); - rb_define_method(oci8_cOCIHandle, "initialize", oci8_handle_initialize, 0); - rb_define_method(oci8_cOCIHandle, "free", oci8_handle_free, 0); - obj = Data_Wrap_Struct(rb_cObject, 0, 0, &oci8_base_class); - rb_ivar_set(oci8_cOCIHandle, id_oci8_class, obj); + Init_oci8_handle(); /* OCI8 class */ cOCI8 = Init_oci8(); @@ -207,7 +141,7 @@ { VALUE klass = rb_define_class(name, oci8_cOCIHandle); VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, base_class); - rb_ivar_set(klass, id_oci8_class, obj); + rb_ivar_set(klass, oci8_id_oci8_class, obj); return klass; } @@ -215,7 +149,7 @@ { VALUE klass = rb_define_class_under(outer, name, oci8_cOCIHandle); VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, base_class); - rb_ivar_set(klass, id_oci8_class, obj); + rb_ivar_set(klass, oci8_id_oci8_class, obj); return klass; } @@ -223,7 +157,7 @@ { VALUE klass = rb_define_class_under(mOCI8BindType, name, cOCI8BindTypeBase); VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, (void*)bind_class); - rb_ivar_set(klass, id_oci8_class, obj); + rb_ivar_set(klass, oci8_id_oci8_class, obj); return klass; } Added: trunk/ruby-oci8/ext/oci8/ocihandle.c =================================================================== --- trunk/ruby-oci8/ext/oci8/ocihandle.c (rev 0) +++ trunk/ruby-oci8/ext/oci8/ocihandle.c 2009-10-23 07:24:50 UTC (rev 370) @@ -0,0 +1,82 @@ +/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */ +/* + * ocihandle.c + * + * Copyright (C) 2009 KUBO Takehiro + * + * implement OCIHandle + * + */ +#include "oci8.h" + +static oci8_base_class_t oci8_base_class = { + NULL, + NULL, + sizeof(oci8_base_t), +}; + +static VALUE oci8_handle_initialize(VALUE self) +{ + rb_raise(rb_eNameError, "private method `new' called for %s:Class", rb_class2name(CLASS_OF(self))); +} + +static VALUE oci8_handle_free(VALUE self) +{ + oci8_base_t *base = DATA_PTR(self); + + oci8_base_free(base); + return self; +} + +static void oci8_handle_mark(oci8_base_t *base) +{ + if (base->klass->mark != NULL) + base->klass->mark(base); +} + +static void oci8_handle_cleanup(oci8_base_t *base) +{ + oci8_base_free(base); + xfree(base); +} + +static VALUE oci8_s_allocate(VALUE klass) +{ + oci8_base_t *base; + const oci8_base_class_t *base_class; + VALUE superklass; + VALUE obj; + + superklass = klass; + while (!RTEST(rb_ivar_defined(superklass, oci8_id_oci8_class))) { + superklass = RCLASS_SUPER(superklass); + if (superklass == rb_cObject) + rb_raise(rb_eRuntimeError, "private method `new' called for %s:Class", rb_class2name(klass)); + } + obj = rb_ivar_get(superklass, oci8_id_oci8_class); + base_class = DATA_PTR(obj); + + base = xmalloc(base_class->size); + memset(base, 0, base_class->size); + + obj = Data_Wrap_Struct(klass, oci8_handle_mark, oci8_handle_cleanup, base); + base->self = obj; + base->klass = base_class; + base->parent = NULL; + base->next = base; + base->prev = base; + base->children = NULL; + return obj; +} + +void Init_oci8_handle(void) +{ + VALUE obj; + + oci8_cOCIHandle = rb_define_class("OCIHandle", rb_cObject); + rb_define_alloc_func(oci8_cOCIHandle, oci8_s_allocate); + rb_define_method(oci8_cOCIHandle, "initialize", oci8_handle_initialize, 0); + rb_define_method(oci8_cOCIHandle, "free", oci8_handle_free, 0); + obj = Data_Wrap_Struct(rb_cObject, 0, 0, &oci8_base_class); + rb_ivar_set(oci8_cOCIHandle, oci8_id_oci8_class, obj); +} From nobody at rubyforge.org Mon Oct 26 10:58:14 2009 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Mon, 26 Oct 2009 10:58:14 -0400 (EDT) Subject: [ruby-oci8-commit] [371] trunk/ruby-oci8: * NEW: fix typo. Message-ID: <20091026145814.E94941588060@rubyforge.org> Revision: 371 Author: kubo Date: 2009-10-26 10:58:14 -0400 (Mon, 26 Oct 2009) Log Message: ----------- * NEW: fix typo. * dist-files, ext/oci8/.document: add ocihandle.c. * ext/oci8/ocihandle.c: add private methods OCIHandle#attr_get_*, OCIHandle#attr_set_* and their rdoc comments. Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/NEWS trunk/ruby-oci8/dist-files trunk/ruby-oci8/ext/oci8/.document trunk/ruby-oci8/ext/oci8/ocihandle.c Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2009-10-23 07:24:50 UTC (rev 370) +++ trunk/ruby-oci8/ChangeLog 2009-10-26 14:58:14 UTC (rev 371) @@ -1,3 +1,9 @@ +2009-10-26 KUBO Takehiro + * NEW: fix typo. + * dist-files, ext/oci8/.document: add ocihandle.c. + * ext/oci8/ocihandle.c: add private methods OCIHandle#attr_get_*, + OCIHandle#attr_set_* and their rdoc comments. + 2009-10-23 KUBO Takehiro * ext/oci8/extconf.rb, ext/oci8/oci8.h, ext/oci8/oci8lib.c, ext/oci8/ocihandle.c: add ocihandle.c and move OCIHandle Modified: trunk/ruby-oci8/NEWS =================================================================== --- trunk/ruby-oci8/NEWS 2009-10-23 07:24:50 UTC (rev 370) +++ trunk/ruby-oci8/NEWS 2009-10-26 14:58:14 UTC (rev 371) @@ -1,6 +1,6 @@ 2.0.3: -* Imcompatible Changes +* Incompatible Changes - Number column in a SQL statement Modified: trunk/ruby-oci8/dist-files =================================================================== --- trunk/ruby-oci8/dist-files 2009-10-23 07:24:50 UTC (rev 370) +++ trunk/ruby-oci8/dist-files 2009-10-26 14:58:14 UTC (rev 371) @@ -31,6 +31,7 @@ ext/oci8/oci8.h ext/oci8/oci8lib.c ext/oci8/ocidatetime.c +ext/oci8/ocihandle.c ext/oci8/ocinumber.c ext/oci8/oraconf.rb ext/oci8/oradate.c Modified: trunk/ruby-oci8/ext/oci8/.document =================================================================== --- trunk/ruby-oci8/ext/oci8/.document 2009-10-23 07:24:50 UTC (rev 370) +++ trunk/ruby-oci8/ext/oci8/.document 2009-10-26 14:58:14 UTC (rev 371) @@ -3,6 +3,7 @@ #env.c oci8.c +ocihandle.c bind.c stmt.c encoding.c Modified: trunk/ruby-oci8/ext/oci8/ocihandle.c =================================================================== --- trunk/ruby-oci8/ext/oci8/ocihandle.c 2009-10-23 07:24:50 UTC (rev 370) +++ trunk/ruby-oci8/ext/oci8/ocihandle.c 2009-10-26 14:58:14 UTC (rev 371) @@ -9,6 +9,23 @@ */ #include "oci8.h" +#ifdef WIN32 +#define MAGIC_NUMBER 0xDEAFBEAFDEAFBEAFui64; +#else +#define MAGIC_NUMBER 0xDEAFBEAFDEAFBEAFull; +#endif + +static long check_data_range(VALUE val, long min, long max, const char *type) +{ + long lval = NUM2LONG(val); + if (lval < min || max < lval) { + rb_raise(rb_eRangeError, "integer %ld too %s to convert to `%s'", + lval, lval < 0 ? "small" : "big", type); + } + return lval; +} + + static oci8_base_class_t oci8_base_class = { NULL, NULL, @@ -20,6 +37,14 @@ rb_raise(rb_eNameError, "private method `new' called for %s:Class", rb_class2name(CLASS_OF(self))); } +/* + * call-seq: + * free() + * + * (new in 2.0.0) + * + * Clears the object internal structure and its dependents. + */ static VALUE oci8_handle_free(VALUE self) { oci8_base_t *base = DATA_PTR(self); @@ -69,14 +94,609 @@ return obj; } +/* + * call-seq: + * attr_get_ub1(attr_type) -> fixnum + * + * (new in 2.0.4) + * + * Gets the value of an attribute as `ub1' datatype. + */ +static VALUE attr_get_ub1(VALUE self, VALUE attr_type) +{ + oci8_base_t *base = DATA_PTR(self); + union { + ub1 value; + ub8 dummy; /* padding for incorrect attrtype to protect the stack */ + } v; + + v.dummy = MAGIC_NUMBER; + Check_Type(attr_type, T_FIXNUM); + oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp)); + return INT2FIX(v.value); +} + +/* + * call-seq: + * attr_get_ub2(attr_type) -> fixnum + * + * (new in 2.0.4) + * + * Gets the value of an attribute as `ub2' datatype. + */ +static VALUE attr_get_ub2(VALUE self, VALUE attr_type) +{ + oci8_base_t *base = DATA_PTR(self); + union { + ub2 value; + ub8 dummy; /* padding for incorrect attrtype to protect the stack */ + } v; + + v.dummy = MAGIC_NUMBER; + Check_Type(attr_type, T_FIXNUM); + oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp)); + return INT2FIX(v.value); +} + +/* + * call-seq: + * attr_get_ub4(attr_type) -> integer + * + * (new in 2.0.4) + * + * Gets the value of an attribute as `ub4' datatype. + */ +static VALUE attr_get_ub4(VALUE self, VALUE attr_type) +{ + oci8_base_t *base = DATA_PTR(self); + union { + ub4 value; + ub8 dummy; /* padding for incorrect attrtype to protect the stack */ + } v; + + v.dummy = MAGIC_NUMBER; + Check_Type(attr_type, T_FIXNUM); + oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp)); + return UINT2NUM(v.value); +} + +/* + * call-seq: + * attr_get_ub8(attr_type) -> integer + * + * (new in 2.0.4) + * + * Gets the value of an attribute as `ub8' datatype. + */ +static VALUE attr_get_ub8(VALUE self, VALUE attr_type) +{ + oci8_base_t *base = DATA_PTR(self); + union { + ub8 value; + ub8 dummy; + } v; + + v.dummy = MAGIC_NUMBER; + Check_Type(attr_type, T_FIXNUM); + oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp)); + return ULL2NUM(v.value); +} + +/* + * call-seq: + * attr_get_sb1(attr_type) -> fixnum + * + * (new in 2.0.4) + * + * Gets the value of an attribute as `sb1' datatype. + */ +static VALUE attr_get_sb1(VALUE self, VALUE attr_type) +{ + oci8_base_t *base = DATA_PTR(self); + union { + sb1 value; + ub8 dummy; /* padding for incorrect attrtype to protect the stack */ + } v; + + v.dummy = MAGIC_NUMBER; + Check_Type(attr_type, T_FIXNUM); + oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp)); + return INT2FIX(v.value); +} + +/* + * call-seq: + * attr_get_sb2(attr_type) -> fixnum + * + * (new in 2.0.4) + * + * Gets the value of an attribute as `sb2' datatype. + */ +static VALUE attr_get_sb2(VALUE self, VALUE attr_type) +{ + oci8_base_t *base = DATA_PTR(self); + union { + sb2 value; + ub8 dummy; /* padding for incorrect attrtype to protect the stack */ + } v; + + v.dummy = MAGIC_NUMBER; + Check_Type(attr_type, T_FIXNUM); + oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp)); + return INT2FIX(v.value); +} + +/* + * call-seq: + * attr_get_sb4(attr_type) -> integer + * + * (new in 2.0.4) + * + * Gets the value of an attribute as `sb4' datatype. + */ +static VALUE attr_get_sb4(VALUE self, VALUE attr_type) +{ + oci8_base_t *base = DATA_PTR(self); + union { + sb4 value; + ub8 dummy; + } v; + + v.dummy = MAGIC_NUMBER; + Check_Type(attr_type, T_FIXNUM); + oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp)); + return INT2NUM(v.value); +} + +/* + * call-seq: + * attr_get_sb8(attr_type) -> integer + * + * (new in 2.0.4) + * + * Gets the value of an attribute as `sb8' datatype. + */ +static VALUE attr_get_sb8(VALUE self, VALUE attr_type) +{ + oci8_base_t *base = DATA_PTR(self); + union { + sb8 value; + ub8 dummy; /* padding for incorrect attrtype to protect the stack */ + } v; + + v.dummy = MAGIC_NUMBER; + Check_Type(attr_type, T_FIXNUM); + oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp)); + return LL2NUM(v.value); +} + +/* + * call-seq: + * attr_get_boolean(attr_type) -> true or false + * + * (new in 2.0.4) + * + * Gets the value of an attribute as `boolean' datatype. + */ +static VALUE attr_get_boolean(VALUE self, VALUE attr_type) +{ + oci8_base_t *base = DATA_PTR(self); + union { + boolean value; + ub8 dummy; /* padding for incorrect attrtype to protect the stack */ + } v; + + v.dummy = MAGIC_NUMBER; + Check_Type(attr_type, T_FIXNUM); + oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp)); + return v.value ? Qtrue : Qfalse; +} + +/* + * call-seq: + * attr_get_string(attr_type) -> string + * + * (new in 2.0.4) + * + * Gets the value of an attribute as `oratext *' datatype. + * The return value is converted to Encoding.default_internal or + * tagged with OCI8.encoding when the ruby version is 1.9. + * + * Caution: If the specified attr_type's datatype is not a + * pointer type, it causes a segmentation fault. + */ +static VALUE attr_get_string(VALUE self, VALUE attr_type) +{ + oci8_base_t *base = DATA_PTR(self); + union { + char *value; + ub8 dummy; /* padding for incorrect attrtype to protect the stack */ + } v; + ub4 size = 0; + + v.dummy = MAGIC_NUMBER; + Check_Type(attr_type, T_FIXNUM); + oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, &size, FIX2INT(attr_type), oci8_errhp)); + return rb_external_str_new_with_enc(v.value, size, oci8_encoding); +} + +/* + * call-seq: + * attr_get_binary(attr_type) -> string + * + * (new in 2.0.4) + * + * Gets the value of an attribute as `ub1 *' datatype. + * The return value is tagged with ASCII-8BIT when the ruby version is 1.9. + * + * Caution: If the specified attr_type's datatype is not a + * pointer type, it causes a segmentation fault. + */ +static VALUE attr_get_binary(VALUE self, VALUE attr_type) +{ + oci8_base_t *base = DATA_PTR(self); + union { + char *value; + ub8 dummy; /* padding for incorrect attrtype to protect the stack */ + } v; + ub4 size = 0; + + v.dummy = 0; + Check_Type(attr_type, T_FIXNUM); + oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, &size, FIX2INT(attr_type), oci8_errhp)); + return rb_tainted_str_new(v.value, size); +} + +/* + * call-seq: + * attr_get_integer(attr_type) -> integer + * + * (new in 2.0.4) + * + * Gets the value of an attribute as `ub1 *' datatype. + * The return value is converted to Integer from internal Oracle NUMBER format. + * + * Caution: If the specified attr_type's datatype is not a + * pointer type, it causes a segmentation fault. + */ +static VALUE attr_get_integer(VALUE self, VALUE attr_type) +{ + oci8_base_t *base = DATA_PTR(self); + union { + OCINumber *value; + ub8 dummy; /* padding for incorrect attrtype to protect the stack */ + } v; + ub4 size = 0; + + v.dummy = 0; + Check_Type(attr_type, T_FIXNUM); + oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, &size, FIX2INT(attr_type), oci8_errhp)); + return oci8_make_integer(v.value, oci8_errhp); +} + +/* + * call-seq: + * attr_set_ub1(attr_type, attr_value) + * + * (new in 2.0.4) + * + * Sets the value of an attribute as `ub1' datatype. + * + * Caution: If the specified attr_type's datatype is a + * pointer type, it causes a segmentation fault. + */ +static VALUE attr_set_ub1(VALUE self, VALUE attr_type, VALUE val) +{ + oci8_base_t *base = DATA_PTR(self); + ub1 value; + + /* validate arguments */ + Check_Type(attr_type, T_FIXNUM); + value = (ub1)check_data_range(val, 0, UCHAR_MAX, "ub1"); + /* set attribute */ + oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp)); + return self; +} + +/* + * call-seq: + * attr_set_ub2(attr_type, attr_value) + * + * (new in 2.0.4) + * + * Sets the value of an attribute as `ub2' datatype. + * + * Caution: If the specified attr_type's datatype is a + * pointer type, it causes a segmentation fault. + */ +static VALUE attr_set_ub2(VALUE self, VALUE attr_type, VALUE val) +{ + oci8_base_t *base = DATA_PTR(self); + ub2 value; + + /* validate arguments */ + Check_Type(attr_type, T_FIXNUM); + value = (ub2)check_data_range(val, 0, USHRT_MAX, "ub2"); + /* set attribute */ + oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp)); + return self; +} + +/* + * call-seq: + * attr_set_ub4(attr_type, attr_value) + * + * (new in 2.0.4) + * + * Sets the value of an attribute as `ub4' datatype. + * + * Caution: If the specified attr_type's datatype is a + * pointer type, it causes a segmentation fault. + */ +static VALUE attr_set_ub4(VALUE self, VALUE attr_type, VALUE val) +{ + oci8_base_t *base = DATA_PTR(self); + ub4 value; + + /* validate arguments */ + Check_Type(attr_type, T_FIXNUM); + value = NUM2UINT(val); + /* set attribute */ + oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp)); + return self; +} + +/* + * call-seq: + * attr_set_ub8(attr_type, attr_value) + * + * (new in 2.0.4) + * + * Sets the value of an attribute as `ub8' datatype. + * + * Caution: If the specified attr_type's datatype is a + * pointer type, it causes a segmentation fault. + */ +static VALUE attr_set_ub8(VALUE self, VALUE attr_type, VALUE val) +{ + oci8_base_t *base = DATA_PTR(self); + ub8 value; + + /* validate arguments */ + Check_Type(attr_type, T_FIXNUM); + value = NUM2ULL(val); + /* set attribute */ + oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp)); + return self; +} + +/* + * call-seq: + * attr_set_sb1(attr_type, attr_value) + * + * (new in 2.0.4) + * + * Sets the value of an attribute as `sb1' datatype. + * + * Caution: If the specified attr_type's datatype is a + * pointer type, it causes a segmentation fault. + */ +static VALUE attr_set_sb1(VALUE self, VALUE attr_type, VALUE val) +{ + oci8_base_t *base = DATA_PTR(self); + sb1 value; + + /* validate arguments */ + Check_Type(attr_type, T_FIXNUM); + value = (sb1)check_data_range(val, CHAR_MIN, CHAR_MAX, "sb1"); + /* set attribute */ + oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp)); + return self; +} + +/* + * call-seq: + * attr_set_sb2(attr_type, attr_value) + * + * (new in 2.0.4) + * + * Sets the value of an attribute as `sb2' datatype. + * + * Caution: If the specified attr_type's datatype is a + * pointer type, it causes a segmentation fault. + */ +static VALUE attr_set_sb2(VALUE self, VALUE attr_type, VALUE val) +{ + oci8_base_t *base = DATA_PTR(self); + sb2 value; + + /* validate arguments */ + Check_Type(attr_type, T_FIXNUM); + value = (sb2)check_data_range(val, SHRT_MIN, SHRT_MAX, "sb2"); + /* set attribute */ + oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp)); + return self; +} + +/* + * call-seq: + * attr_set_sb4(attr_type, attr_value) + * + * (new in 2.0.4) + * + * Sets the value of an attribute as `sb4' datatype. + * + * Caution: If the specified attr_type's datatype is a + * pointer type, it causes a segmentation fault. + */ +static VALUE attr_set_sb4(VALUE self, VALUE attr_type, VALUE val) +{ + oci8_base_t *base = DATA_PTR(self); + sb4 value; + + /* validate arguments */ + Check_Type(attr_type, T_FIXNUM); + value = NUM2INT(val); + /* set attribute */ + oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp)); + return self; +} + +/* + * call-seq: + * attr_set_sb8(attr_type, attr_value) + * + * (new in 2.0.4) + * + * Sets the value of an attribute as `sb8' datatype. + * + * Caution: If the specified attr_type's datatype is a + * pointer type, it causes a segmentation fault. + */ +static VALUE attr_set_sb8(VALUE self, VALUE attr_type, VALUE val) +{ + oci8_base_t *base = DATA_PTR(self); + sb8 value; + + /* validate arguments */ + Check_Type(attr_type, T_FIXNUM); + value = NUM2LL(val); + /* set attribute */ + oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp)); + return self; +} + +/* + * call-seq: + * attr_set_boolean(attr_type, attr_value) + * + * (new in 2.0.4) + * + * Sets the value of an attribute as `boolean' datatype. + * + * Caution: If the specified attr_type's datatype is a + * pointer type, it causes a segmentation fault. + */ +static VALUE attr_set_boolean(VALUE self, VALUE attr_type, VALUE val) +{ + oci8_base_t *base = DATA_PTR(self); + boolean value; + + /* validate arguments */ + Check_Type(attr_type, T_FIXNUM); + value = RTEST(val) ? TRUE : FALSE; + /* set attribute */ + oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp)); + return self; +} + +/* + * call-seq: + * attr_set_string(attr_type, string_value) + * + * (new in 2.0.4) + * + * Sets the value of an attribute as `oratext *' datatype. + * +string_value+ is converted to OCI8.encoding before it is set + * when the ruby version is 1.9. + */ +static VALUE attr_set_string(VALUE self, VALUE attr_type, VALUE val) +{ + oci8_base_t *base = DATA_PTR(self); + + /* validate arguments */ + Check_Type(attr_type, T_FIXNUM); + OCI8SafeStringValue(val); + /* set attribute */ + oci_lc(OCIAttrSet(base->hp.ptr, base->type, RSTRING_PTR(val), RSTRING_LEN(val), FIX2INT(attr_type), oci8_errhp)); + return self; +} + +/* + * call-seq: + * attr_set_binary(attr_type, string_value) + * + * (new in 2.0.4) + * + * Sets the value of an attribute as `ub1 *' datatype. + */ +static VALUE attr_set_binary(VALUE self, VALUE attr_type, VALUE val) +{ + oci8_base_t *base = DATA_PTR(self); + + /* validate arguments */ + Check_Type(attr_type, T_FIXNUM); + SafeStringValue(val); + /* set attribute */ + oci_lc(OCIAttrSet(base->hp.ptr, base->type, RSTRING_PTR(val), RSTRING_LEN(val), FIX2INT(attr_type), oci8_errhp)); + return self; +} + +/* + * call-seq: + * attr_set_integer(attr_type, number) + * + * (new in 2.0.4) + * + * Sets the value of an attribute as `ub1 *' datatype. + * +number+ is converted to internal Oracle NUMBER format before + * it is set. + */ +static VALUE attr_set_integer(VALUE self, VALUE attr_type, VALUE val) +{ + oci8_base_t *base = DATA_PTR(self); + OCINumber value; + + /* validate arguments */ + Check_Type(attr_type, T_FIXNUM); + oci8_set_integer(&value, val, oci8_errhp); + /* set attribute */ + oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp)); + return self; +} + void Init_oci8_handle(void) { VALUE obj; + /* + * (new in 2.0.0) + * + * OCIHandle is the abstract base class of OCI handles and + * OCI descriptors; opaque data types of Oracle Call Interface. + */ oci8_cOCIHandle = rb_define_class("OCIHandle", rb_cObject); rb_define_alloc_func(oci8_cOCIHandle, oci8_s_allocate); - rb_define_method(oci8_cOCIHandle, "initialize", oci8_handle_initialize, 0); - rb_define_method(oci8_cOCIHandle, "free", oci8_handle_free, 0); + rb_define_method_nodoc(oci8_cOCIHandle, "initialize", oci8_handle_initialize, 0); + rb_define_private_method(oci8_cOCIHandle, "free", oci8_handle_free, 0); obj = Data_Wrap_Struct(rb_cObject, 0, 0, &oci8_base_class); rb_ivar_set(oci8_cOCIHandle, oci8_id_oci8_class, obj); + + /* methods to get attributes */ + rb_define_private_method(oci8_cOCIHandle, "attr_get_ub1", attr_get_ub1, 1); + rb_define_private_method(oci8_cOCIHandle, "attr_get_ub2", attr_get_ub2, 1); + rb_define_private_method(oci8_cOCIHandle, "attr_get_ub4", attr_get_ub4, 1); + rb_define_private_method(oci8_cOCIHandle, "attr_get_ub8", attr_get_ub8, 1); + rb_define_private_method(oci8_cOCIHandle, "attr_get_sb1", attr_get_sb1, 1); + rb_define_private_method(oci8_cOCIHandle, "attr_get_sb2", attr_get_sb2, 1); + rb_define_private_method(oci8_cOCIHandle, "attr_get_sb4", attr_get_sb4, 1); + rb_define_private_method(oci8_cOCIHandle, "attr_get_sb8", attr_get_sb8, 1); + rb_define_private_method(oci8_cOCIHandle, "attr_get_boolean", attr_get_boolean, 1); + rb_define_private_method(oci8_cOCIHandle, "attr_get_string", attr_get_string, 1); + rb_define_private_method(oci8_cOCIHandle, "attr_get_binary", attr_get_binary, 1); + rb_define_private_method(oci8_cOCIHandle, "attr_get_integer", attr_get_integer, 1); + + /* methods to set attributes */ + rb_define_private_method(oci8_cOCIHandle, "attr_set_ub1", attr_set_ub1, 2); + rb_define_private_method(oci8_cOCIHandle, "attr_set_ub2", attr_set_ub2, 2); + rb_define_private_method(oci8_cOCIHandle, "attr_set_ub4", attr_set_ub4, 2); + rb_define_private_method(oci8_cOCIHandle, "attr_set_ub8", attr_set_ub8, 2); + rb_define_private_method(oci8_cOCIHandle, "attr_set_sb1", attr_set_sb1, 2); + rb_define_private_method(oci8_cOCIHandle, "attr_set_sb2", attr_set_sb2, 2); + rb_define_private_method(oci8_cOCIHandle, "attr_set_sb4", attr_set_sb4, 2); + rb_define_private_method(oci8_cOCIHandle, "attr_set_sb8", attr_set_sb8, 2); + rb_define_private_method(oci8_cOCIHandle, "attr_set_boolean", attr_set_boolean, 2); + rb_define_private_method(oci8_cOCIHandle, "attr_set_string", attr_set_string, 2); + rb_define_private_method(oci8_cOCIHandle, "attr_set_binary", attr_set_binary, 2); + rb_define_private_method(oci8_cOCIHandle, "attr_set_integer", attr_set_integer, 2); }