1 module uim.sql;
2 
3 public import std.algorithm;
4 public import std.conv;
5 public import std.stdio;
6 public import std.string;
7 
8 public import uim.core;
9 public import uim.sql.statements;
10 public import uim.sql.tables;
11 public import uim.sql.index;
12 public import uim.sql.functions;
13 
14 string OR(string[] conditions) {
15 	string[] c = new string[conditions.length];
16 	foreach(i, x; conditions) c[i] = "("~x~")";
17 	if (conditions.length > 0) return c.join(" OR ");
18 	return "";
19 } 
20 string AND(string[] conditions) {
21 	string[] c = new string[conditions.length];
22 	foreach(i, x; conditions) c[i] = "("~x~")";
23 	if (conditions.length > 0) return c.join(" AND ");
24 	return "";
25 } 
26 
27 alias STRINGAA = string[string];
28 
29 //auto tableNames(Database db) {
30 //	string[] names;
31 //	foreach (row; db.execute("SELECT name FROM sqlite_master WHERE (type='table')")) {
32 //		auto name = row[0].as!string.toUpper;
33 //		if (name == "SQLITE_STAT1") continue;
34 //		
35 //		names ~= name;
36 //	}
37 //	return names;
38 //}
39 //string[] readTableColumns(Database db) {
40 //	string[][string] results;
41 //	foreach(tableName; tableNames(db)) {
42 //		if (tableName == "STOCKS") continue;
43 //		results[tableName] ~= readTableColumns(db, tableName);
44 //	}
45 //	return uniqueColumns(results);
46 //}
47 //string[] uniqueColumns(string[][string] colinTableNames) {
48 //	string[string] results;
49 //	foreach(tName, cols; colinTableNames) 
50 //		foreach(col; cols) results[col] = tName;
51 //	return results.keys;
52 //}
53 //string[] readTableColumns(Database db, string tableName) {
54 //	foreach (row; QueryCache(db.execute("SELECT * FROM "~tableName~" LIMIT 1"))) return row.columnIndexes.keys;
55 //	return null;
56 //}
57 
58 /++
59  readRow - Reading data from a SQL result 
60  +/
61 void readFromDB(T)(DataRow!T dataRow, QueryCache.CachedRow dbRow, size_t[string] colName2Index, size_t[string] ignoreFlds = null) {
62 	if (dataRow) {
63 		if (ignoreFlds) {
64 			foreach(k, v; dbRow.columnIndexes) {
65 				auto kk = k.toUpper;
66 				if (!(kk in ignoreFlds)) dataRow[colName2Index[kk]] = dbRow[v].as!T;
67 			}
68 		}
69 		else {
70 			foreach(k, v; dbRow.columnIndexes) { 
71 				dataRow[colName2Index[k.toUpper]] = dbRow[v].as!T;
72 			}
73 		}
74 	}
75 }
76 
77 void readFromDB(T)(DataMatrix!T matrix, size_t pos, QueryCache.CachedRow dbRow, size_t[string] colName2Index, size_t[string] ignoreFlds = null) {
78 	if (!matrix) return;
79 	
80 	if (auto row = matrix[pos]) {
81 		if (ignoreFlds) {
82 			foreach(k, v; dbRow.columnIndexes) {
83 				auto kk = k.toUpper;
84 				if (!(kk in ignoreFlds)) row[colName2Index[kk]] = dbRow[v].as!T;
85 			}
86 		}
87 		else {
88 			foreach(k, v; dbRow.columnIndexes) { 
89 				auto kk = k.toUpper;
90 				row[colName2Index[kk]] = dbRow[v].as!T;
91 			}
92 		}
93 	}
94 }
95 
96 void readFromDB(T)(DataSplice!T splice, size_t pos, QueryCache.CachedRow dbRow, size_t[string] colName2Index, size_t[string] ignoreFlds = null) {
97 	if ((splice) && (pos < splice.height)) {
98 		if (ignoreFlds) {
99 			foreach(k, v; dbRow.columnIndexes) {
100 				auto kk = k.toUpper;
101 				if (!(kk in ignoreFlds)) splice[pos, colName2Index[kk]] = dbRow[v].as!T;
102 			}
103 		}
104 		else {
105 			foreach(k, v; dbRow.columnIndexes) { 
106 				auto kk = k.toUpper;
107 				splice[pos, colName2Index[kk]] = dbRow[v].as!T;
108 			}
109 		}
110 	}
111 }
112 
113 void save(T)(Database db, DataTable!T rows, string[] sources, string company) {
114 	writeln("--- void save(Database db, DRow[] rows, string[] sources)...");
115 	
116 	auto pre = "(IDAY = %s) AND (NAME = '"~company~"')";	
117 	foreach(iday, row; rows) if (row) {				
118 		auto sel = pre.format(iday);
119 		auto update = "";
120 		foreach(source; sources) {
121 			if (auto cells = row.changedCells(source)) {
122 				update ~= "UPDATE "~source.sets(cells).where(sel)~";";		
123 			}
124 		}
125 		try {
126 			db.execute(update);
127 		}
128 		catch(Exception e) {
129 			foreach(source; sources) {
130 				if (auto cells = row.changedCells(source)) {
131 					db.run("UPDATE "~source.sets(cells).where(sel));		
132 				}
133 			}
134 		}
135 	}
136 }
137 
138 void save(T)(Database db, DataRow!(T)[] rows, string[] tableNames) {
139 	// writeln("--- void save(Database db, DRow[] rows, string[] sources)...");
140 	
141 	auto pre = "(IDAY = %s) AND (NAME = '%s')";	
142 	foreach(row; rows) if (row) {	
143 		auto name = row["NAME"].value!string;
144 		auto iday = row["IDAY"].value!int;
145 		auto sel = pre.format(iday, name);
146 		
147 		auto update = "";
148 		foreach(tableName; tableNames) {
149 			if (auto cells = row.changedCells(tableName)) {
150 				update ~= "UPDATE "~tableName.sets(cells).where(sel)~";";		
151 			}
152 		}
153 		try {
154 			debug writeln(update);
155 			db.run(update);
156 		}
157 		catch(Exception e) {
158 			writeln(e);
159 			foreach(tableName; tableNames) {
160 				if (auto cells = row.changedCells(tableName)) {
161 					db.run("UPDATE "~tableName.sets(cells).where(sel));		
162 				}
163 			}
164 		}
165 	}
166 }
167 //string[] columns(Database db, string tableName, string[] ignoreNames = null) {
168 //	string[] names;
169 //	foreach(row; db.execute("PRAGMA table_info("~tableName~")")) {
170 //		auto name = row[1].as!string.toUpper;
171 //		if(name.isIn(ignoreNames)) continue;
172 //		
173 //		names ~= name;
174 //	}
175 //	return names;
176 //}
177 //
178 //void save(T)(Database db, T[size_t][] changedCellsInRows, string[][string] tableCells, string companyName, size_t start = 0, bool dMode = false) {
179 //	writeln("--- void save(Database db, DRow[] rows, string[] sources)...");
180 //	
181 //	auto pre = "(NAME = '"~companyName~"') AND (IDAY = %s)";	
182 //	foreach(iday, row; changedCellsInRows) if (row) {	
183 //		if (iday < start) continue; 
184 //		auto where = pre.format(iday);
185 //		
186 //		auto update = "";
187 //		foreach(tName, table; tableCells) {
188 //			string[] sets;
189 //			foreach(cell; table) if (cell in row) sets ~= "%s=%s".format(cell, row[cell]);
190 //			if (sets) update ~= "UPDATE %s SET %s WHERE %s;".format(tName, sets.join(","), where);		
191 //		}
192 //		try { 
193 //			//writeln(update);
194 //			db.run(update); }
195 //		catch(Exception e) { writeln(e); }
196 //	}
197 //}
198 
199 string sqlDeleteFrom(string tableName, string where = null) {
200 	if (where) return "DELETE FROM %s WHERE %s;".format(tableName, where); 
201 	return "DELETE FROM %s;".format(tableName);
202 }
203 //void deleteFrom(Database db, string tableName, string where = null) {
204 //	try { db.run(sqlDeleteFrom(tableName, where)); } 
205 //	catch(Exception e) { writeln("ERROR ", e); }
206 //}
207 //
208 //string sqlInsertInto(string tableName, string[] valueNames, string[] values) { 
209 //	return sqlInsertInto(tableName, valueNames.join(","), values.join(",")); }
210 //string sqlInsertInto(string tableName, string valueNames, string values) {
211 //	return "INSERT INTO %s (%s) VALUES(%s);".format(tableName, valueNames, values); }
212 //
213 //void insertInto(Database db, string tableName, string[] valueNames, string[] values) { 
214 //	insertInto(db, tableName, valueNames.join(","), values.join(",")); }
215 //void insertInto(Database db, string tableName, string valueNames, string values) {
216 //	try { db.run(sqlInsertInto(tableName, valueNames, values)); } 
217 //	catch(Exception e) { writeln("ERROR ", e); }
218 //}
219 //void insertInto(Database db, string sql) {
220 //	try { db.run(sql); } 
221 //	catch(Exception e) { writeln("ERROR ", e); }
222 //}
223 //bool exists(Database db, string sql) {
224 //	foreach(data; db.execute(sql)) return true;
225 //	return false;
226 //}
227 
228 string[] quote(string[] source, string quoteString) { return quote(source, quoteString, quoteString); }
229 string[] quote(string[] source, string start, string end) {
230 	string[] result;
231 	foreach(s; source) result ~= start~s~end;
232 	return result;
233 }
234 
235 //void update(Database db, string tableName, string[] sets, string where = null) { update(db, tableName, sets.join(","), where); }
236 //void update(Database db, string tableName, string sets, string[] where) {
237 //	try { db.run(sqlUpdate(tableName, sets, where)); } 
238 //	catch(Exception e) { writeln("ERROR ", e); }
239 //}
240 //void update(Database db, string tableName, string sets, string where = null) {
241 //	try { db.run(sqlUpdate(tableName, sets, where)); } 
242 //	catch(Exception e) { writeln("ERROR ", e); }
243 //}
244 //
245 //auto readTradesLevel0(Database db, string where = "") {
246 //	STRINGAA tradeStrategies;
247 //	auto select = "SELECT ID, L0 FROM TRADES WHERE (LEVEL = 0)"~(where.length > 0 ? " AND "~where : "");
248 //	foreach(row; db.execute(select)) {
249 //		auto id = row[0].as!string;
250 //		auto level0 = row[1].as!string;
251 //		tradeStrategies[level0] = id;
252 //	}
253 //	return tradeStrategies;
254 //}
255 
256 //auto readTradesLevel1(Database db, string where = "") {
257 //	STRINGAA[string] tradeStrategies;
258 //	auto select = "SELECT ID, L0, L1 FROM TRADES WHERE (LEVEL = 1)"~(where.length > 0 ? " AND "~where : "");
259 //	foreach(row; db.execute(select)) {
260 //		auto id = row[0].as!string;
261 //		auto level0 = row[1].as!string;
262 //		auto level1 = row[2].as!string;
263 //		if (level0 !in tradeStrategies) {
264 //			STRINGAA values; 
265 //			tradeStrategies[level0] = values;
266 //		}
267 //		tradeStrategies[level0][level1] = id;
268 //	}
269 //	return tradeStrategies;
270 //}
271 //
272 //auto readTradesLevel2(Database db, string where = "") {
273 //	STRINGAA[string][string] tradeStrategies;
274 //	auto select = "SELECT ID, L0, L1, L2 FROM TRADES WHERE (LEVEL = 2)"~(where.length > 0 ? " AND "~where : "");
275 //	foreach(row; db.execute(select)) {
276 //		auto id = row[0].as!string;
277 //		auto level0 = row[1].as!string;
278 //		auto level1 = row[2].as!string;
279 //		auto level2 = row[3].as!string;
280 //		if (level0 !in tradeStrategies) {
281 //			STRINGAA[string] values;
282 //			tradeStrategies[level0] = values;
283 //		}
284 //		if (level1 !in tradeStrategies[level0]) {
285 //			STRINGAA values;
286 //			tradeStrategies[level0][level1] = values;
287 //		}
288 //		tradeStrategies[level0][level1][level2] = id;
289 //	}
290 //	return tradeStrategies;
291 //}
292 //auto readTradesLevel3(Database db, string where = "") {
293 //	STRINGAA[string][string][string] tradeStrategies;
294 //	auto select = "SELECT ID, L0, L1, L2, L3 FROM TRADES WHERE (LEVEL = 3)"~(where.length > 0 ? " AND "~where : "");
295 //	foreach(row; db.execute(select)) {
296 //		auto id = row[0].as!string;
297 //		auto level0 = row[1].as!string;
298 //		auto level1 = row[2].as!string;
299 //		auto level2 = row[3].as!string;
300 //		auto level3 = row[4].as!string;
301 //		if (level0 !in tradeStrategies) {
302 //			STRINGAA[string][string] values;
303 //			tradeStrategies[level0] = values;
304 //		}
305 //		if (level1 !in tradeStrategies[level0]) {
306 //			STRINGAA[string] values;
307 //			tradeStrategies[level0][level1] = values;
308 //		}
309 //		if (level2 !in tradeStrategies[level0][level1]) {
310 //			STRINGAA values;
311 //			tradeStrategies[level0][level1][level2] = values;
312 //		}
313 //		tradeStrategies[level0][level1][level2][level3] = id;
314 //	}
315 //	return tradeStrategies;
316 //}
317 
318 string deleteStrategy(string strategy) {
319 	return sqlDeleteFrom("trades", "(ID = '%')".format(strategy));
320 }
321 
322 //string[] colNames(Database db, string[] exclusiveCols = []) { return colNames(db, db.tableNames, exclusiveCols); }
323 //string[] colNames(Database db, string[] tableNames, string[] exclusiveCols) {
324 //	string[] result;
325 //	
326 //	foreach(tableName; tableNames) {
327 //		auto cols = db.columns(tableName, exclusiveCols~result);
328 //		result ~= cols;
329 //	}
330 //	
331 //	return result;
332 //}
333 
334 //string[][string] colNamesOfTables(Database db, string[] exclusiveCols) { return colNamesOfTables(db, db.tableNames, exclusiveCols); }
335 //string[][string] colNamesOfTables(Database db, string[] tableNames, string[] exclusiveCols) {
336 //	string[][string] result;
337 //	string[] allColumns;
338 //	
339 //	foreach(tableName; tableNames) {
340 //		auto cols = db.columns(tableName, exclusiveCols~allColumns);
341 //		allColumns ~= cols;
342 //		result[tableName] = cols;
343 //	}
344 //	
345 //	return result;
346 //}
347 //
348 //enum TABLEINITHEIGHT = 7000;
349 //
350 //string[] readCompanies(Database db, string select = "(ID > '%')") {
351 //	string[] result;
352 //	foreach (row; QueryCache(db.execute("SELECT ID FROM COMPANIES WHERE %s ORDER BY ID".format(select)))) 
353 //		result ~= row[0].as!string;
354 //	return result;
355 //}
356 //
357 //string[] readGens(Database db, string select = "(NAME > '%')") {
358 //	string[] result;
359 //	foreach(row; db.execute("SELECT NAME FROM GENS")) result ~= row[0].as!string;
360 //	return result;
361 //}
362 //
363 //T count(T:size_t)(Database db, string table, string where) {
364 //	return SQLSelect("count(*)", table).where(where)(db).oneValue!T;
365 //}