Browse Source

Merge branch 'bind-timestamp-now' into async-integration

Anton Lebedevich 13 years ago
parent
commit
9a7df2bd0a
4 changed files with 20 additions and 1 deletions
  1. 2 0
      README
  2. 6 0
      src/pgsql_fdatetime.erl
  3. 6 0
      src/pgsql_idatetime.erl
  4. 6 1
      test_src/pgsql_tests.erl

+ 2 - 0
README

@@ -120,6 +120,8 @@ Original epgsql API
 
   record      = {int2, time, text, ...} (decode only)
 
+  timestamp and timestamptz parameters can take erlang:now() format {MegaSeconds, Seconds, MicroSeconds}
+
 * Errors
 
   Errors originating from the PostgreSQL backend are returned as {error, #error{}},

+ 6 - 0
src/pgsql_fdatetime.erl

@@ -7,6 +7,7 @@
 -include("pgsql_binary.hrl").
 
 -define(postgres_epoc_jdate, 2451545).
+-define(postgres_epoc_secs, 946684800).
 
 -define(mins_per_hour, 60).
 -define(secs_per_day, 86400.0).
@@ -23,7 +24,9 @@ decode(interval, <<N:1/big-float-unit:64, D:?int32, M:?int32>>) -> {f2time(N), D
 encode(date, D)         -> <<4:?int32, (date2j(D) - ?postgres_epoc_jdate):1/big-signed-unit:32>>;
 encode(time, T)         -> <<8:?int32, (time2f(T)):1/big-float-unit:64>>;
 encode(timetz, {T, TZ}) -> <<12:?int32, (time2f(T)):1/big-float-unit:64, TZ:?int32>>;
+encode(timestamp, TS = {_, _, _})   -> <<8:?int32, (now2f(TS)):1/big-float-unit:64>>;
 encode(timestamp, TS)   -> <<8:?int32, (timestamp2f(TS)):1/big-float-unit:64>>;
+encode(timestamptz, TS = {_, _, _})   -> <<8:?int32, (now2f(TS)):1/big-float-unit:64>>;
 encode(timestamptz, TS) -> <<8:?int32, (timestamp2f(TS)):1/big-float-unit:64>>;
 encode(interval, {T, D, M}) -> <<16:?int32, (time2f(T)):1/big-float-unit:64, D:?int32, M:?int32>>.
 
@@ -94,6 +97,9 @@ timestamp2f({Date, Time}) ->
     D = date2j(Date) - ?postgres_epoc_jdate,
     D * ?secs_per_day + time2f(Time).
 
+now2f({MegaSecs, Secs, MicroSecs}) ->
+    MegaSecs * 1000000 + Secs + MicroSecs / 1000000.0 - ?postgres_epoc_secs.
+
 tmodulo(T, U) ->
     case T < 0 of
         true  -> Q = ceiling(T / U);

+ 6 - 0
src/pgsql_idatetime.erl

@@ -7,6 +7,7 @@
 -include("pgsql_binary.hrl").
 
 -define(postgres_epoc_jdate, 2451545).
+-define(postgres_epoc_usecs, 946684800000000).
 
 -define(mins_per_hour, 60).
 -define(secs_per_minute, 60).
@@ -26,7 +27,9 @@ decode(interval, <<N:?int64, D:?int32, M:?int32>>) -> {i2time(N), D, M}.
 encode(date, D)         -> <<4:?int32, (date2j(D) - ?postgres_epoc_jdate):?int32>>;
 encode(time, T)         -> <<8:?int32, (time2i(T)):?int64>>;
 encode(timetz, {T, TZ}) -> <<12:?int32, (time2i(T)):?int64, TZ:?int32>>;
+encode(timestamp, TS = {_, _, _})   -> <<8:?int32, (now2i(TS)):?int64>>;
 encode(timestamp, TS)   -> <<8:?int32, (timestamp2i(TS)):?int64>>;
+encode(timestamptz, TS = {_, _, _})   -> <<8:?int32, (now2i(TS)):?int64>>;
 encode(timestamptz, TS) -> <<8:?int32, (timestamp2i(TS)):?int64>>;
 encode(interval, {T, D, M}) -> <<16:?int32, (time2i(T)):?int64, D:?int32, M:?int32>>.
 
@@ -88,6 +91,9 @@ timestamp2i({Date, Time}) ->
     D = date2j(Date) - ?postgres_epoc_jdate,
     D * ?usecs_per_day + time2i(Time).
 
+now2i({MegaSecs, Secs, MicroSecs}) ->
+    (MegaSecs * 1000000 + Secs) * 1000000 + MicroSecs - ?postgres_epoc_usecs.
+
 tmodulo(T, U) ->
     case T div U of
         0 -> {T, 0};

+ 6 - 1
test_src/pgsql_tests.erl

@@ -456,7 +456,8 @@ date_time_type_test(Module) ->
               check_type(Module, timetz, "'00:01:02-01'", {{0,1,2.0},1*60*60},
                          [{{0,0,0.0},0}, {{24,0,0.0},-13*60*60}]),
               check_type(Module, timestamp, "'2008-01-02 03:04:05'", {{2008,1,2},{3,4,5.0}},
-                         [{{-4712,1,1},{0,0,0.0}}, {{MaxTsDate,12,31}, {23,59,59.0}}]),
+                         [{{-4712,1,1},{0,0,0.0}}, {{MaxTsDate,12,31}, {23,59,59.0}}, {1322,334285,440966}]),
+              check_type(Module, timestamptz, "'2011-01-02 03:04:05+3'", {{2011, 1, 2}, {0, 4, 5.0}}, [{1324,875970,286983}]),
               check_type(Module, interval, "'1 hour 2 minutes 3.1 seconds'", {{1,2,3.1},0,0},
                          [{{0,0,0.0},0,-178000000 * 12}, {{0,0,0.0},0,178000000 * 12}])
       end).
@@ -727,6 +728,10 @@ check_type(Module, Type, In, Out, Values, Column) ->
 compare(_Type, null, null) -> true;
 compare(float4, V1, V2)    -> abs(V2 - V1) < 0.000001;
 compare(float8, V1, V2)    -> abs(V2 - V1) < 0.000000000000001;
+compare(Type, V1 = {_, _, MS}, {D2, {H2, M2, S2}}) when Type == timestamp;
+                                                        Type == timestamptz ->
+    {D1, {H1, M1, S1}} = calendar:now_to_universal_time(V1),
+    ({D1, H1, M1} =:= {D2, H2, M2}) and (abs(S1 + MS/1000000 - S2) < 0.000000000000001);
 compare(_Type, V1, V2)     -> V1 =:= V2.
 
 %% flush mailbox