1 /**
2 * Copyright © DiamondMVC 2018
3 * License: MIT (https://github.com/DiamondMVC/Diamond/blob/master/LICENSE)
4 * Author: Jacob Jensen (bausshf)
5 */
6 module diamond.data.mapping.engines.mysql.generators.insertgenerator;
7 
8 import std..string : format;
9 import std.traits : hasUDA, FieldNameTuple;
10 import std.algorithm : map;
11 import std.array : join, array;
12 
13 import diamond.core.traits;
14 import diamond.data.mapping.attributes;
15 import diamond.data.mapping.engines.mysql.model : IMySqlModel;
16 
17 package(diamond.data):
18 /**
19 * Generates the insert function for a database model.
20 * Returns:
21 *   The insert function string to use with mixin.
22 */
23 string generateInsert(T : IMySqlModel)()
24 {
25   import models;
26 
27   string s = q{
28     {
29       static const sql = "INSERT INTO `%s` (%s) VALUES (%s)";
30       auto params = getParams(%s);
31 
32       size_t index;
33 
34       %s
35 
36       %s
37     }
38   };
39 
40   string[] columns;
41   string[] paramsInserts;
42   string idName;
43   string idType;
44   string execution;
45 
46   {
47     mixin HandleFields!(T, q{{
48       enum hasId = hasUDA!({{fullName}}, DbId);
49 
50       static if (hasId)
51       {
52         idName = "{{fieldName}}";
53         idType = typeof({{fullName}}).stringof;
54       }
55     }});
56     mixin(handleThem());
57 
58     if (idName)
59     {
60       execution = "model.%s = MySql.scalarInsertRaw!%s(sql, params);".format(idName, idType);
61     }
62     else
63     {
64       execution = "MySql.executeRaw(sql, params);";
65     }
66   }
67 
68   {
69     mixin HandleFields!(T, q{{
70       enum hasNoMap = hasUDA!({{fullName}}, DbNoMap);
71       enum hasId = hasUDA!({{fullName}}, DbId);
72 
73       static if (!hasNoMap && !hasId)
74       {
75         columns ~= "`{{fieldName}}`";
76       }
77     }});
78     mixin(handleThem());
79   }
80 
81   if (!columns || !columns.length)
82   {
83     return "";
84   }
85 
86   {
87     mixin HandleFields!(T, q{{
88       enum hasNoMap = hasUDA!({{fullName}}, DbNoMap);
89       enum hasId = hasUDA!({{fullName}}, DbId);
90 
91       static if (!hasNoMap && !hasId)
92       {
93         enum hasEnum = hasUDA!({{fullName}}, DbEnum);
94         enum hasTimestamp = hasUDA!({{fullName}}, DbTimestamp);
95 
96         static if (hasEnum)
97         {
98           paramsInserts ~= "params[index++] = cast(string)model.{{fieldName}};";
99         }
100         else static if (hasTimestamp)
101         {
102           paramsInserts ~= `
103            model.timestamp = Clock.currTime().asDateTime();
104            params[index++] = model.timestamp;
105           `;
106         }
107         else static if (is(typeof({{fullName}}) == bool))
108         {
109           paramsInserts ~= "params[index++] = cast(ubyte)model.{{fieldName}};";
110         }
111         else
112         {
113           paramsInserts ~= "params[index++] = model.{{fieldName}};";
114         }
115       }
116     }});
117     mixin(handleThem());
118   }
119 
120   if (!paramsInserts || !paramsInserts.length)
121   {
122     return "";
123   }
124 
125   return s.format(T.table, columns.join(","), columns.map!(c => "?").array.join(","), columns.length, paramsInserts.join("\r\n"), execution);
126 }