fix multiline SQL in Java
[sqlgg.git] / gen_csharp.ml
blob517bf9c96ffaf3188d1d19f2458c0ac96c6c314d
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 = J.quote
33 let as_db_type = function
34 | Type.Int -> "Int64"
35 | Type.Text -> "String"
36 | Type.Float -> "Float"
37 | Type.Blob -> "String"
38 | Type.Bool -> "Boolean"
39 | Type.Datetime -> "Datetime"
41 let as_cs_type = as_db_type
43 let get_column attr index =
44 sprintf "reader.Get%s(%u)"
45 (attr.RA.domain >> as_db_type)
46 index
48 let param_type_to_string t = t >> Option.default Type.Text >> as_db_type
50 let schema_to_values = List.mapi (fun i attr -> name_of attr i, attr.RA.domain >> as_cs_type)
51 let schema_to_string schema = schema >> schema_to_values >> G.Values.to_string
53 let output_schema_binder index schema =
54 let name = "callback" in
55 output "public delegate void %s(%s);" name (schema_to_string schema);
56 empty_line ();
57 name
59 let output_schema_binder index schema =
60 match schema with
61 | [] -> None
62 | _ -> Some (output_schema_binder index schema)
64 let params_to_values = List.mapi (fun i (n,t) -> param_name_to_string n i, t >> param_type_to_string)
65 let params_to_values = List.unique & params_to_values
67 let set_param index param =
68 let (id,t) = param in
69 let name = default_name "param" index in
70 (* FIXME unnamed params *)
71 output "IDbDataParameter %s = _cmd.CreateParameter();" name;
72 output "%s.ParameterName = \"@%s\";" name (param_name_to_string id index);
73 output "%s.DbType = DbType.%s;" name (param_type_to_string t);
74 output "_cmd.Parameters.Add(%s);" name
76 let output_params_binder params =
77 List.iteri set_param params;
78 output "_cmd.Prepare();"
80 type t = unit
82 let start () = ()
84 let generate_code index stmt =
85 let values = params_to_values stmt.params in
86 let name = choose_name stmt.props stmt.kind index in
87 let sql = quote (get_sql stmt) in
88 start_class name;
89 output "IDbCommand _cmd;";
90 output "IDbConnection _conn;";
91 output "static string sql = %s;" sql;
92 empty_line ();
93 G.func "public" name ["db","IDbConnection"] (fun () ->
94 output "_cmd = null;";
95 output "_conn = db;";
97 empty_line ();
98 let schema_binder_name = output_schema_binder index stmt.schema in
99 let result = match schema_binder_name with None -> [] | Some name -> ["result",name] in
100 let all_params = values @ result in
101 let doc = match schema_binder_name with None -> [] | Some _ -> ["result", schema_to_string stmt.schema] in
102 comment_xml "execute query" doc;
103 G.func "public int" "execute" all_params (fun () ->
104 output "if (null == _cmd)";
105 output "{"; inc_indent ();
106 output "_cmd = _conn.CreateCommand();";
107 output "_cmd.CommandText = sql;";
108 output_params_binder stmt.params;
109 dec_indent (); output "}";
110 List.iteri
111 (fun i (name,_) -> output "((IDbDataParameter)_cmd.Parameters[%u]).Value = %s;" i name)
112 values;
113 begin match schema_binder_name with
114 | None -> output "return _cmd.ExecuteNonQuery();"
115 | Some name ->
116 output "IDataReader reader = _cmd.ExecuteReader();";
117 let args = List.mapi (fun index attr -> get_column attr index) stmt.schema in
118 let args = String.concat "," args in
119 output "int count = 0;";
120 output "while (reader.Read())";
121 G.open_curly ();
122 output "result(%s);" args;
123 output "count++;";
124 G.close_curly "";
125 output "reader.Close();";
126 output "return count;"
127 end);
128 end_class name;
129 name
131 let generate_all names =
132 start_class "all";
133 List.iter (fun s -> output "public %s %s;" s s) names;
134 empty_line ();
135 G.func "public" "all" ["db","IDbConnection"] (fun () ->
136 List.iter (fun name -> output "%s = new %s(db);" name name) names
138 end_class "all"
140 let generate () name stmts =
141 params_mode := Some Named; (* only named params allowed *)
142 output "using System;";
143 output "using System.Data;";
144 empty_line ();
145 start_ns name;
146 let names = List.mapi generate_code (List.of_enum stmts) in
147 generate_all names;
148 end_ns name