tweak
[sqlgg.git] / gen_csharp.ml
blobec6856b480cca2768bf5ecd33e9b975b28b35339
1 (* C# code generation *)
3 open ExtList
4 open ExtString
5 open Operators
6 open Printf
8 open Stmt
9 open Gen
10 open Sql
12 module G = Gen_cxx
13 module J = Gen_java
15 let comment = G.comment
16 let empty_line = G.empty_line
18 let comment_doc sl =
19 output "/**";
20 output_l (List.map (fun str -> Gen_caml.replace_all ~sub:"*/" ~by:"* /" ~str) sl);
21 output "*/"
23 let comment_xml summary params =
24 let summary = String.nsplit summary "\n" in
25 let params = List.map (fun (n,s) -> sprintf "<param name=\"%s\">%s</param>" n s) params in
26 comment_doc ("<summary>" :: summary @ ("</summary>" :: params))
28 let (start_class,end_class) = J.start_class,J.end_class
29 let (start_ns,end_ns) = J.start_ "namespace"
31 let quote = String.replace_chars (function '\n' -> "\" +\n\"" | '\r' -> "" | '"' -> "\\\"" | c -> String.make 1 c)
32 let quote s = "\"" ^ quote s ^ "\""
34 let as_db_type = function
35 | Type.Int -> "Int64"
36 | Type.Text -> "String"
37 | Type.Float -> "Float"
38 | Type.Blob -> "String"
39 | Type.Bool -> "Boolean"
40 | Type.Datetime -> "Datetime"
42 let as_cs_type = as_db_type
44 let get_column attr index =
45 sprintf "reader.Get%s(%u)"
46 (attr.RA.domain >> as_db_type)
47 index
49 let param_type_to_string t = t >> Option.default Type.Text >> as_db_type
51 let schema_to_values = List.mapi (fun i attr -> name_of attr i, attr.RA.domain >> as_cs_type)
52 let schema_to_string schema = schema >> schema_to_values >> G.Values.to_string
54 let output_schema_binder index schema =
55 let name = "callback" in
56 output "public delegate void %s(%s);" name (schema_to_string schema);
57 empty_line ();
58 name
60 let output_schema_binder index schema =
61 match schema with
62 | [] -> None
63 | _ -> Some (output_schema_binder index schema)
65 let params_to_values = List.mapi (fun i (n,t) -> param_name_to_string n i, t >> param_type_to_string)
66 let params_to_values = List.unique & params_to_values
68 let set_param index param =
69 let (id,t) = param in
70 let name = default_name "param" index in
71 (* FIXME unnamed params *)
72 output "IDbDataParameter %s = cmd.CreateParameter();" name;
73 output "%s.ParameterName = \"@%s\";" name (param_name_to_string id index);
74 output "%s.DbType = DbType.%s;" name (param_type_to_string t);
75 output "cmd.Parameters.Add(%s);" name
77 let output_params_binder params =
78 List.iteri set_param params;
79 output "cmd.Prepare();"
81 type t = unit
83 let start () = ()
85 let generate_code index stmt =
86 let values = params_to_values stmt.params in
87 let name = choose_name stmt.props stmt.kind index in
88 let sql = quote (get_sql stmt) in
89 start_class name;
90 output "IDbCommand cmd;";
91 output "static string sql = %s;" sql;
92 empty_line ();
93 G.func "public" name ["db","IDbConnection"] (fun () ->
94 output "cmd = db.CreateCommand();";
95 output "cmd.CommandText = sql;";
96 output_params_binder stmt.params;
98 empty_line ();
99 let schema_binder_name = output_schema_binder index stmt.schema in
100 let result = match schema_binder_name with None -> [] | Some name -> ["result",name] in
101 let all_params = values @ result in
102 let doc = match schema_binder_name with None -> [] | Some _ -> ["result", schema_to_string stmt.schema] in
103 comment_xml "execute query" doc;
104 G.func "public int" "execute" all_params (fun () ->
105 List.iteri
106 (fun i (name,_) -> output "((IDbDataParameter)cmd.Parameters[%u]).Value = %s;" i name)
107 values;
108 begin match schema_binder_name with
109 | None -> output "return cmd.ExecuteNonQuery();"
110 | Some name ->
111 output "IDataReader reader = cmd.ExecuteReader();";
112 let args = List.mapi (fun index attr -> get_column attr index) stmt.schema in
113 let args = String.concat "," args in
114 output "int count = 0;";
115 output "while (reader.Read())";
116 G.open_curly ();
117 output "result(%s);" args;
118 output "count++;";
119 G.close_curly "";
120 output "reader.Close();";
121 output "return count;"
122 end);
123 end_class name;
124 name
126 let generate_all names =
127 start_class "all";
128 List.iter (fun s -> output "public %s %s;" s s) names;
129 empty_line ();
130 G.func "public" "all" ["db","IDbConnection"] (fun () ->
131 List.iter (fun name -> output "%s = new %s(db);" name name) names
133 end_class "all"
135 let generate () name stmts =
136 params_mode := Some Named; (* only named params allowed *)
137 output "using System;";
138 output "using System.Data;";
139 empty_line ();
140 start_ns name;
141 let names = List.mapi generate_code (List.of_enum stmts) in
142 generate_all names;
143 end_ns name