# HG changeset patch # User Adam Chlipala # Date 1292869364 18000 # Node ID 703c2c94afd5fbf832331fa4fb0c12ad3a8a4f85 # Parent 74d35d9a5d16706ab1d5bc104d5901b5d1205214 Use proper string time format for SQLite diff -r 74d35d9a5d16 -r 703c2c94afd5 include/urweb.h --- 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 diff -r 74d35d9a5d16 -r 703c2c94afd5 src/c/urweb.c --- 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 ""; } +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 ""; +} + 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) { diff -r 74d35d9a5d16 -r 703c2c94afd5 src/sqlite.sml --- 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, ", diff -r 74d35d9a5d16 -r 703c2c94afd5 tests/sqliteTime.ur --- /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 => {[r.Dates.Date]}
); + return {ds} + end + +fun main () = + return
diff -r 74d35d9a5d16 -r 703c2c94afd5 tests/sqliteTime.urp --- /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 diff -r 74d35d9a5d16 -r 703c2c94afd5 tests/sqliteTime.urs --- /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