X-Git-Url: https://git.hcoop.net/hcoop/smlsql.git/blobdiff_plain/8ed75bdee3efeba19532d5d9d06470b98343271f..HEAD:/libpq/pg.sml diff --git a/libpq/pg.sml b/libpq/pg.sml index 63d2720..09c761a 100644 --- a/libpq/pg.sml +++ b/libpq/pg.sml @@ -25,6 +25,8 @@ struct exception Sql of string + type value = string option + fun cerrmsg con = Int32.toString (F_PQstatus.f' (C.Ptr.ro' con)) ^ ": " ^ ZString.toML' (F_PQerrorMessage.f' (C.Ptr.ro' con)) @@ -73,6 +75,12 @@ struct end end + fun makeValue v = + if C.Ptr.isNull' v then + NONE + else + SOME (ZString.toML' v) + fun fold c f b q = let val q = ZString.dupML' q @@ -96,7 +104,11 @@ struct let fun build (~1, acc) = acc | build (j, acc) = - build (j-1, ZString.toML' (F_PQgetvalue.f' (roRes, i, j)) :: acc) + build (j-1, + if F_PQgetisnull.f' (roRes, i, j) <> 0 then + NONE :: acc + else + makeValue (F_PQgetvalue.f' (roRes, i, j)) :: acc) in builder (i+1, f (build (nf-1, []), acc)) end @@ -117,18 +129,27 @@ struct type timestamp = Time.time exception Format of string - fun isNull s = s = "" + fun valueOf v = + case v of + NONE => raise Sql "Trying to read NULL value" + | SOME v => v + + fun isNull s = + case s of + NONE => true + | _ => false fun intToSql n = if n < 0 then "-" ^ Int.toString(~n) else Int.toString n - fun intFromSql "" = 0 - | intFromSql s = + fun intFromSql' "" = 0 + | intFromSql' s = (case Int.fromString s of NONE => raise Format ("Bad integer: " ^ s) | SOME n => n) + fun intFromSql v = intFromSql' (valueOf v) fun stringToSql s = let @@ -137,20 +158,21 @@ struct | xch #"\r" = "\\r" | xch c = str c in - foldl (fn (c, s) => s ^ xch c) "'" (String.explode s) ^ "'" + foldl (fn (c, s) => s ^ xch c) "E'" (String.explode s) ^ "'" end - fun stringFromSql s = s + val stringFromSql = valueOf fun realToSql s = if s < 0.0 then "-" ^ Real.toString(~s) else Real.toString s - fun realFromSql "" = 0.0 - | realFromSql s = + fun realFromSql' "" = 0.0 + | realFromSql' s = (case Real.fromString s of NONE => raise Format ("Bad real: " ^ s) | SOME r => r) + fun realFromSql v = realFromSql' (valueOf v) fun realToString s = realToSql s fun toMonth m = @@ -221,42 +243,45 @@ struct ".000000" ^ offsetStr (Date.offset d) end fun timestampToSql t = "'" ^ timestampToSqlUnquoted t ^ "'" - fun timestampFromSql s = + fun timestampFromSql' s = let val tokens = String.tokens (fn ch => ch = #"-" orelse ch = #" " orelse ch = #":" orelse ch = #"." orelse ch = #"+") s in case tokens of [year, mon, day, hour, minute, second, _, offset] => - Date.toTime (Date.date {day = intFromSql day, hour = intFromSql hour, minute = intFromSql minute, - month = toMonth (intFromSql mon), - offset = SOME (Time.fromSeconds (LargeInt.fromInt (intFromSql offset * 3600))), - second = intFromSql second div 1000, year = intFromSql year}) + Date.toTime (Date.date {day = valOf (Int.fromString day), hour = valOf (Int.fromString hour), minute = valOf (Int.fromString minute), + month = toMonth (valOf (Int.fromString mon)), + offset = SOME (Time.fromSeconds (LargeInt.fromInt (valOf (Int.fromString offset) * 3600))), + second = valOf (Int.fromString second) div 1000, year = valOf (Int.fromString year)}) | [year, mon, day, hour, minute, second, _] => - Date.toTime (Date.date {day = intFromSql day, hour = intFromSql hour, minute = intFromSql minute, - month = toMonth (intFromSql mon), + Date.toTime (Date.date {day = valOf (Int.fromString day), hour = valOf (Int.fromString hour), minute = valOf (Int.fromString minute), + month = toMonth (valOf (Int.fromString mon)), offset = NONE, - second = intFromSql second, year = intFromSql year}) + second = valOf (Int.fromString second), year = valOf (Int.fromString year)}) | [year, mon, day, hour, minute, second] => - Date.toTime (Date.date {day = intFromSql day, hour = intFromSql hour, minute = intFromSql minute, - month = toMonth (intFromSql mon), + Date.toTime (Date.date {day = valOf (Int.fromString day), hour = valOf (Int.fromString hour), minute = valOf (Int.fromString minute), + month = toMonth (valOf (Int.fromString mon)), offset = NONE, - second = intFromSql second div 1000, year = intFromSql year}) + second = valOf (Int.fromString second) div 1000, year = valOf (Int.fromString year)}) | _ => raise Format ("Invalid timestamp " ^ s) end + fun timestampFromSql v = timestampFromSql' (valueOf v) fun boolToSql true = "TRUE" | boolToSql false = "FALSE" - fun boolFromSql "FALSE" = false - | boolFromSql "f" = false - | boolFromSql "false" = false - | boolFromSql "n" = false - | boolFromSql "no" = false - | boolFromSql "0" = false - | boolFromSql "" = false - | boolFromSql _ = true + fun boolFromSql' "FALSE" = false + | boolFromSql' "f" = false + | boolFromSql' "false" = false + | boolFromSql' "n" = false + | boolFromSql' "no" = false + | boolFromSql' "0" = false + | boolFromSql' "" = false + | boolFromSql' _ = true + + fun boolFromSql v = boolFromSql' (valueOf v) end -structure PgClient = SqlClient(PgDriver) \ No newline at end of file +structure PgClient = SqlClient(PgDriver)