11 type param
= string * string
15 String.concat
", " (List.map
(fun (t
,n
) -> t ^
" " ^ n
) x
)
18 String.concat
", " (List.map
(fun (t
,n
) -> n
) x
)
23 let output s
= print_string
(String.make
!indent ' '
); print_endline s
24 let out_shr () = indent := !indent + 2
25 let out_shl () = indent := !indent - 2
26 let open_curly () = output "{"; out_shr ()
27 let close_curly s
= out_shl (); output ("}" ^ s
)
28 let start_struct name
=
29 output (sprintf
"struct %s" name
);
32 close_curly (sprintf
"; // struct %s" name
);
34 let out_public () = out_shl (); output "public:"; out_shr ()
35 let out_private () = out_shl (); output "private:"; out_shr ()
37 let generate_header () =
38 output "// DO NOT EDIT MANUALLY";
40 output "// generated by sql2cpp";
42 output "#pragma once";
45 let ns_name table
= table
.Table.cpp_name
46 let item_name _
= "row"
47 let prefix_name _
= ""
49 let binder_code col index
=
50 sprintf
"Traits::bind_column_%s(stmt, %u, obj.%s);"
51 (Col.type_to_string col
)
55 let param_binder_code index
(name
,t
) =
56 sprintf
"Traits::bind_param_%s(stmt, %s_, %u);"
61 let binder_code_to col index
=
62 if Col.is_primary_key col
then
63 sprintf
"Traits::bind_param_null(stmt, %u);" index
65 sprintf
"Traits::bind_param_%s(stmt, obj.%s, %u);"
66 (Col.type_to_string col
)
71 let output_columns_binder table columns binder_index
=
72 let name = sprintf
"binder_%u" binder_index
in
75 output (sprintf
"typedef %s value_type;" (item_name table
));
76 output (sprintf
"static void of_stmt(sqlite3_stmt* stmt, %s& obj)" (item_name table
));
79 (fun index
(col
,tbl
) -> assert(tbl
=table
); output (binder_code col index
))
82 output (sprintf
"static void to_stmt(sqlite3_stmt* stmt, const %s& obj)" (item_name table
));
85 (fun index
(col
,tbl
) -> assert(tbl
=table
); output (binder_code_to col
(index
+ 1)))
91 let generate_table_code table
=
93 start_struct (item_name table
);
95 (fun col
-> output (sprintf
"%s %s;" (Col.type_to_cpp_string col
) col
.Col.cpp_name
))
97 end_struct (item_name table
)
99 let make_const_params inputs
=
100 (List.map
(fun (name,t
) -> (sprintf
"const %s&" (Type.to_cpp_string t
)),name) inputs
)
102 let output_extra_param_defs placeholders
=
103 List.iter
(fun (name,t
) -> output (sprintf
"const %s& %s_;" (Type.to_cpp_string t
) name)) placeholders
105 let output_extra_params_init names
=
108 | _
-> output (" : " ^
(String.concat
"," (List.map
(fun name -> sprintf
"%s_(%s)" name name) names
)))
110 let output_params_binder binder_index cols_binder ofs inputs
=
112 let name = (sprintf
"params_binder_%u" binder_index
) in
114 output_extra_param_defs inputs
;
115 begin match cols_binder
with
116 | Some binder
-> output (sprintf
"const row& obj_;")
120 let params = (match cols_binder
with | Some binder
-> [sprintf
"const row&","obj"] | None
-> []) @
121 (make_const_params inputs
)
123 output (sprintf
"%s(%s)" name (Cpp.Params.to_string params));
124 let names = List.map
(fun (name,_
) -> name) inputs
in
125 let names = (match cols_binder
with | Some _
-> "obj"::names | None
-> names) in
126 output_extra_params_init names;
130 output (sprintf
"void set_params(sqlite3_stmt* stmt)");
132 begin match cols_binder
with
133 | Some binder
-> output (sprintf
"%s::to_stmt(stmt,obj_);" binder
)
136 List.iteri
(fun index param
-> output (param_binder_code (index
+1+ofs
) param
)) inputs
;
142 let make_params_binder index table cols inputs
=
143 let binder_name = (match cols
with
145 | _
-> Some
(output_columns_binder table cols index
))
147 match binder_name,inputs
with
148 | None
,[] -> "typename Traits::no_params"
149 | _
,_
-> output_params_binder index
binder_name (List.length cols
) inputs
151 let make_name props default
=
152 match Props.get props
"name" with
156 let default_name table str index
= sprintf
"%s%s_%u" (prefix_name table
) str index
158 let generate_select_code table inputs outputs index props sql
=
159 let binder_name = output_columns_binder table outputs index
in
160 let params_binder_name = make_params_binder index table
[] inputs
in
162 output "template<class T>";
163 let params = Cpp.Params.to_string
164 (["sqlite3*","db"; "T&","result"] @ (make_const_params inputs
))
166 let name = make_name props
(default_name table
"select" index
) in
168 (sprintf
"static bool %s(%s)" name params);
171 (sprintf
"return Traits::do_select(db,result,_T(\"%s\"),%s(),%s(%s));"
172 sql
binder_name params_binder_name (Cpp.Params.inline (make_const_params inputs
)));
176 let generate_insert_code columns table index (placeholders,props) sql =
178 let name = make_name props (default_name table "insert" index) in
179 output (sprintf "static bool %s(sqlite3* db, const %s& val)" name (item_name table));
181 output (sprintf "return Traits::do_insert<binder_%s>(db,val,_T(\"%s\"));" (item_name table) sql);
186 let generate_modify_code table cols inputs index props sql
=
187 (* if there is only one input column - do not require full object as a param *)
188 let (cols
,inputs
) = match cols
with
189 | [(x
,_
)] -> [],(x
.Sql.Col.name,x
.Sql.Col.sqltype
)::inputs
192 let params_binder_name = make_params_binder index table cols inputs
in
194 let data_params = make_const_params inputs
in
195 let data_params = (match cols
with
197 | _
-> ((sprintf
"const %s&" (item_name table
)),"val")::data_params)
199 let params = Cpp.Params.to_string (("sqlite3*","db") :: data_params) in
200 let name = make_name props
(default_name table
"modify" index
) in
201 output (sprintf
"static int %s(%s)" name params);
203 output (sprintf
"return Traits::do_execute(db,\"%s\",%s(%s));" sql
204 params_binder_name (Cpp.Params.inline data_params));
208 let generate_delete_code table inputs index props sql
=
209 let params_binder_name = make_params_binder index table
[] inputs
in
211 let data_params = make_const_params inputs
in
212 let params = Cpp.Params.to_string (("sqlite3*","db") :: data_params) in
213 let name = make_name props
(default_name table
"delete" index
) in
214 output (sprintf
"static int %s(%s)" name params);
216 output (sprintf
"return Traits::do_execute(db,\"%s\",%s(%s));" sql
217 params_binder_name (Cpp.Params.inline data_params));
221 let generate_create_code table sql
=
223 output (sprintf
"static int %screate(sqlite3* db)" (prefix_name table
));
225 output (sprintf
"return Traits::do_execute(db,\"%s\",typename Traits::no_params());" sql
);
231 let generate_code index stmt
=
232 let (kind
,table
,props
,sql
) = stmt
in
234 | Stmt.Create
-> generate_table_code table
;
235 generate_create_code table sql
236 | Stmt.Select
(outputs
,exprs
,inputs
) ->
237 generate_select_code table inputs outputs index props sql
238 | Stmt.Modify
(cols
,inputs
) -> generate_modify_code table cols inputs index props sql
239 | Stmt.Delete
(inputs
) -> generate_delete_code table inputs index props sql
241 let rec do_process stmts
=
245 let (some
, other
) = List.partition
(fun (_
,table
,_
,_
) -> table
= t
) stmts
in
246 output "template<class Traits>";
247 start_struct (ns_name t
);
248 List.iteri
generate_code some
;
249 end_struct (ns_name t
);
252 output "namespace sql2cpp";
255 close_curly " // namespace sql2cpp"