[ruby-oci8-commit] [423] trunk/ruby-oci8: * ext/oci8/ocidatetime.c, lib/oci8/datetime.rb: rename

nobody at rubyforge.org nobody at rubyforge.org
Tue Feb 1 08:04:42 EST 2011


Revision: 423
Author:   kubo
Date:     2011-02-01 08:04:42 -0500 (Tue, 01 Feb 2011)

Log Message:
-----------
* ext/oci8/ocidatetime.c, lib/oci8/datetime.rb: rename
    the name of the class to binding timestamp with time zone
    from OCITimestamp to OCITimestampTZ. OCITimestamp will be
    used for timestamp without time zone.

Modified Paths:
--------------
    branches/ruby-oci8-2.0/ChangeLog
    branches/ruby-oci8-2.0/ext/oci8/ocidatetime.c
    branches/ruby-oci8-2.0/lib/oci8/datetime.rb
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/ext/oci8/ocidatetime.c
    trunk/ruby-oci8/lib/oci8/datetime.rb

Modified: branches/ruby-oci8-2.0/ChangeLog
===================================================================
--- branches/ruby-oci8-2.0/ChangeLog	2011-01-30 14:18:54 UTC (rev 422)
+++ branches/ruby-oci8-2.0/ChangeLog	2011-02-01 13:04:42 UTC (rev 423)
@@ -1,3 +1,9 @@
+2011-02-01  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/ocidatetime.c, lib/oci8/datetime.rb: rename
+	    the name of the class to binding timestamp with time zone
+	    from OCITimestamp to OCITimestampTZ. OCITimestamp will be
+	    used for timestamp without time zone.
+
 2011-01-30  KUBO Takehiro  <kubo at jiubao.org>
 	* ext/oci8/oraconf.rb: check Oracle client's cpu type on Solaris as
 	    on Linux and Mac OS X. change error messages on Mac OS X to suggest

Modified: branches/ruby-oci8-2.0/ext/oci8/ocidatetime.c
===================================================================
--- branches/ruby-oci8-2.0/ext/oci8/ocidatetime.c	2011-01-30 14:18:54 UTC (rev 422)
+++ branches/ruby-oci8-2.0/ext/oci8/ocidatetime.c	2011-02-01 13:04:42 UTC (rev 423)
@@ -102,8 +102,38 @@
 
 #if defined RUNTIME_API_CHECK || ORACLE_CLIENT_VERSION >= ORAVER_9_0
 
-VALUE oci8_make_ocitimestamp(OCIDateTime *dttm)
+static void bind_init_elem_common(oci8_bind_t *obind, VALUE svc, ub4 type)
 {
+    ub4 idx = 0;
+    sword rv;
+
+    do {
+        rv = OCIDescriptorAlloc(oci8_envhp, (dvoid*)((dvoid**)obind->valuep + idx), type, 0, 0);
+        if (rv != OCI_SUCCESS)
+            oci8_env_raise(oci8_envhp, rv);
+    } while (++idx < obind->maxar_sz);
+}
+
+static void bind_free_common(oci8_base_t *base, ub4 type)
+{
+    oci8_bind_t *obind = (oci8_bind_t *)base;
+
+    if (obind->valuep != NULL) {
+        ub4 idx = 0;
+        void **pp = (void**)obind->valuep;
+
+        do {
+            if (pp[idx] != NULL) {
+                OCIDescriptorFree(pp[idx], type);
+                pp[idx] = NULL;
+            }
+        } while (++idx < obind->maxar_sz);
+    }
+    oci8_bind_free(base);
+}
+
+VALUE oci8_make_ocitimestamp_tz(OCIDateTime *dttm)
+{
     sb2 year;
     ub1 month;
     ub1 day;
@@ -132,7 +162,7 @@
                        have_tz ? INT2FIX(tz_minute) : Qnil);
 }
 
-OCIDateTime *oci8_set_ocitimestamp(OCIDateTime *dttm, VALUE val, VALUE svc)
+OCIDateTime *oci8_set_ocitimestamp_tz(OCIDateTime *dttm, VALUE val, VALUE svc)
 {
     long year;
     long month;
@@ -214,36 +244,13 @@
     return dttm;
 }
 
-typedef struct {
-    oci8_bind_t obind;
-    ub4 type;
-} oci8_bind_dsc_t;
-
-static void oci8_bind_dsc_free(oci8_base_t *base)
+static VALUE bind_ocitimestamp_tz_get(oci8_bind_t *obind, void *data, void *null_struct)
 {
-    oci8_bind_t *obind = (oci8_bind_t *)base;
-    ub4 type = ((oci8_bind_dsc_t *)base)->type;
-    if (obind->valuep != NULL) {
-        ub4 idx = 0;
-        void **pp = (void**)obind->valuep;
-
-        do {
-            if (pp[idx] != NULL) {
-                OCIDescriptorFree(pp[idx], type);
-                pp[idx] = NULL;
-            }
-        } while (++idx < obind->maxar_sz);
-    }
-    oci8_bind_free(base);
+    return oci8_make_ocitimestamp_tz(*(OCIDateTime **)data);
 }
 
-static VALUE bind_ocitimestamp_get(oci8_bind_t *obind, void *data, void *null_struct)
+static void bind_ocitimestamp_tz_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
 {
-    return oci8_make_ocitimestamp(*(OCIDateTime **)data);
-}
-
-static void bind_ocitimestamp_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
-{
     oci8_base_t *parent;
     oci8_base_t *svcctx;
 
@@ -259,41 +266,36 @@
                  parent, parent ? parent->type : -1,
                  svcctx, svcctx ? svcctx->type : -1);
     }
-    oci8_set_ocitimestamp(*(OCIDateTime **)data, val, svcctx->self);
+    oci8_set_ocitimestamp_tz(*(OCIDateTime **)data, val, svcctx->self);
 }
 
-static void bind_ocitimestamp_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
+static void bind_ocitimestamp_tz_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
 {
-    oci8_bind_dsc_t *obind_dsc = (oci8_bind_dsc_t *)obind;
-
     oci8_link_to_parent((oci8_base_t*)obind, (oci8_base_t*)oci8_get_svcctx(svc));
     obind->value_sz = sizeof(OCIDateTime *);
     obind->alloc_sz = sizeof(OCIDateTime *);
-    obind_dsc->type = OCI_DTYPE_TIMESTAMP_TZ;
 }
 
-static void bind_ocitimestamp_init_elem(oci8_bind_t *obind, VALUE svc)
+static void bind_ocitimestamp_tz_init_elem(oci8_bind_t *obind, VALUE svc)
 {
-    ub4 idx = 0;
-    sword rv;
+    bind_init_elem_common(obind, svc, OCI_DTYPE_TIMESTAMP_TZ);
+}
 
-    do {
-        rv = OCIDescriptorAlloc(oci8_envhp, (dvoid*)((OCIDateTime**)obind->valuep + idx), OCI_DTYPE_TIMESTAMP_TZ, 0, 0);
-        if (rv != OCI_SUCCESS)
-            oci8_env_raise(oci8_envhp, rv);
-    } while (++idx < obind->maxar_sz);
+static void bind_ocitimestamp_tz_free(oci8_base_t *base)
+{
+    bind_free_common(base, OCI_DTYPE_TIMESTAMP_TZ);
 }
 
-static const oci8_bind_class_t bind_ocitimestamp_class = {
+static const oci8_bind_class_t bind_ocitimestamp_tz_class = {
     {
         NULL,
-        oci8_bind_dsc_free,
-        sizeof(oci8_bind_dsc_t)
+        bind_ocitimestamp_tz_free,
+        sizeof(oci8_bind_t)
     },
-    bind_ocitimestamp_get,
-    bind_ocitimestamp_set,
-    bind_ocitimestamp_init,
-    bind_ocitimestamp_init_elem,
+    bind_ocitimestamp_tz_get,
+    bind_ocitimestamp_tz_set,
+    bind_ocitimestamp_tz_init,
+    bind_ocitimestamp_tz_init_elem,
     NULL,
     NULL,
     NULL,
@@ -417,23 +419,18 @@
 
 static void bind_ociinterval_ym_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
 {
-    oci8_bind_dsc_t *obind_dsc = (oci8_bind_dsc_t *)obind;
-
     obind->value_sz = sizeof(OCIInterval*);
     obind->alloc_sz = sizeof(OCIInterval*);
-    obind_dsc->type = OCI_DTYPE_INTERVAL_YM;
 }
 
 static void bind_ociinterval_ym_init_elem(oci8_bind_t *obind, VALUE svc)
 {
-    ub4 idx = 0;
-    sword rv;
+    bind_init_elem_common(obind, svc, OCI_DTYPE_INTERVAL_YM);
+}
 
-    do {
-        rv = OCIDescriptorAlloc(oci8_envhp, (dvoid*)((OCIDateTime**)obind->valuep + idx), OCI_DTYPE_INTERVAL_YM, 0, 0);
-        if (rv != OCI_SUCCESS)
-            oci8_env_raise(oci8_envhp, rv);
-    } while (++idx < obind->maxar_sz);
+static void bind_ociinterval_ym_free(oci8_base_t *base)
+{
+    bind_free_common(base, OCI_DTYPE_INTERVAL_YM);
 }
 
 static VALUE bind_ociinterval_ds_get(oci8_bind_t *obind, void *data, void *null_struct)
@@ -448,30 +445,25 @@
 
 static void bind_ociinterval_ds_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
 {
-    oci8_bind_dsc_t *obind_dsc = (oci8_bind_dsc_t *)obind;
-
     obind->value_sz = sizeof(OCIInterval *);
     obind->alloc_sz = sizeof(OCIInterval *);
-    obind_dsc->type = OCI_DTYPE_INTERVAL_DS;
 }
 
 static void bind_ociinterval_ds_init_elem(oci8_bind_t *obind, VALUE svc)
 {
-    ub4 idx = 0;
-    sword rv;
+    bind_init_elem_common(obind, svc, OCI_DTYPE_INTERVAL_DS);
+}
 
-    do {
-        rv = OCIDescriptorAlloc(oci8_envhp, (dvoid*)((OCIInterval**)obind->valuep + idx), OCI_DTYPE_INTERVAL_DS, 0, 0);
-        if (rv != OCI_SUCCESS)
-            oci8_env_raise(oci8_envhp, rv);
-    } while (++idx < obind->maxar_sz);
+static void bind_ociinterval_ds_free(oci8_base_t *base)
+{
+    bind_free_common(base, OCI_DTYPE_INTERVAL_DS);
 }
 
 static const oci8_bind_class_t bind_ociinterval_ym_class = {
     {
         NULL,
-        oci8_bind_dsc_free,
-        sizeof(oci8_bind_dsc_t)
+        bind_ociinterval_ym_free,
+        sizeof(oci8_bind_t)
     },
     bind_ociinterval_ym_get,
     bind_ociinterval_ym_set,
@@ -486,8 +478,8 @@
 static const oci8_bind_class_t bind_ociinterval_ds_class = {
     {
         NULL,
-        oci8_bind_dsc_free,
-        sizeof(oci8_bind_dsc_t)
+        bind_ociinterval_ds_free,
+        sizeof(oci8_bind_t)
     },
     bind_ociinterval_ds_get,
     bind_ociinterval_ds_set,
@@ -507,7 +499,7 @@
 
 #if defined RUNTIME_API_CHECK || ORACLE_CLIENT_VERSION >= ORAVER_9_0
     if (oracle_client_version >= ORAVER_9_0) {
-        oci8_define_bind_class("OCITimestamp", &bind_ocitimestamp_class);
+        oci8_define_bind_class("OCITimestampTZ", &bind_ocitimestamp_tz_class);
         oci8_define_bind_class("OCIIntervalYM", &bind_ociinterval_ym_class);
         oci8_define_bind_class("OCIIntervalDS", &bind_ociinterval_ds_class);
     }

Modified: branches/ruby-oci8-2.0/lib/oci8/datetime.rb
===================================================================
--- branches/ruby-oci8-2.0/lib/oci8/datetime.rb	2011-01-30 14:18:54 UTC (rev 422)
+++ branches/ruby-oci8-2.0/lib/oci8/datetime.rb	2011-02-01 13:04:42 UTC (rev 423)
@@ -38,6 +38,14 @@
         @@time_new_accepts_timezone = false # prior to ruby 1.9.2
       end
 
+      begin
+        # 2001-01-01 00:00:59.999
+        ::DateTime.civil(2001, 1, 1, 0, 0, Rational(59_999, 1000), 0)
+        @@datetime_has_fractional_second_bug = false
+      rescue ArgumentError
+        @@datetime_has_fractional_second_bug = true
+      end
+
       def self.default_timezone
         @@default_timezone
       end
@@ -162,8 +170,8 @@
           return nil if ary.nil?
 
           year, month, day, hour, minute, sec, fsec, tz_hour, tz_min = ary
-          if sec >= 59 and fsec != 0
-            # convert to a DateTime via a String as a last resort.
+          if @@datetime_has_fractional_second_bug and sec >= 59 and fsec != 0
+            # convert to a DateTime via a String as a workaround
             if tz_hour >= 0 && tz_min >= 0
               sign = ?+
             else
@@ -245,7 +253,7 @@
     end
 
     if OCI8.oracle_client_version >= ORAVER_9_0
-      class DateTimeViaOCITimestamp < OCI8::BindType::OCITimestamp # :nodoc:
+      class DateTimeViaOCITimestampTZ < OCI8::BindType::OCITimestampTZ # :nodoc:
         include OCI8::BindType::Util
 
         def set(val) # :nodoc:
@@ -257,7 +265,7 @@
         end
       end
 
-      class TimeViaOCITimestamp < OCI8::BindType::OCITimestamp # :nodoc:
+      class TimeViaOCITimestampTZ < OCI8::BindType::OCITimestampTZ # :nodoc:
         include OCI8::BindType::Util
 
         def set(val) # :nodoc:
@@ -335,7 +343,7 @@
       if OCI8.oracle_client_version >= ORAVER_9_0
         def self.create(con, val, param, max_array_size) # :nodoc:
           if true # TODO: check Oracle server version
-            DateTimeViaOCITimestamp.new(con, val, param, max_array_size)
+            DateTimeViaOCITimestampTZ.new(con, val, param, max_array_size)
           else
             DateTimeViaOCIDate.new(con, val, param, max_array_size)
           end
@@ -414,7 +422,7 @@
       if OCI8.oracle_client_version >= ORAVER_9_0
         def self.create(con, val, param, max_array_size) # :nodoc:
           if true # TODO: check Oracle server version
-            TimeViaOCITimestamp.new(con, val, param, max_array_size)
+            TimeViaOCITimestampTZ.new(con, val, param, max_array_size)
           else
             TimeViaOCIDate.new(con, val, param, max_array_size)
           end

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2011-01-30 14:18:54 UTC (rev 422)
+++ trunk/ruby-oci8/ChangeLog	2011-02-01 13:04:42 UTC (rev 423)
@@ -1,3 +1,9 @@
+2011-02-01  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/ocidatetime.c, lib/oci8/datetime.rb: rename
+	    the name of the class to binding timestamp with time zone
+	    from OCITimestamp to OCITimestampTZ. OCITimestamp will be
+	    used for timestamp without time zone.
+
 2011-01-30  KUBO Takehiro  <kubo at jiubao.org>
 	* ext/oci8/oci8.c: fix SEGV which depends on GC order.
 	* ext/oci8/oraconf.rb: check Oracle client's cpu type on Solaris as

Modified: trunk/ruby-oci8/ext/oci8/ocidatetime.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/ocidatetime.c	2011-01-30 14:18:54 UTC (rev 422)
+++ trunk/ruby-oci8/ext/oci8/ocidatetime.c	2011-02-01 13:04:42 UTC (rev 423)
@@ -102,8 +102,38 @@
 
 #if defined RUNTIME_API_CHECK || ORACLE_CLIENT_VERSION >= ORAVER_9_0
 
-VALUE oci8_make_ocitimestamp(OCIDateTime *dttm)
+static void bind_init_elem_common(oci8_bind_t *obind, VALUE svc, ub4 type)
 {
+    ub4 idx = 0;
+    sword rv;
+
+    do {
+        rv = OCIDescriptorAlloc(oci8_envhp, (dvoid*)((dvoid**)obind->valuep + idx), type, 0, 0);
+        if (rv != OCI_SUCCESS)
+            oci8_env_raise(oci8_envhp, rv);
+    } while (++idx < obind->maxar_sz);
+}
+
+static void bind_free_common(oci8_base_t *base, ub4 type)
+{
+    oci8_bind_t *obind = (oci8_bind_t *)base;
+
+    if (obind->valuep != NULL) {
+        ub4 idx = 0;
+        void **pp = (void**)obind->valuep;
+
+        do {
+            if (pp[idx] != NULL) {
+                OCIDescriptorFree(pp[idx], type);
+                pp[idx] = NULL;
+            }
+        } while (++idx < obind->maxar_sz);
+    }
+    oci8_bind_free(base);
+}
+
+VALUE oci8_make_ocitimestamp_tz(OCIDateTime *dttm)
+{
     sb2 year;
     ub1 month;
     ub1 day;
@@ -132,7 +162,7 @@
                        have_tz ? INT2FIX(tz_minute) : Qnil);
 }
 
-OCIDateTime *oci8_set_ocitimestamp(OCIDateTime *dttm, VALUE val, VALUE svc)
+OCIDateTime *oci8_set_ocitimestamp_tz(OCIDateTime *dttm, VALUE val, VALUE svc)
 {
     long year;
     long month;
@@ -214,36 +244,13 @@
     return dttm;
 }
 
-typedef struct {
-    oci8_bind_t obind;
-    ub4 type;
-} oci8_bind_dsc_t;
-
-static void oci8_bind_dsc_free(oci8_base_t *base)
+static VALUE bind_ocitimestamp_tz_get(oci8_bind_t *obind, void *data, void *null_struct)
 {
-    oci8_bind_t *obind = (oci8_bind_t *)base;
-    ub4 type = ((oci8_bind_dsc_t *)base)->type;
-    if (obind->valuep != NULL) {
-        ub4 idx = 0;
-        void **pp = (void**)obind->valuep;
-
-        do {
-            if (pp[idx] != NULL) {
-                OCIDescriptorFree(pp[idx], type);
-                pp[idx] = NULL;
-            }
-        } while (++idx < obind->maxar_sz);
-    }
-    oci8_bind_free(base);
+    return oci8_make_ocitimestamp_tz(*(OCIDateTime **)data);
 }
 
-static VALUE bind_ocitimestamp_get(oci8_bind_t *obind, void *data, void *null_struct)
+static void bind_ocitimestamp_tz_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
 {
-    return oci8_make_ocitimestamp(*(OCIDateTime **)data);
-}
-
-static void bind_ocitimestamp_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
-{
     oci8_base_t *parent;
     oci8_base_t *svcctx;
 
@@ -259,41 +266,36 @@
                  parent, parent ? parent->type : -1,
                  svcctx, svcctx ? svcctx->type : -1);
     }
-    oci8_set_ocitimestamp(*(OCIDateTime **)data, val, svcctx->self);
+    oci8_set_ocitimestamp_tz(*(OCIDateTime **)data, val, svcctx->self);
 }
 
-static void bind_ocitimestamp_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
+static void bind_ocitimestamp_tz_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
 {
-    oci8_bind_dsc_t *obind_dsc = (oci8_bind_dsc_t *)obind;
-
     oci8_link_to_parent((oci8_base_t*)obind, (oci8_base_t*)oci8_get_svcctx(svc));
     obind->value_sz = sizeof(OCIDateTime *);
     obind->alloc_sz = sizeof(OCIDateTime *);
-    obind_dsc->type = OCI_DTYPE_TIMESTAMP_TZ;
 }
 
-static void bind_ocitimestamp_init_elem(oci8_bind_t *obind, VALUE svc)
+static void bind_ocitimestamp_tz_init_elem(oci8_bind_t *obind, VALUE svc)
 {
-    ub4 idx = 0;
-    sword rv;
+    bind_init_elem_common(obind, svc, OCI_DTYPE_TIMESTAMP_TZ);
+}
 
-    do {
-        rv = OCIDescriptorAlloc(oci8_envhp, (dvoid*)((OCIDateTime**)obind->valuep + idx), OCI_DTYPE_TIMESTAMP_TZ, 0, 0);
-        if (rv != OCI_SUCCESS)
-            oci8_env_raise(oci8_envhp, rv);
-    } while (++idx < obind->maxar_sz);
+static void bind_ocitimestamp_tz_free(oci8_base_t *base)
+{
+    bind_free_common(base, OCI_DTYPE_TIMESTAMP_TZ);
 }
 
-static const oci8_bind_class_t bind_ocitimestamp_class = {
+static const oci8_bind_class_t bind_ocitimestamp_tz_class = {
     {
         NULL,
-        oci8_bind_dsc_free,
-        sizeof(oci8_bind_dsc_t)
+        bind_ocitimestamp_tz_free,
+        sizeof(oci8_bind_t)
     },
-    bind_ocitimestamp_get,
-    bind_ocitimestamp_set,
-    bind_ocitimestamp_init,
-    bind_ocitimestamp_init_elem,
+    bind_ocitimestamp_tz_get,
+    bind_ocitimestamp_tz_set,
+    bind_ocitimestamp_tz_init,
+    bind_ocitimestamp_tz_init_elem,
     NULL,
     NULL,
     NULL,
@@ -417,23 +419,18 @@
 
 static void bind_ociinterval_ym_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
 {
-    oci8_bind_dsc_t *obind_dsc = (oci8_bind_dsc_t *)obind;
-
     obind->value_sz = sizeof(OCIInterval*);
     obind->alloc_sz = sizeof(OCIInterval*);
-    obind_dsc->type = OCI_DTYPE_INTERVAL_YM;
 }
 
 static void bind_ociinterval_ym_init_elem(oci8_bind_t *obind, VALUE svc)
 {
-    ub4 idx = 0;
-    sword rv;
+    bind_init_elem_common(obind, svc, OCI_DTYPE_INTERVAL_YM);
+}
 
-    do {
-        rv = OCIDescriptorAlloc(oci8_envhp, (dvoid*)((OCIDateTime**)obind->valuep + idx), OCI_DTYPE_INTERVAL_YM, 0, 0);
-        if (rv != OCI_SUCCESS)
-            oci8_env_raise(oci8_envhp, rv);
-    } while (++idx < obind->maxar_sz);
+static void bind_ociinterval_ym_free(oci8_base_t *base)
+{
+    bind_free_common(base, OCI_DTYPE_INTERVAL_YM);
 }
 
 static VALUE bind_ociinterval_ds_get(oci8_bind_t *obind, void *data, void *null_struct)
@@ -448,30 +445,25 @@
 
 static void bind_ociinterval_ds_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
 {
-    oci8_bind_dsc_t *obind_dsc = (oci8_bind_dsc_t *)obind;
-
     obind->value_sz = sizeof(OCIInterval *);
     obind->alloc_sz = sizeof(OCIInterval *);
-    obind_dsc->type = OCI_DTYPE_INTERVAL_DS;
 }
 
 static void bind_ociinterval_ds_init_elem(oci8_bind_t *obind, VALUE svc)
 {
-    ub4 idx = 0;
-    sword rv;
+    bind_init_elem_common(obind, svc, OCI_DTYPE_INTERVAL_DS);
+}
 
-    do {
-        rv = OCIDescriptorAlloc(oci8_envhp, (dvoid*)((OCIInterval**)obind->valuep + idx), OCI_DTYPE_INTERVAL_DS, 0, 0);
-        if (rv != OCI_SUCCESS)
-            oci8_env_raise(oci8_envhp, rv);
-    } while (++idx < obind->maxar_sz);
+static void bind_ociinterval_ds_free(oci8_base_t *base)
+{
+    bind_free_common(base, OCI_DTYPE_INTERVAL_DS);
 }
 
 static const oci8_bind_class_t bind_ociinterval_ym_class = {
     {
         NULL,
-        oci8_bind_dsc_free,
-        sizeof(oci8_bind_dsc_t)
+        bind_ociinterval_ym_free,
+        sizeof(oci8_bind_t)
     },
     bind_ociinterval_ym_get,
     bind_ociinterval_ym_set,
@@ -486,8 +478,8 @@
 static const oci8_bind_class_t bind_ociinterval_ds_class = {
     {
         NULL,
-        oci8_bind_dsc_free,
-        sizeof(oci8_bind_dsc_t)
+        bind_ociinterval_ds_free,
+        sizeof(oci8_bind_t)
     },
     bind_ociinterval_ds_get,
     bind_ociinterval_ds_set,
@@ -507,7 +499,7 @@
 
 #if defined RUNTIME_API_CHECK || ORACLE_CLIENT_VERSION >= ORAVER_9_0
     if (oracle_client_version >= ORAVER_9_0) {
-        oci8_define_bind_class("OCITimestamp", &bind_ocitimestamp_class);
+        oci8_define_bind_class("OCITimestampTZ", &bind_ocitimestamp_tz_class);
         oci8_define_bind_class("OCIIntervalYM", &bind_ociinterval_ym_class);
         oci8_define_bind_class("OCIIntervalDS", &bind_ociinterval_ds_class);
     }

Modified: trunk/ruby-oci8/lib/oci8/datetime.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/datetime.rb	2011-01-30 14:18:54 UTC (rev 422)
+++ trunk/ruby-oci8/lib/oci8/datetime.rb	2011-02-01 13:04:42 UTC (rev 423)
@@ -38,6 +38,14 @@
         @@time_new_accepts_timezone = false # prior to ruby 1.9.2
       end
 
+      begin
+        # 2001-01-01 00:00:59.999
+        ::DateTime.civil(2001, 1, 1, 0, 0, Rational(59_999, 1000), 0)
+        @@datetime_has_fractional_second_bug = false
+      rescue ArgumentError
+        @@datetime_has_fractional_second_bug = true
+      end
+
       def self.default_timezone
         @@default_timezone
       end
@@ -162,8 +170,8 @@
           return nil if ary.nil?
 
           year, month, day, hour, minute, sec, fsec, tz_hour, tz_min = ary
-          if sec >= 59 and fsec != 0
-            # convert to a DateTime via a String as a last resort.
+          if @@datetime_has_fractional_second_bug and sec >= 59 and fsec != 0
+            # convert to a DateTime via a String as a workaround
             if tz_hour >= 0 && tz_min >= 0
               sign = ?+
             else
@@ -245,7 +253,7 @@
     end
 
     if OCI8.oracle_client_version >= ORAVER_9_0
-      class DateTimeViaOCITimestamp < OCI8::BindType::OCITimestamp # :nodoc:
+      class DateTimeViaOCITimestampTZ < OCI8::BindType::OCITimestampTZ # :nodoc:
         include OCI8::BindType::Util
 
         def set(val) # :nodoc:
@@ -257,7 +265,7 @@
         end
       end
 
-      class TimeViaOCITimestamp < OCI8::BindType::OCITimestamp # :nodoc:
+      class TimeViaOCITimestampTZ < OCI8::BindType::OCITimestampTZ # :nodoc:
         include OCI8::BindType::Util
 
         def set(val) # :nodoc:
@@ -335,7 +343,7 @@
       if OCI8.oracle_client_version >= ORAVER_9_0
         def self.create(con, val, param, max_array_size) # :nodoc:
           if true # TODO: check Oracle server version
-            DateTimeViaOCITimestamp.new(con, val, param, max_array_size)
+            DateTimeViaOCITimestampTZ.new(con, val, param, max_array_size)
           else
             DateTimeViaOCIDate.new(con, val, param, max_array_size)
           end
@@ -414,7 +422,7 @@
       if OCI8.oracle_client_version >= ORAVER_9_0
         def self.create(con, val, param, max_array_size) # :nodoc:
           if true # TODO: check Oracle server version
-            TimeViaOCITimestamp.new(con, val, param, max_array_size)
+            TimeViaOCITimestampTZ.new(con, val, param, max_array_size)
           else
             TimeViaOCIDate.new(con, val, param, max_array_size)
           end




More information about the ruby-oci8-commit mailing list