1 (* C# code generation *)
12 module Values
= G.Values
14 let comment = G.comment
15 let empty_line = G.empty_line
19 output_l
(List.map
(fun str
-> Gen_caml.replace_all ~sub
:"*/" ~by
:"* /" ~str
) sl
);
22 let comment_xml summary params
=
23 let summary = String.nsplit
summary "\n" in
24 let params = List.map
(fun (n
,s
) -> sprintf
"<param name=\"%s\">%s</param>" n s
) params in
25 comment_doc ("<summary>" :: summary @ ("</summary>" :: params))
27 let (start_class
,end_class
) = J.start_class
,J.end_class
28 let (start_ns
,end_ns
) = J.start_
"namespace"
34 let as_api_type = function
36 | Type.Text
-> "String"
37 | Type.Float
-> "Float"
38 | Type.Blob
-> "String"
39 | Type.Bool
-> "Boolean"
40 | Type.Datetime
-> "Datetime"
41 | Type.Any
-> "String"
43 let as_lang_type = as_api_type
47 module T
= Translate
(L
)
52 let get_column attr index
=
53 sprintf
"reader.Get%s(%u)"
54 (attr
.domain
|> as_api_type)
57 let schema_to_string = G.Values.to_string $ schema_to_values
59 let output_schema_binder _ schema
=
60 let name = "callback" in
61 output
"public delegate void %s(%s);" name (schema_to_string schema
);
65 let output_schema_binder index schema
=
68 | _
-> Some
(output_schema_binder index schema
)
70 let set_param index param
=
72 let name = default_name
"param" index
in
73 output
"IDbDataParameter %s = _cmd.CreateParameter();" name;
74 output
"%s.ParameterName = \"@%s\";" name id
;
75 output
"%s.DbType = DbType.%s;" name t
; (* FIXME? this is ok because api_type = lang_type *)
76 output
"_cmd.Parameters.Add(%s);" name
78 let output_params_binder params =
79 List.iteri
set_param params;
80 output
"_cmd.Prepare();"
86 let func_execute index stmt
=
87 let values = params_to_values stmt
.params in
88 let schema_binder_name = output_schema_binder index stmt
.schema
in
89 let is_select = Option.is_some
schema_binder_name in
90 let doc = if is_select then ["result", schema_to_string stmt
.schema
] else [] in
91 comment_xml "execute query" doc;
92 let func_name = if is_select then "execute_reader" else "execute" in
93 let result = "public " ^
if is_select then "IEnumerable<IDataReader>" else "int" in
94 G.func
result func_name values (fun () ->
95 output
"if (null == _cmd)";
97 output
"_cmd = _conn.CreateCommand();";
98 output
"_cmd.CommandText = sql;";
99 output_params_binder values;
101 output
"if (null != CommandTimeout) _cmd.CommandTimeout = CommandTimeout.Value;";
103 (fun i
(name,_
) -> output
"((IDbDataParameter)_cmd.Parameters[%u]).Value = %s;" i
name)
105 begin match schema_binder_name with
106 | None
-> output
"return _cmd.ExecuteNonQuery();"
108 output
"IDataReader reader = _cmd.ExecuteReader();";
109 output
"while (reader.Read())";
111 output
"yield return reader;";
113 output
"reader.Close();";
118 let result = match schema_binder_name with None
-> [] | Some
name -> ["result",name] in
119 let all_params = values @ result in
120 G.func
"public int" "execute" all_params (fun () ->
121 let args = List.mapi
(fun index attr
-> get_column attr index
) stmt
.schema
in
122 output
"int count = 0;";
123 output
"foreach (var reader in execute_reader(%s))" (Values.inline
values);
125 output
"result(%s);" (Values.join
args);
128 output
"return count;"
131 match stmt
.schema
with
133 let t = as_lang_type attr
.domain
in
134 G.func
("public IEnumerable<" ^
t ^
">") "rows" values (fun () ->
135 output
"foreach (var reader in execute_reader(%s))" (Values.inline
values);
137 output
"yield return %s;" (get_column attr
0);
142 List.iteri
(fun index attr
->
143 output
"public readonly %s %s;"
144 (as_lang_type attr
.domain
)
148 G.func
"public" "row" ["reader","IDataReader"] (fun () ->
149 List.iteri
(fun i attr
-> output
"%s = %s;" (name_of attr i
) (get_column attr i
)) stmt
.schema
;
152 G.func
"public IEnumerable<row>" "rows" values (fun () ->
153 output
"foreach (var reader in execute_reader(%s))" (Values.inline
values);
155 output
"yield return new row(reader);";
160 else (* not is_select *)
163 | Insert _
when List.length
values > 1 ->
164 G.func
"public int" "execute<T>" ["v","T"] (fun () ->
165 output
"return execute(%s);" (values |> Values.names
|> List.map
((^
) "v.") |> Values.join
)
171 let generate_code index stmt
=
172 let name = choose_name stmt
.props stmt
.kind index
in
173 let sql = quote (get_sql stmt
) in
175 output
"IDbCommand _cmd;";
176 output
"IDbConnection _conn;";
177 output
"public int? CommandTimeout;";
178 output
"static string sql = %s;" sql;
180 G.func
"public" name ["db","IDbConnection"] (fun () ->
181 output
"_cmd = null;";
182 output
"_conn = db;";
185 func_execute index stmt
;
189 let generate_all names
=
191 output
"public readonly IDbConnection db;";
192 List.iter
(fun s
-> output
"public %s %s;" s s
) names
;
194 G.func
"public" "all" ["db","IDbConnection"] (fun () ->
195 output
"this.db = db;";
196 List.iter
(fun name -> output
"%s = new %s(db);" name name) names
200 let generate () name stmts
=
201 params_mode
:= Some Named
; (* only named params allowed *)
202 let using = ["System";"System.Data";"System.Collections.Generic"] in
203 List.iter
(fun s
-> output
"using %s;" s
) using;
206 let names = List.mapi
generate_code stmts
in