# HG changeset patch # User i7tiol # Date 1367090253 0 # Node ID 1b4e81051b66396be86b6c5f1b9ac0ff64da6176 # Parent cbff4e8a8af8933d24ad03059c5fbe0d2c4b5a4f Add converter for timestamp. diff -r cbff4e8a8af8 -r 1b4e81051b66 main/database/NEWS --- 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. diff -r cbff4e8a8af8 -r 1b4e81051b66 main/database/doc/dev-postgresql/timeformats.txt --- 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: diff -r cbff4e8a8af8 -r 1b4e81051b66 main/database/inst/pq_exec_params.m --- 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"); diff -r cbff4e8a8af8 -r 1b4e81051b66 main/database/src/converters.cc --- 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 #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); diff -r cbff4e8a8af8 -r 1b4e81051b66 main/database/src/converters.h --- 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 oct_pq_dynvec_t;