|
|
|
@ -13,6 +13,7 @@ class Xsql {
|
|
|
|
|
this.pool = {}; |
|
|
|
|
this.metaDb = {}; |
|
|
|
|
this.metaDb.tables = {}; |
|
|
|
|
this.metaDb.routines = []; |
|
|
|
|
|
|
|
|
|
this.sqlConfig = sqlConfig; |
|
|
|
|
this.pool = pool; |
|
|
|
@ -56,7 +57,14 @@ class Xsql {
|
|
|
|
|
|
|
|
|
|
// osx mysql server has limitations related to open_tables
|
|
|
|
|
self.pool.query("FLUSH TABLES", [], (err, results) => { |
|
|
|
|
cbk(null, null); |
|
|
|
|
self.pool.query(dataHelp.getRoutines(), [this.sqlConfig.database], (err, results) => { |
|
|
|
|
if (err) { |
|
|
|
|
cbk(err, results) |
|
|
|
|
} else { |
|
|
|
|
self.iterateToCacheRoutines(results) |
|
|
|
|
cbk(null, null) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -80,6 +88,14 @@ class Xsql {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
iterateToCacheRoutines(routineResults) { |
|
|
|
|
for (let i = 0; i < routineResults.length; i++) { |
|
|
|
|
const routine = routineResults[i] |
|
|
|
|
const routineName = routine.routine_name |
|
|
|
|
this.metaDb.routines.push(routineName) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
iterateToCacheTableColumns(schemaResults) { |
|
|
|
|
for (let i = 0; i < schemaResults.length; ++i) { |
|
|
|
|
let schemaRow = schemaResults[i]; |
|
|
|
@ -332,13 +348,16 @@ class Xsql {
|
|
|
|
|
if (i) { |
|
|
|
|
queryParamsObj.query += ", "; |
|
|
|
|
} |
|
|
|
|
if (orderByCols[i][0] === "-") { |
|
|
|
|
let len = orderByCols[i].length; |
|
|
|
|
queryParamsObj.query += " ?? DESC"; |
|
|
|
|
queryParamsObj.params.push(orderByCols[i].substring(1, len)); |
|
|
|
|
const aggregationFunction = this.getAggregationFunction(orderByCols[i]); |
|
|
|
|
const columnName = this.getColumnNameWithoutAggregationFunctions(orderByCols[i]); |
|
|
|
|
const orderByDirection = orderByCols[i][0] === "-" ? 'DESC' : 'ASC'; |
|
|
|
|
|
|
|
|
|
if (aggregationFunction) { |
|
|
|
|
queryParamsObj.query += `${aggregationFunction}(??) ${orderByDirection}`; |
|
|
|
|
queryParamsObj.params.push(columnName); |
|
|
|
|
} else { |
|
|
|
|
queryParamsObj.query += " ?? ASC"; |
|
|
|
|
queryParamsObj.params.push(orderByCols[i]); |
|
|
|
|
queryParamsObj.query += `?? ${orderByDirection}`; |
|
|
|
|
queryParamsObj.params.push(columnName); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -358,6 +377,16 @@ class Xsql {
|
|
|
|
|
queryParamsObj.query += ",count(1) as _count "; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getColumnsForGroupBy(tableName, reqQueryParams, queryParamsObj) { |
|
|
|
|
const updatedQueryParams = Object.assign({}, reqQueryParams); |
|
|
|
|
if ('_groupbyfields' in updatedQueryParams) { |
|
|
|
|
// allows you to group by different fields than you have in the select
|
|
|
|
|
updatedQueryParams['_fields'] = updatedQueryParams['_groupbyfields']; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return this.getColumnsForSelectStmt(tableName, updatedQueryParams, queryParamsObj) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getColumnsForSelectStmt(tableName, reqQueryParams, queryParamsObj) { |
|
|
|
|
let table = this.metaDb.tables[tableName]; |
|
|
|
|
let cols = []; |
|
|
|
@ -398,13 +427,41 @@ class Xsql {
|
|
|
|
|
if (i) { |
|
|
|
|
queryParamsObj.query += ","; |
|
|
|
|
} |
|
|
|
|
const aggregationFunction = this.getAggregationFunction(cols[i]); |
|
|
|
|
|
|
|
|
|
if (aggregationFunction) { |
|
|
|
|
queryParamsObj.query += `${aggregationFunction}(??)`; |
|
|
|
|
const columnName = this.getColumnNameWithoutAggregationFunctions(cols[i]); |
|
|
|
|
queryParamsObj.params.push(columnName); |
|
|
|
|
} else { |
|
|
|
|
queryParamsObj.query += "??"; |
|
|
|
|
queryParamsObj.params.push(cols[i]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return cols.join(","); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getAggregationFunction(rawColumnName) { |
|
|
|
|
const AGGREGATION_FUNCTION_REGEX = /^[-]?(AVG|BIT_AND|BIT_OR|BIT_XOR|COUNT|COUNTDISTINCT|GROUP_CONCAT|JSON_ARRAYAGG|JSON_OBJECTAGG|MAX|MIN|STD|STDDEV|STDDEV_POP|STDDEV_SAMP|SUM|VAR_POP|VAR_SAMP|VARIANCE)\((.*)\)$/i; |
|
|
|
|
const aggFuncMatch = rawColumnName.match(AGGREGATION_FUNCTION_REGEX); |
|
|
|
|
if (aggFuncMatch && aggFuncMatch.length === 3) { |
|
|
|
|
// match will look like (3) ["AVG(timestamp)", "AVG", "timestamp", index: 0, input: "AVG(timestamp)", groups: undefined]
|
|
|
|
|
return aggFuncMatch[1]; |
|
|
|
|
} |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getColumnNameWithoutAggregationFunctions(rawColumnName) { |
|
|
|
|
const AGGREGATION_FUNCTION_REGEX = /^[-]?(AVG|BIT_AND|BIT_OR|BIT_XOR|COUNT|COUNTDISTINCT|GROUP_CONCAT|JSON_ARRAYAGG|JSON_OBJECTAGG|MAX|MIN|STD|STDDEV|STDDEV_POP|STDDEV_SAMP|SUM|VAR_POP|VAR_SAMP|VARIANCE)\((.*)\)$/i; |
|
|
|
|
const aggFuncMatch = rawColumnName.match(AGGREGATION_FUNCTION_REGEX); |
|
|
|
|
if (aggFuncMatch && aggFuncMatch.length === 3) { |
|
|
|
|
// match will look like (3) ["AVG(timestamp)", "AVG", "timestamp", index: 0, input: "AVG(timestamp)", groups: undefined]
|
|
|
|
|
return aggFuncMatch[2]; |
|
|
|
|
} |
|
|
|
|
return rawColumnName.replace(/-/, ''); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
removeUnknownColumns(inputColumns, tableName) { |
|
|
|
|
let cols = inputColumns; |
|
|
|
|
let unknown_cols_in_input = []; |
|
|
|
@ -414,9 +471,11 @@ class Xsql {
|
|
|
|
|
// find unknown fields if any
|
|
|
|
|
for (var j = 0; j < cols.length; ++j) { |
|
|
|
|
let found = 0; |
|
|
|
|
// Used to allow aggregation functions like AVG(timestamp)
|
|
|
|
|
let columnNameWithoutAggregationClauses = this.getColumnNameWithoutAggregationFunctions(cols[j]); |
|
|
|
|
|
|
|
|
|
for (var i = 0; i < tableColumns.length; ++i) { |
|
|
|
|
if (tableColumns[i]["column_name"] === cols[j]) { |
|
|
|
|
if (tableColumns[i]["column_name"] === columnNameWithoutAggregationClauses) { |
|
|
|
|
found = 1; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -732,7 +791,12 @@ class Xsql {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tableObj["routes"] = routes; |
|
|
|
|
var procList = this.getProcList() |
|
|
|
|
for (var j = 0; j < procList.length; j++) { |
|
|
|
|
routes.push(this.prepareRoute(internal, 'post', apiPrefix, '_proc/' + procList[j])) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tableObj['routes'] = routes; |
|
|
|
|
|
|
|
|
|
schemaRoutes.push(tableObj); |
|
|
|
|
} |
|
|
|
@ -741,6 +805,14 @@ class Xsql {
|
|
|
|
|
return schemaRoutes; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getProcList() { |
|
|
|
|
let procRoutes = [] |
|
|
|
|
for (let procName in this.metaDb.routines) { |
|
|
|
|
procRoutes.push(this.metaDb.routines[procName]) |
|
|
|
|
} |
|
|
|
|
return procRoutes |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getJoinType(joinInQueryParams) { |
|
|
|
|
//console.log('joinInQueryParams',joinInQueryParams);
|
|
|
|
|
|
|
|
|
|