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.updategenerator;
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 update function for a database model.
20 * Returns:
21 *   The update function string to use with mixin.
22 */
23 string generateUpdate(T : IMySqlModel)()
24 {
25   import models;
26 
27   string s = q{
28     {
29       static const sql = "UPDATE `%s` SET %s WHERE `%s` = ?";
30       auto params = getParams(%s);
31 
32       size_t index;
33 
34       %s
35 
36       %s
37 
38       MySql.executeRaw(sql, params);
39     }
40   };
41 
42   string[] columns;
43   string[] paramsUpdates;
44   string idName;
45   string idParams;
46 
47   {
48     mixin HandleFields!(T, q{{
49       enum hasNoMap = hasUDA!({{fullName}}, DbNoMap);
50       enum hasId = hasUDA!({{fullName}}, DbId);
51 
52       static if (!hasNoMap && !hasId)
53       {
54         columns ~= "`{{fieldName}}` = ?";
55       }
56     }});
57     mixin(handleThem());
58   }
59 
60   if (!columns || !columns.length)
61   {
62     return "";
63   }
64 
65   {
66     mixin HandleFields!(T, q{{
67       enum hasId = hasUDA!({{fullName}}, DbId);
68 
69       static if (hasId)
70       {
71         idName = "{{fieldName}}";
72         idParams = "params[%s] = model.{{fieldName}};".format(columns.length);
73       }
74     }});
75     mixin(handleThem());
76 
77     if (!idName)
78     {
79       return "";
80     }
81   }
82 
83   {
84     mixin HandleFields!(T, q{{
85       enum hasNoMap = hasUDA!({{fullName}}, DbNoMap);
86       enum hasId = hasUDA!({{fullName}}, DbId);
87 
88       static if (!hasNoMap && !hasId)
89       {
90         enum hasEnum = hasUDA!({{fullName}}, DbEnum);
91         enum hasTimestamp = hasUDA!({{fullName}}, DbTimestamp);
92 
93         static if (hasEnum)
94         {
95           paramsUpdates ~= "params[index++] = cast(string)model.{{fieldName}};";
96         }
97         else static if (hasTimestamp)
98         {
99           paramsUpdates ~= `
100            model.timestamp = Clock.currTime().asDateTime();
101            params[index++] = model.timestamp;
102           `;
103         }
104         else static if (is(typeof({{fullName}}) == bool))
105         {
106           paramsUpdates ~= "params[index++] = cast(ubyte)model.{{fieldName}};";
107         }
108         else
109         {
110           paramsUpdates ~= "params[index++] = model.{{fieldName}};";
111         }
112       }
113     }});
114     mixin(handleThem());
115   }
116 
117   if (!paramsUpdates || !paramsUpdates.length)
118   {
119     return "";
120   }
121 
122   return s.format(T.table, columns.join(","), idName, (columns.length + 1), paramsUpdates.join("\r\n"), idParams);
123 }