changeset 11661:1b4e81051b66 octave-forge

Add converter for timestamp.
author i7tiol
date Sat, 27 Apr 2013 19:17:33 +0000
parents cbff4e8a8af8
children fbd81057dab0
files main/database/NEWS main/database/doc/dev-postgresql/timeformats.txt main/database/inst/pq_exec_params.m main/database/src/converters.cc main/database/src/converters.h
diffstat 5 files changed, 142 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/main/database/NEWS	Sat Apr 27 17:58:18 2013 +0000
+++ b/main/database/NEWS	Sat Apr 27 19:17:33 2013 +0000
@@ -1,3 +1,5 @@
+ ** New converter for type timestamp.
+
  ** New function pq_conninfo.
 
  ** Fix for includes on Apple.
--- a/main/database/doc/dev-postgresql/timeformats.txt	Sat Apr 27 17:58:18 2013 +0000
+++ b/main/database/doc/dev-postgresql/timeformats.txt	Sat Apr 27 19:17:33 2013 +0000
@@ -1,7 +1,7 @@
 timestamp:
 
 Timestamp (8 byte, float or int) (microseconds (int) or seconds
-(float) before or after 'midnight' 2000-01-01; does not fit range?)
+(float) before or after 2000-01-01 00:00)
 
 
 timestamptz:
--- a/main/database/inst/pq_exec_params.m	Sat Apr 27 17:58:18 2013 +0000
+++ b/main/database/inst/pq_exec_params.m	Sat Apr 27 19:17:33 2013 +0000
@@ -126,6 +126,10 @@
 ## storing the 'small currency' (e.g. Cent) fraction in the last two
 ## digits
 ## @tab yes
+## @item timestamp
+## @tab 8-byte-time-value (see below), positive or negative time
+## interval from 2000-01-01 00:00.
+## @tab yes
 ## @item any array
 ## @tab Structure with fields @code{data} (holding a cell-array with
 ## entries of a type corresponding to the Postgresql element type),
@@ -150,10 +154,17 @@
 ## @tab yes
 ## @end multitable
 ##
+## 8-byte-time-value: int64 scalar, representing microseconds, if server
+## is configured for integer date/time; double scalar, representing
+## seconds, if server is configured for float date/time (deprecated).
+## There is no automatic conversion from an octave variable, an error is
+## thrown if the wrong of both types is supplied. One can use
+## @code{pq_conninfo} to query the respective server configuration.
+##
 ## Octaves @code{NA} corresponds to a Postgresql NULL value (not
 ## @code{NaN}, which is interpreted as a value of a float type!).
 ##
-## @seealso {pq_update_types}
+## @seealso {pq_update_types, pq_conninfo}
 ## @end deftypefn
 
 ## PKG_ADD: __all_db_opts__ ("pq_exec_params");
--- a/main/database/src/converters.cc	Sat Apr 27 17:58:18 2013 +0000
+++ b/main/database/src/converters.cc	Sat Apr 27 19:17:33 2013 +0000
@@ -24,6 +24,7 @@
 #include <libpq-fe.h>
 
 #include "converters.h"
+#include "pq_connection.h"
 
 // remember to adjust OCT_PQ_NUM_CONVERTERS in converters.h
 
@@ -664,6 +665,129 @@
 
 /* end type money */
 
+// helpers for time types
+
+static inline octave_value time_8byte_to_octave (const char *c, bool int_dt)
+{
+  if (int_dt)
+    {
+      return octave_value (octave_int64 (int64_t (be64toh (*((int64_t *) c)))));
+    }
+  else
+    {
+      union
+      {
+        double d;
+        int64_t i;
+      }
+      swap;
+
+      swap.i = be64toh (*((int64_t *) c));
+
+      return octave_value (swap.d);
+    }
+}
+
+static inline int time_8byte_from_octave (const octave_value &ov,
+                                          oct_pq_dynvec_t &val,
+                                          bool int_dt)
+{
+  if (int_dt)
+    {
+      // don't convert automatically because of possible overflow
+      if (ov.is_float_type ())
+        {
+          error ("floating point octave_value provided for 8-byte time value, but postgresql is configured for int64");
+          return 1;
+        }
+
+      int64_t i8 = ov.int64_scalar_value ();
+
+      if (error_state)
+        {
+          error ("can not convert octave_value to int64 time value");
+          return 1;
+        }
+
+      OCT_PQ_PUT(val, int64_t, htobe64 (i8))
+
+      return 0;
+    }
+  else
+    {
+      // don't convert automatically because of possible loss of accuracy
+      if (ov.is_integer_type ())
+        {
+          error ("integer type octave_value provided for 8-byte time value, but postgresql is configured for double");
+          return 1;
+        }
+
+      union
+      {
+        double d;
+        int64_t i;
+      }
+      swap;
+
+      swap.d = ov.double_value ();
+
+      if (error_state)
+        {
+          error ("can not convert octave_value to double time value");
+          return 1;
+        }
+
+      OCT_PQ_PUT(val, int64_t, htobe64 (swap.i))
+
+      return 0;
+    }
+}
+
+// end helpers for time types
+
+/* type timestamp */
+
+int to_octave_str_timestamp (const octave_pq_connection &conn,
+                             const char *c, octave_value &ov, int nb)
+{
+  return 1;
+}
+
+int to_octave_bin_timestamp (const octave_pq_connection &conn,
+                             const char *c, octave_value &ov, int nb)
+{
+  ov = time_8byte_to_octave (c, conn.integer_datetimes);
+
+  return 0;
+}
+
+int from_octave_str_timestamp (const octave_pq_connection &conn,
+                               const octave_value &ov, oct_pq_dynvec_t &val)
+{
+  return 1;
+}
+
+int from_octave_bin_timestamp (const octave_pq_connection &conn,
+                               const octave_value &ov, oct_pq_dynvec_t &val)
+{
+  return (time_8byte_from_octave (ov, val, conn.integer_datetimes));
+}
+
+oct_pq_conv_t conv_timestamp = {0,
+                                0,
+                                oct_pq_el_oids_t (),
+                                oct_pq_conv_cache_t (),
+                                false,
+                                false,
+                                false,
+                                "timestamp",
+                                &to_octave_str_timestamp,
+                                &to_octave_bin_timestamp,
+                                &from_octave_str_timestamp,
+                                &from_octave_bin_timestamp};
+
+/* end type timestamp */
+
 oct_pq_conv_t *t_conv_ptrs[OCT_PQ_NUM_CONVERTERS] = {&conv_bool,
                                                      &conv_oid,
                                                      &conv_float8,
@@ -676,6 +800,7 @@
                                                      &conv_int2,
                                                      &conv_int4,
                                                      &conv_int8,
-                                                     &conv_money};
+                                                     &conv_money,
+                                                     &conv_timestamp};
 
 oct_pq_conv_ptrs_t conv_ptrs (OCT_PQ_NUM_CONVERTERS, t_conv_ptrs);
--- a/main/database/src/converters.h	Sat Apr 27 17:58:18 2013 +0000
+++ b/main/database/src/converters.h	Sat Apr 27 19:17:33 2013 +0000
@@ -32,7 +32,7 @@
 
 #include "wrap_endian.h"
 
-#define OCT_PQ_NUM_CONVERTERS 13
+#define OCT_PQ_NUM_CONVERTERS 14
 
 typedef std::vector<char> oct_pq_dynvec_t;