1 /** 2 * Copyright © DiamondMVC 2019 3 * License: MIT (https://github.com/DiamondMVC/Diamond/blob/master/LICENSE) 4 * Author: Jacob Jensen (bausshf) 5 */ 6 module diamond.data.mapping.engines.mysql.mysqlmodel; 7 8 import std.variant : Variant; 9 alias Column = Variant; 10 11 import std.traits : hasUDA, isSomeString, OriginalType; 12 import std..string : format; 13 14 import vibe.data.serialization : ignore; 15 16 import diamond.data.mapping.engines.mysql.mysqladapter; 17 import diamond.data.mapping.engines.mysql.mysqlentityformatter; 18 import diamond.data.mapping.engines.mysql : dbConnectionString; 19 import diamond.data.mapping.attributes; 20 21 import diamond.database; 22 23 /// Interface for a mysql model. 24 interface IMySqlModel { } 25 26 import diamond.data.mapping.model; 27 /** 28 * Creates a new mysql model. 29 * Params: 30 * tableName = The name of the table the model is associated with. 31 */ 32 class MySqlModel(string tableName) : Model, IMySqlModel 33 { 34 import models; 35 import mysql; 36 37 private: 38 /// The row. 39 Row _row; 40 /// The index. 41 size_t _index; 42 43 public: 44 /// The name of the table associated with the mysql model. 45 @ignore static const string table = tableName; 46 47 final 48 { 49 /// Creates a new mysql model. 50 this(this TModel)() 51 { 52 super(); 53 54 auto adapter = getMySqlAdapter!TModel; 55 56 static const formatter = new MySqlEntityFormatter!TModel; 57 58 auto model = cast(TModel)this; 59 60 mixin("setReader(" ~ formatter.generateRead() ~ ");"); 61 mixin("setInserter(" ~ formatter.generateInsert() ~ ");"); 62 mixin("setUpdater(" ~ formatter.generateUpdate() ~ ");"); 63 mixin("setDeleter(" ~ formatter.generateDelete() ~ ");"); 64 mixin("setReaderRelationship(" ~ formatter.generateReadRelationship() ~ ");"); 65 } 66 67 /** 68 * Retrieves a value from the model's data. 69 * Returns: 70 * The value. 71 */ 72 T retrieve(T, bool nullable = false, bool isEnum = false)() 73 { 74 Column value = Column.init; 75 76 static if (nullable && isEnum) 77 { 78 value = retrieveNullableEnumImpl(); 79 80 if (!value.hasValue) 81 { 82 value = T.init; 83 } 84 else 85 { 86 value = cast(T)value.get!(OriginalType!T); 87 } 88 } 89 else static if (isEnum) 90 { 91 value = cast(T)retrieveEnumImpl().get!(OriginalType!T); 92 } 93 else static if (nullable) 94 { 95 value = retrieveNullableImpl(); 96 97 if (!value.hasValue) 98 { 99 value = T.init; 100 } 101 } 102 else static if (is(T == bool)) 103 { 104 value = retrieveBoolImpl(); 105 } 106 else static if (isSomeString!T) 107 { 108 value = retrieveTextImpl(); 109 } 110 else 111 { 112 value = retrieveDefaultImpl(); 113 } 114 115 moveToNextColumn(); 116 117 if (!value.hasValue) 118 { 119 return T.init; 120 } 121 122 return value.get!T; 123 } 124 125 @property 126 { 127 /// Gets the raw mysql row. 128 @ignore Row row() @system { return _row; } 129 130 /// Sets the raw mysql row. 131 @ignore void row(Row newRow) @system 132 { 133 _row = newRow; 134 } 135 } 136 } 137 138 protected: 139 /// Moves to the next column. 140 void moveToNextColumn() 141 { 142 _index++; 143 } 144 145 /// Retrieves a nullable enum value. 146 Variant retrieveNullableEnumImpl() 147 { 148 Variant value = void; 149 150 if (_row.isNull(_index)) 151 { 152 value = Variant.init; 153 } 154 else 155 { 156 value = _row[_index]; 157 } 158 159 return value; 160 } 161 162 /// Retrieves an enum value. 163 Variant retrieveEnumImpl() 164 { 165 return _row[_index]; 166 } 167 168 /// Retrieves a nullable value. 169 Variant retrieveNullableImpl() 170 { 171 return retrieveNullableEnumImpl(); 172 } 173 174 /// Retrieves a boolean value. 175 bool retrieveBoolImpl() 176 { 177 return cast(bool)_row[_index].get!ubyte; 178 } 179 180 /// Retrieves a text value. 181 string retrieveTextImpl() 182 { 183 return retrieveDefaultImpl().get!string; 184 } 185 186 /// Retrieves any kind of value. 187 Variant retrieveDefaultImpl() 188 { 189 return _row[_index]; 190 } 191 }