summaryrefslogtreecommitdiff
path: root/src/sql.sml
diff options
context:
space:
mode:
Diffstat (limited to 'src/sql.sml')
-rw-r--r--src/sql.sml82
1 files changed, 54 insertions, 28 deletions
diff --git a/src/sql.sml b/src/sql.sml
index 91e303c3..59b4eac6 100644
--- a/src/sql.sml
+++ b/src/sql.sml
@@ -1,4 +1,4 @@
-structure Sql = struct
+structure Sql :> SQL = struct
open Mono
@@ -20,24 +20,30 @@ datatype exp =
| Recd of (string * exp) list
| Proj of exp * string
-datatype reln =
- Known
- | Sql of string
- | PCon0 of string
- | PCon1 of string
- | Eq
+datatype cmp =
+ Eq
| Ne
| Lt
| Le
| Gt
| Ge
+datatype reln =
+ Known
+ | Sql of string
+ | PCon0 of string
+ | PCon1 of string
+ | Cmp of cmp
+
+datatype lop =
+ And
+ | Or
+
datatype prop =
True
| False
| Unknown
- | And of prop * prop
- | Or of prop * prop
+ | Lop of lop * prop * prop
| Reln of reln * exp list
| Cond of exp * prop
@@ -177,14 +183,14 @@ val uw_ident = wrapP ident (fn s => if String.isPrefix "uw_" s andalso size s >=
else
NONE)
-val field = wrap (follow t_ident
- (follow (const ".")
- uw_ident))
- (fn (t, ((), f)) => (t, f))
+val field = wrap (follow (opt (follow t_ident (const ".")))
+ uw_ident)
+ (fn (SOME (t, ()), f) => (t, f)
+ | (NONE, f) => ("T", f)) (* Should probably deal with this MySQL/SQLite case better some day. *)
datatype Rel =
- Exps of exp * exp -> prop
- | Props of prop * prop -> prop
+ RCmp of cmp
+ | RLop of lop
datatype sqexp =
SqConst of Prim.t
@@ -200,7 +206,7 @@ datatype sqexp =
| Unmodeled
| Null
-fun cmp s r = wrap (const s) (fn () => Exps (fn (e1, e2) => Reln (r, [e1, e2])))
+fun cmp s r = wrap (const s) (fn () => RCmp r)
val sqbrel = altL [cmp "=" Eq,
cmp "<>" Ne,
@@ -208,8 +214,8 @@ val sqbrel = altL [cmp "=" Eq,
cmp "<" Lt,
cmp ">=" Ge,
cmp ">" Gt,
- wrap (const "AND") (fn () => Props And),
- wrap (const "OR") (fn () => Props Or)]
+ wrap (const "AND") (fn () => RLop Or),
+ wrap (const "OR") (fn () => RLop And)]
datatype ('a, 'b) sum = inl of 'a | inr of 'b
@@ -238,7 +244,7 @@ fun string chs =
end
else
NONE
- | _ => NONE
+ | _ => NONE
val prim =
altL [wrap (follow (wrapP (follow (keep Char.isDigit) (follow (const ".") (keep Char.isDigit)))
@@ -267,7 +273,25 @@ fun sqlify chs =
((PCon (_, PConFfi {mod = "Basis", con = "False", ...}, NONE), _),
(EPrim (Prim.String (Prim.Normal, "FALSE")), _))], _), _) :: chs =>
SOME (e, chs)
-
+
+ | _ => NONE
+
+fun sqlifySqlcache chs =
+ case chs of
+ (* Could have variables as well as FFIs. *)
+ Exp (e as (ERel _, _)) :: chs => SOME (e, chs)
+ (* If it is an FFI, match the entire expression. *)
+ | Exp (e as (EFfiApp ("Basis", f, [(_, _)]), _)) :: chs =>
+ if String.isPrefix "sqlify" f then
+ SOME (e, chs)
+ else
+ NONE
+ | Exp (ECase (e, [((PCon (_, PConFfi {mod = "Basis", con = "True", ...}, NONE), _),
+ (EPrim (Prim.String (Prim.Normal, "TRUE")), _)),
+ ((PCon (_, PConFfi {mod = "Basis", con = "False", ...}, NONE), _),
+ (EPrim (Prim.String (Prim.Normal, "FALSE")), _))], _), _) :: chs =>
+ SOME (e, chs)
+
| _ => NONE
fun constK s = wrap (const s) (fn () => s)
@@ -281,6 +305,8 @@ val funcName = altL [constK "COUNT",
val unmodeled = altL [const "COUNT(*)",
const "CURRENT_TIMESTAMP"]
+val sqlcacheMode = ref false;
+
fun sqexp chs =
log "sqexp"
(altL [wrap prim SqConst,
@@ -292,7 +318,7 @@ fun sqexp chs =
wrap known SqKnown,
wrap func SqFunc,
wrap unmodeled (fn () => Unmodeled),
- wrap sqlify Inj,
+ wrap (if !sqlcacheMode then sqlifySqlcache else sqlify) Inj,
wrap (follow (const "COALESCE(") (follow sqexp (follow (const ",")
(follow (keep (fn ch => ch <> #")")) (const ")")))))
(fn ((), (e, _)) => e),
@@ -317,7 +343,7 @@ fun sqexp chs =
and known chs = wrap (follow known' (follow (const "(") (follow sqexp (const ")"))))
(fn ((), ((), (e, ()))) => e) chs
-
+
and func chs = wrap (follow funcName (follow (const "(") (follow sqexp (const ")"))))
(fn (f, ((), (e, ()))) => (f, e)) chs
@@ -396,22 +422,22 @@ val insert = log "insert"
val delete = log "delete"
(wrap (follow (const "DELETE FROM ")
(follow uw_ident
- (follow (const " AS T_T WHERE ")
+ (follow (follow (opt (const " AS T_T")) (const " WHERE "))
sqexp)))
- (fn ((), (tab, ((), es))) => (tab, es)))
+ (fn ((), (tab, (_, es))) => (tab, es)))
val setting = log "setting"
- (wrap (follow uw_ident (follow (const " = ") sqexp))
- (fn (f, ((), e)) => (f, e)))
+ (wrap (follow uw_ident (follow (const " = ") sqexp))
+ (fn (f, ((), e)) => (f, e)))
val update = log "update"
(wrap (follow (const "UPDATE ")
(follow uw_ident
- (follow (const " AS T_T SET ")
+ (follow (follow (opt (const " AS T_T")) (const " SET "))
(follow (list setting)
(follow (ws (const "WHERE "))
sqexp)))))
- (fn ((), (tab, ((), (fs, ((), e))))) =>
+ (fn ((), (tab, (_, (fs, ((), e))))) =>
(tab, fs, e)))
val dml = log "dml"