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.model; 7 8 import std.traits : hasUDA; 9 import std..string : format; 10 import std.datetime : Date, DateTime, Clock, SysTime; 11 12 import vibe.data.serialization : ignore; 13 14 import diamond.data.mapping.model; 15 import diamond.data.mapping.attributes; 16 import diamond.data.mapping.engines.mysql.generators; 17 import diamond.database : getParams, MySql; 18 19 /// Base-interface for a mysql model. 20 interface IMySqlModel { } 21 22 /** 23 * Converts a SysTime to a DateTime. 24 * Params: 25 * sysTime = The SysTime to convert. 26 * Returns: 27 * The converted DateTime. 28 */ 29 private DateTime asDateTime(SysTime sysTime) 30 { 31 return DateTime(sysTime.year, sysTime.month, sysTime.day, sysTime.hour, sysTime.minute, sysTime.second); 32 } 33 34 /** 35 * Creates a new mysql model. 36 * Params: 37 * tableName = The name of the table the model is associated with. 38 */ 39 class MySqlModel(string tableName) : Model, IMySqlModel 40 { 41 import mysql.result : Row; 42 43 private 44 { 45 /// The row. 46 Row _row; 47 /// The index. 48 size_t _index; 49 50 /** 51 * Retrieves a value from the row. 52 * Params: 53 * T = The type. 54 * nullable = Boolean determining whether the value is nullable or not. 55 * isEnum = Boolean determining whether the value is an enum or not. 56 * column = The column index of the value. 57 * Returns: 58 * The value. 59 */ 60 final T retrieve(T, bool nullable = false, bool isEnum = false)(size_t column) @system 61 { 62 import std.traits : OriginalType; 63 64 static if (nullable && isEnum) 65 { 66 return cast(T)(_row.isNull(column) ? T.init : _row[column].get!(OriginalType!T)); 67 } 68 else static if (isEnum) 69 { 70 return cast(T)(_row[column].get!(OriginalType!T)); 71 } 72 else static if (nullable) 73 { 74 return _row.isNull(column) ? T.init : _row[column].get!T; 75 } 76 else static if (is(T == bool)) 77 { 78 return cast(bool)_row[column].get!ubyte; 79 } 80 else 81 { 82 return _row[column].get!T; 83 } 84 } 85 86 /** 87 * Retrieves a value from the row. 88 * Params: 89 * T = The type. 90 * nullable = Boolean determining whether the value is nullable or not. 91 * isEnum = Boolean determining whether the value is an enum or not. 92 * Returns: 93 * The value. 94 */ 95 final T retrieve(T, bool nullable = false, bool isEnum = false)() @system 96 { 97 auto value = retrieve!(T, nullable, isEnum)(_index); 98 _index++; 99 return value; 100 } 101 } 102 103 public: 104 final: 105 /// The table name. 106 @ignore static const string table = tableName; 107 108 /// Creates a new database model. 109 this(this TModel)() 110 { 111 auto model = cast(TModel)this; 112 113 enum readNullEnumFomat = "model.%s = retrieve!(%s, true, true);"; 114 enum readNullFomat = "model.%s = retrieve!(%s, true, false);"; 115 enum readEnumFomat = "model.%s = retrieve!(%s, false, true);"; 116 enum readBoolFormat = "model.%s = retrieve!(%s);"; 117 enum readFomat = "model.%s = retrieve!(%s);"; 118 119 import models; 120 mixin 121 ( 122 "super(%s, %s, %s, %s);".format 123 ( 124 generateRead!TModel, generateInsert!TModel, 125 generateUpdate!TModel, generateDelete!TModel 126 ) 127 ); 128 } 129 130 @property 131 { 132 /// Gets the raw row. 133 @ignore Row row() @system { return _row; } 134 135 /// Sets the native row. Settings this manually outside the engine is undefined-behavior. 136 @ignore void row(Row newRow) @system 137 { 138 _row = newRow; 139 } 140 } 141 }