changeset 1352:703c2c94afd5

Use proper string time format for SQLite
author Adam Chlipala <adam@chlipala.net>
date Mon, 20 Dec 2010 13:22:44 -0500
parents 74d35d9a5d16
children e9cf053108ed
files include/urweb.h src/c/urweb.c src/sqlite.sml tests/sqliteTime.ur tests/sqliteTime.urp tests/sqliteTime.urs
diffstat 6 files changed, 94 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/include/urweb.h	Mon Dec 20 09:34:10 2010 -0500
+++ b/include/urweb.h	Mon Dec 20 13:22:44 2010 -0500
@@ -295,4 +295,8 @@
 
 failure_kind uw_runCallback(uw_context, void (*callback)(uw_context));
 
+uw_Basis_string uw_Basis_timeToStringf(uw_context, const char *fmt, uw_Basis_time);
+uw_Basis_time uw_Basis_stringToTimef(uw_context, const char *fmt, uw_Basis_string);
+uw_Basis_time uw_Basis_stringToTimef_error(uw_context, const char *fmt, uw_Basis_string);
+
 #endif
--- a/src/c/urweb.c	Mon Dec 20 09:34:10 2010 -0500
+++ b/src/c/urweb.c	Mon Dec 20 13:22:44 2010 -0500
@@ -2055,6 +2055,7 @@
 
 #define TIME_FMT "%x %X"
 #define TIME_FMT_PG "%Y-%m-%d %T"
+#define TIME_FMT_PG "%Y-%m-%d %T"
 
 uw_Basis_string uw_Basis_htmlifyTime(uw_context ctx, uw_Basis_time t) {
   size_t len;
@@ -2560,6 +2561,21 @@
     return "<Invalid time>";
 }
 
+uw_Basis_string uw_Basis_timeToStringf(uw_context ctx, const char *fmt, uw_Basis_time t) {
+  size_t len;
+  char *r;
+  struct tm stm;
+
+  if (localtime_r(&t, &stm)) {
+    uw_check_heap(ctx, TIMES_MAX);
+    r = ctx->heap.front;
+    len = strftime(r, TIMES_MAX, fmt, &stm);
+    ctx->heap.front += len+1;
+    return r;
+  } else
+    return "<Invalid time>";
+}
+
 uw_Basis_int *uw_Basis_stringToInt(uw_context ctx, uw_Basis_string s) {
   char *endptr;
   uw_Basis_int n = strtoll(s, &endptr, 10);
@@ -2643,6 +2659,19 @@
   }
 }
 
+uw_Basis_time *uw_Basis_stringToTimef(uw_context ctx, const char *fmt, uw_Basis_string s) {
+  char *end = strchr(s, 0);
+  struct tm stm;
+
+  if (strptime(s, fmt, &stm) == end) {
+    uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
+    *r = mktime(&stm);
+    return r;
+  }
+  else
+    return NULL;
+}
+
 uw_Basis_int uw_Basis_stringToInt_error(uw_context ctx, uw_Basis_string s) {
   char *endptr;
   uw_Basis_int n = strtoll(s, &endptr, 10);
@@ -2704,6 +2733,31 @@
     uw_error(ctx, FATAL, "Can't parse bool: %s", s);
 }
 
+uw_Basis_time uw_Basis_unsqlTime(uw_context ctx, uw_Basis_string s) {
+  char *dot = strchr(s, '.'), *end = strchr(s, 0);
+  struct tm stm = {};
+
+  if (dot) {
+    *dot = 0;
+    if (strptime(s, TIME_FMT_PG, &stm)) {
+      *dot = '.';
+      return mktime(&stm);
+    }
+    else {
+      *dot = '.';
+      uw_error(ctx, FATAL, "Can't parse time: %s", s);
+    }
+  }
+  else {
+    if (strptime(s, TIME_FMT_PG, &stm) == end) {
+      return mktime(&stm);
+    } else if (strptime(s, TIME_FMT, &stm) == end) {
+      return mktime(&stm);
+    } else
+      uw_error(ctx, FATAL, "Can't parse time: %s", s);
+  }
+}
+
 uw_Basis_time uw_Basis_stringToTime_error(uw_context ctx, uw_Basis_string s) {
   char *dot = strchr(s, '.'), *end = strchr(s, 0);
   struct tm stm = {};
@@ -2729,29 +2783,14 @@
   }
 }
 
-uw_Basis_time uw_Basis_unsqlTime(uw_context ctx, uw_Basis_string s) {
-  char *dot = strchr(s, '.'), *end = strchr(s, 0);
+uw_Basis_time uw_Basis_stringToTimef_error(uw_context ctx, const char *fmt, uw_Basis_string s) {
+  char *end = strchr(s, 0);
   struct tm stm = {};
 
-  if (dot) {
-    *dot = 0;
-    if (strptime(s, TIME_FMT_PG, &stm)) {
-      *dot = '.';
-      return mktime(&stm);
-    }
-    else {
-      *dot = '.';
-      uw_error(ctx, FATAL, "Can't parse time: %s", s);
-    }
-  }
-  else {
-    if (strptime(s, TIME_FMT_PG, &stm) == end) {
-      return mktime(&stm);
-    } else if (strptime(s, TIME_FMT, &stm) == end) {
-      return mktime(&stm);
-    } else
-      uw_error(ctx, FATAL, "Can't parse time: %s", s);
-  }
+  if (strptime(s, fmt, &stm) == end)
+    return mktime(&stm);
+  else
+    uw_error(ctx, FATAL, "Can't parse time: %s", s);
 }
 
 uw_Basis_blob uw_Basis_stringToBlob_error(uw_context ctx, uw_Basis_string s, size_t len) {
--- a/src/sqlite.sml	Mon Dec 20 09:34:10 2010 -0500
+++ b/src/sqlite.sml	Mon Dec 20 13:22:44 2010 -0500
@@ -402,6 +402,8 @@
              newline]
     end
 
+val fmt = "\"%Y-%m-%d %H:%M:%S\""
+
 fun p_getcol {loc, wontLeakStrings, col = i, typ = t} =
     let
         fun p_unsql t =
@@ -415,7 +417,11 @@
                     box [string "uw_strdup(ctx, (uw_Basis_string)sqlite3_column_text(stmt, ", string (Int.toString i), string "))"]
               | Char => box [string "sqlite3_column_text(stmt, ", string (Int.toString i), string ")[0]"]
               | Bool => box [string "(uw_Basis_bool)sqlite3_column_int(stmt, ", string (Int.toString i), string ")"]
-              | Time => box [string "uw_Basis_stringToTime_error(ctx, (uw_Basis_string)sqlite3_column_text(stmt, ", string (Int.toString i), string "))"]
+              | Time => box [string "uw_Basis_stringToTimef_error(ctx, ",
+                             string fmt,
+                             string ", (uw_Basis_string)sqlite3_column_text(stmt, ",
+                             string (Int.toString i),
+                             string "))"]
               | Blob => box [string "({",
                              newline,
                              string "char *data = (char *)sqlite3_column_blob(stmt, ",
@@ -591,7 +597,9 @@
                                                      string ")"]
                                       | Time => box [string "sqlite3_bind_text(stmt, ",
                                                      string (Int.toString (i + 1)),
-                                                     string ", uw_Basis_attrifyTime(ctx, ",
+                                                     string ", uw_Basis_timeToStringf(ctx, ",
+                                                     string fmt,
+                                                     string ", ",
                                                      arg,
                                                      string "), -1, SQLITE_TRANSIENT)"]
                                       | Blob => box [string "sqlite3_bind_blob(stmt, ",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/sqliteTime.ur	Mon Dec 20 13:22:44 2010 -0500
@@ -0,0 +1,14 @@
+table dates : { Date : time }
+
+fun aform () =
+    let
+        val a : time = readError "01/02/03 04:06:07"
+    in
+        dml(INSERT INTO dates (Date) VALUES ({[a]}));
+        ds <- queryX (SELECT * FROM dates)
+                     (fn r => <xml>{[r.Dates.Date]}<br/></xml>);
+        return <xml><body>{ds}</body></xml>
+    end
+
+fun main () =
+  return <xml><body><form><submit action={aform}/></form></body></xml>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/sqliteTime.urp	Mon Dec 20 13:22:44 2010 -0500
@@ -0,0 +1,5 @@
+dbms sqlite
+database /tmp/test
+sql sqliteTime.sql
+
+sqliteTime
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/sqliteTime.urs	Mon Dec 20 13:22:44 2010 -0500
@@ -0,0 +1,1 @@
+val main : unit -> transaction page