2016-09-26 09:28:47 +00:00
|
|
|
|
2015-01-23 13:09:30 +00:00
|
|
|
/**
|
2016-09-24 14:32:31 +00:00
|
|
|
* Simulates a connection to a database by making asynchronous requests to a
|
|
|
|
* remote REST service that returns the results in JSON format.
|
2015-01-23 13:09:30 +00:00
|
|
|
* Using this class can perform any operation that can be done with a database,
|
|
|
|
* like open/close a connection or selecion/updating queries.
|
2016-09-24 14:32:31 +00:00
|
|
|
*
|
|
|
|
* Warning! You should set a well defined dababase level privileges to use this
|
|
|
|
* class or you could have a serious security hole in you application becasuse
|
|
|
|
* the user can send any statement to the server. For example: DROP DATABASE
|
2021-01-23 16:15:02 +00:00
|
|
|
*/
|
2020-05-03 20:35:24 +00:00
|
|
|
var Connection = new Class();
|
2016-09-26 09:28:47 +00:00
|
|
|
module.exports = Connection;
|
|
|
|
|
2022-05-30 01:30:33 +00:00
|
|
|
var Flag = {
|
2016-09-26 09:28:47 +00:00
|
|
|
NOT_NULL : 1
|
|
|
|
,PRI_KEY : 2
|
|
|
|
,AI : 512 | 2 | 1
|
|
|
|
};
|
|
|
|
|
2022-05-30 01:30:33 +00:00
|
|
|
var Type = {
|
2016-09-26 09:28:47 +00:00
|
|
|
BOOLEAN : 1
|
|
|
|
,INTEGER : 3
|
|
|
|
,DOUBLE : 4
|
|
|
|
,STRING : 5
|
|
|
|
,DATE : 8
|
|
|
|
,DATE_TIME : 9
|
|
|
|
};
|
|
|
|
|
2020-05-04 19:55:18 +00:00
|
|
|
Connection.extend({
|
2016-09-26 09:28:47 +00:00
|
|
|
Flag: Flag
|
|
|
|
,Type: Type
|
2015-01-23 13:09:30 +00:00
|
|
|
});
|
|
|
|
|
2020-05-04 19:55:18 +00:00
|
|
|
Connection.implement({
|
2016-09-23 22:47:34 +00:00
|
|
|
Extends: Vn.JsonConnection
|
2015-01-23 13:09:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Runs a SQL query on the database.
|
|
|
|
*
|
|
|
|
* @param {String} sql The SQL statement
|
2022-11-28 08:51:31 +00:00
|
|
|
* @return {ResultSet} The result
|
2021-01-23 16:15:02 +00:00
|
|
|
*/
|
2022-11-28 08:51:31 +00:00
|
|
|
,async execSql(sql) {
|
|
|
|
const json = await this.send('core/query', {sql});
|
2022-05-28 15:49:46 +00:00
|
|
|
const results = [];
|
2022-11-28 08:51:31 +00:00
|
|
|
let err;
|
2022-05-28 15:49:46 +00:00
|
|
|
|
2016-05-05 15:47:45 +00:00
|
|
|
if (json)
|
2015-01-23 13:09:30 +00:00
|
|
|
try {
|
2016-05-05 15:47:45 +00:00
|
|
|
if (json && json instanceof Array)
|
2022-05-28 15:49:46 +00:00
|
|
|
for (let i = 0; i < json.length; i++)
|
2020-05-03 20:35:24 +00:00
|
|
|
if (json[i] !== true) {
|
2022-05-28 15:49:46 +00:00
|
|
|
const rows = json[i].data;
|
|
|
|
const columns = json[i].columns;
|
|
|
|
|
|
|
|
const data = new Array(rows.length);
|
|
|
|
results.push({
|
|
|
|
data,
|
|
|
|
columns,
|
|
|
|
tables: json[i].tables
|
|
|
|
});
|
|
|
|
|
|
|
|
for (let j = 0; j < rows.length; j++) {
|
|
|
|
const row = data[j] = {};
|
|
|
|
for (let k = 0; k < columns.length; k++)
|
|
|
|
row[columns[k].name] = rows[j][k];
|
|
|
|
}
|
2015-01-23 13:09:30 +00:00
|
|
|
|
2022-05-28 15:49:46 +00:00
|
|
|
for (let j = 0; j < columns.length; j++) {
|
|
|
|
let castFunc = null;
|
|
|
|
const col = columns[j];
|
2015-01-23 13:09:30 +00:00
|
|
|
|
2022-05-28 15:49:46 +00:00
|
|
|
switch (col.type) {
|
2016-09-26 09:28:47 +00:00
|
|
|
case Type.DATE:
|
|
|
|
case Type.DATE_TIME:
|
|
|
|
case Type.TIMESTAMP:
|
2015-01-23 13:09:30 +00:00
|
|
|
castFunc = this.valueToDate;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-05-03 20:35:24 +00:00
|
|
|
if (castFunc !== null) {
|
2022-05-28 15:49:46 +00:00
|
|
|
if (col.def != null)
|
|
|
|
col.def = castFunc(col.def);
|
2015-01-23 13:09:30 +00:00
|
|
|
|
2022-05-28 15:49:46 +00:00
|
|
|
for (let k = 0; k < data.length; k++)
|
|
|
|
if (data[k][col.name] != null)
|
|
|
|
data[k][col.name] = castFunc(data[k][col.name]);
|
2015-01-23 13:09:30 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-28 15:49:46 +00:00
|
|
|
} else
|
|
|
|
results.push(json[i]);
|
2020-05-03 20:35:24 +00:00
|
|
|
} catch (e) {
|
2022-11-28 08:51:31 +00:00
|
|
|
err = e;
|
2015-01-23 13:09:30 +00:00
|
|
|
}
|
2016-05-05 15:47:45 +00:00
|
|
|
|
2022-11-28 08:51:31 +00:00
|
|
|
return new Db.ResultSet(results, err);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Runs a stmt on the database.
|
|
|
|
*
|
|
|
|
* @param {Sql.Stmt} stmt The statement
|
|
|
|
* @param {Object} params The query params
|
|
|
|
* @return {ResultSet} The result
|
|
|
|
*/
|
|
|
|
,async execStmt(stmt, params) {
|
|
|
|
return await this.execSql(stmt.render(params));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Runs a query on the database.
|
|
|
|
*
|
|
|
|
* @param {String} query The SQL statement
|
|
|
|
* @param {Object} params The query params
|
|
|
|
* @return {ResultSet} The result
|
|
|
|
*/
|
|
|
|
,async execQuery(query, params) {
|
|
|
|
return await this.execStmt(new Sql.String({query}), params);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parses a value to date.
|
|
|
|
*/
|
|
|
|
,valueToDate(value) {
|
|
|
|
return fixTz(new Date(value));
|
2015-01-23 13:09:30 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-05-04 19:55:18 +00:00
|
|
|
// TODO: Read time zone from db configuration
|
|
|
|
var tz = {timeZone: 'Europe/Madrid'};
|
|
|
|
var isLocal = Intl
|
|
|
|
.DateTimeFormat()
|
|
|
|
.resolvedOptions()
|
|
|
|
.timeZone == tz.timeZone;
|
|
|
|
|
|
|
|
function fixTz(date) {
|
|
|
|
if (isLocal) return date;
|
|
|
|
|
|
|
|
var localDate = new Date(date.toLocaleString('en-US', tz));
|
|
|
|
var hasTime = localDate.getHours()
|
|
|
|
|| localDate.getMinutes()
|
|
|
|
|| localDate.getSeconds()
|
|
|
|
|| localDate.getMilliseconds();
|
|
|
|
|
|
|
|
if (!hasTime) {
|
|
|
|
date.setHours(date.getHours() + 12);
|
|
|
|
date.setHours(0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return date;
|
|
|
|
}
|