1 module dpq.query; 2 3 import dpq.connection; 4 import dpq.value; 5 import dpq.exception; 6 import dpq.result; 7 8 version(unittest) 9 { 10 import std.stdio; 11 private Connection c; 12 } 13 14 struct Query 15 { 16 private string _command; 17 private Value[] _params; 18 private Connection* _connection; 19 20 this(string command, Value[] params = []) 21 { 22 if (_dpqLastConnection == null) 23 throw new DPQException("Query: No established connection was found and none was provided."); 24 25 _connection = _dpqLastConnection; 26 _command = command; 27 _params = params; 28 } 29 30 this(ref Connection conn, string command = "", Value[] params = []) 31 { 32 _connection = &conn; 33 _command = command; 34 _params = params; 35 } 36 37 38 unittest 39 { 40 writeln(" * Query"); 41 42 c = Connection("host=127.0.0.1 dbname=test user=test"); 43 44 writeln("\t * this()"); 45 Query q; 46 assert(q._connection == null); 47 48 writeln("\t * this(command, params[])"); 49 string cmd = "some command"; 50 q = Query(cmd); 51 assert(q._connection != null, `not null 2`); 52 assert(q._command == cmd, `cmd`); 53 assert(q._params == [], `empty arr`); 54 55 Connection c2 = Connection("host=127.0.0.1 dbname=test user=test"); 56 writeln("\t * this(Connection, command, params[])"); 57 q = Query(c2); 58 assert(q._connection == &c2); 59 60 q = Query(cmd); 61 assert(q._connection == &c2); 62 } 63 64 @property void connection(ref Connection conn) 65 { 66 _connection = &conn; 67 } 68 69 @property string command() 70 { 71 return _command; 72 } 73 74 @property void command(string c) 75 { 76 _command = c; 77 } 78 79 void addParam(T)(T val) 80 { 81 _params ~= Value(val); 82 } 83 84 unittest 85 { 86 Query q; 87 assert(q._params.length == 0); 88 89 q.addParam(1); 90 91 assert(q._params.length == 1); 92 assert(q._params[0] == Value(1)); 93 } 94 95 ref Query opBinary(string op, T)(T val) 96 if (op == "<<") 97 { 98 addParam(val); 99 return this; 100 } 101 102 void opAssign(string str) 103 { 104 command = str; 105 } 106 107 @property Result run() 108 { 109 import std.datetime; 110 111 StopWatch sw; 112 sw.start(); 113 114 Result r = _connection.execParams(_command, _params); 115 sw.stop(); 116 117 r.time = sw.peek(); 118 return r; 119 } 120 121 Result run(T...)(T params) 122 { 123 foreach (p; params) 124 addParam(p); 125 126 return run(); 127 } 128 129 bool runAsync(T...)(T params) 130 { 131 foreach (p; params) 132 addParam(p); 133 134 return runAsync(); 135 } 136 137 bool runAsync() 138 { 139 _connection.sendParams(_command, _params); 140 return true; // FIXME: must return the actual result from PQsendQueryParams 141 } 142 143 unittest 144 { 145 writeln("\t * run"); 146 147 auto c = Connection("host=127.0.0.1 dbname=test user=test"); 148 149 auto q = Query("SELECT 1::INT"); 150 151 auto r = q.run(); 152 assert(r.rows == 1); 153 assert(r.columns == 1); 154 assert(r[0][0].as!int == 1); 155 156 writeln("\t\t * async"); 157 q.runAsync(); 158 159 r = c.lastResult(); 160 assert(r.rows == 1); 161 assert(r.columns == 1); 162 assert(r[0][0].as!int == 1); 163 164 writeln("\t * run(params...)"); 165 166 q = "SELECT $1"; 167 q.run(1); 168 assert(r.rows == 1); 169 assert(r.columns == 1); 170 assert(r[0][0].as!int == 1); 171 172 writeln("\t\t * async"); 173 174 q.runAsync(1); 175 r = c.lastResult(); 176 assert(r.rows == 1); 177 assert(r.columns == 1); 178 assert(r[0][0].as!int == 1); 179 } 180 }