yekonga-server
Version:
Yekonga Server
1,699 lines (1,399 loc) • 71.1 kB
JavaScript
// @ts-nocheck
const H = Yekonga.Helper;
const path = serverLibrary.path;
const ObjectId = serverLibrary.mongodb.ObjectId;
const moment = serverLibrary.moment;
var mysqlConnection = require('./database/mysql.connect');
var mongodbConnection = require('./database/mongodb.connect');
var nedbConnection = require('./database/nedb.connect');
module.exports = function(conf) {
var database = new DatabaseQuery();
if (!conf && Yekonga.Config.database) {
conf = Yekonga.Config.database[Yekonga.Config.defaultDatabase]
}
if (conf) {
database.config(conf);
}
return database;
}
class DatabaseQuery {
async mysqlConnection(options) {
if (!this.connection || this.connection.state == 'disconnected') {
var db_connect = mysqlConnection();
db_connect.connect(options);
this.connectionObject = db_connect;
this.connection = db_connect.connection;
}
return this;
}
async mongodbConnection(options) {
if (!this.connection || this.connection.state == 'disconnected') {
var db_connect = mongodbConnection();
this.connection = await db_connect.connect(options);
// console.debug(this.connection)
}
return this;
}
async config(options) {
this.config = options;
this.databaseType = options.type;
if (options.type == 'mongodb') {
this.mongodbConnection(options);
} else if (options.type == 'nedb') {
this.database = nedbConnection(options.tables);
} else if (options.type == 'mysql') {
this.mysqlConnection(options);
}
return this;
}
table(table, generateId) {
var query = new Query(this);
return query.table(table, generateId);
}
async query(str) {
var query = new Query(this);
return await query.execute(str);
}
statement() {
if (this.databaseType == 'mysql') {
return this.connection;
} else if (this.databaseType == 'mongodb') {
return this.connection;
} else if (this.databaseType == 'nedb') {
return this.database;
}
}
}
class Query {
constructor(parent) {
this._prefix = null;
this._id = '';
this._query = '';
this._table = '';
this._primaryKey = null;
this._addedFields = {};
this._select = {};
this._data = {};
this._where = [];
this._join = [];
this._leftJoin = [];
this._rightJoin = [];
this._group = [];
this._having = []
this._sort = {};
this._skip = 0;
this._limit = 0;
this._page = 1;
this._with = [];
this._setFieldKey = [];
this._throughTable = null;
this._currentIndexColor = null;
this._databaseType = null;
this._aggregate = null;
this.$parent = parent;
this.databaseType = parent.databaseType;
if (this.$parent.config.type == 'nedb') {
this.setNedb(this.$parent.database);
} else if (this.$parent.config.type == 'mongodb') {
this.setMongodb(this.$parent.connection);
} else {
this.setMysql(this.$parent.connection);
}
}
table(table, generateId) {
var prefix = (this._prefix) ? this._prefix : "";
this._table = prefix + table;
if (generateId) {
this._primaryKey = generateId;
} else {
this._primaryKey = this.__getPrimaryKey(table);
}
return this;
}
__getPrimaryKey(table) {
var val = Yekonga.Helper.toSingular(Yekonga.Helper.getUnderscore(table));
val = Yekonga.Helper.getColumn(`${val}_id`);
return val;
}
getVariables() {
if (this._page > 1) {
this._skip = (this._page - 1) * this._limit;
}
var _variables = {
_prefix: this._prefix,
_id: this._id,
_query: this._query,
_table: this._table,
_primaryKey: this._primaryKey,
_addedFields: this._addedFields,
_select: this._select,
_join: this._join,
_leftJoin: this._leftJoin,
_rightJoin: this._rightJoin,
_group: this._group,
_having: this._having,
_sort: this._sort,
_skip: this._skip,
_limit: this._limit,
_page: this._page,
_with: this._with,
_setFieldKey: this._setFieldKey,
_throughTable: this._throughTable,
_currentIndexColor: this._currentIndexColor,
_databaseType: this._databaseType,
_aggregate: this._aggregate,
};
var variables = Yekonga.Helper.copyJson(_variables);
variables._data = this._data,
variables._where = [...this._where],
variables.$parent = this.$parent;
variables.database = this.database;
return variables;
}
setMysql(database) {
this.database = database;
this._databaseType = 'mysql';
return this;
}
setNedb(database) {
this.database = database;
this._databaseType = 'nedb';
return this;
}
setMongodb(database) {
this.database = database;
this._databaseType = 'mongodb';
return this;
}
async execute(query) {
let result = await this.getControl().execute(query);
return result;
}
collection() {
return this.getControl().getCollection();
}
addField(value) {
if (value && typeof value === 'object') {
if (typeof this._addedFields !== 'object' || !this._addedFields) this._addedFields = {};
for (const key in value) {
this._addedFields[key] = value[key];
}
}
return this;
}
select(value) {
if (value) {
if (Array.isArray(value)) {
if (this._databaseType == 'nedb' || this._databaseType == 'mongodb') {
if (Array.isArray(this._select)) this._select = {};
if (typeof this._select !== 'object' || !this._select) this._select = {}
for (const val of value) {
this._select[val] = 1;
}
} else {
this._select = value;
}
} else if (typeof value === 'object') {
for (const val of value) {
if (this._databaseType == 'nedb' || this._databaseType == 'mongodb') {
if (Array.isArray(this._select)) this._select = {};
if (typeof this._select !== 'object' || !this._select) this._select = {}
this._select[val] = 1;
} else {
this._select.push(val);
}
}
} else {
if (this._databaseType == 'nedb' || this._databaseType == 'mongodb') {
if (Array.isArray(this._select)) this._select = {};
if (typeof this._select !== 'object' || !this._select) this._select = {}
this._select[value] = 1;
} else {
this._select.push(value);
}
}
}
return this;
}
selectRaw(string) {
this._select.push(string);
return this;
}
set(field, value) {
if (Array.isArray(field)) {
if (field.length) {
this._data = field;
}
} else if (typeof field === 'object' && field) {
for (var i in field) {
var iKey = i;
var iValue = field[iKey];
this._data[iKey] = iValue;
}
} else if (typeof field === 'string') {
this._data[field] = value;
}
return this;
}
through(table, foreignKey, localKey, where) {
if (where == null) {
where = {};
}
this._throughTable = {
table: table,
foreignKey: foreignKey,
localKey: localKey,
where: where,
};
return this;
}
setGetWhere(arg1, arg2, arg3, arg4, arg5) {
var _singleWhere = null;
var compare = '=';
var type = (arg4) ? arg4 : 'BASIC';
var andor = (arg5) ? arg5 : 'AND';
if (['$and', '$or', '$nor'].includes(arg1)) {
type = 'GROUP';
andor = (arg1 == '$or') ? 'OR' : 'AND';
_singleWhere = {
'column': arg1,
'type': type,
'compare': compare,
'value': arg2,
'andor': andor
}
} else if (typeof arg2 == 'undefined' && arg1 && typeof arg1 == 'object' && !Array.isArray(arg1)) {
var whereGroup = [];
for (const key in arg1) {
if (arg1.hasOwnProperty(key)) {
const value = arg1[key];
const where = this.setGetWhere(key, value);
if (where) {
whereGroup.push(where);
}
}
}
_singleWhere = whereGroup;
} else if (typeof arg3 == 'undefined') {
var column = arg1
var value = (typeof arg2 == 'object') ? arg2 : { '$eq': arg2 };
compare = '=';
_singleWhere = {
'column': column,
'type': type,
'compare': compare,
'value': value,
'andor': andor
}
} else if (typeof arg2 != 'undefined' && typeof arg3 != 'undefined') {
var column = arg1;
var value = arg3;
compare = arg2;
if (compare == "=") {
value = { '$eq': value }
} else if (compare == "!=") {
value = { '$ne': value }
} else if (compare == "<") {
value = { '$lt': value }
} else if (compare == "<=") {
value = { '$lte': value }
} else if (compare == ">") {
value = { '$gt': value }
} else if (compare == ">=") {
value = { '$gte': value }
} else if (compare.toUpperCase() == "IN") {
value = { '$in': value }
} else if (compare.toUpperCase() == "NOT IN") {
value = { '$nin': value }
} else if (compare.toUpperCase() == "EXISTS") {
value = { '$exists': (value ? true : false) }
} else if (compare.toUpperCase() == "LIKE") {
value = (new RegExp(value, "i"))
}
_singleWhere = {
'column': column,
'type': type,
'compare': compare,
'value': value,
'andor': andor
}
}
return _singleWhere;
}
where(arg1, arg2, arg3, arg4, arg5) {
var _where = this.setGetWhere(arg1, arg2, arg3, arg4, arg5);
if (_where) {
if (Array.isArray(_where)) {
for (const row of _where) {
this._where.push(row);
}
} else {
this._where.push(_where);
}
}
return this;
}
orWhere(arg1, arg2, arg3, arg4) {
var andor = 'OR';
this.where(arg1, arg2, arg3, arg4, andor);
return this;
}
whereGroup(params, andor) {
var type = 'GROUP';
andor = (andor) ? andor : 'AND';
if (typeof params === 'object') {
var iWhereGroup = this.setGetWhere(params);
if (Array.isArray(iWhereGroup) && iWhereGroup.length > 0) {
this._where.push({
type: type,
andor: andor,
value: iWhereGroup
});
}
}
return this;
}
orWhereGroup(column, iCompare, iType, iAndor) {
var andor = 'OR';
this.whereGroup(column, andor);
return this;
}
whereGroupLike(params, iAndor) {
var compare = 'LIKE';
var type = 'LIKE';
this.whereGroup(params, 'AND');
}
orWhereGroupLike(params, iAndor) {
var compare = 'LIKE';
var type = 'LIKE';
this.whereGroup(params, 'OR');
}
whereRaw(string, andor) {
andor = (andor) ? andor : 'AND';
this._where.push({
type: 'RAW',
andor: andor,
value: string
});
return this;
}
whereIn(column, value, type, andor) {
var compare = 'IN';
type = (type) ? type : 'IN';
this.where(column, compare, value, type, andor);
return this;
}
whereNotIn(column, value, andor) {
var compare = 'NOT IN';
var type = 'IN';
this.whereIn(column, value, type, andor)
return this;
}
orWhereIn(column, value) {
var compare = 'IN';
var type = 'IN';
var andor = 'OR';
this.where(column, compare, value, type, andor);
return this;
}
orWhereNotIn(column, value) {
var compare = 'NOT IN';
var type = 'IN';
var andor = 'OR';
this.where(column, compare, value, type, andor);
return this;
}
whereNull(column, value, type, andor) {
var compare = 'IS';
type = (type) ? type : 'NULL';
this.where(column, compare, value, type, andor);
return this;
}
whereNotNull(column, value, andor) {
var compare = 'IS NOT';
var type = 'NULL';
this.whereIn(column, value, type, andor)
return this;
}
whereLike(colums, value, iAndor, andor) {
if (!value) return;
if (!colums) return;
andor = (andor) ? andor : 'AND';
iAndor = (iAndor) ? iAndor : 'OR';
var type = 'GROUP';
var iWhereGroup = [];
// console.debug(colums)
if (!Array.isArray(colums)) colums = colums.split(',');
if (Array.isArray(colums)) {
for (var key of colums) {
var iColumn = key.toString().trim();
var iValue = value;
var iCompare = 'LIKE';
var iType = 'LIKE';
if (iColumn != '') {
iWhereGroup.push({
'column': iColumn,
'type': iType,
'compare': iCompare,
'value': iValue,
'andor': iAndor,
});
}
}
}
if (iWhereGroup.length) {
this._where.push({
type: 'GROUP',
andor: andor,
value: iWhereGroup
});
}
return this;
}
having(column, compare, value) {
if (typeof value === 'undefined') {
value = compare;
compare = '=';
}
this._having.push(`${column} ${compare} ${value}`);
return this;
}
havingRaw(string) {
this._having.push(string);
return this;
}
groupBy(arg1, arg2) {
if (!Array.isArray(this._group)) this._group = [];
if (Array.isArray(arg1)) {
for (const col of arg1) {
this._group.push(col);
}
} else if (arg1 && typeof arg1 == 'object') {
for (const key in arg1) {
var col = {
key,
value: arg1[key]
};
this._group.push(col);
}
} else {
this._group.push({ key: arg1, value: arg2 });
}
return this;
}
orderBy(firstParam, secondParam) {
if (Array.isArray(this._sort) || typeof this._sort != 'object' || !this._sort) this._sort = {};
this._sort[firstParam] = (secondParam.toLowerCase() == 'desc') ? -1 : 1;
return this;
}
limit(value) {
this._limit = value;
return this;
}
page(value) {
this._page = value;
return this;
}
join(table, firstParam, compare, secondParam) {
this._join.push(`INNER JOIN ${table} ON ${firstParam} ${compare} ${secondParam}`);
return this;
}
leftJoin(table, firstParam, compare, secondParam) {
this._leftJoin.push(`LEFT JOIN${table} ON ${firstParam} ${compare} ${secondParam}`);
}
rightJoin(table, firstParam, compare, secondParam) {
this._rightJoin.push(`RIGHT JOIN ${table} ON ${firstParam} ${compare} ${secondParam}`);
}
with(table, foreignKey, localKey = null, select = ['*'], one = false) {
if (localKey == null) {
localKey = table + '_id';
}
this._with.push({
table: table,
foreignKey: foreignKey,
localKey: localKey,
select: select,
one: one,
});
return this;
}
withOne(table, foreignKey, localKey = null, select = ['*']) {
return this.with(table, foreignKey, localKey, select, true)
}
getControl() {
var control = null;
if (this.databaseType == 'mysql') {
control = new ProcessSqlQuery(this.getVariables());
} else {
control = new ProcessMongoQuery(this.getVariables());
}
return control;
}
async paginate(query, pagination = true) {
const $this = this;
var page = this._page;
var perPage = (this._limit) ? this._limit : (pagination ? 10 : null);
try {
var total = 0;
var lastPage = 1;
var offset = 1;
if (pagination) {
lastPage = Math.ceil(total / perPage);
offset = (page - 1) * perPage;
this._limit = perPage;
this._skip = offset;
}
let result = await this.getControl().find();
if (result.error) return result;
if (pagination) {
var prevPage = (page <= 1) ? null : +page - 1;
var from = offset + 1;
var to = offset + result.length;
var totalCount = await this.getControl().count();
// console.debug(totalCount)
total = (totalCount) ? totalCount : 0;
lastPage = Math.ceil(total / perPage);
var nextPage = (page >= lastPage) ? null : +page + 1;
return {
total: total,
currentPage: page,
perPage: perPage,
lastPage: lastPage,
nextPage: nextPage,
prevPage: prevPage,
from: from,
to: to,
data: result,
}
}
return result;
} catch (error) {
console.error(error);
return $this.errorHandler(error);
}
}
async get(req, array) {
if (array) {
this.select(array);
}
var result = await this.paginate(req, false);
return result;
}
find(req, array) {
return this.get(req, array);
}
async first(req, array) {
this.limit(1);
var result = await this.get(req, array);
result = this.queryResult(result, true);
return result;
}
findOne(req, array) {
return this.first(req, array);
}
async createIndex(keys, options) {
let result = await this.getControl().createIndex(keys, options);
return result;
}
async create(data, setPrimaryKey = true) {
this.set(data);
if (Array.isArray(this._data)) {
this._data = this._data.map((v) => {
if (!v[this._primaryKey]) {
v[this._primaryKey] = Yekonga.Helper.getHexString();
}
if (this.databaseType == 'mongodb') {
v[this._primaryKey] = new ObjectId(v[this._primaryKey])
}
return v;
})
} else {
if (!this._data[this._primaryKey]) {
this._data[this._primaryKey] = Yekonga.Helper.getHexString();
}
if (this.databaseType == 'mongodb') {
this._data[this._primaryKey] = new ObjectId(this._data[this._primaryKey])
}
}
let result = await this.getControl().create();
if (Yekonga.Socket && result.affectedCount) {
Yekonga.Socket.emit('database', {
action: 'create',
model: Yekonga.Helper.getClass(this._table),
id: Array.isArray(result.data)
? result.data.map(v => v[this._primaryKey])
: (result.data)? result.data[this._primaryKey]: null
});
}
return result;
}
async update(data) {
this.set(data);
let result = await this.getControl().update();
if (Yekonga.Socket && result.affectedCount) {
Yekonga.Socket.emit('database', {
action: 'update',
model: Yekonga.Helper.getClass(this._table),
id: result.data.map(v => v[this._primaryKey])
});
}
return result;
}
async delete(id) {
if (id) {
this._where.push(this.setGetWhere(this._primaryKey, { '$eq': id }))
}
let result = await this.getControl().delete();
if (Yekonga.Socket && result.affectedCount) {
Yekonga.Socket.emit('database', {
action: 'delete',
model: Yekonga.Helper.getClass(this._table),
id: result.data.map(v => v[this._primaryKey])
});
}
return result;
}
count() {
return this.getControl().count();
}
sum(column, column2) {
return this.getControl().sum(column, column2);
}
max(column) {
return this.getControl().max(column);
}
min(column) {
return this.getControl().min(column);
}
avg(column) {
return this.getControl().average(column);
}
average(column) {
return this.getControl().average(column);
}
async lists(column) {
var result = await this.find(null, [column]);
return result.map(function(elem, index, array) {
var value = elem[column];
if (value) {
return value;
}
})
}
async pluck(column) {
var result = await this.findOne(null, [column]);
if (result) {
return result[column];
}
return null;
}
async exists() {
var result = await this.findOne();
if (result) {
return true;
}
return false;
}
async chart(array, dateset_keys, label_column) {
var _result = await this.find(null, array);
var chart = {}
chart.labels = [];
chart.datasets = [];
for (let key in dateset_keys) {
var dataset = {
label: dateset_keys[key],
key: key,
data: [],
backgroundColor: this.getColor(),
borderColor: null,
}
chart.datasets.push(dataset);
}
chart.title = 'YeKonga';
var start_time = await this.min(label_column);
start_time = (start_time) ? moment(start_time).format('YYYY-MM-DD') : '2017-12-01';
var date_differance = moment().diff(start_time, 'd');
for (let i = 0; i < date_differance; i++) {
var time = moment(start_time).add(i, 'd').format('YYYY-MM-DD');
chart.labels.push(time);
var _subdata = {};
for (let _dataset of chart.datasets) {
_subdata[_dataset.key] = 0;
}
for (let x = 0; x < _result.length; x++) {
var _elem = _result[x];
if (_elem.label == time) {
for (let _dataset of chart.datasets) {
_subdata[_dataset.key] = _elem[_dataset.key];
}
// data_total = elem.total;
// data_amount = elem.amount;
break;
}
}
for (let _dataset of chart.datasets) {
_dataset.data.push(_subdata[_dataset.key]);
}
}
return chart;
}
async pie(array, dateset_keys, label_column, value_column) {
var _result = await this.find(null, array);
var chart = {}
chart.title = 'Robert Konga';
chart.labels = [];
chart.datasets = [];
var dataset = {
label: chart.title,
data: [],
backgroundColor: [],
borderColor: [],
}
chart.datasets.push(dataset);
var _subdata = {};
for (let key in dateset_keys) {
chart.labels.push(dateset_keys[key]);
var _value = 0;
for (let i = 0; i < _result.length; i++) {
var _elem = _result[i];
if (_elem[label_column] == key) {
_value = _elem[value_column];
break;
}
}
chart.datasets[0].data.push(_value)
chart.datasets[0].backgroundColor.push(this.getColor())
}
return chart;
}
getColor() {
var colors = [
'rgb(255, 99, 132)',
'rgb(255, 159, 64)',
'rgb(255, 205, 86)',
'rgb(75, 192, 192)',
'rgb(54, 162, 235)',
'rgb(153, 102, 255)',
'rgb(201, 203, 207)'
];
if (this._currentIndexColor == null) {
this._currentIndexColor = 0;
} else {
this._currentIndexColor++;
}
if (this._currentIndexColor >= colors.length) {
this._currentIndexColor = 0;
}
return colors[this._currentIndexColor];
}
queryResult(result, single = false) {
if (result && result.data) result = result.data;
var __result = (single) ? null : [];
if (result) {
if (result.error) {
__result = result;
} else if (result.length) {
if (single) {
__result = (Array.isArray(result)) ? result[0] : result;
} else {
__result = (Array.isArray(result)) ? result : [result];
}
}
}
return __result;
}
errorHandler(_error) {
let __error = _error;
if (this._databaseType == 'nedb') {
__error = {
message: _error.message,
name: _error.name,
errors: _error.errors,
}
} else if (this._databaseType == 'mongodb') {
__error = {
message: _error.message,
name: _error.name,
errors: _error.errors,
}
}
return {
error: __error
};
}
}
class ProcessSqlQuery {
constructor(params) {
this._prefix = null;
this._id = '';
this._query = '';
this._table = '';
this._primaryKey = null;
this._addedFields = {};
this._select = [];
this._selectRaw = [];
this._data = {};
this._setFieldKey = [];
this._setValue = [];
this._setValueArray = false;
this._where = [];
this._join = [];
this._leftJoin = [];
this._rightJoin = [];
this._group = {};
this._having = {};
this._sort = {};
this._skip = 0;
this._limit = 0;
this._page = 0;
this._with = [];
this._throughTable = null;
this._currentIndexColor = null;
this._databaseType = null;
this._aggregate = null;
this.$parent = null;
for (const key in params) {
if (params.hasOwnProperty(key)) {
const value = params[key];
this[key] = value;
}
}
}
setData() {
var compare = '=';
if (Array.isArray(this._data)) {
this._setValueArray = true;
if (this._data.length) {
for (var key in this._data[0]) {
this._setFieldKey.push(`${key}`);
}
for (var row of this._data) {
var i_values = [];
for (var i in row) {
var iValue = row[i];
if (iValue == null) {
i_values.push(`${this.addslashes(iValue)}`);
} else {
i_values.push(`'${this.addslashes(iValue)}'`);
}
}
let _i_values = '(' + i_values.join(',') + ')';
this._setValue.push(_i_values);
}
}
} else if (typeof this._data === 'object' && this._data) {
for (var i in this._data) {
var iKey = i;
var iValue = this._data[iKey];
if (iValue == null) {
this._setValue.push(`\`${iKey}\` ${compare} ${this.addslashes(iValue)}`);
} else {
this._setValue.push(`\`${iKey}\` ${compare} '${this.addslashes(iValue)}'`);
}
}
} else if (typeof this._data === 'string') {
if (iValue == null) {
this._setValue.push(`\`${this._data}\` ${compare} ${this.addslashes(iValue)}`);
} else {
this._setValue.push(`\`${this._data}\` ${compare} '${this.addslashes(iValue)}'`);
}
}
}
getJoin() {
var query = '';
if (this._join.length) {
query += ' ' + this._join.join(' ');
}
if (this._leftJoin.length) {
query += ' ' + this._leftJoin.join(' ');
}
if (this._rightJoin.length) {
query += ' ' + this._rightJoin.join(' ');
}
return query;
}
getWhere() {
var query = '';
var andor = `WHERE`;
var _where = [...this._where];
// console.debug(_where);
for (var i = 0; i < _where.length; i++) {
const where = _where[i];
andor = (i == 0) ? andor : where.andor;
if (where.type == 'GROUP') {
let where_query_group = '';
let andor_group = '';
for (var ii = 0; ii < where.value.length; ii++) {
const group_where = {...where.value[ii] };
andor_group = (ii == 0) ? andor_group : where.andor;
for (const key in group_where) {
if (group_where.hasOwnProperty(key)) {
const value = group_where[key];
var _data = this.getValueFromMongo(value);
group_where.value = _data.value;
group_where.compare = _data.compare;
group_where.column = key;
}
}
where_query_group += ` ${andor_group} \`${group_where.column}\` ${group_where.compare} ${this.getWhereValue(group_where.value, group_where.compare)} `;
}
query += ` ${andor} (${where_query_group})`;
} else {
var _data = this.getValueFromMongo(where.value);
where.value = _data.value;
where.compare = _data.compare;
query += ` ${andor} \`${where.column}\` ${where.compare} ${this.getWhereValue(where.value, where.compare)} `;
}
}
return query;
}
getWhereValue(value, type) {
if (type == 'IN') {
if (Array.isArray(value)) {
value = value.map((item, index, array) => {
return this.addslashes(item);
});
return `("` + value.join('", "') + `")`;
} else {
return `(` + this.addslashes(value) + `)`;
}
} else if (value == null || value == undefined) {
return null;
} else if (type == 'LIKE') {
return '"%' + this.addslashes(value) + '%"';
} else {
return '"' + this.addslashes(value) + '"';
}
}
addslashes(value) {
if (value && typeof value == 'string') {
value = value.replace(/\\/g, '\\\\').
replace(/\u0008/g, '\\b').
replace(/\t/g, '\\t').
replace(/\n/g, '\\n').
replace(/\f/g, '\\f').
replace(/\r/g, '\\r').
replace(/'/g, '\\\'').
replace(/"/g, '\\"');
}
return value;
}
getValueFromMongo(value) {
var compare = '=';
// console.debug(value)
if (value['$eq']) {
compare = "=";
value = value['$eq'];
} else if (value['$ne']) {
compare = "!=";
value = value['$ne'];
} else if (value['$lt']) {
compare = "<";
value = value['$lt'];
} else if (value['$lte']) {
compare = "<=";
value = value['$lte'];
} else if (value['$gt']) {
compare = ">";
value = value['$gt'];
} else if (value['$gte']) {
compare = ">=";
value = value['$gte'];
} else if (value['$in']) {
compare = "IN";
value = value['$in'];
} else if (value['$nin']) {
compare = "NOT IN";
value = value['$nin'];
} else if (value instanceof RegExp) {
compare = "LIKE";
value = value.source;
} else if (value['$not']) {
if (value['$not']['$lt']) {
compare = ">=";
value = value['$not']['$lt'];
} else if (value['$not']['$lte']) {
compare = ">";
value = value['$not']['$lte'];
} else if (value['$not']['$gt']) {
compare = "<=";
value = value['$not']['$gt'];
} else if (value['$not']['$gte']) {
compare = "<";
value = value['$not']['$gte'];
}
} else if (Array.isArray(value)) {
compare = "IN";
}
return { value: value, compare: compare };
}
getGroup() {
var query = '';
var sources = this._group;
if (sources.length) {
var groupQueries = []
// @ts-ignore
for (const row of sources) {
var key = null;
if (typeof row == 'string') {
key = row;
groupQueries.push(`${key}`);
} else if (row) {
if (row.key == '_id') {
if (row.value && row.value.group) {
key = row.value.group.substr(1);
groupQueries.push(`\`${key}\``);
this._selectRaw.push(`\`${key}\` as \`group\``);
}
if (row.value && row.value.period) {
var format = row.value.period['$dateToString'].format;
var date = row.value.period['$dateToString'].date.substr(1);
var groupColumn = `DATE_FORMAT(\`${date}\`, '${format}')`;
groupQueries.push(`${groupColumn}`);
this._selectRaw.push(`${groupColumn} as \`period\``);
}
} else if (row.value && row.value['$sum']) {
key = (row.value['$sum'] == 1) ? 1 : row.value['$sum'].substr(1);
this._selectRaw.push(`SUM(${key}) as \`${row.key}\``)
}
}
}
if (groupQueries.length) {
query += ` GROUP BY ${groupQueries.join(', ')}`;
}
}
return query;
}
getSort() {
var query = '';
if (this._sort) {
for (const key in this._sort) {
if (Object.hasOwnProperty.call(this._sort, key)) {
const value = this._sort[key];
query += ` ORDER BY ${key} ${(value == 1)? 'ASC':'DESC'}`;
}
}
}
return query;
}
getHaving() {
var query = '';
if (this._having.length) {
query += ` HAVING ${this._having.join(' AND ')}`;
}
return query;
}
getLimit(count) {
var query = '';
if (count) {
query += ` LIMIT ${count}`
} else if (this._limit) {
query += ` LIMIT ${this._limit}`
}
return query;
}
getSkip() {
var query = '';
if (this._skip) {
query += ` OFFSET ${this._skip}`;
}
return query;
}
async find() {
const $this = this;
var result = await $this.execute($this.toSql());
result = $this.queryResult(result, false);
return result;
}
async createIndex(keys, options) {}
async create() {
const $this = this;
var error = null;
var affectedCount = 0;
var affectedData = this._data;
var result = await $this.execute($this.toSql('create'));
// console.debug(result);
// result = $this.queryResult(result, true);
if (result && result.affectedRows) {
affectedCount = result.affectedRows;
} else if (result && result.error) {
affectedData = null;
error = result.error.message;
}
return {
error: error,
data: affectedData,
affectedCount: affectedCount
}
}
async update() {
const $this = this;
var error = null;
var affectedCount = 0;
var affectedData = this._data;
var result = await $this.execute($this.toSql('update'));
// result = $this.queryResult(result, true);
if (result && result.changedRows) {
affectedCount = result.changedRows;
} else if (result && result.error) {
error = result.error.message;
}
return {
error: error,
data: affectedData,
affectedCount: affectedCount
}
}
async delete() {
const $this = this;
var error = null;
var affectedCount = 0;
var affectedData = null;
var result = await $this.execute($this.toSql('delete'));
result = $this.queryResult(result, true);
if (result && result.affectedRows) {
affectedCount = result.affectedRows;
} else if (result && result.error) {
error = result.error.message;
}
return {
error: error,
data: affectedData,
affectedCount: affectedCount
}
}
limit(value) {
this._limit = value;
return this;
}
skip(value) {
this._skip = value;
return this;
}
page(value) {
this._page = value;
this._skip = 0;
return this;
}
select(value) {
this._select = value;
return this;
}
async count() {
const $this = this;
if ($this._group.length) {
var query = `COUNT(DISTICT ${$this._group.join(',')}) as result`;
} else {
var query = `COUNT(*) as result`;
}
// @ts-ignore
$this._selectRaw = query;
$this.limit(1);
$this.page(1);
$this.skip(0);
$this.select([query]);
var result = await $this.execute($this.toSql());
result = $this.queryResult(result, true);
if (result) {
return result.result;
}
return 0;
}
async sum(column, column2) {
var value = Array.isArray(column) ? column : [column];
if (column2) {
value.push(column2);
}
var query = `SUM(\`${value.join('`*`')}\`) as result`;
this.limit(1);
this.select([query]);
var result = await this.execute(this.toSql());
// console.debug(result)
result = this.queryResult(result, true);
if (result) {
return (result.result == null) ? 0 : result.result;
}
return 0;
}
async max(column) {
var query = `MAX(${column}) as result`;
this.limit(1);
this.select([query]);
var result = await this.execute(this.toSql());
result = this.queryResult(result, true);
if (result) {
return result.result;
}
return 0;
}
async min(column) {
var query = `MIN(${column}) as result`;
this.limit(1);
this.select([query]);
var result = await this.execute(this.toSql());
result = this.queryResult(result, true);
if (result) {
return result.result;
}
return 0;
}
async average(column) {
var query = `AVG(${column}) as result`;
this.limit(1);
this.select([query]);
var result = await this.execute(this.toSql());
result = this.queryResult(result, true);
if (result) {
return result.result;
}
return 0;
}
execute(query) {
const $this = this;
const $parent = this.$parent;
return new Promise((resolve, reject) => {
try {
if (Array.isArray(query)) {
var chunk = 200;
var total = query.length;
let result = [];
for (let i = 0; i < ((total - total % chunk) / chunk + 1); i++) {
var _query = '';
$parent.connection.beginTransaction(function(err) {
if (err) {
// console.debug(err.sqlMessage)
return resolve({
error: {
message: err.sqlMessage,
sql: err.sql
},
})
}
for (let ii = 0; ii < chunk; ii++) {
const row = query[((i * chunk) + ii)];
if (row) {
_query += row;
}
}
$parent.connection.query(_query, function(error, docs, fields) {
if (error) {
return $parent.connection.rollback(function() {
throw error;
});
}
result.push(docs);
});
$parent.connection.commit(function(error) {
if (error) {
return $parent.connection.rollback(function() {
throw error;
});
}
});
});
}
return resolve(result);
} else {
$parent.connection.query(query, function(error, docs, fields) {
if (error) {
return resolve({
error: {
message: error.sqlMessage,
sql: error.sql
},
})
}
return resolve(docs);
});
}
} catch (error) {
console.error(error);
return resolve($this.errorHandler(error));
}
});
}
toSql(execute = 'query', count = false) {
var query = '';
if (typeof execute == 'undefined' || execute == 'query') {
var groupQuery = this.getGroup();
var selectString = '';
if (this._selectRaw && !Array.isArray(this._selectRaw)) this._selectRaw = [this._selectRaw];
if (!this._selectRaw || !(Array.isArray(this._selectRaw) && this._selectRaw.length)) {
selectString = this._select.length ?
`\`${this._select.join('`, `')}\`` : ((this._selectRaw.length)? '':'*');
} else {
selectString += this._selectRaw.length ?
`${this._selectRaw.join(', ')}`: '';
}
query = `SELECT ${selectString} FROM \`${this._table}\``;
query += this.getJoin();
query += this.getWhere();
if (count) {
query += this.getLimit(1);
} else {
query += groupQuery;
query += this.getHaving();
query += this.getSort();
query += this.getLimit();
query += this.getSkip();
}
} else if (execute == 'create') {
this.setData();
query += ` INSERT INTO \`${this._table}\` `;
if (this._setValueArray) {
query += ` (\`${this._setFieldKey.join('`, `')}\`) `;
query += ` VALUES ${this._setValue.join(', ')} `;
} else {
query += ` SET ${this._setValue.join(', ')} `;
}
} else if (execute == 'update') {
this.setData();
query += ` UPDATE \`${this._table}\` `;
query += ` SET ${this._setValue.join(', ')} `;
query += this.getWhere();
} else if (execute == 'delete') {
query += ` DELETE FROM \`${this._table}\` `;
query += this.getWhere();
} else if (execute == 'fields') {
query += ` SELECT * FROM \`${this._table}\` `;
}
// console.debug(query);
return query;
}
queryResult(result, single = false) {
if (result && result.data) result = result.data;
var __result = (single) ? null : [];
if (result) {
if (result.error || result.errors) {
__result = result;
} else if (result.length) {
if (single) {
__result = (Array.isArray(result)) ? result.pop() : result;
} else {
__result = (Array.isArray(result)) ? result : [result];
}
} else {
// console.debug(result);
}
}
return __result;
}
errorHandler(_error) {
return {
error: _error
};
}
}
class ProcessMongoQuery {
constructor(params){
this._prefix = null;
this._id = '';
this._query = '';
this._table = '';
this._primaryKey = null;
this._addedFields = {};
this._select = [];
this._data = {};
this._where = [];
this._join = [];
this._leftJoin = [];