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.NativeQuery; 13 14 import hunt.entity; 15 import hunt.collection.ArrayList; 16 import hunt.collection.List; 17 import hunt.logging; 18 import hunt.Number; 19 import hunt.String; 20 import hunt.Integer; 21 import hunt.Long; 22 import hunt.Double; 23 import hunt.Float; 24 import hunt.Short; 25 import hunt.Byte; 26 import hunt.Boolean; 27 import hunt.Nullable; 28 import hunt.entity.EntityException; 29 import hunt.sql.util.DBType; 30 import hunt.sql.SQLUtils; 31 32 import std.regex; 33 import std.format; 34 35 // version(WITH_HUNT_TRACE) 36 // { 37 // import hunt.trace.Constrants; 38 // import hunt.trace.Plugin; 39 // import hunt.trace.Span; 40 // } 41 42 import std.algorithm; 43 44 deprecated("Using RowSet instead.") 45 alias ResultSet = RowSet; 46 47 class NativeQuery 48 { 49 50 private string _nativeSql; 51 private EntityManager _manager; 52 private Object[int] _params; 53 private Object[string] _parameters; 54 private int _lastInsertId = -1; 55 private int _affectRows = 0; 56 57 // version (WITH_HUNT_TRACE) 58 // { 59 // private Span _span; 60 // private string[string] _tags; 61 // } 62 63 this(EntityManager manager, string sql) 64 { 65 _manager = manager; 66 _nativeSql = sql; 67 } 68 69 // version (WITH_HUNT_TRACE) 70 // { 71 // private void beginTrace(string name) 72 // { 73 // _tags.clear(); 74 // _span = traceSpanBefore(name); 75 // } 76 77 // private void endTrace(string error = null) 78 // { 79 // if (_span !is null) 80 // { 81 // traceSpanAfter(_span, _tags, error); 82 // } 83 // } 84 // } 85 86 public RowSet getResultList() 87 { 88 auto sql = paramedSql(); 89 // version (WITH_HUNT_TRACE) 90 // { 91 // beginTrace("NativeQuery getResultList"); 92 // scope (exit) 93 // { 94 // _tags["sql"] = sql; 95 // endTrace(); 96 // } 97 // } 98 auto stmt = _manager.getSession().prepare(sql); 99 return stmt.query(); 100 } 101 102 public int executeUpdate() 103 { 104 auto sql = paramedSql(); 105 // version (WITH_HUNT_TRACE) 106 // { 107 // beginTrace("NativeQuery executeUpdate"); 108 // scope (exit) 109 // { 110 // _tags["sql"] = sql; 111 // endTrace(); 112 // } 113 // } 114 auto stmt = _manager.getSession().prepare(sql); 115 //TODO row line count is 0 for Update 116 _lastInsertId = stmt.lastInsertId(); 117 _affectRows = stmt.affectedRows(); 118 return stmt.execute(); 119 } 120 121 public int lastInsertId() 122 { 123 return _lastInsertId; 124 } 125 126 public int affectedRows() 127 { 128 return _affectRows; 129 } 130 131 132 public void setParameter(R)(int idx, R param) 133 { 134 static if (is(R == int) || is(R == uint)) 135 { 136 _params[idx] = new Integer(param); 137 } 138 else static if (is(R == char)) 139 { 140 _params[idx] = new String(cast(string)[param]); 141 } 142 else static if (is(R == string)) 143 { 144 _params[idx] = new String(param); 145 } 146 else static if(is(R == byte[]) || is(R == ubyte[])) { 147 _params[idx] = new Bytes(cast(byte[])param); 148 } 149 else static if (is(R == bool)) 150 { 151 _params[idx] = new Boolean(param); 152 } 153 else static if (is(R == double)) 154 { 155 _params[idx] = new Double(param); 156 } 157 else static if (is(R == float)) 158 { 159 _params[idx] = new Float(param); 160 } 161 else static if (is(R == short) || is(R == ushort)) 162 { 163 _params[idx] = new Short(param); 164 } 165 else static if (is(R == long) || is(R == ulong)) 166 { 167 _params[idx] = new Long(param); 168 } 169 else static if (is(R == byte) || is(R == ubyte)) 170 { 171 _params[idx] = new Byte(param); 172 } 173 else static if (is(R == class)) 174 { 175 _params[key] = param; 176 } 177 else 178 { 179 throw new EntityException("IllegalArgument not support : " ~ R.stringof); 180 } 181 } 182 183 public void setParameter(R)(string key, R param) 184 { 185 static if (is(R == int) || is(R == uint)) 186 { 187 _parameters[key] = new Integer(param); 188 } 189 else static if (is(R == string) || is(R == char) || is(R == byte[])) 190 { 191 _parameters[key] = new String(param); 192 } 193 else static if (is(R == bool)) 194 { 195 _parameters[key] = new Boolean(param); 196 } 197 else static if (is(R == double)) 198 { 199 _parameters[key] = new Double(param); 200 } 201 else static if (is(R == float)) 202 { 203 _parameters[key] = new Float(param); 204 } 205 else static if (is(R == short) || is(R == ushort)) 206 { 207 _parameters[key] = new Short(param); 208 } 209 else static if (is(R == long) || is(R == ulong)) 210 { 211 _parameters[key] = new Long(param); 212 } 213 else static if (is(R == byte) || is(R == ubyte)) 214 { 215 _parameters[key] = new Byte(param); 216 } 217 else static if (is(R == class)) 218 { 219 _parameters[key] = param; 220 } 221 else 222 { 223 throw new EntityException("IllegalArgument not support : " ~ R.stringof); 224 } 225 } 226 227 private string paramedSql() 228 { 229 version(HUNT_DEBUG) info(_nativeSql); 230 231 string str = _nativeSql; 232 foreach (k, v; _parameters) 233 { 234 auto re = regex(r":" ~ k ~ r"([^\w])", "g"); 235 if ((cast(String) v !is null) || (cast(Nullable!string) v !is null)) 236 { 237 str = str.replaceAll(re, quoteSqlString(v.toString()) ~ "$1"); 238 } 239 else 240 { 241 str = str.replaceAll(re, v.toString() ~ "$1"); 242 } 243 } 244 245 246 if (_params.length > 0) 247 { 248 auto keys = _params.keys; 249 sort!("a < b")(keys); 250 List!Object params = new ArrayList!Object(); 251 foreach (e; keys) 252 { 253 params.add(_params[e]); 254 } 255 256 auto opt = _manager.getDbOption(); 257 string dbtype; 258 if (opt.isMysql()) 259 { 260 dbtype = DBType.MYSQL.name; 261 } 262 else if (opt.isPgsql()) 263 { 264 dbtype = DBType.POSTGRESQL.name; 265 } 266 // else if (opt.isSqlite()) 267 // { 268 // dbtype = DBType.SQLITE.name; 269 270 // } 271 else 272 { 273 throw new Exception("not support dbtype : %s".format(opt.schemeName())); 274 } 275 str = SQLUtils.format(str, DBType.MYSQL.name, params); 276 } 277 278 version(HUNT_DEBUG) info(str); 279 return str; 280 } 281 282 }