forked from verdnatura/hedera-web
175 lines
4.5 KiB
JavaScript
175 lines
4.5 KiB
JavaScript
import { JsonConnection } from '../vn/json-connection'
|
|
import { ResultSet } from './result-set'
|
|
|
|
/**
|
|
* Simulates a connection to a database by making asynchronous requests to a
|
|
* remote REST service that returns the results in JSON format.
|
|
* Using this class can perform any operation that can be done with a database,
|
|
* like open/close a connection or selecion/updating queries.
|
|
*
|
|
* 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
|
|
*/
|
|
const Flag = {
|
|
NOT_NULL: 1,
|
|
PRI_KEY: 2,
|
|
AI: 512 | 2 | 1
|
|
}
|
|
|
|
const Type = {
|
|
BOOLEAN: 1,
|
|
INTEGER: 3,
|
|
DOUBLE: 4,
|
|
STRING: 5,
|
|
DATE: 8,
|
|
DATE_TIME: 9
|
|
}
|
|
|
|
export class Connection extends JsonConnection {
|
|
static Flag = Flag
|
|
static Type = Type
|
|
|
|
/**
|
|
* Runs a SQL query on the database.
|
|
*
|
|
* @param {String} sql The SQL statement
|
|
* @return {ResultSet} The result
|
|
*/
|
|
async execSql (sql) {
|
|
const json = await this.send('core/query', { sql })
|
|
const results = []
|
|
let err
|
|
|
|
if (json) {
|
|
try {
|
|
if (json && json instanceof Array) {
|
|
for (let i = 0; i < json.length; i++) {
|
|
if (json[i] !== true) {
|
|
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] }
|
|
}
|
|
|
|
for (let j = 0; j < columns.length; j++) {
|
|
let castFunc = null
|
|
const col = columns[j]
|
|
|
|
switch (col.type) {
|
|
case Type.DATE:
|
|
case Type.DATE_TIME:
|
|
case Type.TIMESTAMP:
|
|
castFunc = this.valueToDate
|
|
break
|
|
}
|
|
|
|
if (castFunc !== null) {
|
|
if (col.def != null) { col.def = castFunc(col.def) }
|
|
|
|
for (let k = 0; k < data.length; k++) {
|
|
if (data[k][col.name] != null) { data[k][col.name] = castFunc(data[k][col.name]) }
|
|
}
|
|
}
|
|
}
|
|
} else { results.push(json[i]) }
|
|
}
|
|
}
|
|
} catch (e) {
|
|
err = e
|
|
}
|
|
}
|
|
|
|
return new ResultSet(results, err)
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
const sql = query.replace(/#\w+/g, key => {
|
|
const value = params[key.substring(1)]
|
|
return value ? this.renderValue(value) : key
|
|
})
|
|
|
|
return await this.execSql(sql)
|
|
}
|
|
|
|
async query (query, params) {
|
|
const res = await this.execQuery(query, params)
|
|
return res.fetchData()
|
|
}
|
|
|
|
async getObject (query, params) {
|
|
const res = await this.execQuery(query, params)
|
|
return res.fetchObject()
|
|
}
|
|
|
|
async getValue (query, params) {
|
|
const res = await this.execQuery(query, params)
|
|
return res.fetchValue()
|
|
}
|
|
|
|
renderValue (v) {
|
|
switch (typeof v) {
|
|
case 'number':
|
|
return v
|
|
case 'boolean':
|
|
return (v) ? 'TRUE' : 'FALSE'
|
|
case 'string':
|
|
return "'" + v.replace(this.regexp, this.replaceFunc) + "'"
|
|
default:
|
|
if (v instanceof Date) {
|
|
if (!isNaN(v.getTime())) {
|
|
const unixTime = parseInt(fixTz(v).getTime() / 1000)
|
|
return 'DATE(FROM_UNIXTIME(' + unixTime + '))'
|
|
} else { return '0000-00-00' }
|
|
} else { return 'NULL' }
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Parses a value to date.
|
|
*/
|
|
valueToDate (value) {
|
|
return fixTz(new Date(value))
|
|
}
|
|
}
|
|
|
|
// TODO: Read time zone from db configuration
|
|
const tz = { timeZone: 'Europe/Madrid' }
|
|
const isLocal = Intl
|
|
.DateTimeFormat()
|
|
.resolvedOptions()
|
|
.timeZone === tz.timeZone
|
|
|
|
function fixTz (date) {
|
|
if (isLocal) return date
|
|
|
|
const localDate = new Date(date.toLocaleString('en-US', tz))
|
|
const hasTime = localDate.getHours() ||
|
|
localDate.getMinutes() ||
|
|
localDate.getSeconds() ||
|
|
localDate.getMilliseconds()
|
|
|
|
if (!hasTime) {
|
|
date.setHours(date.getHours() + 12)
|
|
date.setHours(0, 0, 0, 0)
|
|
}
|
|
|
|
return date
|
|
}
|