UNPKG

yekonga-server

Version:
1,699 lines (1,399 loc) 71.1 kB
// @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 = [];