1 module utile.db; 2 import std, utile.except; 3 4 public import utile.db.mysql, utile.db.sqlite; 5 6 alias Blob = const(ubyte)[]; 7 8 string DB_NULL_STRING() 9 { 10 __gshared immutable char z; 11 return (&z)[0 .. 1]; 12 } 13 14 Blob DB_NULL_BLOB() 15 { 16 __gshared immutable ubyte z; 17 return (&z)[0 .. 1]; 18 } 19 20 unittest 21 { 22 { 23 scope db = new SQLite(null); 24 25 { 26 Blob arr = [1, 2, 3]; 27 28 auto res = db.queryOne!Blob(`select ?;`, arr); 29 30 assert(res == arr); 31 } 32 33 { 34 auto res = db.query!(uint, string)(`select ?, ?;`, 123, `hello`).array; 35 36 assert(res.equal(tuple(123, `hello`).only)); 37 } 38 39 { 40 auto res = db.queryOne!uint(`select ?;`, 123); 41 42 assert(res == 123); 43 } 44 } 45 46 version (Utile_Mysql) 47 { 48 MySQL db; 49 50 auto res = db.query!(uint, string)(`select ?, ?;`, 123, `hello`); 51 auto res2 = db.queryOne!uint(`select ?;`, 123); 52 } 53 } 54 55 package: 56 57 mixin template DbBase() 58 { 59 template query(T...) 60 { 61 auto query(A...)(string sql, A args) 62 { 63 auto stmt = prepare(sql); 64 bind(stmt, args); 65 66 static if (T.length) 67 { 68 return process!T(stmt); 69 } 70 else 71 { 72 process(stmt); 73 auto that = this; 74 75 struct S 76 { 77 auto id() => that.lastId(stmt); 78 auto affected() => that.affected(stmt); 79 } 80 81 return S(); 82 } 83 } 84 } 85 86 template queryOne(T...) 87 { 88 auto queryOne(A...)(string sql, A args) 89 { 90 auto res = query!T(sql, args); 91 res.empty && throwError(`query returned no rows`); 92 93 auto e = res.front; 94 95 res.popFront; 96 res.empty || throwError(`query returned multiple rows`); 97 98 return e; 99 } 100 } 101 }