多维表格
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1068 lines
29 KiB

7 years ago
'use strict';
const mysql = require('mysql');
const dataHelp = require('./util/data.helper.js');
const whereHelp = require('./util/whereClause.helper.js');
7 years ago
const assert = require('assert')
//define class§
7 years ago
class Xsql {
constructor(sqlConfig, pool) {
//define this variables
this.sqlConfig = {}
this.pool = {}
this.metaDb = {};
this.metaDb.tables = {};
this.sqlConfig = sqlConfig;
this.pool = pool;
}
/**************** START : Cache functions ****************/
7 years ago
init(cbk) {
this.dbCacheInitAsync((err, results) => {
cbk(err, results)
})
}
dbCacheInitAsync(cbk) {
let self = this;
self.pool.query(dataHelp.getSchemaQuery(), [this.sqlConfig.database], (err, results) => {
if (err) {
console.log('Cache init failed during database reading')
console.log(err, results)
cbk(err, results)
} else {
self.iterateToCacheTables(results)
self.iterateToCacheTablePks(results)
self.iterateToCacheTableColumns(results)
self.iterateToCacheTableFks(results)
// osx mysql server has limitations related to open_tables
self.pool.query('FLUSH TABLES', [], (err, results) => {
cbk(null, null)
})
}
})
}
iterateToCacheTables(schemaResults) {
for (let i = 0; i < schemaResults.length; ++i) {
let schemaRow = schemaResults[i];
let tableName = schemaRow['table_name'];
if (!(tableName in this.metaDb.tables)) {
this.metaDb.tables[tableName] = {}
this.metaDb.tables[tableName]['primaryKeys'] = []
this.metaDb.tables[tableName]['foreignKeys'] = []
this.metaDb.tables[tableName]['columns'] = []
this.metaDb.tables[tableName]['indicies'] = []
this.metaDb.tables[tableName]['isView'] = schemaRow['table_name']['isView']
7 years ago
}
}
}
iterateToCacheTableColumns(schemaResults) {
for (let i = 0; i < schemaResults.length; ++i) {
let schemaRow = schemaResults[i];
let tableName = schemaRow['table_name'];
let col = {};
col['column_name'] = schemaRow['column_name']
col['ordinal_position'] = schemaRow['ordinal_position']
col['column_key'] = schemaRow['column_key']
col['data_type'] = schemaRow['data_type']
col['column_type'] = schemaRow['column_type']
dataHelp.findOrInsertObjectArrayByKey(col, 'column_name', this.metaDb.tables[tableName]['columns'])
}
}
iterateToCacheTablePks(schemaResults) {
for (let i = 0; i < schemaResults.length; ++i) {
let schemaRow = schemaResults[i];
let tableName = schemaRow['table_name'];
if (schemaRow['column_key'] === 'PRI') {
let pk = {};
pk['column_name'] = schemaRow['column_name']
pk['ordinal_position'] = schemaRow['ordinal_position']
pk['column_key'] = schemaRow['column_key']
pk['data_type'] = schemaRow['data_type']
pk['column_type'] = schemaRow['column_type']
dataHelp.findOrInsertObjectArrayByKey(pk, 'column_name', this.metaDb.tables[tableName]['primaryKeys'])
}
}
}
iterateToCacheTableFks(schemaResults) {
for (let i = 0; i < schemaResults.length; ++i) {
let schemaRow = schemaResults[i];
let tableName = schemaRow['table_name'];
if (schemaRow['referenced_table_name']) {
let fk = {};
fk['column_name'] = schemaRow['column_name']
fk['table_name'] = schemaRow['table_name']
fk['referenced_table_name'] = schemaRow['referenced_table_name']
fk['referenced_column_name'] = schemaRow['referenced_column_name']
fk['data_type'] = schemaRow['data_type']
fk['column_type'] = schemaRow['column_type']
dataHelp.findOrInsertObjectArrayByKey(fk, 'column_name', this.metaDb.tables[tableName]['foreignKeys'])
//console.log(fk['referenced_table_name'],fk['referenced_column_name'],tableName, schemaRow['column_name'], this.metaDb.tables[tableName]['foreignKeys'].length)
}
}
}
/**************** END : Cache functions ****************/
7 years ago
exec(query, params) {
let _this = this;
return new Promise(function (resolve, reject) {
//console.log('mysql>', query, params);
_this.pool.query(query, params, function (error, rows, _fields) {
if (error) {
console.log('mysql> ', error);
return reject(error);
}
return resolve(rows);
});
});
}
typeOfColumn(Type) {
//TODO: Im sure there are more types to handle here
const strTypes = ['varchar', 'text', 'char', 'tinytext', 'mediumtext', 'longtext', 'blob', 'mediumblob', 'longblob'];
const intTypes = ['int', 'long', 'smallint', 'mediumint', 'bigint', 'tinyint'];
const flatTypes = ['float', 'double', 'decimal'];
const dateTypes = ['date', 'datetime', 'timestamp', 'time', 'year'];
if (dataHelp.getType(Type, strTypes)) {
return "string"
} else if (dataHelp.getType(Type, intTypes)) {
return "int"
} else if (dataHelp.getType(Type, flatTypes)) {
return "float"
} else if (dataHelp.getType(Type, dateTypes)) {
return "date"
} else {
return "unknown"
}
}
isTypeOfColumnNumber(Type) {
//console.log(Type, this.typeOfColumn(Type));
return ('int' === this.typeOfColumn(Type) || 'float' === this.typeOfColumn(Type))
}
7 years ago
getLimitClause(reqParams) {
//defaults
reqParams._index = 0;
reqParams._len = 20;
if ('_size' in reqParams && parseInt(reqParams._size) < 100) {
reqParams._len = parseInt(reqParams._size)
}
if ('_p' in reqParams && parseInt(reqParams._p) > 0) {
reqParams._index = (parseInt(reqParams._p) - 1) * reqParams._len;
7 years ago
}
//console.log(reqParams._index, reqParams._len);
return [reqParams._index, reqParams._len]
}
prepareBulkInsert(tableName, objectArray, queryParamsObj) {
if (tableName in this.metaDb.tables && objectArray) {
let insObj = objectArray[0];
// goal => insert into ?? (?,?..?) values ? [tablName, col1,col2...coln,[[ObjValues_1],[ObjValues_2],...[ObjValues_N]]
queryParamsObj.query = ' INSERT INTO ?? ( '
queryParamsObj.params.push(tableName)
let cols = [];
let colPresent = false;
/**************** START : prepare column names to be inserted ****************/
// iterate over all column in table and have only ones existing in objects to be inserted
for (var i = 0; i < this.metaDb.tables[tableName]['columns'].length; ++i) {
let colName = this.metaDb.tables[tableName]['columns'][i]['column_name']
if (colName in insObj) {
if (colPresent) {
queryParamsObj.query += ','
}
queryParamsObj.query += colName
colPresent = true;
}
cols.push(colName)
//console.log('> > ', queryParamsObj.query);
}
queryParamsObj.query += ' ) values ?'
/**************** END : prepare column names to be inserted ****************/
/**************** START : prepare value object in prepared statement ****************/
// iterate over sent object array
let arrOfArr = []
for (var i = 0; i < objectArray.length; ++i) {
let arrValues = []
for (var j = 0; j < cols.length; ++j) {
if (cols[j] in objectArray[i])
arrValues.push(objectArray[i][cols[j]])
}
arrOfArr.push(arrValues);
}
queryParamsObj.params.push(arrOfArr)
/**************** END : prepare value object in prepared statement ****************/
}
}
getGroupByClause(_groupby, tableName, queryParamsObj) {
if (_groupby) {
queryParamsObj.query += ' group by ' + _groupby + ' '
return _groupby
}
}
getHavingClause(_having, tableName, queryParamsObj) {
if (_having) {
let whereClauseObj = whereHelp.getConditionClause(_having, 'having')
if (whereClauseObj.err === 0) {
queryParamsObj.query = queryParamsObj.query + ' having ' + whereClauseObj.query;
queryParamsObj.params = queryParamsObj.params.concat(whereClauseObj.params)
}
//console.log('> > > after where clause filling up:', queryParamsObj.query, queryParamsObj.params);
}
}
getWhereClause(queryparams, tableName, queryParamsObj, appendToWhere) {
if (queryparams) {
let whereClauseObj = whereHelp.getConditionClause(queryparams)
if (whereClauseObj.err === 0) {
queryParamsObj.query = queryParamsObj.query + appendToWhere + whereClauseObj.query;
queryParamsObj.params = queryParamsObj.params.concat(whereClauseObj.params)
}
}
}
getOrderByClause(queryparams, tableName, queryParamsObj) {
7 years ago
if (queryparams._sort) {
queryParamsObj.query += ' ORDER BY '
7 years ago
let orderByCols = queryparams._sort.split(',')
for (let i = 0; i < orderByCols.length; ++i) {
if (i) {
queryParamsObj.query += ', '
7 years ago
}
if (orderByCols[i][0] === '-') {
let len = orderByCols[i].length;
queryParamsObj.query += ' ?? DESC'
queryParamsObj.params.push(orderByCols[i].substring(1, len))
7 years ago
} else {
queryParamsObj.query += ' ?? ASC'
queryParamsObj.params.push(orderByCols[i])
7 years ago
}
}
}
}
getColumnsForSelectStmtWithGrpBy(reqQueryParams, tableName, queryParamsObj) {
let grpByCols = reqQueryParams._groupby.split(',');
for (var i = 0; i < grpByCols.length; ++i) {
if (i) {
queryParamsObj.query += ','
}
queryParamsObj.query += ' ??'
queryParamsObj.params.push(grpByCols[i])
}
queryParamsObj.query += ',count(1) as _count '
}
getColumnsForSelectStmt(tableName, reqQueryParams, queryParamsObj) {
7 years ago
let table = this.metaDb.tables[tableName];
let cols = [];
let _fieldsInQuery = [];
let removeFieldsObj = {};
// populate _fields array from query params
if ('_fields' in reqQueryParams) {
_fieldsInQuery = reqQueryParams['_fields'].split(',')
} else {
queryParamsObj.query += ' * '
7 years ago
return " * ";
}
// get column name in _fields and mark column name which start with '-'
for (let i = 0; i < _fieldsInQuery.length; ++i) {
if (_fieldsInQuery[i][0] === '-') {
7 years ago
removeFieldsObj[_fieldsInQuery[i].substring(1, _fieldsInQuery[i].length)] = 1;
} else {
cols.push(_fieldsInQuery[i])
}
}
if (!cols.length) {
// for each column in table - add only which are not in removeFieldsObj
for (let i = 0; i < table['columns'].length; ++i) {
if (!(table['columns'][i]['column_name'] in removeFieldsObj)) {
cols.push(table['columns'][i]['column_name'])
}
}
} else {
cols = this.removeUnknownColumns(cols, tableName)
}
for (var i = 0; i < cols.length; ++i) {
if (i) {
queryParamsObj.query += ','
}
queryParamsObj.query += '??'
queryParamsObj.params.push(cols[i])
}
7 years ago
return cols.join(',')
}
removeUnknownColumns(inputColumns, tableName) {
let cols = inputColumns;
let unknown_cols_in_input = []
let shadowCols = [];
let tableColumns = this.metaDb.tables[tableName]['columns']
// find unknown fields if any
for (var j = 0; j < cols.length; ++j) {
let found = 0;
for (var i = 0; i < tableColumns.length; ++i) {
if (tableColumns[i]['column_name'] === cols[j]) {
found = 1;
break;
}
}
if (!found) {
unknown_cols_in_input.push(j)
}
}
// if there are unknown fields - remove and ignore 'em
if (unknown_cols_in_input.length) {
for (var i = 0; i < cols.length; ++i) {
if (unknown_cols_in_input.indexOf(i) === -1) {
shadowCols.push(cols[i])
}
}
cols = [];
cols = shadowCols;
}
return cols;
}
getPrimaryKeyName(tableName) {
let pk = null
if (tableName in this.metaDb.tables) {
pk = this.metaDb.tables[tableName].primaryKeys[0]['column_name']
}
return pk
}
7 years ago
getPrimaryKeyWhereClause(tableName, pksValues) {
let whereClause = '';
let whereCol = '';
let whereValue = '';
let pks = []
if (tableName in this.metaDb.tables) {
pks = this.metaDb.tables[tableName].primaryKeys;
} else {
return null
}
// number of primary keys in table and one sent should be same
if (pksValues.length !== pks.length) {
return null
}
// get a where clause out of the above columnNames and their values
for (let i = 0; i < pks.length; ++i) {
let type = dataHelp.getColumnType(pks[i]);
7 years ago
whereCol = pks[i]['column_name']
if (type === 'string') {
whereValue = mysql.escape(pksValues[i])
} else if (type === 'int') {
whereValue = parseInt(pksValues[i])
} else if (type === 'float') {
whereValue = parseFloat(pksValues[i])
} else if (type === 'date') {
whereValue = Date(pksValues[i])
} else {
console.error(pks[i])
assert(false, 'Unhandled type of primary key')
}
if (i) {
whereClause += ' and '
}
whereClause += whereCol + ' = ' + whereValue;
}
return whereClause;
}
getForeignKeyWhereClause(parentTable, parentId, childTable) {
let whereValue = '';
//get all foreign keys of child table
let fks = this.metaDb.tables[childTable].foreignKeys;
let fk = dataHelp.findObjectInArrayByKey('referenced_table_name', parentTable, fks);
let whereCol = fk['column_name']
let colType = dataHelp.getColumnType(fk);
7 years ago
if (colType === 'string') {
whereValue = mysql.escape(parentId)
} else if (colType === 'int') {
whereValue = mysql.escape(parseInt(parentId))
} else if (colType === 'float') {
whereValue = mysql.escape(parseFloat(parentId))
} else if (colType === 'date') {
whereValue = mysql.escape(Date(parentId))
} else {
console.error(pks[i])
assert(false, 'Unhandled column type in foreign key handling')
}
return whereCol + ' = ' + whereValue;
}
prepareRoute(internal, httpType, apiPrefix, urlRoute, routeType) {
7 years ago
let route = {};
route['httpType'] = httpType;
route['routeUrl'] = apiPrefix + urlRoute;
if (internal) {
route['routeType'] = routeType;
}
7 years ago
return route;
}
getSchemaRoutes(internal, apiPrefix) {
7 years ago
let schemaRoutes = [];
for (var tableName in this.metaDb.tables) {
if (tableName in this.sqlConfig.ignoreTables) {
//console.log('ignore table', tableName);
} else {
7 years ago
let routes = []
let tableObj = {}
let table = this.metaDb.tables[tableName];
let isView = this.metaDb.tables[tableName]['isView'];
tableObj['resource'] = tableName;
routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/describe', 'describe'))
routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/count', 'count'))
routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/groupby', 'groupby'))
routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/distinct', 'distinct'))
routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/ugroupby', 'ugroupby'))
routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/chart', 'chart'))
routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/aggregate', 'aggregate'))
routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/findOne', 'findOne'))
routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/autoChart', 'autoChart'))
if (!isView) {
routes.push(this.prepareRoute(internal, 'post', apiPrefix, tableName, 'create'))
}
routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName, 'list'))
if (!isView) {
routes.push(this.prepareRoute(internal, 'post', apiPrefix, tableName + '/bulk', 'bulkInsert'))
routes.push(this.prepareRoute(internal, 'delete', apiPrefix, tableName + '/bulk', 'bulkDelete'))
}
routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/bulk', 'bulkRead'))
if (!isView) {
routes.push(this.prepareRoute(internal, 'put', apiPrefix, tableName, 'update'))
routes.push(this.prepareRoute(internal, 'patch', apiPrefix, tableName + '/:id', 'patch'))
routes.push(this.prepareRoute(internal, 'delete', apiPrefix, tableName + '/:id', 'delete'))
}
routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/:id', 'read'))
routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/:id/exists', 'exists'))
for (var j = 0; j < table['foreignKeys'].length; ++j) {
let fk = table['foreignKeys'][j]
if (fk['referenced_table_name'] in this.sqlConfig.ignoreTables) {
//console.log('ignore table',fk['referenced_table_name']);
} else {
routes.push(this.prepareRoute(internal, 'get', apiPrefix, fk['referenced_table_name'] + '/:id/' + fk['table_name'], 'relational'))
}
7 years ago
}
7 years ago
tableObj['routes'] = routes;
schemaRoutes.push(tableObj);
}
7 years ago
}
return schemaRoutes;
}
getJoinType(joinInQueryParams) {
//console.log('joinInQueryParams',joinInQueryParams);
switch (joinInQueryParams) {
case '_lj':
return ' left join '
break;
case '_rj':
return ' right join '
break;
// case '_fj':
// return ' full join '
// break;
case '_ij':
return ' inner join '
break;
case '_j':
return ' join '
break;
}
return ' join '
}
7 years ago
globalRoutesPrint(apiPrefix) {
let r = []
r.push(apiPrefix + "tables")
r.push(apiPrefix + "xjoin")
7 years ago
if (this.sqlConfig.dynamic) {
r.push(apiPrefix + "dynamic")
r.push("/upload")
r.push("/uploads")
r.push("/download")
}
7 years ago
return r;
}
getChartQueryAndParamsFromStepPair(tableName, columnName, stepArray, isRange = false) {
let obj = {}
obj.query = ''
obj.params = []
//console.log('getChartQueryAndParamsFromStepArray',isRange);
//select ? as ??, count(*) as _count from ?? where ?? between ? and ?
if (stepArray.length && stepArray.length >= 2 && stepArray.length % 2 === 0) {
for (let i = 0; i < stepArray.length && stepArray.length >= 2; i = i + 2) {
obj.query = obj.query + dataHelp.getChartQuery();
if (i + 2 < stepArray.length) {
obj.query = obj.query + ' union '
}
obj.params.push((stepArray[i]) + ' to ' + stepArray[i + 1])
obj.params.push(columnName)
obj.params.push(tableName)
obj.params.push(columnName)
obj.params.push(stepArray[i])
obj.params.push(stepArray[i + 1])
}
}
//console.log('step spread query', obj);
return obj;
}
getChartQueryAndParamsFromStepArray(tableName, columnName, stepArray, isRange = false) {
let obj = {}
obj.query = ''
obj.params = []
//console.log('getChartQueryAndParamsFromStepArray',isRange);
if (stepArray.length && stepArray.length >= 2) {
for (let i = 0; i < stepArray.length - 1; i = i + 1) {
obj.query = obj.query + dataHelp.getChartQuery();
if (i + 2 < stepArray.length) {
obj.query = obj.query + ' union '
}
if (i && isRange === false) {
stepArray[i] = stepArray[i] + 1
}
if (isRange === false) {
obj.params.push((stepArray[i]) + ' to ' + stepArray[i + 1])
} else {
obj.params.push((stepArray[0]) + ' to ' + stepArray[i + 1])
}
obj.params.push(columnName)
obj.params.push(tableName)
obj.params.push(columnName)
if (isRange === false) {
obj.params.push(stepArray[i])
obj.params.push(stepArray[i + 1])
} else {
obj.params.push(stepArray[0])
obj.params.push(stepArray[i + 1])
}
}
}
//console.log('step spread query', obj);
return obj;
}
getChartQueryAndParamsFromMinMaxStddev(tableName, columnName, min, max, stddev, isRange = false) {
let stepArray = dataHelp.getStepArray(min, max, stddev)
//console.log('steparray', stepArray);
let obj = this.getChartQueryAndParamsFromStepArray(tableName, columnName, stepArray, isRange)
//console.log('steparray', obj);
return obj
}
getChartQueryAndParamsFromMinMaxStep(tableName, columnName, min, max, step, isRange = false) {
let stepArray = dataHelp.getStepArraySimple(min, max, step)
//console.log('steparray', stepArray);
let obj = this.getChartQueryAndParamsFromStepArray(tableName, columnName, stepArray, isRange)
//console.log('steparray', obj);
return obj
}
_getGrpByHavingOrderBy(req, tableName, queryParamsObj, listType) {
/**************** add group by ****************/
this.getGroupByClause(req.query._groupby, req.app.locals._tableName, queryParamsObj);
/**************** add having ****************/
this.getHavingClause(req.query._having, req.app.locals._tableName, queryParamsObj);
/**************** add order clause ****************/
this.getOrderByClause(req.query, req.app.locals._tableName, queryParamsObj);
/**************** add limit clause ****************/
if (listType === 2) { //nested
queryParamsObj.query += ' limit 1 '
} else {
queryParamsObj.query += ' limit ?,? '
queryParamsObj.params = queryParamsObj.params.concat(this.getLimitClause(req.query));
}
}
/**
*
* @param req
* @param res
* @param queryParamsObj : {query, params}
* @param listType : 0:list, 1:nested, 2:findOne, 3:bulkRead, 4:distinct, 5:xjoin
*
* Updates query, params for query of type listType
*/
prepareListQuery(req, res, queryParamsObj, listType = 0) {
queryParamsObj.query = 'select ';
queryParamsObj.params = [];
if (listType === 4) { //list type distinct
queryParamsObj.query += ' distinct '
}
/**************** select columns ****************/
if (req.query._groupby) {
this.getColumnsForSelectStmtWithGrpBy(req.query, req.app.locals._tableName, queryParamsObj);
} else {
this.getColumnsForSelectStmt(req.app.locals._tableName, req.query, queryParamsObj);
}
/**************** add tableName ****************/
queryParamsObj.query += ' from ?? ';
if (listType === 1) { //nested list
req.app.locals._tableName = req.app.locals._childTable;
queryParamsObj.params.push(req.app.locals._childTable);
queryParamsObj.query += ' where ';
/**************** add where foreign key ****************/
let whereClause = this.getForeignKeyWhereClause(req.app.locals._parentTable,
req.params.id,
req.app.locals._childTable);
if (!whereClause) {
return res.status(400).send({
error: "Table is made of composite primary keys - all keys were not in input"
})
}
queryParamsObj.query += whereClause;
this.getWhereClause(req.query._where, req.app.locals._tableName, queryParamsObj, ' and ');
} else if (listType === 3) { //bulkRead
// select * from table where pk in (ids) and whereConditions
queryParamsObj.params.push(req.app.locals._tableName);
queryParamsObj.query += ' where ?? in ';
queryParamsObj.params.push(this.getPrimaryKeyName(req.app.locals._tableName));
queryParamsObj.query += '('
if (req.query && req.query._ids) {
let ids = req.query._ids.split(',')
for (var i = 0; i < ids.length; ++i) {
if (i) {
queryParamsObj.query += ','
}
queryParamsObj.query += '?'
queryParamsObj.params.push(ids[i])
}
}
queryParamsObj.query += ') '
this.getWhereClause(req.query._where, req.app.locals._tableName, queryParamsObj, ' and ');
} else {
queryParamsObj.params.push(req.app.locals._tableName);
/**************** add where clause ****************/
this.getWhereClause(req.query._where, req.app.locals._tableName, queryParamsObj, ' where ');
}
this._getGrpByHavingOrderBy(req, req.app.locals._tableName, queryParamsObj)
//console.log(queryParamsObj.query, queryParamsObj.params);
}
_joinTableNames(isSecondJoin, joinTables, index, queryParamsObj) {
if (isSecondJoin) {
/**
* in second join - there will be ONE table and an ON condition
* if clause deals with this
*
*/
// add : join / left join / right join / full join / inner join
queryParamsObj.query += this.getJoinType(joinTables[index])
queryParamsObj.query += ' ?? as ?? '
// eg: tbl.tableName
let tableNameAndAs = joinTables[index + 1].split('.')
if (tableNameAndAs.length === 2 && !(tableNameAndAs[1] in this.sqlConfig.ignoreTables)) {
queryParamsObj.params.push(tableNameAndAs[1])
queryParamsObj.params.push(tableNameAndAs[0])
} else {
queryParamsObj.grammarErr = 1
console.log('there was no dot for tableName ', joinTables[index + 1]);
}
} else {
/**
* in first join - there will be TWO tables and an ON condition
* else clause deals with this
*/
// first table
queryParamsObj.query += ' ?? as ?? '
// add : join / left join / right join / full join / inner join
queryParamsObj.query += this.getJoinType(joinTables[index + 1])
// second table
queryParamsObj.query += ' ?? as ?? '
let tableNameAndAs = joinTables[index].split('.')
if (tableNameAndAs.length === 2 && !(tableNameAndAs[1] in this.sqlConfig.ignoreTables)) {
queryParamsObj.params.push(tableNameAndAs[1])
queryParamsObj.params.push(tableNameAndAs[0])
} else {
queryParamsObj.grammarErr = 1
console.log('there was no dot for tableName ', joinTables[index]);
}
tableNameAndAs = []
tableNameAndAs = joinTables[index + 2].split('.')
if (tableNameAndAs.length === 2 && !(tableNameAndAs[1] in this.sqlConfig.ignoreTables)) {
queryParamsObj.params.push(tableNameAndAs[1])
queryParamsObj.params.push(tableNameAndAs[0])
} else {
queryParamsObj.grammarErr = 1
console.log('there was no dot for tableName ', joinTables[index]);
}
}
}
prepareJoinQuery(req, res, queryParamsObj) {
queryParamsObj.query = 'SELECT '
queryParamsObj.grammarErr = 0;
while (1) {
/**************** START : get fields ****************/
if (req.query._fields) {
let fields = req.query._fields.split(',')
// from _fields to - ??, ??, ?? [col1,col2,col3]
for (var i = 0; i < fields.length && (!queryParamsObj.grammarErr); ++i) {
if (i) {
queryParamsObj.query += ','
}
queryParamsObj.query += ' ?? '
queryParamsObj.params.push(fields[i])
let aliases = fields[i].split('.');
if (aliases.length === 2) {
queryParamsObj.query += 'as ' + aliases[0] + '_' + aliases[1];
//console.log(queryParamsObj.query);
} else {
queryParamsObj.grammarErr = 1;
}
}
} else {
queryParamsObj.grammarErr = 1;
}
queryParamsObj.query += ' from '
if(queryParamsObj.grammarErr){
break;
}
/**************** END : get fields ****************/
/**************** START : get join + on ****************/
let joinTables = req.query._join.split(',')
if (joinTables.length < 3) {
//console.log('grammar error ', joinTables.length);
queryParamsObj.grammarErr = 1;
break;
}
//console.log('jointables.length', joinTables);
let onCondnCount = 0;
for (let i = 0; i < joinTables.length - 1 && queryParamsObj.grammarErr === 0; i = i + 2) {
onCondnCount++;
this._joinTableNames(i, joinTables, i, queryParamsObj)
if (queryParamsObj.grammarErr) {
console.log('failed at _joinTableNames', queryParamsObj);
break;
}
//console.log('after join tables', queryParamsObj);
let onCondn = '_on' + (onCondnCount)
let onCondnObj = {}
if (onCondn in req.query) {
//console.log(onCondn, req.query[onCondn]);
onCondnObj = whereHelp.getConditionClause(req.query[onCondn], ' on ')
//console.log('onCondnObj', onCondnObj);
queryParamsObj.query += ' on ' + onCondnObj.query
queryParamsObj.params = queryParamsObj.params.concat(onCondnObj.params)
} else {
queryParamsObj.grammarErr = 1;
//console.log('No on condition: ', onCondn);
break;
}
if (i === 0) {
i = i + 1
}
}
/**************** END : get join + on ****************/
if(queryParamsObj.grammarErr){
break;
} else {
this.getWhereClause(req.query._where, ' ignore ', queryParamsObj, ' where ');
this._getGrpByHavingOrderBy(req, 'ignore', queryParamsObj, 5)
//console.log('after where',queryParamsObj);
}
break;
}
if (queryParamsObj.grammarErr) {
queryParamsObj.query = ''
queryParamsObj.params = []
}
return queryParamsObj;
}
7 years ago
}
//expose class
module.exports = Xsql;