1 module hunt.entity.eql.EqlInfo; 2 3 import hunt.entity.EntityDeserializer; 4 import hunt.entity.eql.Common; 5 import hunt.entity.dialect; 6 import hunt.logging; 7 8 import hunt.entity.EntityInfoMaker; 9 10 import std.array; 11 import std.format; 12 import std.traits; 13 import std.range; 14 15 class EqlObject 16 { 17 private string _className; 18 private string _tableName; 19 private string _name; 20 private Object[] _selectItem; 21 22 this(string name , string clsName = null) 23 { 24 _name = name; 25 _className = clsName; 26 } 27 28 string className() { return _className ;} 29 30 void setClassName(string name) 31 { 32 _className = name; 33 } 34 35 string tableName() { return _tableName; } 36 void setTableName(string tbName) 37 { 38 _tableName = tbName; 39 } 40 41 void putSelectItem( Object o) 42 { 43 _selectItem ~= o; 44 } 45 46 Object[] getSelectItems() 47 { 48 return _selectItem; 49 } 50 51 override string toString() 52 { 53 return "( ObjName : %s , ClsName : %s , TableName : %s )".format(_name,_className,_tableName); 54 } 55 } 56 57 58 import hunt.entity; 59 import hunt.entity.DefaultEntityManagerFactory; 60 61 import hunt.logging; 62 63 import std.conv; 64 import std.string; 65 import std.traits; 66 import std.variant; 67 68 class EqlInfo(T : Object, F : Object = T) { 69 70 private EntityFieldInfo[string] _fields; 71 private string _factoryName = defaultEntityManagerFactoryName(); 72 private string _tableName; 73 private string _tableNameInLower; // for PostgreSQL, the column's name will be converted to lowercase. 74 private string _entityClassName; 75 private string _autoIncrementKey; 76 private string _primaryKey; 77 private EntityManager _manager; 78 private Dialect _dialect; 79 private T _data; 80 private F _owner; 81 private string _tablePrefix; 82 83 private EntityMetaInfo _metaInfo; 84 85 private Object[string] _joinConds; 86 87 88 // pragma(msg, "T = "~T.stringof~ " F = "~F.stringof); 89 // pragma(msg,makeImport!(T)()); 90 // pragma(msg,makeInitEntityData!(T,F)); 91 // pragma(msg,makeDeserializer!(T)); 92 // pragma(msg,makeSetIncreaseKey!(T)); 93 // pragma(msg,makeGetPrimaryValue!(T)); 94 // pragma(msg,makeSetPrimaryValue!(T)()); 95 96 mixin(makeImport!(T)()); 97 mixin(makeInitEntityData!(T,F)()); 98 mixin(makeJoinConds!(T,F)()); 99 mixin(makeDeserializer!(T)()); 100 mixin(makeSetIncreaseKey!(T)()); 101 mixin(makeGetPrimaryValue!(T)()); 102 mixin(makeSetPrimaryValue!(T)()); 103 104 this(EntityManager manager = null, T t = null, F owner = null) 105 { 106 if (t is null) { 107 _data = new T(); 108 } 109 else { 110 _data = t; 111 } 112 static if (is(T == F)){ 113 _owner = _data; 114 } 115 else{ 116 _owner = owner; 117 } 118 _manager = manager; 119 if (_manager) { 120 _data.setManager(_manager); 121 _tablePrefix = _manager.getPrefix(); 122 } 123 initializeEntityInfo(); 124 125 } 126 127 128 private void initializeEntityInfo() { 129 // _metaInfo = extractEntityInfo!(T)(); 130 _metaInfo = T.metaInfo; // extractEntityInfo!(T)(); 131 132 _entityClassName = _metaInfo.simpleName; 133 _tableName = _tablePrefix ~ _metaInfo.tableName; 134 _tableNameInLower = _tableName.toLower(); 135 136 initEntityData(); 137 initJoinConds(); 138 } 139 140 EntityFieldInfo getPrimaryField() { 141 if (_primaryKey.length > 0) 142 return _fields[_primaryKey]; 143 return null; 144 } 145 146 147 EntityFieldInfo opDispatch(string name)() 148 { 149 EntityFieldInfo info = _fields.get(name,null); 150 if (info is null) 151 throw new EntityException("Cannot find entityfieldinfo by name : " ~ name); 152 return info; 153 } 154 155 string getFactoryName() { return _factoryName; }; 156 string getEntityClassName() { return _entityClassName; } 157 string getTableName() { return _tableName; } 158 string getAutoIncrementKey() { return _autoIncrementKey; } 159 EntityFieldInfo[string] getFields() { return _fields; } 160 string getPrimaryKeyString() { return _primaryKey; } 161 EntityFieldInfo getSingleField(string name) { return _fields.get(name,null); } 162 string getJoinCond(string member) { 163 auto cond = _joinConds.get(member,null); 164 return cond !is null ? cond.toString() : null; 165 } 166 Object[string] getJoinConds() { 167 return _joinConds; 168 } 169 170 171 private string toColumnName(string fieldName) { 172 return _metaInfo.columnName(fieldName); 173 } 174 175 private string getCountAsName() { 176 if(_manager.getDbOption().isPgsql()) { 177 return EntityExpression.getCountAsName(_tableNameInLower); 178 } else { 179 return EntityExpression.getCountAsName(_tableName); 180 } 181 } 182 } 183 184 185 string makeSetPrimaryValue(T)() { 186 string R; 187 string name; 188 foreach(memberName; __traits(derivedMembers, T)) { 189 static if (__traits(getProtection, __traits(getMember, T, memberName)) == "public") { 190 alias memType = typeof(__traits(getMember, T ,memberName)); 191 static if (!isFunction!(memType) && hasUDA!(__traits(getMember, T ,memberName), PrimaryKey)) { 192 R = typeof(__traits(getMember, T ,memberName)).stringof; 193 name = memberName; 194 } 195 } 196 } 197 return ` 198 public void setPrimaryValue(string value) { 199 _data.`~name~` = value.to!`~R~`; 200 }`; 201 } 202 203 204 string makeGetPrimaryValue(T)() { 205 string R; 206 string name; 207 foreach(memberName; __traits(derivedMembers, T)) { 208 static if (__traits(getProtection, __traits(getMember, T, memberName)) == "public") { 209 alias memType = typeof(__traits(getMember, T ,memberName)); 210 static if (!isFunction!(memType) && hasUDA!(__traits(getMember, T ,memberName), PrimaryKey)) { 211 R = typeof(__traits(getMember, T ,memberName)).stringof; 212 name = memberName; 213 } 214 } 215 } 216 return ` 217 public `~R~` getPrimaryValue() { 218 return _data.`~name~`; 219 }`; 220 } 221 222 string makeSetIncreaseKey(T)() { 223 string name; 224 foreach(memberName; __traits(derivedMembers, T)) { 225 static if (__traits(getProtection, __traits(getMember, T, memberName)) == "public") { 226 alias memType = typeof(__traits(getMember, T ,memberName)); 227 static if (!isFunction!(memType) && (hasUDA!(__traits(getMember, T ,memberName), AutoIncrement) || hasUDA!(__traits(getMember, T ,memberName), Auto))) { 228 name = memberName; 229 } 230 } 231 } 232 if (name == "") 233 return ` 234 public void setIncreaseKey(ref T entity, int value) { 235 }`; 236 else 237 return ` 238 public void setIncreaseKey(ref T entity, int value) { 239 entity.`~name~` = value; 240 }`; 241 } 242 243 private string makeJoinConds(T, F)() { 244 string str = ` 245 private void initJoinConds() {`; 246 247 static foreach (string memberName; FieldNameTuple!T) {{ 248 alias currentMember = __traits(getMember, T, memberName); 249 250 static if (__traits(getProtection, currentMember) != "public") { 251 enum isEntityMember = false; 252 } else static if(hasUDA!(currentMember, Transient)) { 253 enum isEntityMember = false; 254 } else { 255 enum isEntityMember = true; 256 } 257 258 static if (isEntityMember) { 259 alias memType = typeof(currentMember); 260 string columnName; 261 string referencedColumnName; 262 263 static if (hasUDA!(currentMember, JoinColumn) && is(memType == class)) { 264 columnName = "\""~getUDAs!(currentMember, JoinColumn)[0].name~"\""; 265 referencedColumnName = "\""~getUDAs!(currentMember, JoinColumn)[0].referencedColumnName~"\""; 266 267 str ~= ` 268 { 269 EntityMetaInfo memberMetaInfo = ` ~ memType.stringof ~ `.metaInfo; 270 string rightTableName = _tablePrefix ~ memberMetaInfo.tableName; 271 auto joinCond = new JoinCond(_tableName, ` ~ 272 memberName.stringof~ `, ` ~ columnName ~ `,` ~ referencedColumnName ~ 273 `, rightTableName, memberMetaInfo.primaryKey); 274 _joinConds[_entityClassName ~ "." ~ ` ~ memberName.stringof ~ `] = joinCond; 275 } 276 `; 277 } 278 } 279 }} 280 281 str ~=` 282 }`; 283 return str; 284 } 285 286 287 /** 288 * 289 */ 290 class JoinCond 291 { 292 private string _joinCond; 293 294 this(string leftTable, string fieldName, string joinCol, string referencedColumnName, 295 string rightTable, string rightTablePrimaryKey) 296 { 297 version(HUNT_ENTITY_DEBUG) { 298 hunt.logging.warningf("leftTable: %s, fieldName: %s, joinCol: %s, referencedColumn: %s, rightTable: %s", 299 leftTable, fieldName, joinCol, referencedColumnName, rightTable); 300 } 301 302 if(referencedColumnName.empty()) 303 _joinCond = leftTable ~ "." ~ joinCol ~ " = " ~ rightTable ~ "." ~ rightTablePrimaryKey; 304 else 305 _joinCond = leftTable ~ "." ~ joinCol ~ " = " ~ rightTable ~ "." ~ referencedColumnName; 306 } 307 308 override string toString() 309 { 310 return _joinCond; 311 } 312 }