xmysql-timzoned 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +28 -0
- package/.travis.yml +17 -0
- package/LICENSE +22 -0
- package/bin/index.js +94 -0
- package/dockerfile +33 -0
- package/index.js +1 -0
- package/lib/util/cmd.helper.js +109 -0
- package/lib/util/data.helper.js +211 -0
- package/lib/util/whereClause.helper.js +350 -0
- package/lib/xapi.js +509 -0
- package/lib/xctrl.js +589 -0
- package/lib/xsql.js +1321 -0
- package/package.json +46 -0
package/lib/xsql.js
ADDED
@@ -0,0 +1,1321 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
const mysql = require("mysql");
|
4
|
+
const dataHelp = require("./util/data.helper.js");
|
5
|
+
const whereHelp = require("./util/whereClause.helper.js");
|
6
|
+
const assert = require("assert");
|
7
|
+
|
8
|
+
//define class§
|
9
|
+
class Xsql {
|
10
|
+
constructor(sqlConfig, pool) {
|
11
|
+
//define this variables
|
12
|
+
this.sqlConfig = {};
|
13
|
+
this.pool = {};
|
14
|
+
this.metaDb = {};
|
15
|
+
this.metaDb.tables = {};
|
16
|
+
this.metaDb.routines = [];
|
17
|
+
|
18
|
+
this.sqlConfig = sqlConfig;
|
19
|
+
this.pool = pool;
|
20
|
+
}
|
21
|
+
|
22
|
+
/**************** START : Cache functions ****************/
|
23
|
+
init(cbk) {
|
24
|
+
this.dbCacheInitAsync((err, results) => {
|
25
|
+
cbk(err, results);
|
26
|
+
});
|
27
|
+
}
|
28
|
+
|
29
|
+
dbCacheInitAsync(cbk) {
|
30
|
+
let self = this;
|
31
|
+
|
32
|
+
self.pool.query(
|
33
|
+
dataHelp.getSchemaQuery(),
|
34
|
+
[this.sqlConfig.database],
|
35
|
+
(err, results) => {
|
36
|
+
if (err) {
|
37
|
+
console.log("Cache init failed during database reading");
|
38
|
+
console.log(err, results);
|
39
|
+
cbk(err, results);
|
40
|
+
} else {
|
41
|
+
for (var i = 0; i < results.length; ++i) {
|
42
|
+
let keys = Object.keys(results[i]);
|
43
|
+
|
44
|
+
for (var j = 0; j < keys.length; ++j) {
|
45
|
+
let value = results[i][keys[j]];
|
46
|
+
|
47
|
+
results[i][keys[j].toLowerCase()] = value;
|
48
|
+
|
49
|
+
//console.log(value);
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
self.iterateToCacheTables(results);
|
54
|
+
self.iterateToCacheTablePks(results);
|
55
|
+
self.iterateToCacheTableColumns(results);
|
56
|
+
self.iterateToCacheTableFks(results);
|
57
|
+
|
58
|
+
// osx mysql server has limitations related to open_tables
|
59
|
+
self.pool.query("FLUSH TABLES", [], (err, results) => {
|
60
|
+
self.pool.query(dataHelp.getRoutines(), [this.sqlConfig.database], (err, results) => {
|
61
|
+
if (err) {
|
62
|
+
cbk(err, results)
|
63
|
+
} else {
|
64
|
+
self.iterateToCacheRoutines(results)
|
65
|
+
cbk(null, null)
|
66
|
+
}
|
67
|
+
})
|
68
|
+
});
|
69
|
+
}
|
70
|
+
}
|
71
|
+
);
|
72
|
+
}
|
73
|
+
|
74
|
+
iterateToCacheTables(schemaResults) {
|
75
|
+
for (let i = 0; i < schemaResults.length; ++i) {
|
76
|
+
let schemaRow = schemaResults[i];
|
77
|
+
|
78
|
+
let tableName = schemaRow["table_name"];
|
79
|
+
|
80
|
+
if (!(tableName in this.metaDb.tables)) {
|
81
|
+
this.metaDb.tables[tableName] = {};
|
82
|
+
this.metaDb.tables[tableName]["primaryKeys"] = [];
|
83
|
+
this.metaDb.tables[tableName]["foreignKeys"] = [];
|
84
|
+
this.metaDb.tables[tableName]["columns"] = [];
|
85
|
+
this.metaDb.tables[tableName]["indicies"] = [];
|
86
|
+
this.metaDb.tables[tableName]["isView"] = schemaRow["isView"];
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
iterateToCacheRoutines(routineResults) {
|
92
|
+
for (let i = 0; i < routineResults.length; i++) {
|
93
|
+
const routine = routineResults[i]
|
94
|
+
const routineName = routine.routine_name
|
95
|
+
this.metaDb.routines.push(routineName)
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
iterateToCacheTableColumns(schemaResults) {
|
100
|
+
for (let i = 0; i < schemaResults.length; ++i) {
|
101
|
+
let schemaRow = schemaResults[i];
|
102
|
+
let tableName = schemaRow["table_name"];
|
103
|
+
let col = {};
|
104
|
+
col["column_name"] = schemaRow["column_name"];
|
105
|
+
col["ordinal_position"] = schemaRow["ordinal_position"];
|
106
|
+
col["column_key"] = schemaRow["column_key"];
|
107
|
+
col["data_type"] = schemaRow["data_type"];
|
108
|
+
col["column_type"] = schemaRow["column_type"];
|
109
|
+
|
110
|
+
dataHelp.findOrInsertObjectArrayByKey(
|
111
|
+
col,
|
112
|
+
"column_name",
|
113
|
+
this.metaDb.tables[tableName]["columns"]
|
114
|
+
);
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
iterateToCacheTablePks(schemaResults) {
|
119
|
+
for (let i = 0; i < schemaResults.length; ++i) {
|
120
|
+
let schemaRow = schemaResults[i];
|
121
|
+
let tableName = schemaRow["table_name"];
|
122
|
+
|
123
|
+
if (schemaRow["column_key"] === "PRI") {
|
124
|
+
let pk = {};
|
125
|
+
pk["column_name"] = schemaRow["column_name"];
|
126
|
+
pk["ordinal_position"] = schemaRow["ordinal_position"];
|
127
|
+
pk["column_key"] = schemaRow["column_key"];
|
128
|
+
pk["data_type"] = schemaRow["data_type"];
|
129
|
+
pk["column_type"] = schemaRow["column_type"];
|
130
|
+
|
131
|
+
dataHelp.findOrInsertObjectArrayByKey(
|
132
|
+
pk,
|
133
|
+
"column_name",
|
134
|
+
this.metaDb.tables[tableName]["primaryKeys"]
|
135
|
+
);
|
136
|
+
}
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
iterateToCacheTableFks(schemaResults) {
|
141
|
+
for (let i = 0; i < schemaResults.length; ++i) {
|
142
|
+
let schemaRow = schemaResults[i];
|
143
|
+
let tableName = schemaRow["table_name"];
|
144
|
+
|
145
|
+
if (schemaRow["referenced_table_name"]) {
|
146
|
+
let fk = {};
|
147
|
+
|
148
|
+
fk["column_name"] = schemaRow["column_name"];
|
149
|
+
fk["table_name"] = schemaRow["table_name"];
|
150
|
+
fk["referenced_table_name"] = schemaRow["referenced_table_name"];
|
151
|
+
fk["referenced_column_name"] = schemaRow["referenced_column_name"];
|
152
|
+
fk["data_type"] = schemaRow["data_type"];
|
153
|
+
fk["column_type"] = schemaRow["column_type"];
|
154
|
+
|
155
|
+
dataHelp.findOrInsertObjectArrayByKey(
|
156
|
+
fk,
|
157
|
+
"column_name",
|
158
|
+
this.metaDb.tables[tableName]["foreignKeys"]
|
159
|
+
);
|
160
|
+
|
161
|
+
//console.log(fk['referenced_table_name'],fk['referenced_column_name'],tableName, schemaRow['column_name'], this.metaDb.tables[tableName]['foreignKeys'].length)
|
162
|
+
}
|
163
|
+
}
|
164
|
+
}
|
165
|
+
|
166
|
+
/**************** END : Cache functions ****************/
|
167
|
+
|
168
|
+
exec(query, params) {
|
169
|
+
let _this = this;
|
170
|
+
return new Promise(function(resolve, reject) {
|
171
|
+
//console.log('mysql>', query, params);
|
172
|
+
_this.pool.query(query, params, function(error, rows, _fields) {
|
173
|
+
if (error) {
|
174
|
+
console.log("mysql> ", error);
|
175
|
+
return reject(error);
|
176
|
+
}
|
177
|
+
return resolve(rows);
|
178
|
+
});
|
179
|
+
});
|
180
|
+
}
|
181
|
+
|
182
|
+
typeOfColumn(Type) {
|
183
|
+
//TODO: Im sure there are more types to handle here
|
184
|
+
const strTypes = [
|
185
|
+
"varchar",
|
186
|
+
"text",
|
187
|
+
"char",
|
188
|
+
"tinytext",
|
189
|
+
"mediumtext",
|
190
|
+
"longtext",
|
191
|
+
"blob",
|
192
|
+
"mediumblob",
|
193
|
+
"longblob"
|
194
|
+
];
|
195
|
+
const intTypes = [
|
196
|
+
"int",
|
197
|
+
"long",
|
198
|
+
"smallint",
|
199
|
+
"mediumint",
|
200
|
+
"bigint",
|
201
|
+
"tinyint"
|
202
|
+
];
|
203
|
+
const flatTypes = ["float", "double", "decimal"];
|
204
|
+
const dateTypes = ["date", "datetime", "timestamp", "time", "year"];
|
205
|
+
|
206
|
+
if (dataHelp.getType(Type, strTypes)) {
|
207
|
+
return "string";
|
208
|
+
} else if (dataHelp.getType(Type, intTypes)) {
|
209
|
+
return "int";
|
210
|
+
} else if (dataHelp.getType(Type, flatTypes)) {
|
211
|
+
return "float";
|
212
|
+
} else if (dataHelp.getType(Type, dateTypes)) {
|
213
|
+
return "date";
|
214
|
+
} else {
|
215
|
+
return "unknown";
|
216
|
+
}
|
217
|
+
}
|
218
|
+
|
219
|
+
isTypeOfColumnNumber(Type) {
|
220
|
+
//console.log(Type, this.typeOfColumn(Type));
|
221
|
+
return (
|
222
|
+
"int" === this.typeOfColumn(Type) || "float" === this.typeOfColumn(Type)
|
223
|
+
);
|
224
|
+
}
|
225
|
+
|
226
|
+
getLimitClause(reqParams) {
|
227
|
+
//defaults
|
228
|
+
reqParams._index = 0;
|
229
|
+
reqParams._len = 20;
|
230
|
+
|
231
|
+
if ("_size" in reqParams) {
|
232
|
+
if (parseInt(reqParams._size) > 0 && parseInt(reqParams._size) <= 100) {
|
233
|
+
reqParams._len = parseInt(reqParams._size);
|
234
|
+
} else if (parseInt(reqParams._size) > 100) {
|
235
|
+
reqParams._len = 100;
|
236
|
+
}
|
237
|
+
}
|
238
|
+
|
239
|
+
if ("_p" in reqParams && parseInt(reqParams._p) > 0) {
|
240
|
+
reqParams._index = parseInt(reqParams._p) * reqParams._len;
|
241
|
+
}
|
242
|
+
|
243
|
+
//console.log(reqParams._index, reqParams._len);
|
244
|
+
|
245
|
+
return [reqParams._index, reqParams._len];
|
246
|
+
}
|
247
|
+
|
248
|
+
prepareBulkInsert(tableName, objectArray, queryParamsObj) {
|
249
|
+
if (tableName in this.metaDb.tables && objectArray) {
|
250
|
+
let insObj = objectArray[0];
|
251
|
+
|
252
|
+
// goal => insert into ?? (?,?..?) values ? [tablName, col1,col2...coln,[[ObjValues_1],[ObjValues_2],...[ObjValues_N]]
|
253
|
+
queryParamsObj.query = " INSERT INTO ?? ( ";
|
254
|
+
queryParamsObj.params.push(tableName);
|
255
|
+
|
256
|
+
let cols = [];
|
257
|
+
let colPresent = false;
|
258
|
+
|
259
|
+
/**************** START : prepare column names to be inserted ****************/
|
260
|
+
// iterate over all column in table and have only ones existing in objects to be inserted
|
261
|
+
for (
|
262
|
+
var i = 0;
|
263
|
+
i < this.metaDb.tables[tableName]["columns"].length;
|
264
|
+
++i
|
265
|
+
) {
|
266
|
+
let colName = this.metaDb.tables[tableName]["columns"][i][
|
267
|
+
"column_name"
|
268
|
+
];
|
269
|
+
|
270
|
+
if (colName in insObj) {
|
271
|
+
if (colPresent) {
|
272
|
+
queryParamsObj.query += ",";
|
273
|
+
}
|
274
|
+
|
275
|
+
queryParamsObj.query += colName;
|
276
|
+
|
277
|
+
colPresent = true;
|
278
|
+
}
|
279
|
+
|
280
|
+
cols.push(colName);
|
281
|
+
|
282
|
+
//console.log('> > ', queryParamsObj.query);
|
283
|
+
}
|
284
|
+
|
285
|
+
queryParamsObj.query += " ) values ?";
|
286
|
+
/**************** END : prepare column names to be inserted ****************/
|
287
|
+
|
288
|
+
/**************** START : prepare value object in prepared statement ****************/
|
289
|
+
// iterate over sent object array
|
290
|
+
let arrOfArr = [];
|
291
|
+
for (var i = 0; i < objectArray.length; ++i) {
|
292
|
+
let arrValues = [];
|
293
|
+
for (var j = 0; j < cols.length; ++j) {
|
294
|
+
if (cols[j] in objectArray[i])
|
295
|
+
arrValues.push(objectArray[i][cols[j]]);
|
296
|
+
}
|
297
|
+
arrOfArr.push(arrValues);
|
298
|
+
}
|
299
|
+
queryParamsObj.params.push(arrOfArr);
|
300
|
+
/**************** END : prepare value object in prepared statement ****************/
|
301
|
+
}
|
302
|
+
}
|
303
|
+
|
304
|
+
getGroupByClause(_groupby, tableName, queryParamsObj) {
|
305
|
+
if (_groupby) {
|
306
|
+
queryParamsObj.query += " group by " + _groupby + " ";
|
307
|
+
return _groupby;
|
308
|
+
}
|
309
|
+
}
|
310
|
+
|
311
|
+
getHavingClause(_having, tableName, queryParamsObj) {
|
312
|
+
if (_having) {
|
313
|
+
let whereClauseObj = whereHelp.getConditionClause(_having, "having");
|
314
|
+
|
315
|
+
if (whereClauseObj.err === 0) {
|
316
|
+
queryParamsObj.query =
|
317
|
+
queryParamsObj.query + " having " + whereClauseObj.query;
|
318
|
+
queryParamsObj.params = queryParamsObj.params.concat(
|
319
|
+
whereClauseObj.params
|
320
|
+
);
|
321
|
+
}
|
322
|
+
|
323
|
+
//console.log('> > > after where clause filling up:', queryParamsObj.query, queryParamsObj.params);
|
324
|
+
}
|
325
|
+
}
|
326
|
+
|
327
|
+
getWhereClause(queryparams, tableName, queryParamsObj, appendToWhere) {
|
328
|
+
if (queryparams) {
|
329
|
+
let whereClauseObj = whereHelp.getConditionClause(queryparams);
|
330
|
+
|
331
|
+
if (whereClauseObj.err === 0) {
|
332
|
+
queryParamsObj.query =
|
333
|
+
queryParamsObj.query + appendToWhere + whereClauseObj.query;
|
334
|
+
queryParamsObj.params = queryParamsObj.params.concat(
|
335
|
+
whereClauseObj.params
|
336
|
+
);
|
337
|
+
}
|
338
|
+
}
|
339
|
+
}
|
340
|
+
|
341
|
+
getOrderByClause(queryparams, tableName, queryParamsObj) {
|
342
|
+
if (queryparams._sort) {
|
343
|
+
queryParamsObj.query += " ORDER BY ";
|
344
|
+
|
345
|
+
let orderByCols = queryparams._sort.split(",");
|
346
|
+
|
347
|
+
for (let i = 0; i < orderByCols.length; ++i) {
|
348
|
+
if (i) {
|
349
|
+
queryParamsObj.query += ", ";
|
350
|
+
}
|
351
|
+
const aggregationFunction = this.getAggregationFunction(orderByCols[i]);
|
352
|
+
const columnName = this.getColumnNameWithoutAggregationFunctions(orderByCols[i]);
|
353
|
+
const orderByDirection = orderByCols[i][0] === "-" ? 'DESC' : 'ASC';
|
354
|
+
|
355
|
+
if (aggregationFunction) {
|
356
|
+
queryParamsObj.query += `${aggregationFunction}(??) ${orderByDirection}`;
|
357
|
+
queryParamsObj.params.push(columnName);
|
358
|
+
} else {
|
359
|
+
queryParamsObj.query += `?? ${orderByDirection}`;
|
360
|
+
queryParamsObj.params.push(columnName);
|
361
|
+
}
|
362
|
+
}
|
363
|
+
}
|
364
|
+
}
|
365
|
+
|
366
|
+
getColumnsForSelectStmtWithGrpBy(reqQueryParams, tableName, queryParamsObj) {
|
367
|
+
let grpByCols = reqQueryParams._groupby.split(",");
|
368
|
+
|
369
|
+
for (var i = 0; i < grpByCols.length; ++i) {
|
370
|
+
if (i) {
|
371
|
+
queryParamsObj.query += ",";
|
372
|
+
}
|
373
|
+
queryParamsObj.query += " ??";
|
374
|
+
queryParamsObj.params.push(grpByCols[i]);
|
375
|
+
}
|
376
|
+
|
377
|
+
queryParamsObj.query += ",count(1) as _count ";
|
378
|
+
}
|
379
|
+
|
380
|
+
getColumnsForGroupBy(tableName, reqQueryParams, queryParamsObj) {
|
381
|
+
const updatedQueryParams = Object.assign({}, reqQueryParams);
|
382
|
+
if ('_groupbyfields' in updatedQueryParams) {
|
383
|
+
// allows you to group by different fields than you have in the select
|
384
|
+
updatedQueryParams['_fields'] = updatedQueryParams['_groupbyfields'];
|
385
|
+
}
|
386
|
+
|
387
|
+
return this.getColumnsForSelectStmt(tableName, updatedQueryParams, queryParamsObj)
|
388
|
+
}
|
389
|
+
|
390
|
+
getColumnsForSelectStmt(tableName, reqQueryParams, queryParamsObj) {
|
391
|
+
let table = this.metaDb.tables[tableName];
|
392
|
+
let cols = [];
|
393
|
+
let _fieldsInQuery = [];
|
394
|
+
let removeFieldsObj = {};
|
395
|
+
|
396
|
+
// populate _fields array from query params
|
397
|
+
if ("_fields" in reqQueryParams) {
|
398
|
+
_fieldsInQuery = reqQueryParams["_fields"].split(",");
|
399
|
+
} else {
|
400
|
+
queryParamsObj.query += " * ";
|
401
|
+
return " * ";
|
402
|
+
}
|
403
|
+
|
404
|
+
// get column name in _fields and mark column name which start with '-'
|
405
|
+
for (let i = 0; i < _fieldsInQuery.length; ++i) {
|
406
|
+
if (_fieldsInQuery[i][0] === "-") {
|
407
|
+
removeFieldsObj[
|
408
|
+
_fieldsInQuery[i].substring(1, _fieldsInQuery[i].length)
|
409
|
+
] = 1;
|
410
|
+
} else {
|
411
|
+
cols.push(_fieldsInQuery[i]);
|
412
|
+
}
|
413
|
+
}
|
414
|
+
|
415
|
+
if (!cols.length) {
|
416
|
+
// for each column in table - add only which are not in removeFieldsObj
|
417
|
+
for (let i = 0; i < table["columns"].length; ++i) {
|
418
|
+
if (!(table["columns"][i]["column_name"] in removeFieldsObj)) {
|
419
|
+
cols.push(table["columns"][i]["column_name"]);
|
420
|
+
}
|
421
|
+
}
|
422
|
+
} else {
|
423
|
+
cols = this.removeUnknownColumns(cols, tableName);
|
424
|
+
}
|
425
|
+
|
426
|
+
for (var i = 0; i < cols.length; ++i) {
|
427
|
+
if (i) {
|
428
|
+
queryParamsObj.query += ",";
|
429
|
+
}
|
430
|
+
const aggregationFunction = this.getAggregationFunction(cols[i]);
|
431
|
+
|
432
|
+
if (aggregationFunction) {
|
433
|
+
queryParamsObj.query += `${aggregationFunction}(??)`;
|
434
|
+
const columnName = this.getColumnNameWithoutAggregationFunctions(cols[i]);
|
435
|
+
queryParamsObj.params.push(columnName);
|
436
|
+
} else {
|
437
|
+
queryParamsObj.query += "??";
|
438
|
+
queryParamsObj.params.push(cols[i]);
|
439
|
+
}
|
440
|
+
}
|
441
|
+
|
442
|
+
return cols.join(",");
|
443
|
+
}
|
444
|
+
|
445
|
+
getAggregationFunction(rawColumnName) {
|
446
|
+
const AGGREGATION_FUNCTION_REGEX = /^[-]?(AVG|BIT_AND|BIT_OR|BIT_XOR|COUNT|COUNTDISTINCT|GROUP_CONCAT|JSON_ARRAYAGG|JSON_OBJECTAGG|MAX|MIN|STD|STDDEV|STDDEV_POP|STDDEV_SAMP|SUM|VAR_POP|VAR_SAMP|VARIANCE)\((.*)\)$/i;
|
447
|
+
const aggFuncMatch = rawColumnName.match(AGGREGATION_FUNCTION_REGEX);
|
448
|
+
if (aggFuncMatch && aggFuncMatch.length === 3) {
|
449
|
+
// match will look like (3) ["AVG(timestamp)", "AVG", "timestamp", index: 0, input: "AVG(timestamp)", groups: undefined]
|
450
|
+
return aggFuncMatch[1];
|
451
|
+
}
|
452
|
+
return null;
|
453
|
+
}
|
454
|
+
|
455
|
+
getColumnNameWithoutAggregationFunctions(rawColumnName) {
|
456
|
+
const AGGREGATION_FUNCTION_REGEX = /^[-]?(AVG|BIT_AND|BIT_OR|BIT_XOR|COUNT|COUNTDISTINCT|GROUP_CONCAT|JSON_ARRAYAGG|JSON_OBJECTAGG|MAX|MIN|STD|STDDEV|STDDEV_POP|STDDEV_SAMP|SUM|VAR_POP|VAR_SAMP|VARIANCE)\((.*)\)$/i;
|
457
|
+
const aggFuncMatch = rawColumnName.match(AGGREGATION_FUNCTION_REGEX);
|
458
|
+
if (aggFuncMatch && aggFuncMatch.length === 3) {
|
459
|
+
// match will look like (3) ["AVG(timestamp)", "AVG", "timestamp", index: 0, input: "AVG(timestamp)", groups: undefined]
|
460
|
+
return aggFuncMatch[2];
|
461
|
+
}
|
462
|
+
return rawColumnName.replace(/-/, '');
|
463
|
+
}
|
464
|
+
|
465
|
+
removeUnknownColumns(inputColumns, tableName) {
|
466
|
+
let cols = inputColumns;
|
467
|
+
let unknown_cols_in_input = [];
|
468
|
+
let shadowCols = [];
|
469
|
+
let tableColumns = this.metaDb.tables[tableName]["columns"];
|
470
|
+
|
471
|
+
// find unknown fields if any
|
472
|
+
for (var j = 0; j < cols.length; ++j) {
|
473
|
+
let found = 0;
|
474
|
+
// Used to allow aggregation functions like AVG(timestamp)
|
475
|
+
let columnNameWithoutAggregationClauses = this.getColumnNameWithoutAggregationFunctions(cols[j]);
|
476
|
+
|
477
|
+
for (var i = 0; i < tableColumns.length; ++i) {
|
478
|
+
if (tableColumns[i]["column_name"] === columnNameWithoutAggregationClauses) {
|
479
|
+
found = 1;
|
480
|
+
break;
|
481
|
+
}
|
482
|
+
}
|
483
|
+
|
484
|
+
if (!found) {
|
485
|
+
unknown_cols_in_input.push(j);
|
486
|
+
}
|
487
|
+
}
|
488
|
+
|
489
|
+
// if there are unknown fields - remove and ignore 'em
|
490
|
+
if (unknown_cols_in_input.length) {
|
491
|
+
for (var i = 0; i < cols.length; ++i) {
|
492
|
+
if (unknown_cols_in_input.indexOf(i) === -1) {
|
493
|
+
shadowCols.push(cols[i]);
|
494
|
+
}
|
495
|
+
}
|
496
|
+
|
497
|
+
cols = [];
|
498
|
+
cols = shadowCols;
|
499
|
+
}
|
500
|
+
|
501
|
+
return cols;
|
502
|
+
}
|
503
|
+
|
504
|
+
getPrimaryKeyName(tableName) {
|
505
|
+
let pk = null;
|
506
|
+
if (tableName in this.metaDb.tables) {
|
507
|
+
pk = this.metaDb.tables[tableName].primaryKeys[0]["column_name"];
|
508
|
+
}
|
509
|
+
return pk;
|
510
|
+
}
|
511
|
+
|
512
|
+
getPrimaryKeyWhereClause(tableName, pksValues) {
|
513
|
+
let whereClause = "";
|
514
|
+
let whereCol = "";
|
515
|
+
let whereValue = "";
|
516
|
+
let pks = [];
|
517
|
+
|
518
|
+
if (tableName in this.metaDb.tables) {
|
519
|
+
pks = this.metaDb.tables[tableName].primaryKeys;
|
520
|
+
} else {
|
521
|
+
return null;
|
522
|
+
}
|
523
|
+
|
524
|
+
// number of primary keys in table and one sent should be same
|
525
|
+
if (pksValues.length !== pks.length) {
|
526
|
+
return null;
|
527
|
+
}
|
528
|
+
|
529
|
+
// get a where clause out of the above columnNames and their values
|
530
|
+
for (let i = 0; i < pks.length; ++i) {
|
531
|
+
let type = dataHelp.getColumnType(pks[i]);
|
532
|
+
|
533
|
+
whereCol = pks[i]["column_name"];
|
534
|
+
|
535
|
+
if (type === "string") {
|
536
|
+
whereValue = mysql.escape(pksValues[i]);
|
537
|
+
} else if (type === "int") {
|
538
|
+
whereValue = parseInt(pksValues[i]);
|
539
|
+
} else if (type === "float") {
|
540
|
+
whereValue = parseFloat(pksValues[i]);
|
541
|
+
} else if (type === "date") {
|
542
|
+
whereValue = Date(pksValues[i]);
|
543
|
+
} else {
|
544
|
+
console.error(pks[i]);
|
545
|
+
assert(false, "Unhandled type of primary key");
|
546
|
+
}
|
547
|
+
|
548
|
+
if (i) {
|
549
|
+
whereClause += " and ";
|
550
|
+
}
|
551
|
+
|
552
|
+
whereClause += whereCol + " = " + whereValue;
|
553
|
+
}
|
554
|
+
|
555
|
+
return whereClause;
|
556
|
+
}
|
557
|
+
|
558
|
+
getForeignKeyWhereClause(parentTable, parentId, childTable) {
|
559
|
+
let whereValue = "";
|
560
|
+
|
561
|
+
//get all foreign keys of child table
|
562
|
+
let fks = this.metaDb.tables[childTable].foreignKeys;
|
563
|
+
let fk = dataHelp.findObjectInArrayByKey(
|
564
|
+
"referenced_table_name",
|
565
|
+
parentTable,
|
566
|
+
fks
|
567
|
+
);
|
568
|
+
let whereCol = fk["column_name"];
|
569
|
+
let colType = dataHelp.getColumnType(fk);
|
570
|
+
|
571
|
+
if (colType === "string") {
|
572
|
+
whereValue = mysql.escape(parentId);
|
573
|
+
} else if (colType === "int") {
|
574
|
+
whereValue = mysql.escape(parseInt(parentId));
|
575
|
+
} else if (colType === "float") {
|
576
|
+
whereValue = mysql.escape(parseFloat(parentId));
|
577
|
+
} else if (colType === "date") {
|
578
|
+
whereValue = mysql.escape(Date(parentId));
|
579
|
+
} else {
|
580
|
+
console.error(pks[i]);
|
581
|
+
assert(false, "Unhandled column type in foreign key handling");
|
582
|
+
}
|
583
|
+
|
584
|
+
return whereCol + " = " + whereValue;
|
585
|
+
}
|
586
|
+
|
587
|
+
prepareRoute(internal, httpType, apiPrefix, urlRoute, routeType) {
|
588
|
+
let route = {};
|
589
|
+
route["httpType"] = httpType;
|
590
|
+
route["routeUrl"] = apiPrefix + urlRoute;
|
591
|
+
if (internal) {
|
592
|
+
route["routeType"] = routeType;
|
593
|
+
}
|
594
|
+
return route;
|
595
|
+
}
|
596
|
+
|
597
|
+
getSchemaRoutes(internal, apiPrefix) {
|
598
|
+
let schemaRoutes = [];
|
599
|
+
|
600
|
+
for (var tableName in this.metaDb.tables) {
|
601
|
+
if (tableName in this.sqlConfig.ignoreTables) {
|
602
|
+
//console.log('ignore table', tableName);
|
603
|
+
} else {
|
604
|
+
let routes = [];
|
605
|
+
let tableObj = {};
|
606
|
+
let table = this.metaDb.tables[tableName];
|
607
|
+
let isView = this.metaDb.tables[tableName]["isView"];
|
608
|
+
|
609
|
+
tableObj["resource"] = tableName;
|
610
|
+
|
611
|
+
// order of routes is important for express routing - DO NOT CHANGE ORDER
|
612
|
+
routes.push(
|
613
|
+
this.prepareRoute(
|
614
|
+
internal,
|
615
|
+
"get",
|
616
|
+
apiPrefix,
|
617
|
+
tableName + "/describe",
|
618
|
+
"describe"
|
619
|
+
)
|
620
|
+
);
|
621
|
+
routes.push(
|
622
|
+
this.prepareRoute(
|
623
|
+
internal,
|
624
|
+
"get",
|
625
|
+
apiPrefix,
|
626
|
+
tableName + "/count",
|
627
|
+
"count"
|
628
|
+
)
|
629
|
+
);
|
630
|
+
routes.push(
|
631
|
+
this.prepareRoute(
|
632
|
+
internal,
|
633
|
+
"get",
|
634
|
+
apiPrefix,
|
635
|
+
tableName + "/groupby",
|
636
|
+
"groupby"
|
637
|
+
)
|
638
|
+
);
|
639
|
+
routes.push(
|
640
|
+
this.prepareRoute(
|
641
|
+
internal,
|
642
|
+
"get",
|
643
|
+
apiPrefix,
|
644
|
+
tableName + "/distinct",
|
645
|
+
"distinct"
|
646
|
+
)
|
647
|
+
);
|
648
|
+
routes.push(
|
649
|
+
this.prepareRoute(
|
650
|
+
internal,
|
651
|
+
"get",
|
652
|
+
apiPrefix,
|
653
|
+
tableName + "/ugroupby",
|
654
|
+
"ugroupby"
|
655
|
+
)
|
656
|
+
);
|
657
|
+
routes.push(
|
658
|
+
this.prepareRoute(
|
659
|
+
internal,
|
660
|
+
"get",
|
661
|
+
apiPrefix,
|
662
|
+
tableName + "/chart",
|
663
|
+
"chart"
|
664
|
+
)
|
665
|
+
);
|
666
|
+
routes.push(
|
667
|
+
this.prepareRoute(
|
668
|
+
internal,
|
669
|
+
"get",
|
670
|
+
apiPrefix,
|
671
|
+
tableName + "/aggregate",
|
672
|
+
"aggregate"
|
673
|
+
)
|
674
|
+
);
|
675
|
+
routes.push(
|
676
|
+
this.prepareRoute(
|
677
|
+
internal,
|
678
|
+
"get",
|
679
|
+
apiPrefix,
|
680
|
+
tableName + "/findOne",
|
681
|
+
"findOne"
|
682
|
+
)
|
683
|
+
);
|
684
|
+
routes.push(
|
685
|
+
this.prepareRoute(
|
686
|
+
internal,
|
687
|
+
"get",
|
688
|
+
apiPrefix,
|
689
|
+
tableName + "/autoChart",
|
690
|
+
"autoChart"
|
691
|
+
)
|
692
|
+
);
|
693
|
+
|
694
|
+
if (!isView && !this.sqlConfig.readOnly) {
|
695
|
+
routes.push(
|
696
|
+
this.prepareRoute(internal, "post", apiPrefix, tableName, "create")
|
697
|
+
);
|
698
|
+
}
|
699
|
+
routes.push(
|
700
|
+
this.prepareRoute(internal, "get", apiPrefix, tableName, "list")
|
701
|
+
);
|
702
|
+
|
703
|
+
if (!isView && !this.sqlConfig.readOnly) {
|
704
|
+
routes.push(
|
705
|
+
this.prepareRoute(
|
706
|
+
internal,
|
707
|
+
"post",
|
708
|
+
apiPrefix,
|
709
|
+
tableName + "/bulk",
|
710
|
+
"bulkInsert"
|
711
|
+
)
|
712
|
+
);
|
713
|
+
routes.push(
|
714
|
+
this.prepareRoute(
|
715
|
+
internal,
|
716
|
+
"delete",
|
717
|
+
apiPrefix,
|
718
|
+
tableName + "/bulk",
|
719
|
+
"bulkDelete"
|
720
|
+
)
|
721
|
+
);
|
722
|
+
}
|
723
|
+
routes.push(
|
724
|
+
this.prepareRoute(
|
725
|
+
internal,
|
726
|
+
"get",
|
727
|
+
apiPrefix,
|
728
|
+
tableName + "/bulk",
|
729
|
+
"bulkRead"
|
730
|
+
)
|
731
|
+
);
|
732
|
+
|
733
|
+
if (!isView && !this.sqlConfig.readOnly) {
|
734
|
+
routes.push(
|
735
|
+
this.prepareRoute(internal, "put", apiPrefix, tableName, "update")
|
736
|
+
);
|
737
|
+
routes.push(
|
738
|
+
this.prepareRoute(
|
739
|
+
internal,
|
740
|
+
"patch",
|
741
|
+
apiPrefix,
|
742
|
+
tableName + "/:id",
|
743
|
+
"patch"
|
744
|
+
)
|
745
|
+
);
|
746
|
+
routes.push(
|
747
|
+
this.prepareRoute(
|
748
|
+
internal,
|
749
|
+
"delete",
|
750
|
+
apiPrefix,
|
751
|
+
tableName + "/:id",
|
752
|
+
"delete"
|
753
|
+
)
|
754
|
+
);
|
755
|
+
}
|
756
|
+
|
757
|
+
routes.push(
|
758
|
+
this.prepareRoute(
|
759
|
+
internal,
|
760
|
+
"get",
|
761
|
+
apiPrefix,
|
762
|
+
tableName + "/:id",
|
763
|
+
"read"
|
764
|
+
)
|
765
|
+
);
|
766
|
+
routes.push(
|
767
|
+
this.prepareRoute(
|
768
|
+
internal,
|
769
|
+
"get",
|
770
|
+
apiPrefix,
|
771
|
+
tableName + "/:id/exists",
|
772
|
+
"exists"
|
773
|
+
)
|
774
|
+
);
|
775
|
+
|
776
|
+
for (var j = 0; j < table["foreignKeys"].length; ++j) {
|
777
|
+
let fk = table["foreignKeys"][j];
|
778
|
+
|
779
|
+
if (fk["referenced_table_name"] in this.sqlConfig.ignoreTables) {
|
780
|
+
//console.log('ignore table',fk['referenced_table_name']);
|
781
|
+
} else {
|
782
|
+
routes.push(
|
783
|
+
this.prepareRoute(
|
784
|
+
internal,
|
785
|
+
"get",
|
786
|
+
apiPrefix,
|
787
|
+
fk["referenced_table_name"] + "/:id/" + fk["table_name"],
|
788
|
+
"relational"
|
789
|
+
)
|
790
|
+
);
|
791
|
+
}
|
792
|
+
}
|
793
|
+
|
794
|
+
var procList = this.getProcList()
|
795
|
+
for (var j = 0; j < procList.length; j++) {
|
796
|
+
routes.push(this.prepareRoute(internal, 'post', apiPrefix, '_proc/' + procList[j]))
|
797
|
+
}
|
798
|
+
|
799
|
+
tableObj['routes'] = routes;
|
800
|
+
|
801
|
+
schemaRoutes.push(tableObj);
|
802
|
+
}
|
803
|
+
}
|
804
|
+
|
805
|
+
return schemaRoutes;
|
806
|
+
}
|
807
|
+
|
808
|
+
getProcList() {
|
809
|
+
let procRoutes = []
|
810
|
+
for (let procName in this.metaDb.routines) {
|
811
|
+
procRoutes.push(this.metaDb.routines[procName])
|
812
|
+
}
|
813
|
+
return procRoutes
|
814
|
+
}
|
815
|
+
|
816
|
+
getJoinType(joinInQueryParams) {
|
817
|
+
//console.log('joinInQueryParams',joinInQueryParams);
|
818
|
+
|
819
|
+
switch (joinInQueryParams) {
|
820
|
+
case "_lj":
|
821
|
+
return " left join ";
|
822
|
+
break;
|
823
|
+
|
824
|
+
case "_rj":
|
825
|
+
return " right join ";
|
826
|
+
break;
|
827
|
+
|
828
|
+
// case '_fj':
|
829
|
+
// return ' full join '
|
830
|
+
// break;
|
831
|
+
|
832
|
+
case "_ij":
|
833
|
+
return " inner join ";
|
834
|
+
break;
|
835
|
+
|
836
|
+
case "_j":
|
837
|
+
return " join ";
|
838
|
+
break;
|
839
|
+
}
|
840
|
+
|
841
|
+
return " join ";
|
842
|
+
}
|
843
|
+
|
844
|
+
globalRoutesPrint(apiPrefix) {
|
845
|
+
let r = [];
|
846
|
+
|
847
|
+
r.push(apiPrefix + "tables");
|
848
|
+
r.push(apiPrefix + "xjoin");
|
849
|
+
|
850
|
+
if (this.sqlConfig.dynamic) {
|
851
|
+
r.push(apiPrefix + "dynamic");
|
852
|
+
r.push("/upload");
|
853
|
+
r.push("/uploads");
|
854
|
+
r.push("/download");
|
855
|
+
}
|
856
|
+
|
857
|
+
return r;
|
858
|
+
}
|
859
|
+
|
860
|
+
getChartQueryAndParamsFromStepPair(
|
861
|
+
tableName,
|
862
|
+
columnName,
|
863
|
+
stepArray,
|
864
|
+
isRange = false
|
865
|
+
) {
|
866
|
+
let obj = {};
|
867
|
+
|
868
|
+
obj.query = "";
|
869
|
+
obj.params = [];
|
870
|
+
|
871
|
+
//console.log('getChartQueryAndParamsFromStepArray',isRange);
|
872
|
+
|
873
|
+
//select ? as ??, count(*) as _count from ?? where ?? between ? and ?
|
874
|
+
|
875
|
+
if (
|
876
|
+
stepArray.length &&
|
877
|
+
stepArray.length >= 2 &&
|
878
|
+
stepArray.length % 2 === 0
|
879
|
+
) {
|
880
|
+
for (
|
881
|
+
let i = 0;
|
882
|
+
i < stepArray.length && stepArray.length >= 2;
|
883
|
+
i = i + 2
|
884
|
+
) {
|
885
|
+
obj.query = obj.query + dataHelp.getChartQuery();
|
886
|
+
|
887
|
+
if (i + 2 < stepArray.length) {
|
888
|
+
obj.query = obj.query + " union ";
|
889
|
+
}
|
890
|
+
|
891
|
+
obj.params.push(stepArray[i] + " to " + stepArray[i + 1]);
|
892
|
+
obj.params.push(columnName);
|
893
|
+
obj.params.push(tableName);
|
894
|
+
obj.params.push(columnName);
|
895
|
+
obj.params.push(stepArray[i]);
|
896
|
+
obj.params.push(stepArray[i + 1]);
|
897
|
+
}
|
898
|
+
}
|
899
|
+
|
900
|
+
//console.log('step spread query', obj);
|
901
|
+
|
902
|
+
return obj;
|
903
|
+
}
|
904
|
+
|
905
|
+
getChartQueryAndParamsFromStepArray(
|
906
|
+
tableName,
|
907
|
+
columnName,
|
908
|
+
stepArray,
|
909
|
+
isRange = false
|
910
|
+
) {
|
911
|
+
let obj = {};
|
912
|
+
|
913
|
+
obj.query = "";
|
914
|
+
obj.params = [];
|
915
|
+
|
916
|
+
//console.log('getChartQueryAndParamsFromStepArray',isRange);
|
917
|
+
|
918
|
+
if (stepArray.length && stepArray.length >= 2) {
|
919
|
+
for (let i = 0; i < stepArray.length - 1; i = i + 1) {
|
920
|
+
obj.query = obj.query + dataHelp.getChartQuery();
|
921
|
+
if (i + 2 < stepArray.length) {
|
922
|
+
obj.query = obj.query + " union ";
|
923
|
+
}
|
924
|
+
|
925
|
+
if (i && isRange === false) {
|
926
|
+
stepArray[i] = stepArray[i] + 1;
|
927
|
+
}
|
928
|
+
|
929
|
+
if (isRange === false) {
|
930
|
+
obj.params.push(stepArray[i] + " to " + stepArray[i + 1]);
|
931
|
+
} else {
|
932
|
+
obj.params.push(stepArray[0] + " to " + stepArray[i + 1]);
|
933
|
+
}
|
934
|
+
|
935
|
+
obj.params.push(columnName);
|
936
|
+
obj.params.push(tableName);
|
937
|
+
obj.params.push(columnName);
|
938
|
+
|
939
|
+
if (isRange === false) {
|
940
|
+
obj.params.push(stepArray[i]);
|
941
|
+
obj.params.push(stepArray[i + 1]);
|
942
|
+
} else {
|
943
|
+
obj.params.push(stepArray[0]);
|
944
|
+
obj.params.push(stepArray[i + 1]);
|
945
|
+
}
|
946
|
+
}
|
947
|
+
}
|
948
|
+
|
949
|
+
//console.log('step spread query', obj);
|
950
|
+
|
951
|
+
return obj;
|
952
|
+
}
|
953
|
+
|
954
|
+
getChartQueryAndParamsFromMinMaxStddev(
|
955
|
+
tableName,
|
956
|
+
columnName,
|
957
|
+
min,
|
958
|
+
max,
|
959
|
+
stddev,
|
960
|
+
isRange = false
|
961
|
+
) {
|
962
|
+
let stepArray = dataHelp.getStepArray(min, max, stddev);
|
963
|
+
|
964
|
+
//console.log('steparray', stepArray);
|
965
|
+
|
966
|
+
let obj = this.getChartQueryAndParamsFromStepArray(
|
967
|
+
tableName,
|
968
|
+
columnName,
|
969
|
+
stepArray,
|
970
|
+
isRange
|
971
|
+
);
|
972
|
+
|
973
|
+
//console.log('steparray', obj);
|
974
|
+
|
975
|
+
return obj;
|
976
|
+
}
|
977
|
+
|
978
|
+
getChartQueryAndParamsFromMinMaxStep(
|
979
|
+
tableName,
|
980
|
+
columnName,
|
981
|
+
min,
|
982
|
+
max,
|
983
|
+
step,
|
984
|
+
isRange = false
|
985
|
+
) {
|
986
|
+
let stepArray = dataHelp.getStepArraySimple(min, max, step);
|
987
|
+
|
988
|
+
//console.log('steparray', stepArray);
|
989
|
+
|
990
|
+
let obj = this.getChartQueryAndParamsFromStepArray(
|
991
|
+
tableName,
|
992
|
+
columnName,
|
993
|
+
stepArray,
|
994
|
+
isRange
|
995
|
+
);
|
996
|
+
|
997
|
+
//console.log('steparray', obj);
|
998
|
+
|
999
|
+
return obj;
|
1000
|
+
}
|
1001
|
+
|
1002
|
+
_getGrpByHavingOrderBy(req, tableName, queryParamsObj, listType) {
|
1003
|
+
/**************** add group by ****************/
|
1004
|
+
this.getGroupByClause(
|
1005
|
+
req.query._groupby,
|
1006
|
+
req.app.locals._tableName,
|
1007
|
+
queryParamsObj
|
1008
|
+
);
|
1009
|
+
|
1010
|
+
/**************** add having ****************/
|
1011
|
+
this.getHavingClause(
|
1012
|
+
req.query._having,
|
1013
|
+
req.app.locals._tableName,
|
1014
|
+
queryParamsObj
|
1015
|
+
);
|
1016
|
+
|
1017
|
+
/**************** add order clause ****************/
|
1018
|
+
this.getOrderByClause(req.query, req.app.locals._tableName, queryParamsObj);
|
1019
|
+
|
1020
|
+
/**************** add limit clause ****************/
|
1021
|
+
if (listType === 2) {
|
1022
|
+
//nested
|
1023
|
+
queryParamsObj.query += " limit 1 ";
|
1024
|
+
} else {
|
1025
|
+
queryParamsObj.query += " limit ?,? ";
|
1026
|
+
queryParamsObj.params = queryParamsObj.params.concat(
|
1027
|
+
this.getLimitClause(req.query)
|
1028
|
+
);
|
1029
|
+
}
|
1030
|
+
}
|
1031
|
+
|
1032
|
+
/**
|
1033
|
+
*
|
1034
|
+
* @param req
|
1035
|
+
* @param res
|
1036
|
+
* @param queryParamsObj : {query, params}
|
1037
|
+
* @param listType : 0:list, 1:nested, 2:findOne, 3:bulkRead, 4:distinct, 5:xjoin
|
1038
|
+
*
|
1039
|
+
* Updates query, params for query of type listType
|
1040
|
+
*/
|
1041
|
+
prepareListQuery(req, res, queryParamsObj, listType = 0) {
|
1042
|
+
queryParamsObj.query = "select ";
|
1043
|
+
queryParamsObj.params = [];
|
1044
|
+
|
1045
|
+
if (listType === 4) {
|
1046
|
+
//list type distinct
|
1047
|
+
queryParamsObj.query += " distinct ";
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
/**************** select columns ****************/
|
1051
|
+
if (req.query._groupby) {
|
1052
|
+
this.getColumnsForSelectStmtWithGrpBy(
|
1053
|
+
req.query,
|
1054
|
+
req.app.locals._tableName,
|
1055
|
+
queryParamsObj
|
1056
|
+
);
|
1057
|
+
} else {
|
1058
|
+
this.getColumnsForSelectStmt(
|
1059
|
+
req.app.locals._tableName,
|
1060
|
+
req.query,
|
1061
|
+
queryParamsObj
|
1062
|
+
);
|
1063
|
+
}
|
1064
|
+
|
1065
|
+
/**************** add tableName ****************/
|
1066
|
+
queryParamsObj.query += " from ?? ";
|
1067
|
+
|
1068
|
+
if (listType === 1) {
|
1069
|
+
//nested list
|
1070
|
+
|
1071
|
+
req.app.locals._tableName = req.app.locals._childTable;
|
1072
|
+
|
1073
|
+
queryParamsObj.params.push(req.app.locals._childTable);
|
1074
|
+
|
1075
|
+
queryParamsObj.query += " where ";
|
1076
|
+
|
1077
|
+
/**************** add where foreign key ****************/
|
1078
|
+
let whereClause = this.getForeignKeyWhereClause(
|
1079
|
+
req.app.locals._parentTable,
|
1080
|
+
req.params.id,
|
1081
|
+
req.app.locals._childTable
|
1082
|
+
);
|
1083
|
+
|
1084
|
+
if (!whereClause) {
|
1085
|
+
return res.status(400).send({
|
1086
|
+
error:
|
1087
|
+
"Table is made of composite primary keys - all keys were not in input"
|
1088
|
+
});
|
1089
|
+
}
|
1090
|
+
queryParamsObj.query += whereClause;
|
1091
|
+
|
1092
|
+
this.getWhereClause(
|
1093
|
+
req.query._where,
|
1094
|
+
req.app.locals._tableName,
|
1095
|
+
queryParamsObj,
|
1096
|
+
" and "
|
1097
|
+
);
|
1098
|
+
} else if (listType === 3) {
|
1099
|
+
//bulkRead
|
1100
|
+
|
1101
|
+
// select * from table where pk in (ids) and whereConditions
|
1102
|
+
queryParamsObj.params.push(req.app.locals._tableName);
|
1103
|
+
queryParamsObj.query += " where ?? in ";
|
1104
|
+
queryParamsObj.params.push(
|
1105
|
+
this.getPrimaryKeyName(req.app.locals._tableName)
|
1106
|
+
);
|
1107
|
+
|
1108
|
+
queryParamsObj.query += "(";
|
1109
|
+
|
1110
|
+
if (req.query && req.query._ids) {
|
1111
|
+
let ids = req.query._ids.split(",");
|
1112
|
+
for (var i = 0; i < ids.length; ++i) {
|
1113
|
+
if (i) {
|
1114
|
+
queryParamsObj.query += ",";
|
1115
|
+
}
|
1116
|
+
queryParamsObj.query += "?";
|
1117
|
+
queryParamsObj.params.push(ids[i]);
|
1118
|
+
}
|
1119
|
+
}
|
1120
|
+
queryParamsObj.query += ") ";
|
1121
|
+
this.getWhereClause(
|
1122
|
+
req.query._where,
|
1123
|
+
req.app.locals._tableName,
|
1124
|
+
queryParamsObj,
|
1125
|
+
" and "
|
1126
|
+
);
|
1127
|
+
} else {
|
1128
|
+
queryParamsObj.params.push(req.app.locals._tableName);
|
1129
|
+
|
1130
|
+
/**************** add where clause ****************/
|
1131
|
+
this.getWhereClause(
|
1132
|
+
req.query._where,
|
1133
|
+
req.app.locals._tableName,
|
1134
|
+
queryParamsObj,
|
1135
|
+
" where "
|
1136
|
+
);
|
1137
|
+
}
|
1138
|
+
|
1139
|
+
this._getGrpByHavingOrderBy(req, req.app.locals._tableName, queryParamsObj);
|
1140
|
+
|
1141
|
+
//console.log(queryParamsObj.query, queryParamsObj.params);
|
1142
|
+
}
|
1143
|
+
|
1144
|
+
_joinTableNames(isSecondJoin, joinTables, index, queryParamsObj) {
|
1145
|
+
if (isSecondJoin) {
|
1146
|
+
/**
|
1147
|
+
* in second join - there will be ONE table and an ON condition
|
1148
|
+
* if clause deals with this
|
1149
|
+
*
|
1150
|
+
*/
|
1151
|
+
|
1152
|
+
// add : join / left join / right join / full join / inner join
|
1153
|
+
queryParamsObj.query += this.getJoinType(joinTables[index]);
|
1154
|
+
queryParamsObj.query += " ?? as ?? ";
|
1155
|
+
|
1156
|
+
// eg: tbl.tableName
|
1157
|
+
let tableNameAndAs = joinTables[index + 1].split(".");
|
1158
|
+
|
1159
|
+
if (
|
1160
|
+
tableNameAndAs.length === 2 &&
|
1161
|
+
!(tableNameAndAs[1] in this.sqlConfig.ignoreTables)
|
1162
|
+
) {
|
1163
|
+
queryParamsObj.params.push(tableNameAndAs[1]);
|
1164
|
+
queryParamsObj.params.push(tableNameAndAs[0]);
|
1165
|
+
} else {
|
1166
|
+
queryParamsObj.grammarErr = 1;
|
1167
|
+
console.log("there was no dot for tableName ", joinTables[index + 1]);
|
1168
|
+
}
|
1169
|
+
} else {
|
1170
|
+
/**
|
1171
|
+
* in first join - there will be TWO tables and an ON condition
|
1172
|
+
* else clause deals with this
|
1173
|
+
*/
|
1174
|
+
|
1175
|
+
// first table
|
1176
|
+
queryParamsObj.query += " ?? as ?? ";
|
1177
|
+
// add : join / left join / right join / full join / inner join
|
1178
|
+
queryParamsObj.query += this.getJoinType(joinTables[index + 1]);
|
1179
|
+
// second table
|
1180
|
+
queryParamsObj.query += " ?? as ?? ";
|
1181
|
+
|
1182
|
+
let tableNameAndAs = joinTables[index].split(".");
|
1183
|
+
if (
|
1184
|
+
tableNameAndAs.length === 2 &&
|
1185
|
+
!(tableNameAndAs[1] in this.sqlConfig.ignoreTables)
|
1186
|
+
) {
|
1187
|
+
queryParamsObj.params.push(tableNameAndAs[1]);
|
1188
|
+
queryParamsObj.params.push(tableNameAndAs[0]);
|
1189
|
+
} else {
|
1190
|
+
queryParamsObj.grammarErr = 1;
|
1191
|
+
console.log("there was no dot for tableName ", joinTables[index]);
|
1192
|
+
}
|
1193
|
+
|
1194
|
+
tableNameAndAs = [];
|
1195
|
+
tableNameAndAs = joinTables[index + 2].split(".");
|
1196
|
+
if (
|
1197
|
+
tableNameAndAs.length === 2 &&
|
1198
|
+
!(tableNameAndAs[1] in this.sqlConfig.ignoreTables)
|
1199
|
+
) {
|
1200
|
+
queryParamsObj.params.push(tableNameAndAs[1]);
|
1201
|
+
queryParamsObj.params.push(tableNameAndAs[0]);
|
1202
|
+
} else {
|
1203
|
+
queryParamsObj.grammarErr = 1;
|
1204
|
+
console.log("there was no dot for tableName ", joinTables[index]);
|
1205
|
+
}
|
1206
|
+
}
|
1207
|
+
}
|
1208
|
+
|
1209
|
+
prepareJoinQuery(req, res, queryParamsObj) {
|
1210
|
+
queryParamsObj.query = "SELECT ";
|
1211
|
+
queryParamsObj.grammarErr = 0;
|
1212
|
+
|
1213
|
+
while (1) {
|
1214
|
+
/**************** START : get fields ****************/
|
1215
|
+
if (req.query._fields) {
|
1216
|
+
let fields = req.query._fields.split(",");
|
1217
|
+
|
1218
|
+
// from _fields to - ??, ??, ?? [col1,col2,col3]
|
1219
|
+
for (var i = 0; i < fields.length && !queryParamsObj.grammarErr; ++i) {
|
1220
|
+
if (i) {
|
1221
|
+
queryParamsObj.query += ",";
|
1222
|
+
}
|
1223
|
+
queryParamsObj.query += " ?? ";
|
1224
|
+
queryParamsObj.params.push(fields[i]);
|
1225
|
+
let aliases = fields[i].split(".");
|
1226
|
+
if (aliases.length === 2) {
|
1227
|
+
queryParamsObj.query += "as " + aliases[0] + "_" + aliases[1];
|
1228
|
+
//console.log(queryParamsObj.query);
|
1229
|
+
} else {
|
1230
|
+
queryParamsObj.grammarErr = 1;
|
1231
|
+
}
|
1232
|
+
}
|
1233
|
+
} else {
|
1234
|
+
queryParamsObj.grammarErr = 1;
|
1235
|
+
}
|
1236
|
+
|
1237
|
+
queryParamsObj.query += " from ";
|
1238
|
+
|
1239
|
+
if (queryParamsObj.grammarErr) {
|
1240
|
+
break;
|
1241
|
+
}
|
1242
|
+
|
1243
|
+
/**************** END : get fields ****************/
|
1244
|
+
|
1245
|
+
/**************** START : get join + on ****************/
|
1246
|
+
let joinTables = req.query._join.split(",");
|
1247
|
+
if (joinTables.length < 3) {
|
1248
|
+
//console.log('grammar error ', joinTables.length);
|
1249
|
+
queryParamsObj.grammarErr = 1;
|
1250
|
+
break;
|
1251
|
+
}
|
1252
|
+
|
1253
|
+
//console.log('jointables.length', joinTables);
|
1254
|
+
|
1255
|
+
let onCondnCount = 0;
|
1256
|
+
|
1257
|
+
for (
|
1258
|
+
let i = 0;
|
1259
|
+
i < joinTables.length - 1 && queryParamsObj.grammarErr === 0;
|
1260
|
+
i = i + 2
|
1261
|
+
) {
|
1262
|
+
onCondnCount++;
|
1263
|
+
|
1264
|
+
this._joinTableNames(i, joinTables, i, queryParamsObj);
|
1265
|
+
|
1266
|
+
if (queryParamsObj.grammarErr) {
|
1267
|
+
console.log("failed at _joinTableNames", queryParamsObj);
|
1268
|
+
break;
|
1269
|
+
}
|
1270
|
+
|
1271
|
+
//console.log('after join tables', queryParamsObj);
|
1272
|
+
|
1273
|
+
let onCondn = "_on" + onCondnCount;
|
1274
|
+
let onCondnObj = {};
|
1275
|
+
if (onCondn in req.query) {
|
1276
|
+
//console.log(onCondn, req.query[onCondn]);
|
1277
|
+
onCondnObj = whereHelp.getConditionClause(req.query[onCondn], " on ");
|
1278
|
+
//console.log('onCondnObj', onCondnObj);
|
1279
|
+
queryParamsObj.query += " on " + onCondnObj.query;
|
1280
|
+
queryParamsObj.params = queryParamsObj.params.concat(
|
1281
|
+
onCondnObj.params
|
1282
|
+
);
|
1283
|
+
} else {
|
1284
|
+
queryParamsObj.grammarErr = 1;
|
1285
|
+
//console.log('No on condition: ', onCondn);
|
1286
|
+
break;
|
1287
|
+
}
|
1288
|
+
|
1289
|
+
if (i === 0) {
|
1290
|
+
i = i + 1;
|
1291
|
+
}
|
1292
|
+
}
|
1293
|
+
/**************** END : get join + on ****************/
|
1294
|
+
|
1295
|
+
if (queryParamsObj.grammarErr) {
|
1296
|
+
break;
|
1297
|
+
} else {
|
1298
|
+
this.getWhereClause(
|
1299
|
+
req.query._where,
|
1300
|
+
" ignore ",
|
1301
|
+
queryParamsObj,
|
1302
|
+
" where "
|
1303
|
+
);
|
1304
|
+
this._getGrpByHavingOrderBy(req, "ignore", queryParamsObj, 5);
|
1305
|
+
//console.log('after where',queryParamsObj);
|
1306
|
+
}
|
1307
|
+
|
1308
|
+
break;
|
1309
|
+
}
|
1310
|
+
|
1311
|
+
if (queryParamsObj.grammarErr) {
|
1312
|
+
queryParamsObj.query = "";
|
1313
|
+
queryParamsObj.params = [];
|
1314
|
+
}
|
1315
|
+
|
1316
|
+
return queryParamsObj;
|
1317
|
+
}
|
1318
|
+
}
|
1319
|
+
|
1320
|
+
//expose class
|
1321
|
+
module.exports = Xsql;
|