diff --git a/Makefile b/Makefile index 6a22b02..6cde888 100644 --- a/Makefile +++ b/Makefile @@ -2,21 +2,21 @@ INSTALL_ARGS := $(if $(PREFIX),--prefix $(PREFIX),) # Default rule default: - jbuilder build @install + dune build @install install: - jbuilder install $(INSTALL_ARGS) + dune install $(INSTALL_ARGS) uninstall: - jbuilder uninstall $(INSTALL_ARGS) + dune uninstall $(INSTALL_ARGS) reinstall: uninstall install test: - jbuilder build @runtest + dune build @runtest example: - jbuilder build examples/server.exe + dune build examples/server.exe clean: rm -rf _build diff --git a/dune-project b/dune-project new file mode 100644 index 0000000..d29a4af --- /dev/null +++ b/dune-project @@ -0,0 +1,2 @@ +(lang dune 2.0) +(name sequoia) diff --git a/mysql/dune b/mysql/dune new file mode 100644 index 0000000..96c0c28 --- /dev/null +++ b/mysql/dune @@ -0,0 +1,4 @@ +(library + (name sequoia_mysql) + (public_name sequoia-mysql) + (libraries sequoia unix)) diff --git a/mysql/jbuild b/mysql/jbuild deleted file mode 100644 index 3bfa920..0000000 --- a/mysql/jbuild +++ /dev/null @@ -1,8 +0,0 @@ -(jbuild_version 1) - -(library - ((name sequoia_mysql) - (public_name sequoia-mysql) - (libraries - (sequoia - unix)))) diff --git a/mysql/mysql.ml b/mysql/mysql.ml index 60873ae..9ac5cf4 100644 --- a/mysql/mysql.ml +++ b/mysql/mysql.ml @@ -105,7 +105,7 @@ module Field = struct | Null.Datetime (_, t) -> t | Null.Enum (_, t, _) -> t | fld -> table fld - +(* let to_string : type a b. (a, b) t -> string = function | Time (name, table) -> sprintf "%s.%s" (Table.name table) name | Timestamp (name, table) -> sprintf "%s.%s" (Table.name table) name @@ -118,7 +118,7 @@ module Field = struct | Null.Datetime (name, table) -> sprintf "%s.%s" (Table.name table) name | Null.Enum (name, table, _) -> sprintf "%s.%s" (Table.name table) name | other -> to_string other - + *) let to_string fld = let t = table fld in sprintf "%s.%s" (Table.name t) (name fld) @@ -392,7 +392,7 @@ module Expr = struct Lit (Lit.Date { base_time with year; month; day }) let datetime ?(year = 0) ?(month = 0) ?(day = 0) ?(hour = 0) ?(minute = 0) ?(second = 0) = fun _ -> - Lit (Lit.Datetime { base_time with year; month; day; minute; second }) + Lit (Lit.Datetime { year; month; day; hour; minute; second }) let enum inst = fun _ -> Lit (Lit.Enum inst) @@ -419,17 +419,17 @@ module Expr = struct let compress f = fun src -> Compress (f src) let concat f = fun src -> Concat (f src) let concat_ws sep l = fun src -> Concat_ws (sep, List.map (fun f -> f src) l) - let connection_id () = fun src -> Connection_id + let connection_id () = fun _ -> Connection_id let conv f i j = fun src -> Conv (f src, i, j) let cos f = fun src -> Cos (f src) let cot f = fun src -> Cot (f src) let count ?(distinct = false) f = fun src -> Count (f src, distinct) let crc32 f = fun src -> Crc32 (f src) - let current_date () = fun src -> Current_date - let current_time () = fun src -> Current_time - let current_timestamp () = fun src -> Current_timestamp - let current_user () = fun src -> Current_user - let database () = fun src -> Database + let current_date () = fun _ -> Current_date + let current_time () = fun _ -> Current_time + let current_timestamp () = fun _ -> Current_timestamp + let current_user () = fun _ -> Current_user + let database () = fun _ -> Database let date_of : ('s M.Select.source -> [< `Date | `Datetime] time t) -> 's M.Select.source -> [`Date] time t = fun f src -> DateFn (f src) let date_add f i u = fun src -> Date_add (f src, i, u) let date_format f fmt = fun src -> Date_format (f src, fmt) @@ -448,7 +448,7 @@ module Expr = struct let ifnull f g = fun src -> Ifnull (f src, g src) let last_day f = fun src -> Last_day (f src) let length f = fun src -> Length (f src) - let localtime () = fun src -> Localtime + let localtime () = fun _ -> Localtime let log f = fun src -> Log (f src) let log10 f = fun src -> Log10 (f src) let log2 f = fun src -> Log2 (f src) @@ -460,7 +460,7 @@ module Expr = struct let minute f = fun src -> Minute (f src) let month f = fun src -> Month (f src) let monthname f = fun src -> Monthname (f src) - let now () = fun src -> Now + let now () = fun _ -> Now let nullif f g = fun src -> Nullif (f src, g src) let ord f = fun src -> Ord (f src) let pow f = fun src -> Pow (f src) @@ -489,23 +489,23 @@ module Expr = struct let timestampdiff u f g = fun src -> Timestampdiff (u, f src, g src) let trim f = fun src -> Trim (f src) let uncompress f = fun src -> Uncompress (f src) - let utc_date () = fun src -> Utc_date - let utc_time () = fun src -> Utc_time - let utc_timestamp () = fun src -> Utc_timestamp - let uuid () = fun src -> Uuid - let uuid_short () = fun src -> Uuid_short - let week () = fun src -> Week - let weekday () = fun src -> Weekday - let weekofyear () = fun src -> Weekofyear + let utc_date () = fun _ -> Utc_date + let utc_time () = fun _ -> Utc_time + let utc_timestamp () = fun _ -> Utc_timestamp + let uuid () = fun _ -> Uuid + let uuid_short () = fun _ -> Uuid_short + let week () = fun _ -> Week + let weekday () = fun _ -> Weekday + let weekofyear () = fun _ -> Weekofyear let upper f = fun src -> Upper (f src) - let year () = fun src -> Year + let year () = fun _ -> Year let as_time f = fun src -> Cast (f src, Time) let as_timestamp f = fun src -> Cast (f src, Timestamp) let as_date f = fun src -> Cast (f src, Date) let as_datetime f = fun src -> Cast (f src, Datetime) - let rec build + let build : type a. handover:handover -> build_step -> a t -> build_step = fun ~handover st e -> let build_param = build_param D.placeholder in @@ -543,7 +543,7 @@ module Expr = struct | Collation e -> fn "COLLATION(" [e] ")" | Compress e -> fn "COMPRESS(" [e] ")" | Concat l -> fn "CONCAT(" l ")" - | Concat_ws (s, l) -> fn "CONCAT_WS" l ")" + | Concat_ws (_s, l) -> fn "CONCAT_WS" l ")" | Connection_id -> fn "CONNECTION_ID" [] ")" | Conv (e1, i, j) -> fn "CONV(" [e1] (sprintf ", %d, %d)" i j) | Cos e -> fn "COS(" [e] ")" @@ -576,13 +576,13 @@ module Expr = struct | If (b, t, f) -> let st1 = fn "IF(" [b] "" in let st2 = fn ~st:st1 (st1.repr ^ ", ") [t; f] ")" in - Sequoia.{ st2 with params = st1.params @ st2.params } + { st2 with params = st1.params @ st2.params } | From_days e -> fn "FROM_DAYS(" [e] ")" | From_unixtime e -> fn "FROM_UNIXTIME(" [e] ")" | Ifnull (e1, e2) -> let st1 = fn "IFNULL(" [e1] "" in let st2 = fn ~st:st1 (st1.repr ^ ", ") [e2] ")" in - Sequoia.{ st2 with params = st1.params @ st2.params } + { st2 with params = st1.params @ st2.params } | Last_day e -> fn "LAST_DAY(" [e] ")" | Length e -> fn "LENGTH(" [e] ")" | Localtime -> fn "LOCALTIME(" [] ")" diff --git a/postgresql/dune b/postgresql/dune new file mode 100644 index 0000000..3c5c752 --- /dev/null +++ b/postgresql/dune @@ -0,0 +1,4 @@ +(library + (name sequoia_postgresql) + (public_name sequoia-postgresql) + (libraries sequoia unix)) diff --git a/postgresql/jbuild b/postgresql/jbuild deleted file mode 100644 index 242b876..0000000 --- a/postgresql/jbuild +++ /dev/null @@ -1,8 +0,0 @@ -(jbuild_version 1) - -(library - ((name sequoia_postgresql) - (public_name sequoia-postgresql) - (libraries - (sequoia - unix)))) diff --git a/postgresql/postgresql.ml b/postgresql/postgresql.ml index 8cd9f44..fdad42c 100644 --- a/postgresql/postgresql.ml +++ b/postgresql/postgresql.ml @@ -105,7 +105,7 @@ module Field = struct | Null.Datetime (_, t) -> t | Null.Enum (_, t, _) -> t | fld -> table fld - +(* let to_string : type a b. (a, b) t -> string = function | Time (name, table) -> sprintf "%s.%s" (Table.name table) name | Timestamp (name, table) -> sprintf "%s.%s" (Table.name table) name @@ -118,7 +118,7 @@ module Field = struct | Null.Datetime (name, table) -> sprintf "%s.%s" (Table.name table) name | Null.Enum (name, table, _) -> sprintf "%s.%s" (Table.name table) name | other -> to_string other - + *) let to_string fld = let t = table fld in sprintf "%s.%s" (Table.name t) (name fld) @@ -392,7 +392,7 @@ module Expr = struct Lit (Lit.Date { base_time with year; month; day }) let datetime ?(year = 0) ?(month = 0) ?(day = 0) ?(hour = 0) ?(minute = 0) ?(second = 0) = fun _ -> - Lit (Lit.Datetime { base_time with year; month; day; minute; second }) + Lit (Lit.Datetime { year; month; day; hour; minute; second }) let enum inst = fun _ -> Lit (Lit.Enum inst) @@ -419,17 +419,17 @@ module Expr = struct let compress f = fun src -> Compress (f src) let concat f = fun src -> Concat (f src) let concat_ws sep l = fun src -> Concat_ws (sep, List.map (fun f -> f src) l) - let connection_id () = fun src -> Connection_id + let connection_id () = fun _ -> Connection_id let conv f i j = fun src -> Conv (f src, i, j) let cos f = fun src -> Cos (f src) let cot f = fun src -> Cot (f src) let count ?(distinct = false) f = fun src -> Count (f src, distinct) let crc32 f = fun src -> Crc32 (f src) - let current_date () = fun src -> Current_date - let current_time () = fun src -> Current_time - let current_timestamp () = fun src -> Current_timestamp - let current_user () = fun src -> Current_user - let database () = fun src -> Database + let current_date () = fun _ -> Current_date + let current_time () = fun _ -> Current_time + let current_timestamp () = fun _ -> Current_timestamp + let current_user () = fun _ -> Current_user + let database () = fun _ -> Database let date_of : ('s M.Select.source -> [< `Date | `Datetime] time t) -> 's M.Select.source -> [`Date] time t = fun f src -> DateFn (f src) let date_add f i u = fun src -> Date_add (f src, i, u) let date_format f fmt = fun src -> Date_format (f src, fmt) @@ -448,7 +448,7 @@ module Expr = struct let ifnull f g = fun src -> Ifnull (f src, g src) let last_day f = fun src -> Last_day (f src) let length f = fun src -> Length (f src) - let localtime () = fun src -> Localtime + let localtime () = fun _ -> Localtime let log f = fun src -> Log (f src) let log10 f = fun src -> Log10 (f src) let log2 f = fun src -> Log2 (f src) @@ -460,7 +460,7 @@ module Expr = struct let minute f = fun src -> Minute (f src) let month f = fun src -> Month (f src) let monthname f = fun src -> Monthname (f src) - let now () = fun src -> Now + let now () = fun _ -> Now let nullif f g = fun src -> Nullif (f src, g src) let ord f = fun src -> Ord (f src) let pow f = fun src -> Pow (f src) @@ -489,23 +489,23 @@ module Expr = struct let timestampdiff u f g = fun src -> Timestampdiff (u, f src, g src) let trim f = fun src -> Trim (f src) let uncompress f = fun src -> Uncompress (f src) - let utc_date () = fun src -> Utc_date - let utc_time () = fun src -> Utc_time - let utc_timestamp () = fun src -> Utc_timestamp - let uuid () = fun src -> Uuid - let uuid_short () = fun src -> Uuid_short - let week () = fun src -> Week - let weekday () = fun src -> Weekday - let weekofyear () = fun src -> Weekofyear + let utc_date () = fun _ -> Utc_date + let utc_time () = fun _ -> Utc_time + let utc_timestamp () = fun _ -> Utc_timestamp + let uuid () = fun _ -> Uuid + let uuid_short () = fun _ -> Uuid_short + let week () = fun _ -> Week + let weekday () = fun _ -> Weekday + let weekofyear () = fun _ -> Weekofyear let upper f = fun src -> Upper (f src) - let year () = fun src -> Year + let year () = fun _ -> Year let as_time f = fun src -> Cast (f src, Time) let as_timestamp f = fun src -> Cast (f src, Timestamp) let as_date f = fun src -> Cast (f src, Date) let as_datetime f = fun src -> Cast (f src, Datetime) - let rec build + let build : type a. handover:handover -> build_step -> a t -> build_step = fun ~handover st e -> let build_param = build_param D.placeholder in @@ -543,7 +543,7 @@ module Expr = struct | Collation e -> fn "COLLATION(" [e] ")" | Compress e -> fn "COMPRESS(" [e] ")" | Concat l -> fn "CONCAT(" l ")" - | Concat_ws (s, l) -> fn "CONCAT_WS" l ")" + | Concat_ws (_s, l) -> fn "CONCAT_WS" l ")" | Connection_id -> fn "CONNECTION_ID" [] ")" | Conv (e1, i, j) -> fn "CONV(" [e1] (sprintf ", %d, %d)" i j) | Cos e -> fn "COS(" [e] ")" @@ -577,13 +577,13 @@ module Expr = struct | If (b, t, f) -> let st1 = fn "CASE WHEN " [b] " THEN " in let st2 = fn ~st:st1 (st1.repr ^ " ELSE ") [t; f] " END " in - Sequoia.{ st2 with params = st1.params @ st2.params } + { st2 with params = st1.params @ st2.params } | From_days e -> fn "FROM_DAYS(" [e] ")" | From_unixtime e -> fn "FROM_UNIXTIME(" [e] ")" | Ifnull (e1, e2) -> let st1 = fn "IFNULL(" [e1] "" in let st2 = fn ~st:st1 (st1.repr ^ ", ") [e2] ")" in - Sequoia.{ st2 with params = st1.params @ st2.params } + { st2 with params = st1.params @ st2.params } | Last_day e -> fn "LAST_DAY(" [e] ")" | Length e -> fn "LENGTH(" [e] ")" | Localtime -> fn "LOCALTIME(" [] ")" diff --git a/ppx/dune b/ppx/dune new file mode 100644 index 0000000..28d143c --- /dev/null +++ b/ppx/dune @@ -0,0 +1,5 @@ +(library + (name sequoia_ppx) + (public_name sequoia-ppx) + (kind ppx_rewriter) + (libraries ppxlib sequoia)) diff --git a/ppx/jbuild b/ppx/jbuild deleted file mode 100644 index 5048228..0000000 --- a/ppx/jbuild +++ /dev/null @@ -1,11 +0,0 @@ -(jbuild_version 1) - -(library - ((name sequoia_ppx) - (public_name sequoia-ppx) - (kind ppx_rewriter) - (libraries - (sequoia - ppx_tools_versioned - ocaml-compiler-libs - ocaml-migrate-parsetree)))) diff --git a/ppx/sequoia_ppx.ml b/ppx/sequoia_ppx.ml index e330c7f..5c3cce8 100644 --- a/ppx/sequoia_ppx.ml +++ b/ppx/sequoia_ppx.ml @@ -1,12 +1,10 @@ -open Migrate_parsetree -open Ast_404 - -open Ast_mapper -open Ast_helper +open Ppxlib open Asttypes -open Longident open Parsetree -open Ast_convenience_404 +open Ast_builder.Default +open Ast_helper +open Longident +let lident x = Longident.Lident x open Printf @@ -23,9 +21,9 @@ let load_state () = | None -> None let error loc msg = - raise @@ Location.Error (Location.error ~loc msg) + Location.Error.(raise @@ make ~loc ~sub:[] msg) -let construct s = Exp.construct (lid s) +let construct s = Exp.construct (Located.lident ~loc:Location.none s) let there = construct "There" None let skip x = construct "Skip" (Some x) @@ -50,27 +48,27 @@ let find_reference loc refs ref = with Not_found -> error loc (sprintf "reference for %s.%s not found" (fst ref) (snd ref)) -module StringSet = Set.Make(struct +module StringSet = Stdlib.Set.Make(struct type t = string - let compare = compare + let compare = Stdlib.compare end) let rec map_expr_list loc f = function | { pexp_desc = - Pexp_construct ({ txt = Lident "::" } as cons, - Some ({ pexp_desc = Pexp_tuple [expr; rest]; pexp_loc } as args)) } as e -> + Pexp_construct ({ txt = Lident "::"; _ } as cons, + Some ({ pexp_desc = Pexp_tuple [expr; rest]; pexp_loc; _ } as args)); _ } as e -> let l = [f pexp_loc expr; map_expr_list pexp_loc f rest] in { e with pexp_desc = Pexp_construct (cons, Some { args with pexp_desc = Pexp_tuple l }) } | { pexp_desc = - Pexp_construct ({ txt = Lident "[]" }, None) } as e -> + Pexp_construct ({ txt = Lident "[]"; _ }, None); _ } as e -> e - | { pexp_desc = Pexp_open (ovr, loc, ({ pexp_loc } as e)) } as expr -> + | { pexp_desc = Pexp_open (ovr, ({ pexp_loc; _ } as e)); _ } as expr -> let e = map_expr_list pexp_loc f e in - { expr with pexp_desc = Pexp_open (ovr, loc, e) } + { expr with pexp_desc = Pexp_open (ovr, e) } - | e -> + | _ -> error loc "unexpected element in select expression" let add_table t u ts = @@ -81,7 +79,7 @@ let add_table t u ts = let rec map_query st loc = function | { pexp_desc = - Pexp_let (rec_flag, [{ pvb_expr } as b], ({ pexp_loc } as expr)) } -> + Pexp_let (rec_flag, [{ pvb_expr; _ } as b], ({ pexp_loc; _ } as expr)); _ } -> let e = map_query st loc pvb_expr in let binding = { b with pvb_expr = e } in @@ -89,9 +87,9 @@ let rec map_query st loc = function Exp.let_ rec_flag [binding] expr (* nested let%sql = ... *) - | { pexp_desc = Pexp_extension ({ txt = "sql"; loc }, pstr) } -> + | { pexp_desc = Pexp_extension ({ txt = "sql"; loc }, pstr); _ } -> begin match pstr with - | PStr [{ pstr_desc = Pstr_eval (expr, _) }] -> + | PStr [{ pstr_desc = Pstr_eval (expr, _); _ }] -> let expr = match load_state () with | Some st -> map_query st loc expr @@ -104,26 +102,26 @@ let rec map_query st loc = function (* from MyTable.table *) | { pexp_desc = Pexp_apply ({ pexp_desc = - Pexp_ident { txt = Lident "from"; loc } }, + Pexp_ident { txt = Lident "from"; _ }; _ }, [(_, { pexp_desc = - Pexp_ident { txt = Ldot (Lident t, _) } })]) } as e -> + Pexp_ident { txt = Ldot (Lident t, _); _ }; _ })]); _ } as e -> st.tables := [t]; e (* {left,right,inner}_join (that Table.fk) *) | { pexp_desc = Pexp_apply - (({ pexp_desc = Pexp_ident { txt = Lident join_fun } } as join), + (({ pexp_desc = Pexp_ident { txt = Lident join_fun; _ }; _ } as join), [(Nolabel, ({ pexp_desc = Pexp_apply (({ pexp_desc = - Pexp_ident { txt = Lident "that" } } as rel), + Pexp_ident { txt = Lident "that"; _ }; _ } as rel), (([(Nolabel, { pexp_desc = Pexp_ident { txt = Ldot (Lident tbl, fld) - ; loc } })]) as args)) } as join_args))]) } as e + ; loc; _ }; _ })]) as args)); _ } as join_args))]); _ } as e when join_fun = "left_join" || join_fun = "right_join" || join_fun = "inner_join" -> @@ -144,17 +142,17 @@ let rec map_query st loc = function (* {left,right,inner}_join (this Table.fk) *) | { pexp_desc = Pexp_apply - (({ pexp_desc = Pexp_ident { txt = Lident join_fun } } as join), + (({ pexp_desc = Pexp_ident { txt = Lident join_fun; _ }; _ } as join), [(Nolabel, ({ pexp_desc = Pexp_apply (({ pexp_desc = - Pexp_ident { txt = Lident "this" } } as rel), + Pexp_ident { txt = Lident "this"; _ }; _ } as rel), (([(Nolabel, { pexp_desc = Pexp_ident { txt = Ldot (Lident tbl, fld) - ; loc } })]) as args)) } as join_args))]) } as e + ; loc; _ }; _ })]) as args)); _ } as join_args))]); _ } as e when join_fun = "left_join" || join_fun = "right_join" || join_fun = "inner_join" -> @@ -175,17 +173,17 @@ let rec map_query st loc = function (* {left,right,inner}_join (self Table.k) *) | { pexp_desc = Pexp_apply - (({ pexp_desc = Pexp_ident { txt = Lident join_fun } } as join), + (({ pexp_desc = Pexp_ident { txt = Lident join_fun; _ }; _ } as join), [(Nolabel, ({ pexp_desc = Pexp_apply - (({ pexp_desc = Pexp_ident { txt = Lident "self" } } as rel), + (({ pexp_desc = Pexp_ident { txt = Lident "self"; _ }; _ } as rel), (([ (Nolabel, { pexp_desc = Pexp_ident - { txt = Ldot (Lident tbl, fld) ; loc } }) + { txt = Ldot (Lident tbl, _fld) ; loc; _ }; _ }) ; _ - ]) as args)) } as join_args))]) } as e + ]) as args)); _ } as join_args))]); _ } as e when join_fun = "left_join" || join_fun = "right_join" || join_fun = "inner_join" -> @@ -205,30 +203,30 @@ let rec map_query st loc = function (* select *) | { pexp_desc = Pexp_apply (({ pexp_desc = - Pexp_ident { txt = Lident "select"; loc } } as select), [lbl, args]) } as e -> + Pexp_ident { txt = Lident "select"; loc; _ }; _ } as select), [lbl, args]); _ } as e -> { e with pexp_desc = Pexp_apply (select, [lbl, map_expr_list loc (map_select st) args]) } (* select ~distinct:... *) | { pexp_desc = Pexp_apply (({ pexp_desc = - Pexp_ident { txt = Lident "select"; loc } } as select), - [(Labelled "distinct", _) as dist; lbl, args]) } as e -> + Pexp_ident { txt = Lident "select"; loc; _ }; _ } as select), + [(Labelled "distinct", _) as dist; lbl, args]); _ } as e -> { e with pexp_desc = Pexp_apply (select, [dist; lbl, map_expr_list loc (map_select st) args]) } (* group_by Expr.[...] *) | { pexp_desc = Pexp_apply (({ pexp_desc = - Pexp_ident { txt = Lident "group_by"; loc } } as gb), [lbl, args]) } as e -> + Pexp_ident { txt = Lident "group_by"; loc; _ }; _ } as gb), [lbl, args]);_ } as e -> { e with pexp_desc = Pexp_apply (gb, [lbl, map_expr_list loc (map_select st) args]) } (* group_by Expr.[...] ~having:... *) | { pexp_desc = Pexp_apply (({ pexp_desc = - Pexp_ident { txt = Lident "group_by"; loc } } as gb), - [(lbl, args); (Labelled "having", hav)]) } as e -> + Pexp_ident { txt = Lident "group_by"; loc; _ }; _ } as gb), + [(lbl, args); (Labelled "having", hav)]); _ } as e -> { e with pexp_desc = Pexp_apply (gb, @@ -239,8 +237,8 @@ let rec map_query st loc = function (* group_by ~having:... Expr.[...] *) | { pexp_desc = Pexp_apply (({ pexp_desc = - Pexp_ident { txt = Lident "group_by"; loc } } as gb), - [(Labelled "having", hav); (lbl, args)]) } as e -> + Pexp_ident { txt = Lident "group_by"; loc; _ }; _ } as gb), + [(Labelled "having", hav); (lbl, args)]); _ } as e -> { e with pexp_desc = Pexp_apply (gb, @@ -251,46 +249,46 @@ let rec map_query st loc = function (* order_by Expr.[...] *) | { pexp_desc = Pexp_apply (({ pexp_desc = - Pexp_ident { txt = Lident "order_by"; loc } } as ob), [lbl, args]) } as e -> + Pexp_ident { txt = Lident "order_by"; loc; _ }; _ } as ob), [lbl, args]); _ } as e -> { e with pexp_desc = Pexp_apply (ob, [lbl, map_expr_list loc (map_select st) args]) } (* field Table.field *) | { pexp_desc = Pexp_apply (({ pexp_desc = - Pexp_ident { txt = Lident fn; loc } } as fld), + Pexp_ident { txt = Lident fn; loc; _ }; _ } as fld), ([ (Nolabel, { pexp_desc = - Pexp_ident { txt = Ldot (Lident table, field) } }) - ] as args)) } as e - when fn = "field"|| fn = "foreign_key" -> + Pexp_ident { txt = Ldot (Lident table, _field);_ };_ }) + ] as args));_ } as e + when fn = "field"|| fn = "foreign_key" -> let steps = build_steps (index loc table !(st.tables)) in { e with pexp_desc = Pexp_apply (fld, snoc (Nolabel, steps) args) } - | { pexp_desc = Pexp_apply (({ pexp_loc } as e), args) } as expr -> + | { pexp_desc = Pexp_apply (({ pexp_loc;_ } as e), args);_ } as expr -> let args = List.map - (fun (lbl, ({ pexp_loc } as e)) -> + (fun (lbl, ({ pexp_loc; _ } as e)) -> (lbl, map_query st pexp_loc e)) args in let e = map_query st pexp_loc e in { expr with pexp_desc = Pexp_apply (e, args) } - | { pexp_desc = Pexp_open (ovr, loc, ({ pexp_loc } as e)) } as expr -> + | { pexp_desc = Pexp_open (ovr, ({ pexp_loc;_ } as e));_ } as expr -> let e = map_query st pexp_loc e in - { expr with pexp_desc = Pexp_open (ovr, loc, e) } + { expr with pexp_desc = Pexp_open (ovr, e) } | e -> e -and map_select st loc = function +and map_select st _loc = function (* select [...; field|foreign_key|unwrap Table.field; ...] *) | { pexp_desc = Pexp_apply (({ pexp_desc = - Pexp_ident { txt = Lident fn; loc } } as fld), + Pexp_ident { txt = Lident fn; loc; _ };_ } as fld), ([(_, { pexp_desc = - Pexp_ident { txt = Ldot (Lident t, _) } })] as args)) } as e + Pexp_ident { txt = Ldot (Lident t, _); _ }; _ })] as args)); _ } as e when fn = "field" || fn = "foreign_key" || fn = "unwrap" -> let steps = build_steps (index loc t !(st.tables)) in { e with pexp_desc = Pexp_apply (fld, snoc (Nolabel, steps) args) } @@ -298,20 +296,20 @@ and map_select st loc = function (* select [...; subquery (from ...); ...] *) | { pexp_desc = Pexp_apply (({ pexp_desc = - Pexp_ident { txt = Lident "subquery"; loc } } as sub), - [(lbl, expr)]) } as e -> + Pexp_ident { txt = Lident "subquery"; _ }; _ } as sub), + [(lbl, expr)]); _ } as e -> let st' = { st with tables = ref [] } in let expr = map_query st' expr.pexp_loc expr in { e with pexp_desc = Pexp_apply (sub, [(lbl, expr)]) } - | { pexp_desc = Pexp_apply (fn, args) } as e -> + | { pexp_desc = Pexp_apply (fn, args); _ } as e -> let args = List.map (fun (lbl, arg_expr) -> match arg_expr with (* List argument: map each expression *) - | { pexp_desc = Pexp_construct ({ txt = Lident "::" }, _) } -> + | { pexp_desc = Pexp_construct ({ txt = Lident "::"; _ }, _); _ } -> (lbl, map_expr_list arg_expr.pexp_loc (map_select st) arg_expr) | _ -> (lbl, map_select st arg_expr.pexp_loc arg_expr)) @@ -321,111 +319,120 @@ and map_select st loc = function | e -> e -let rec map_module table references loc = function +let rec map_module table references _loc = function | [] -> () (* Field.foreign_key name ~references:Some.field *) | { pstr_desc = Pstr_value (_, - [{ pvb_pat = { ppat_desc = Ppat_var { txt = field } } + [{ pvb_pat = { ppat_desc = Ppat_var { txt = field; _ }; _ } ; pvb_expr = { pexp_desc = Pexp_apply ({ pexp_desc = - Pexp_ident { txt = Ldot (Lident "Field", "foreign_key") } }, + Pexp_ident { txt = Ldot (Lident "Field", "foreign_key"); _ };_ }, [ (Nolabel, - { pexp_desc = Pexp_constant (Pconst_string (_, None)) }) + { pexp_desc = Pexp_constant (Pconst_string (_, _, None)); _ }) ; (Labelled "references", { pexp_desc = Pexp_ident - { txt = Ldot (Lident ref_table, ref_field) } }) - ]) } - }]) - ; pstr_loc } :: rest -> + { txt = Ldot (Lident ref_table, ref_field); _ };_ }) + ]); _ }; _ }]) + ; pstr_loc; _ } :: rest -> Hashtbl.add references (table, field) (ref_table, ref_field); map_module table references pstr_loc rest (* Field.foreign_key ~references:Some.field name *) | { pstr_desc = Pstr_value (_, - [{ pvb_pat = { ppat_desc = Ppat_var { txt = field } } + [{ pvb_pat = { ppat_desc = Ppat_var { txt = field;_ };_ } ; pvb_expr = { pexp_desc = Pexp_apply ({ pexp_desc = - Pexp_ident { txt = Ldot (Lident "Field", "foreign_key") } }, + Pexp_ident { txt = Ldot (Lident "Field", "foreign_key");_ };_ }, [ (Labelled "references", { pexp_desc = Pexp_ident - { txt = Ldot (Lident ref_table, ref_field) } }) + { txt = Ldot (Lident ref_table, ref_field);_ };_ }) ; (Nolabel, - { pexp_desc = Pexp_constant (Pconst_string (_, None)) }) - ]) } - }]) - ; pstr_loc } :: rest -> + { pexp_desc = Pexp_constant (Pconst_string (_, _, None));_ }) + ]); _ }; _ }]) + ; pstr_loc; _ } :: rest -> Hashtbl.add references (table, field) (ref_table, ref_field); map_module table references pstr_loc rest - | { pstr_loc } :: rest -> + | { pstr_loc; _ } :: rest -> map_module table references pstr_loc rest -let sql_mapper references _config _cookies = - { default_mapper with - expr = - (fun mapper expr -> - match expr with - (* let%sql = ... *) - | { pexp_desc = Pexp_extension ({ txt = "sql"; loc }, pstr) } -> - begin match pstr with - | PStr [{ pstr_desc = Pstr_eval (expr, _) }] -> - let expr = - match load_state () with - | Some st -> map_query st loc expr - | None -> expr in - Ast_helper.with_default_loc loc (fun () -> expr) - | _ -> - error loc "invalid sql" - end - | x -> default_mapper.expr mapper x) - - ; structure_item = - (fun mapper str -> - match str with - (* module%sql ... = struct ... end *) - | { pstr_desc = Pstr_extension (({ txt = "sql"; loc }, pstr), _) } -> - begin match pstr with - | PStr - [{ pstr_desc = - Pstr_module - ({ pmb_name = { txt = name } - ; pmb_expr = { pmod_desc = Pmod_structure strs } - ; pmb_loc } as m) }] -> - map_module name references pmb_loc strs; - global_references := Some references; - let str = Str.module_ m in - Ast_helper.with_default_loc loc (fun () -> str) - | PStr - [{ pstr_desc = - Pstr_value (rec_flag, [{ pvb_expr } as b]) }] -> - let str = - match load_state () with - | Some st -> - let expr = map_query st loc pvb_expr in - let binding = { b with pvb_expr = expr } in - Str.value rec_flag [binding] - | None -> - Str.value rec_flag [b] in - Ast_helper.with_default_loc loc (fun () -> str) - | _ -> - error loc "invalid sql" - end - | x -> default_mapper.structure_item mapper x) - } - -let migration = - Versions.migrate Versions.ocaml_404 Versions.ocaml_current +let map_expr _references expr = + (* let%sql = ... *) + match load_state () with + | Some st -> map_query st expr.pexp_loc expr + | None -> expr + +let map_str references pstr = + match pstr with + { pstr_desc = + Pstr_module + ({ pmb_name = { txt = Some name; _ } + ; pmb_expr = { pmod_desc = Pmod_structure strs; _ } + ; pmb_loc; _ } as m); pstr_loc; _ } -> + map_module name references pmb_loc strs; + global_references := Some references; + let str = Str.module_ m in + Ast_helper.with_default_loc pstr_loc (fun () -> str) + | { pstr_desc = + Pstr_value (rec_flag, [{ pvb_expr; _ } as b]); pstr_loc; _ } -> + let str = + match load_state () with + | Some st -> + let expr = map_query st pstr_loc pvb_expr in + let binding = { b with pvb_expr = expr } in + Str.value rec_flag [binding] + | None -> + Str.value rec_flag [b] in + Ast_helper.with_default_loc pstr_loc (fun () -> str) + | s -> s + +let references = Hashtbl.create 16 + +let map_all = object + inherit Ast_traverse.map as super + + method! expression e = + super#expression (map_expr references e) + + method! structure_item = + (fun i -> super#structure_item (map_str references i)) + end + +let rule_expr = + let ctx = Extension.Context.expression in + let pat = Ast_pattern.(single_expr_payload __) in + let ext = Extension.declare "sql" ctx pat + (fun ~loc:_ ~path:_ -> map_all#expression) in + Context_free.Rule.extension ext + +(* transform a list of structure_items in one *) +let flatten_str items = + match items with + | [x] -> x + | _ -> + Str.include_ { pincl_mod = Mod.structure items + ; pincl_loc = Location.none + ; pincl_attributes = [] } + +(* TODO: why is flatten_str needed ? *) +let rule_str_item = + let ctx = Extension.Context.structure_item in + let pat = Ast_pattern.(pstr __) in + let ext = Extension.declare "sql" ctx pat + (fun ~loc:_ ~path:_ l -> + flatten_str (List.map map_all#structure_item l)) in + Context_free.Rule.extension ext let () = - let references = Hashtbl.create 16 in - Driver.register ~name:"ppx_sequoia" - Versions.ocaml_404 (sql_mapper references) + Driver.register_transformation + ~rules:[rule_expr; rule_str_item] + "ppx_sequoia" diff --git a/sequoia-mysql.opam b/sequoia-mysql.opam index 7b6d648..042354a 100644 --- a/sequoia-mysql.opam +++ b/sequoia-mysql.opam @@ -1,12 +1,12 @@ opam-version: "1.2" -version: "0.1.0" +version: "0.2.0" maintainer: "Andre Nathan " authors: "Andre Nathan " homepage: "https://github.com/andrenth/sequoia" bug-reports: "https://github.com/andrenth/sequoia" license: "MIT" dev-repo: "https://github.com/andrenth/sequoia" -available: [ ocaml-version >= "4.04.0" ] +available: [ ocaml-version >= "4.12.0" ] build: [ ["jbuilder" "subst" "-n" name] {pinned} ["jbuilder" "build" "-p" name "-j" jobs] diff --git a/sequoia-postgresql.opam b/sequoia-postgresql.opam index 2c94539..ab7dea7 100644 --- a/sequoia-postgresql.opam +++ b/sequoia-postgresql.opam @@ -1,18 +1,28 @@ opam-version: "1.2" -version: "0.1.0" +version: "0.2.0" maintainer: "Andre Nathan " authors: "Andre Nathan " homepage: "https://github.com/andrenth/sequoia" bug-reports: "https://github.com/andrenth/sequoia" license: "MIT" dev-repo: "https://github.com/andrenth/sequoia" -available: [ ocaml-version >= "4.04.0" ] +available: [ ocaml-version >= "4.12.0" ] build: [ - ["jbuilder" "build" "-p" name "-j" jobs] + ["dune" "subst"] {dev} + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] ] -build-test: [["jbuilder" "runtest" "-p" name "-j" jobs]] depends: [ - "jbuilder" {build} + "dune" {build} "base-unix" "sequoia" ] diff --git a/sequoia-ppx.opam b/sequoia-ppx.opam index dece24c..d236c65 100644 --- a/sequoia-ppx.opam +++ b/sequoia-ppx.opam @@ -1,18 +1,28 @@ opam-version: "1.2" -version: "0.1.0" +version: "0.2.0" maintainer: "Andre Nathan " authors: "Andre Nathan " homepage: "https://github.com/andrenth/sequoia" bug-reports: "https://github.com/andrenth/sequoia" license: "MIT" dev-repo: "https://github.com/andrenth/sequoia" -available: [ ocaml-version >= "4.04.0" ] +available: [ ocaml-version >= "4.12.0" ] build: [ - ["jbuilder" "build" "-p" name "-j" jobs] + ["dune" "subst"] {dev} + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] ] -build-test: [["jbuilder" "runtest" "-p" name "-j" jobs]] depends: [ - "jbuilder" {build} + "dune" {build} "sequoia" "ppx_tools_versioned" "ocaml-migrate-parsetree" diff --git a/sequoia-sqlite.opam b/sequoia-sqlite.opam index 61ab0d6..e89cd5e 100644 --- a/sequoia-sqlite.opam +++ b/sequoia-sqlite.opam @@ -1,12 +1,12 @@ opam-version: "1.2" -version: "0.1.0" +version: "0.2.0" maintainer: "Andre Nathan " authors: "Andre Nathan " homepage: "https://github.com/andrenth/sequoia" bug-reports: "https://github.com/andrenth/sequoia" license: "MIT" dev-repo: "https://github.com/andrenth/sequoia" -available: [ ocaml-version >= "4.04.0" ] +available: [ ocaml-version >= "4.12.0" ] build: [ ["jbuilder" "subst" "-n" name] {pinned} ] diff --git a/sequoia.opam b/sequoia.opam index c540f65..8e9db57 100644 --- a/sequoia.opam +++ b/sequoia.opam @@ -1,16 +1,27 @@ opam-version: "1.2" -version: "0.1.0" +version: "0.2.0" maintainer: "Andre Nathan " authors: "Andre Nathan " homepage: "https://github.com/andrenth/sequoia" bug-reports: "https://github.com/andrenth/sequoia" license: "MIT" dev-repo: "https://github.com/andrenth/sequoia" -available: [ ocaml-version >= "4.04.0" ] +available: [ ocaml-version >= "4.12.0" ] build: [ - ["jbuilder" "build" "-p" name "-j" jobs] + ["dune" "subst"] {dev} + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] ] build-test: [["jbuilder" "runtest" "-p" name "-j" jobs]] depends: [ - "jbuilder" {build} + "dune" {build} ] diff --git a/sqlite/dune b/sqlite/dune new file mode 100644 index 0000000..a3e94d2 --- /dev/null +++ b/sqlite/dune @@ -0,0 +1,4 @@ +(library + (name sequoia_sqlite) + (public_name sequoia-sqlite) + (libraries sequoia)) diff --git a/sqlite/jbuild b/sqlite/jbuild deleted file mode 100644 index de54a37..0000000 --- a/sqlite/jbuild +++ /dev/null @@ -1,6 +0,0 @@ -(jbuild_version 1) - -(library - ((name sequoia_sqlite) - (public_name sequoia-sqlite) - (libraries (sequoia)))) diff --git a/sqlite/sqlite.ml b/sqlite/sqlite.ml index 29805bc..1003e78 100644 --- a/sqlite/sqlite.ml +++ b/sqlite/sqlite.ml @@ -62,8 +62,7 @@ module Expr = struct | Sum : int t -> int t | Total : int t -> int t - let avg f = fun src -> Avg (f src) - let changes () = fun src -> Changes + let changes () = fun _ -> Changes let char f = fun src -> Char (f src) let coalesce f = fun src -> Coalesce (f src) let glob pat f = fun src -> Glob (pat, f src) @@ -78,7 +77,7 @@ module Expr = struct let max f = fun src -> Max (f src) let min f = fun src -> Min (f src) let nullif f g = fun src -> Nullif (f src, g src) - let random () = fun src -> Random + let random () = fun _ -> Random let randomblob f = fun src -> Randomblob (f src) let replace f s1 s2 = fun src -> Replace (f src, s1, s2) let round f ?digits = fun src -> Round (f src, digits) @@ -102,7 +101,7 @@ module Expr = struct let sum f = fun src -> Sum (f src) let total f = fun src -> Total (f src) - let rec build + let build : type a. handover:handover -> build_step -> a t -> build_step = fun ~handover st e -> let fn ?(st = st) = diff --git a/src/delete.ml b/src/delete.ml index baf79ca..e207bbb 100644 --- a/src/delete.ml +++ b/src/delete.ml @@ -4,7 +4,7 @@ open Common module type S = sig type _ t - val delete : ?where:('t Table.t -> bool Expr.t) -> from:'t Table.t -> 't t + val delete : ?where:('t Table.t -> bool Expr.t) -> from:'t Table.t -> unit -> 't t val seal : handover:Expr.handover -> 't t -> string * Param.t list module Expr : module type of Query_common.UpdateDeleteExpr @@ -16,7 +16,7 @@ module Make (D : Driver.S) : S = struct type 't t = | D : { table : 't Table.t; where : 'a Expr.t option } -> 't t - let delete ?where ~from = + let delete ?where ~from () = let where = match where with | Some expr -> Some (expr from) diff --git a/src/delete.mli b/src/delete.mli index e0f2497..31c26de 100644 --- a/src/delete.mli +++ b/src/delete.mli @@ -4,7 +4,7 @@ module type S = sig (** The type of [DELETE] queries. *) val delete : ?where:('t Table.t -> bool Expr.t) - -> from:'t Table.t + -> from:'t Table.t -> unit -> 't t (** Define a [DELETE] query on the table given by [from] and conditions specified by [where]. *) diff --git a/src/dune b/src/dune new file mode 100644 index 0000000..9089f7b --- /dev/null +++ b/src/dune @@ -0,0 +1,6 @@ +(include_subdirs unqualified) + +(library + (name sequoia) + (public_name sequoia) + (modules :standard)) diff --git a/src/expr.mli b/src/expr.mli index b5f481f..525d1a5 100644 --- a/src/expr.mli +++ b/src/expr.mli @@ -5,6 +5,7 @@ type 'a t = .. (** The type of expressions. It is extended by the query modules (i.e. [Select], [Insert], etc.) to account for expressions that are only valid for the respective query types. *) + type 'a cast = .. (** The type that represents an SQL [CAST()]. *) @@ -49,51 +50,73 @@ module Base : sig val (=) : ('a -> 'b t) -> ('a -> 'b t) -> 'a -> bool t (** The [=] operator. *) + val (=%) : ('a -> string t) -> string -> 'a -> bool t (** The [LIKE] operator. *) + val (<>) : ('a -> 'b t) -> ('a -> 'b t) -> 'a -> bool t (** The [<>] operator. *) + val (<>%) : ('a -> string t) -> string -> 'a -> bool t (** The [NOT LIKE] operator. *) + val (>) : ('a -> 'b t) -> ('a -> 'b t) -> 'a -> bool t (** The [>] operator. *) + val (>=) : ('a -> 'b t) -> ('a -> 'b t) -> 'a -> bool t (** The [>=] operator. *) + val (<) : ('a -> 'b t) -> ('a -> 'b t) -> 'a -> bool t (** The [<] operator. *) + val (<=) : ('a -> 'b t) -> ('a -> 'b t) -> 'a -> bool t (** The [<=] operator. *) + val (&&) : ('a -> bool t) -> ('a -> bool t) -> 'a -> bool t (** The [AND] operator. *) + val (||) : ('a -> bool t) -> ('a -> bool t) -> 'a -> bool t (** The [OR] operator. *) + val (+) : ('a -> int t) -> ('a -> int t) -> 'a -> int t (** The [+] operator for integers. *) + val (-) : ('a -> int t) -> ('a -> int t) -> 'a -> int t (** The [-] operator for integers. *) + val ( * ) : ('a -> int t) -> ('a -> int t) -> 'a -> int t (** The [*] operator for integers. *) + val (/) : ('a -> int t) -> ('a -> int t) -> 'a -> int t (** The [/] operator for integers. *) + val (+.) : ('a -> float t) -> ('a -> float t) -> 'a -> float t (** The [+] operator for floats. *) + val (-.) : ('a -> float t) -> ('a -> float t) -> 'a -> float t (** The [-] operator for floats. *) + val ( *. ) : ('a -> float t) -> ('a -> float t) -> 'a -> float t (** The [*] operator for floats. *) + val (/.) : ('a -> float t) -> ('a -> float t) -> 'a -> float t (** The [/] operator for floats. *) + val (<<) : ('a -> int t) -> int -> 'a -> int t (** The [<<] operator. *) + val (>>) : ('a -> int t) -> int -> 'a -> int t (** The [>>] operator. *) + val (=?) : ('a -> 'b t) -> ('a -> 'b t) list -> 'a -> bool t (** The [IN] operator. *) + val (<>?) : ('a -> 'b t) -> ('a -> 'b t) list -> 'a -> bool t (** The [NOT IN] operator. *) val is_null : ('a -> 'b option t) -> 'a -> bool t (** The [IS NULL] operator. *) + val is_not_null : ('a -> 'b option t) -> 'a -> bool t (** The [IS NOT NULL] operator. *) @@ -101,12 +124,16 @@ module Base : sig val bool : bool -> 'a -> bool t (** A boolean value expression. *) + val int : int -> 'a -> int t (** An int value expression. *) + val float : float -> 'a -> float t (** A float value expression. *) + val string : string -> 'a -> string t (** A string value expression. *) + val blob : bytes -> 'a -> bytes t (** A blob value expression. *) @@ -114,12 +141,16 @@ module Base : sig val as_bool : ('a -> 'b t) -> 'a -> bool t (** Cast to bool. *) + val as_int : ('a -> 'b t) -> 'a -> int t (** Cast to int. *) + val as_float : ('a -> 'b t) -> 'a -> float t (** Cast to float. *) + val as_string : ('a -> 'b t) -> 'a -> string t (** Cast to string. *) + val as_blob : ('a -> 'b t) -> 'a -> bytes t (** Cast to blob. *) @@ -127,12 +158,16 @@ module Base : sig module Null : sig val bool : bool -> 'a -> bool option t (** A nullable boolean value expression. *) + val int : int -> 'a -> int option t (** A nullable int value expression. *) + val float : float -> 'a -> float option t (** A nullable float value expression. *) + val string : string -> 'a -> string option t (** A nullable string value expression. *) + val blob : bytes -> 'a -> bytes option t (** A nullable blob value expression. *) end diff --git a/src/field.mli b/src/field.mli index 7c8bee5..bfb1cee 100644 --- a/src/field.mli +++ b/src/field.mli @@ -17,19 +17,25 @@ type ('t1, 't2) foreign_key = ('t1, int) t * ('t2, int) t val name : ('t, 'a) t -> string (** The name of a field. *) + val table : ('t, 'a) t -> 't Table.t (** The table a field belongs to. *) + val to_string : ('t, 'a) t -> string (** The string representation of a field, i.e. [table].[name]. *) val bool : 't Table.t -> string -> ('t, bool) t (** A boolean field. *) + val int : 't Table.t -> string -> ('t, int) t (** An integer field. *) + val float : 't Table.t -> string -> ('t, float) t (** A float field. *) + val string : 't Table.t -> string -> ('t, string) t (** A string field. *) + val blob : 't Table.t -> string -> ('t, bytes) t (** A blob field. *) @@ -48,12 +54,16 @@ module Null : sig val bool : 't Table.t -> string -> ('t, bool option) t (** A nullable boolean field. *) + val int : 't Table.t -> string -> ('t, int option) t (** A nullable int field. *) + val float : 't Table.t -> string -> ('t, float option) t (** A nullable float field. *) + val string : 't Table.t -> string -> ('t, string option) t (** A nullable string field. *) + val blob : 't Table.t -> string -> ('t, bytes option) t (** A nullable blob field. *) end diff --git a/src/jbuild b/src/jbuild deleted file mode 100644 index 5f479cf..0000000 --- a/src/jbuild +++ /dev/null @@ -1,5 +0,0 @@ -(jbuild_version 1) - -(library - ((name sequoia) - (public_name sequoia))) diff --git a/src/query_common.ml b/src/query_common.ml index c5bfc5a..1d18e5f 100644 --- a/src/query_common.ml +++ b/src/query_common.ml @@ -42,7 +42,7 @@ module UpdateDeleteExpr = struct let field fld = fun table -> Field (fld, table) let foreign_key fk = fun table -> Foreign (fk, table) - let rec build + let build : type a. placeholder:(int -> string) -> handover:Expr.handover -> build_step @@ -92,7 +92,6 @@ module InsertReplace = struct | f::fs -> Field.name f ^ ", " ^ join_fields fs let expr_placeholders ~placeholder i vs = - let open Lit in let rec eps : type t a n. int -> (t, a, n) Lit.Vector.t -> string list = fun i exprs -> diff --git a/src/select.ml b/src/select.ml index 075c5db..a55f81f 100644 --- a/src/select.ml +++ b/src/select.ml @@ -224,10 +224,10 @@ module Make (D : Driver.S) : S = struct type 'a t = 'a Expr.t let (-->) expr alias = fun src -> As (expr src, alias) - let alias name = fun src -> Alias name + let alias name = fun _src -> Alias name let field fld steps = fun src -> Field (fld, src, steps) let foreign_key fk steps = fun src -> Foreign (fk, src, steps) - let subquery sel = fun src -> Select sel + let subquery sel = fun _src -> Select sel (* XXX is there a better name for this? *) let unwrap diff --git a/src/sequoia.ml b/src/sequoia.ml index fef89aa..7ea2135 100644 --- a/src/sequoia.ml +++ b/src/sequoia.ml @@ -1,5 +1,3 @@ -open Printf -open Common module type NAMED = sig type t diff --git a/src/sequoia.mli b/src/sequoia.mli index e26d26e..c8b233f 100644 --- a/src/sequoia.mli +++ b/src/sequoia.mli @@ -13,25 +13,34 @@ module type S = sig module Param : module type of Param (** Query parameters. *) + module Lit : module type of Lit (** Literal values. *) + module Expr : module type of Expr (** Expressions. *) + module Table : module type of Table (** SQL tables. *) + module Field : module type of Field (** Field definitions. *) + module Vector : module type of Vector (** Heterogeneous lists with type-encoded length. *) module Select : Select.S (** [SELECT] queries. *) + module Insert : Insert.S (** [INSERT] queries. *) + module Replace : Replace.S (** [REPLACE] queries. *) + module Update : Update.S (** [UPDATE] queries. *) + module Delete : Delete.S (** [DELETE] queries. *) diff --git a/src/update.ml b/src/update.ml index 45c6a86..f2e7ada 100644 --- a/src/update.ml +++ b/src/update.ml @@ -20,6 +20,7 @@ module type S = sig val asc : ('t Table.t -> 'a Expr.t) -> 't Table.t -> ('t, 'a) expr val desc : ('t Table.t -> 'a Expr.t) -> 't Table.t -> ('t, 'a) expr + end module Vector : Vector.S with type ('t, 'a) elem := ('t, 'a) expr @@ -37,7 +38,14 @@ module type S = sig type ('t, 'a) mk = 't Table.t -> ('t, 'a) Expr.expr + module Vec : Vector.S with type ('t, 'a) elem := ('t, 'a) Expr.expr module Vector : Vector.S with type ('t, 'a) elem := ('t, 'a) mk + + val vectormk_to_vector : 't Table.t + -> ('t, 'a, 'n) Vector.t + -> ('t, 'a, 'n) Vec.t + + end module Vector : Vector.S with type ('t, 'a) elem := ('t, 'a) mk @@ -167,7 +175,7 @@ module Make (D : Driver.S) : S = struct let vec = OrderBy.vectormk_to_vector stmt.table bl in U { stmt with order_by = Some vec } - let build_updates ~handover st table updates = + let build_updates ~handover st _table updates = let fold : type t a b. build_step * int -> (t, a) Field.t * (b, a) Expr.expr diff --git a/src/update.mli b/src/update.mli index 1cfe26e..cbf946e 100644 --- a/src/update.mli +++ b/src/update.mli @@ -67,8 +67,14 @@ module type S = sig type ('t, 'a) mk = 't Table.t -> ('t, 'a) Expr.expr (** The type of [UPDATE] expression builders. *) + module Vec : Vector.S with type ('t, 'a) elem := ('t, 'a) Expr.expr module Vector : Vector.S with type ('t, 'a) elem := ('t, 'a) mk (** Vector of [UPDATE] expression builders. *) + + val vectormk_to_vector : 't Table.t + -> ('t, 'a, 'n) Vector.t + -> ('t, 'a, 'n) Vec.t + end module Vector : Vector.S with type ('t, 'a) elem := ('t, 'a) mk diff --git a/src/vector.ml b/src/vector.ml index 3dba920..4f68f96 100644 --- a/src/vector.ml +++ b/src/vector.ml @@ -46,7 +46,7 @@ struct | (::) : ('a, 'b, 'n) t * ('a, 'b, 'm, 'n) matrix -> ('a, 'b, 'm Nat.s, 'n) matrix - type 'z matrix_folder = { mf : 'a 'b. 'z -> ('a, 'b) E.elem -> 'z } + (*type 'z matrix_folder = { mf : 'a 'b. 'z -> ('a, 'b) E.elem -> 'z }*) let rec matrix_fold_left : type a b m n. 'z folder -> 'z -> (a, b, m, n) matrix -> 'z = diff --git a/test/dune b/test/dune new file mode 100644 index 0000000..7a665b1 --- /dev/null +++ b/test/dune @@ -0,0 +1,8 @@ +(alias + (name runtest) + (deps t.exe)) + +(executable + (name t) + (libraries sequoia sequoia-mysql) + (preprocess (pps sequoia-ppx))) diff --git a/test/jbuild b/test/jbuild deleted file mode 100644 index 08e5a00..0000000 --- a/test/jbuild +++ /dev/null @@ -1,12 +0,0 @@ -(jbuild_version 1) - -(alias - ((name runtest) - (deps (t.exe)))) - -(executable - ((name t) - (libraries - (sequoia - sequoia-mysql)) - (preprocess (pps (sequoia-ppx))))) diff --git a/test/ppx/dune b/test/ppx/dune new file mode 100644 index 0000000..af5e3e2 --- /dev/null +++ b/test/ppx/dune @@ -0,0 +1,20 @@ +(alias + (name runtest) + (deps t.exe)) + +(rule + (target t.ml) + (deps + (:t t.cppo.ml) + (glob_files tables/*.ml) + (glob_files queries/*.ml)) + (action + (chdir ${ROOT} (run cppo %{t} -o %{target})))) + +(executable + (name t) + (libraries + sequoia + sequoia-mysql + sequoia-ppx) + (preprocess (pps sequoia-ppx))) diff --git a/test/ppx/jbuild b/test/ppx/jbuild deleted file mode 100644 index c876b6b..0000000 --- a/test/ppx/jbuild +++ /dev/null @@ -1,22 +0,0 @@ -(jbuild_version 1) - -(alias - ((name runtest) - (deps (t.exe)))) - -(rule - ((targets (t.ml)) - (deps - (t.cppo.ml - (glob_files tables/*.ml) - (glob_files queries/*.ml))) - (action - (chdir ${ROOT} (run ${bin:cppo} -V OCAML:${ocaml_version} ${<} -o ${@}))))) - -(executable - ((name t) - (libraries - (sequoia - sequoia-mysql - sequoia-ppx)) - (preprocess (pps (sequoia-ppx))))) diff --git a/test/ppx/queries/q8.ml b/test/ppx/queries/q8.ml index b7056cc..8777ac8 100644 --- a/test/ppx/queries/q8.ml +++ b/test/ppx/queries/q8.ml @@ -1,6 +1,6 @@ let q8 = let query, params = - Mysql.(Expr.(Update.(Vector.(Expr.(Vector.(OrderBy.Expr.(Vector.( + Mysql.(Expr.(Update.(Vector.(Expr.(OrderBy.(Expr.(Vector.( update User.table ~set: [ User.name, string "John Doe" diff --git a/test/ppx/queries/q9.ml b/test/ppx/queries/q9.ml index 075287d..a224029 100644 --- a/test/ppx/queries/q9.ml +++ b/test/ppx/queries/q9.ml @@ -1,6 +1,6 @@ let q9 = let query, params = Mysql.(Expr.(Delete.(Expr.( - delete ~from:User.table ~where:(field User.name = string "john doe") + delete ~from:User.table ~where:(field User.name = string "john doe") () |> seal )))) in query, params diff --git a/test/ppx/readme/jbuild b/test/ppx/readme/jbuild deleted file mode 100644 index 634d225..0000000 --- a/test/ppx/readme/jbuild +++ /dev/null @@ -1,13 +0,0 @@ -(jbuild_version 1) - -(alias - ((name runtest) - (deps (readme.exe)))) - -(executable - ((name readme) - (libraries - (sequoia - sequoia-mysql - sequoia-ppx)) - (preprocess (pps (sequoia-ppx))))) diff --git a/test/ppx/t.cppo.ml b/test/ppx/t.cppo.ml index 229ba33..d06ab96 100644 --- a/test/ppx/t.cppo.ml +++ b/test/ppx/t.cppo.ml @@ -10,12 +10,15 @@ module Bool = struct (module struct type t = True let to_string = "TRUE" + let _ = True (* avoid warning *) end : Mysql.Enum.Instance) | False -> (module struct type t = False let to_string = "FALSE" - end : Mysql.Enum.Instance) + let _ = False + end : Mysql.Enum.Instance) + end module Tables = struct diff --git a/test/t.ml b/test/t.ml index e23cfc3..c6fbf85 100644 --- a/test/t.ml +++ b/test/t.ml @@ -20,6 +20,9 @@ module Tables = struct let team = Field.foreign_key "team_id" ~references:Team.id let user = Field.foreign_key "user_id" ~references:User.id end + let _ = TeamUser.id (* avoid unused warning *) + let _ = TeamUser.team (* avoid unused warning *) + let _ = TeamUser.user (* avoid unused warning *) module Project = struct include (val Mysql.table "projects") @@ -27,6 +30,8 @@ module Tables = struct let leader = Field.foreign_key "leader_id" ~references:User.id let title = Field.string "title" end + let _ = Project.id + let _ = Project.title end let () =