1 /* 2 * Entity - Entity is an object-relational mapping tool for the D programming language. Referring to the design idea of JPA. 3 * 4 * Copyright (C) 2015-2018 Shanghai Putao Technology Co., Ltd 5 * 6 * Developer: HuntLabs.cn 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.entity.criteria.CriteriaBuilder; 13 14 import hunt.entity; 15 import hunt.entity.dialect; 16 import hunt.Exceptions; 17 import hunt.logging; 18 19 import std.conv; 20 import std.format; 21 import std.traits; 22 import std.variant; 23 24 class CriteriaBuilder 25 { 26 27 private EntityManagerFactory _factory; 28 private EntityManager _manager; 29 30 this(EntityManagerFactory factory) { 31 _factory = factory; 32 } 33 34 CriteriaBuilder setManager(EntityManager manager) { 35 _manager = manager; 36 return this; 37 } 38 39 EntityManager getManager() {return _manager;} 40 41 QueryBuilder createQueryBuilder() { 42 return _factory.createQueryBuilder(); 43 } 44 45 Dialect getDialect() { 46 return _factory.getDialect(); 47 } 48 49 // Database getDatabase() { 50 // return _factory.getDatabase(); 51 // } 52 53 CriteriaQuery!(T,F) createQuery(T : Object,F : Object = T)() { 54 return new CriteriaQuery!(T,F)(this); 55 } 56 57 CriteriaDelete!(T,F) createCriteriaDelete(T : Object,F : Object = T)() { 58 return new CriteriaDelete!(T,F)(this); 59 } 60 61 CriteriaUpdate!(T,F) createCriteriaUpdate(T : Object,F : Object = T)() { 62 return new CriteriaUpdate!(T,F)(this); 63 } 64 65 Order asc(EntityFieldInfo info) { 66 return new Order(info.getFullColumn(), OrderBy.ASC); 67 } 68 69 Order desc(EntityFieldInfo info) { 70 return new Order(info.getFullColumn(), OrderBy.DESC); 71 } 72 73 //P should be Predicate 74 Predicate and(P...)(P predicates) { 75 return new Predicate().andValue(predicates); 76 } 77 78 //P should be Predicate 79 Predicate or(P...)(P predicates) { 80 return new Predicate().orValue(predicates); 81 } 82 83 EntityExpression max(EntityFieldInfo info) { 84 return new EntityExpression(info.getColumnName(), info.getTableName()).setColumnSpecifier("MAX"); 85 } 86 87 EntityExpression min(EntityFieldInfo info) { 88 return new EntityExpression(info.getColumnName(), info.getTableName()).setColumnSpecifier("MIN"); 89 } 90 91 EntityExpression avg(EntityFieldInfo info) { 92 return new EntityExpression(info.getColumnName(), info.getTableName()).setColumnSpecifier("AVG"); 93 } 94 95 EntityExpression sum(EntityFieldInfo info) { 96 return new EntityExpression(info.getColumnName(), info.getTableName()).setColumnSpecifier("SUM"); 97 } 98 99 EntityExpression count(EntityFieldInfo info) { 100 return new EntityExpression(info.getColumnName(), info.getTableName()).setColumnSpecifier("COUNT"); 101 } 102 103 // deprecated("Unsupported any more") 104 EntityExpression count(T)(Root!T root) { 105 return new EntityExpression(root.getPrimaryField().getColumnName(), root.getPrimaryField().getTableName()).setColumnSpecifier("COUNT"); 106 } 107 108 EntityExpression countDistinct(EntityFieldInfo info) { 109 return new EntityExpression(info.getColumnName(), info.getTableName()).setDistinct(true).setColumnSpecifier("COUNT"); 110 } 111 112 // deprecated("Unsupported any more") 113 EntityExpression countDistinct(T)(Root!T root) { 114 return new EntityExpression(root.getPrimaryField().getColumnName(), root.getPrimaryField().getTableName()).setDistinct(true).setColumnSpecifier("COUNT"); 115 } 116 117 Predicate equal(T)(EntityFieldInfo info, T t, bool check = true) { 118 static if (isBuiltinType!T) { 119 if (check) 120 assertType!(T)(info); 121 return new Predicate().addValue(info.getFullColumn(), "=", quoteSqlfNeed(t)); 122 } 123 else { 124 Predicate p; 125 if (info.getJoinColumn() != "") { 126 auto entityInfo = new EntityInfo!(T,T)(_manager, t); 127 p = new Predicate().addValue(info.getJoinColumn(), "=", quoteSqlfNeed(entityInfo.getPrimaryValue())); 128 } 129 else { 130 throw new EntityException("cannot compare field %s with type %".format(info.getFieldName(), typeid(T).stringof)); 131 } 132 return p; 133 } 134 } 135 136 137 /// for get lazy data 138 Predicate lazyEqual(T)(EntityFieldInfo info, T t, bool check = true) { 139 static if (isBuiltinType!T) { 140 if (check) 141 assertType!(T)(info); 142 return new Predicate().addValue(info.getFullColumn(), "=", t); 143 } 144 else { 145 Predicate p; 146 if (info.getJoinColumn() != "") { 147 auto entityInfo = new EntityInfo!(T,T)(_manager, t); 148 p = new Predicate().addValue(info.getJoinColumn(), "=", quoteSqlfNeed(entityInfo.getPrimaryValue())); 149 } 150 else { 151 throw new EntityException("cannot compare field %s with type %".format(info.getFieldName(), typeid(T).stringof)); 152 } 153 return p; 154 } 155 } 156 157 /// for get lazy data 158 Predicate lazyManyToManyEqual(T)(EntityFieldInfo info, T t, bool check = true) { 159 auto condTable = info.getJoinTable(); 160 auto condColumn = info.getJoinColumn(); 161 if(info.isMainMapped()) 162 condColumn = info.getInverseJoinColumn(); 163 static if (isBuiltinType!T) { 164 if (check) 165 assertType!(T)(info); 166 return new Predicate().addValue(condTable~"."~condColumn, "=", t); 167 } 168 else { 169 Predicate p; 170 if (info.getJoinColumn() != "") { 171 auto entityInfo = new EntityInfo!(T,T)(_manager, t); 172 p = new Predicate().addValue(condTable~"."~condColumn, "=", quoteSqlfNeed(entityInfo.getPrimaryValue())); 173 } 174 else { 175 throw new EntityException("cannot compare field %s with type %".format(info.getFieldName(), typeid(T).stringof)); 176 } 177 return p; 178 } 179 } 180 181 Predicate equal(EntityFieldInfo info) { 182 Variant va = info.getColumnFieldData(); 183 if(va.type == typeid(string)) { 184 string value = va.get!string(); 185 return new Predicate().addValue(info.getFullColumn(), "=", escapeWithQuotes(value)); 186 } else { 187 return new Predicate().addValue(info.getFullColumn(), "=", info.getColumnFieldData().toString()); 188 } 189 } 190 191 Predicate notEqual(T)(EntityFieldInfo info, T t){ 192 193 static if (isBuiltinType!T) { 194 if (check) 195 assertType!(T)(info); 196 return new Predicate().addValue(info.getFullColumn(), "<>", quoteSqlfNeed(t)); 197 } 198 else { 199 Predicate p; 200 if (info.getJoinColumn() != "") { 201 auto entityInfo = new EntityInfo!(T,T)(_manager, t); 202 p = new Predicate().addValue(info.getJoinColumn(), "<>", quoteSqlfNeed(entityInfo.getPrimaryValue())); 203 } 204 else { 205 throw new EntityException("cannot compare field %s with type %".format(info.getFieldName(), typeid(T).stringof)); 206 } 207 return p; 208 } 209 } 210 211 Predicate notEqual(EntityFieldInfo info){ 212 return new Predicate().addValue(info.getFullColumn(), "<>", info.getColumnFieldData().toString()); 213 } 214 215 Predicate gt(T)(EntityFieldInfo info, T t){ 216 assertType!(T)(info); 217 return new Predicate().addValue(info.getFullColumn(), ">", quoteSqlfNeed(t)); 218 } 219 220 Predicate gt(EntityFieldInfo info){ 221 return new Predicate().addValue(info.getFullColumn(), ">", info.getColumnFieldData().toString()); 222 } 223 224 Predicate ge(T)(EntityFieldInfo info, T t){ 225 assertType!(T)(info); 226 return new Predicate().addValue(info.getFullColumn(), ">=", quoteSqlfNeed(t)); 227 } 228 229 Predicate ge(EntityFieldInfo info){ 230 return new Predicate().addValue(info.getFullColumn(), ">=", info.getColumnFieldData().toString()); 231 } 232 233 Predicate lt(T)(EntityFieldInfo info, T t){ 234 assertType!(T)(info); 235 return new Predicate().addValue(info.getFullColumn(), "<", quoteSqlfNeed(t)); 236 } 237 238 Predicate lt(EntityFieldInfo info){ 239 return new Predicate().addValue(info.getFullColumn(), "<", info.getColumnFieldData().toString()); 240 } 241 242 Predicate le(T)(EntityFieldInfo info, T t){ 243 assertType!(T)(info); 244 return new Predicate().addValue(info.getFullColumn(), "<=", quoteSqlfNeed(t)); 245 } 246 247 Predicate le(EntityFieldInfo info){ 248 return new Predicate().addValue(info.getFullColumn(), "<=", info.getColumnFieldData().toString()); 249 } 250 251 Predicate like(EntityFieldInfo info, string pattern) { 252 return new Predicate().addValue(info.getFullColumn(), "like", quoteSqlfNeed(pattern)); 253 } 254 255 Predicate notLike(EntityFieldInfo info, string pattern) { 256 return new Predicate().addValue(info.getFullColumn(), "not like", quoteSqlfNeed(pattern)); 257 } 258 259 Predicate between(T)(EntityFieldInfo info, T t1, T t2) { 260 assertType!(T)(info); 261 return new Predicate().betweenValue(info.getFullColumn(), quoteSqlfNeed(t1), quoteSqlfNeed(t2)); 262 } 263 264 Predicate In(T...)(EntityFieldInfo info, T args) { 265 foreach(k,v; args) { 266 if (k == 0) { 267 assertType!(typeof(v))(info); 268 } 269 } 270 return new Predicate().In(info.getFullColumn(), args); 271 } 272 273 void assertType(T)(EntityFieldInfo info) { 274 if (info.getColumnFieldData().hasValue()) { 275 static if (is(T == string)) { 276 if (info.getColumnFieldData().type != typeid(string)) { 277 throw new EntityException("EntityFieldInfo %s type need been string not %s".format(info.getFieldName(), info.getColumnFieldData().type)); 278 } 279 }else { 280 if (info.getColumnFieldData().type == typeid(string)) { 281 throw new EntityException("EntityFieldInfo %s type need been number not string".format(info.getFieldName())); 282 } 283 } 284 } 285 else { 286 throw new EntityException("EntityFieldInfo %s is object can not be Predicate".format(info.getFieldName())); 287 } 288 } 289 290 private string quoteSqlfNeed(T)(T t) 291 { 292 static if(is(T == string)) { 293 return escapeWithQuotes(t); 294 } else { 295 return t.to!string; 296 } 297 } 298 299 string escapeWithQuotes(string str) { 300 301 DatabaseOption options = _manager.getDbOption(); 302 303 if(options.isPgsql()) { 304 return PgUtil.escapeWithQuotes(str); 305 } else if(options.isMysql) { 306 return MySQLUtil.escapeWithQuotes(str); 307 } 308 309 return str; 310 } 311 }