1 (* C# code generation *)
13 module Values
= G.Values
15 let comment = G.comment
16 let empty_line = G.empty_line
20 output_l
(List.map
(fun str
-> Gen_caml.replace_all ~sub
:"*/" ~by
:"* /" ~str
) sl
);
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"
35 let as_api_type = function
41 | Decimal
-> "Decimal"
42 | Datetime
-> "Datetime"
44 | Unit _
-> assert false
46 let as_lang_type = as_api_type
50 module T
= Translate
(L
)
55 let get_column attr index
=
56 sprintf
"reader.Get%s(%u)"
57 (attr
.domain
|> as_api_type)
60 let schema_to_string = G.Values.to_string $
G.Values.inject $ schema_to_values
62 let output_schema_binder _ schema
=
63 let name = "callback" in
64 output
"public delegate void %s(%s);" name (schema_to_string schema
);
68 let output_schema_binder index schema
=
71 | _
-> Some
(output_schema_binder index schema
)
73 let set_param index param
=
75 let name = default_name
"param" index
in
76 output
"IDbDataParameter %s = _cmd.CreateParameter();" name;
77 output
"%s.ParameterName = \"@%s\";" name id
;
78 output
"%s.DbType = DbType.%s;" name t
; (* FIXME? this is ok because api_type = lang_type *)
79 output
"_cmd.Parameters.Add(%s);" name
81 let output_params_binder params =
82 List.iteri
set_param params;
83 output
"_cmd.Prepare();"
89 let func_execute index stmt
=
90 let params = params_only stmt
.vars
in
91 let values = G.Values.inject
@@ values_of_params
params in
92 let schema_binder_name = output_schema_binder index stmt
.schema
in
93 let is_select = Option.is_some
schema_binder_name in
94 let doc = if is_select then ["result", schema_to_string stmt
.schema
] else [] in
95 comment_xml "execute query" doc;
96 let func_name = if is_select then "execute_reader" else "execute" in
97 let result = "public " ^
if is_select then "IEnumerable<IDataReader>" else "int" in
98 G.func
result func_name values (fun () ->
99 output
"if (null == _cmd)";
101 output
"_cmd = _conn.CreateCommand();";
102 output
"_cmd.CommandText = sql;";
103 output_params_binder values;
105 output
"if (null != CommandTimeout) _cmd.CommandTimeout = CommandTimeout.Value;";
107 (fun i
(name,_
) -> output
"((IDbDataParameter)_cmd.Parameters[%u]).Value = %s;" i
name)
109 begin match schema_binder_name with
110 | None
-> output
"return _cmd.ExecuteNonQuery();"
112 output
"IDataReader reader = _cmd.ExecuteReader();";
113 output
"while (reader.Read())";
115 output
"yield return reader;";
117 output
"reader.Close();";
122 let result = match schema_binder_name with None
-> [] | Some
name -> ["result",name] in
123 let all_params = values @ result in
124 G.func
"public int" "execute" all_params (fun () ->
125 let args = List.mapi
(fun index attr
-> get_column attr index
) stmt
.schema
in
126 output
"int count = 0;";
127 output
"foreach (var reader in execute_reader(%s))" (Values.inline
values);
129 output
"result(%s);" (Values.join
args);
132 output
"return count;"
135 match stmt
.schema
with
137 let t = as_lang_type attr
.domain
in
138 G.func
("public IEnumerable<" ^
t ^
">") "rows" values (fun () ->
139 output
"foreach (var reader in execute_reader(%s))" (Values.inline
values);
141 output
"yield return %s;" (get_column attr
0);
146 List.iteri
(fun index attr
->
147 output
"public readonly %s %s;"
148 (as_lang_type attr
.domain
)
152 G.func
"public" "row" ["reader","IDataReader"] (fun () ->
153 List.iteri
(fun i attr
-> output
"%s = %s;" (name_of attr i
) (get_column attr i
)) stmt
.schema
;
156 G.func
"public IEnumerable<row>" "rows" values (fun () ->
157 output
"foreach (var reader in execute_reader(%s))" (Values.inline
values);
159 output
"yield return new row(reader);";
164 else (* not is_select *)
167 | Insert _
when List.length
values > 1 ->
168 G.func
"public int" "execute<T>" ["v","T"] (fun () ->
169 output
"return execute(%s);" (values |> Values.names
|> List.map
((^
) "v.") |> Values.join
)
175 let generate_code index stmt
=
176 let name = choose_name stmt
.props stmt
.kind index
in
177 let sql = quote (get_sql_string_only stmt
) in
179 output
"IDbCommand _cmd;";
180 output
"IDbConnection _conn;";
181 output
"public int? CommandTimeout;";
182 output
"static string sql = %s;" sql;
184 G.func
"public" name ["db","IDbConnection"] (fun () ->
185 output
"_cmd = null;";
186 output
"_conn = db;";
189 func_execute index stmt
;
193 let generate_all names
=
195 output
"public readonly IDbConnection db;";
196 List.iter
(fun s
-> output
"public %s %s;" s s
) names
;
198 G.func
"public" "all" ["db","IDbConnection"] (fun () ->
199 output
"this.db = db;";
200 List.iter
(fun name -> output
"%s = new %s(db);" name name) names
204 let generate () name stmts
=
205 params_mode
:= Some Named
; (* only named params allowed *)
206 let using = ["System";"System.Data";"System.Collections.Generic"] in
207 List.iter
(fun s
-> output
"using %s;" s
) using;
210 let names = List.mapi
generate_code stmts
in