@synatic/sql-to-mongo
Advanced tools
Comparing version 1.1.4 to 1.1.5
@@ -5,2 +5,9 @@ const _allowableFunctions = require('./MongoFunctions'); | ||
/** | ||
* Checks whether the expression is null or its type is null | ||
* | ||
* @param {any} val - the expression value to check | ||
* @returns {boolean} - whether it is null or not | ||
* @private | ||
*/ | ||
function _checkNullOrEmptyType(val) { | ||
@@ -11,2 +18,44 @@ return !val || (val && !val.type); | ||
/** | ||
* Returns a function to check whether the column supports a function | ||
* | ||
* @param {import('./types').Column} column - the column to check | ||
* @returns {()=>*} - the function to check the column type | ||
*/ | ||
function findFnFromColumnType(column) { | ||
return (fn) => | ||
fn.name === column.expr.name.toLowerCase() && | ||
(!fn.type || fn.type === column.expr.type) && | ||
fn.allowQuery; | ||
} | ||
/** | ||
* Checks whether the column contains an allowed function | ||
* | ||
* @param {import('./types').Column} column - the column to check | ||
* @returns {boolean} - whether the column contains an allowed query function | ||
*/ | ||
function checkIfContainsAllowedFunctions(column) { | ||
return ( | ||
column.expr.type === 'function' && | ||
!_allowableFunctions.functionMappings.find(findFnFromColumnType(column)) | ||
); | ||
} | ||
/** | ||
* Checks whether the column contains an allowed aggregate function | ||
* | ||
* @param {import('./types').Column} column - the column to check | ||
* @returns {boolean} - whether the column contains an allowed aggregate function | ||
*/ | ||
function checkIfContainsAllowedAggregateFunctions(column) { | ||
if (column.expr.type !== 'aggr_func') { | ||
return false; | ||
} | ||
const someValue = _allowableFunctions.functionMappings.find( | ||
findFnFromColumnType(column) | ||
); | ||
return !someValue; | ||
} | ||
/** | ||
* Checks whether a mongo query can be performed or an aggregate is required | ||
@@ -16,3 +65,3 @@ * | ||
* @param {import('./types').ParserOptions} [options] - the parser options | ||
* @returns {boolean} | ||
* @returns {boolean} - if the sql or ast can be executed as a query | ||
* @throws | ||
@@ -27,5 +76,7 @@ */ | ||
const columns = typeof ast.columns === 'string' ? null : ast.columns; | ||
const asColumns = isSelectAll | ||
? [] | ||
: columns.map((c) => c.as).filter((c) => !!c); | ||
const checkAsUsedInWhere = (expr) => { | ||
@@ -69,2 +120,4 @@ if (!expr) { | ||
const hasUnion = !!ast.union; | ||
const hasTableAlias = !!(ast.from && ast.from[0] && ast.from[0].as); | ||
const isAggregate = | ||
@@ -82,49 +135,13 @@ moreThanOneFrom || | ||
whereContainsOtherTable || | ||
hasUnion; | ||
hasUnion || | ||
hasTableAlias; | ||
return !isAggregate; | ||
} | ||
/** | ||
* | ||
* @param {import('./types').Column} column | ||
* @returns {boolean} | ||
*/ | ||
function checkIfContainsAllowedFunctions(column) { | ||
return ( | ||
column.expr.type === 'function' && | ||
!_allowableFunctions.functionMappings.find(findFnFromColumnType(column)) | ||
); | ||
} | ||
/** | ||
* Checks whether the expression statement contains other tables to execute a sub select | ||
* | ||
* @param {import('./types').Column} column | ||
* @returns {boolean} | ||
* @param {import('./types').Expression} expr - the expressions to check | ||
* @returns {boolean} - whether the expression contains other tables | ||
*/ | ||
function checkIfContainsAllowedAggregateFunctions(column) { | ||
if (column.expr.type !== 'aggr_func') { | ||
return false; | ||
} | ||
const someValue = _allowableFunctions.functionMappings.find( | ||
findFnFromColumnType(column) | ||
); | ||
return !someValue; | ||
} | ||
/** | ||
* | ||
* @param {import('./types').Column} column | ||
* @returns {()=>*} | ||
*/ | ||
function findFnFromColumnType(column) { | ||
return (fn) => | ||
fn.name === column.expr.name.toLowerCase() && | ||
(!fn.type || fn.type === column.expr.type) && | ||
fn.allowQuery; | ||
} | ||
/** | ||
* | ||
* @param {import('./types').Expression} expr | ||
* @returns {boolean} | ||
*/ | ||
function checkWhereContainsOtherTable(expr) { | ||
@@ -131,0 +148,0 @@ if (!expr) { |
/** | ||
* Finds all the queries in a an AST where statement that are AST's themselves | ||
* Finds all the queries in an AST where statement that are AST's themselves | ||
* | ||
@@ -4,0 +4,0 @@ * @param {import('../types').Expression} where |
@@ -17,3 +17,11 @@ const groupByColumnParserModule = require('./groupByColumnParser'); | ||
function forceGroupBy(ast) { | ||
/** | ||
* | ||
* Checks whether the query needs to force a group by | ||
* | ||
* @param {import('../types').AST} ast - the ast to check if a group by needs to be forced | ||
* @returns {boolean} - whether a group by needs to be forced | ||
* @private | ||
*/ | ||
function _forceGroupBy(ast) { | ||
if (ast.groupby) { | ||
@@ -38,3 +46,10 @@ return false; | ||
function hasIdCol(columns) { | ||
/** | ||
* Checks whether an _id column is specified | ||
* | ||
* @param {Array} columns - the columns to check | ||
* @returns {boolean} - whether an _id column is specified | ||
* @private | ||
*/ | ||
function _hasIdCol(columns) { | ||
if (!columns || columns.length === 0) { | ||
@@ -137,3 +152,4 @@ return false; | ||
[], | ||
false | ||
false, | ||
ast.from && ast.from[0] ? ast.from[0].as : null | ||
), | ||
@@ -151,2 +167,3 @@ }; | ||
pipeline = pipeline.concat(pipeLineJoin); | ||
// todo check where this gets inserted | ||
if (wherePiece) { | ||
@@ -156,5 +173,10 @@ pipeline.push(wherePiece); | ||
} | ||
} else { | ||
if (wherePiece) { | ||
pipeline.push(wherePiece); | ||
wherePiece = null; | ||
} | ||
} | ||
const checkForceGroupBy = forceGroupBy(ast); | ||
const checkForceGroupBy = _forceGroupBy(ast); | ||
@@ -204,3 +226,7 @@ if (ast.groupby || checkForceGroupBy) { | ||
columns.forEach((column) => { | ||
projectColumnParserModule.projectColumnParser(column, result); | ||
projectColumnParserModule.projectColumnParser( | ||
column, | ||
result, | ||
ast.from && ast.from[0] ? ast.from[0].as : null | ||
); | ||
}); | ||
@@ -251,5 +277,5 @@ if (result.count.length > 0) { | ||
if (wherePiece) { | ||
pipeline.unshift(wherePiece); | ||
} | ||
// if (wherePiece) { | ||
// pipeline.unshift(wherePiece); | ||
// } | ||
@@ -291,3 +317,3 @@ // for if initial query is subquery | ||
!isSelectAll(ast.columns) && | ||
!hasIdCol(ast.columns) | ||
!_hasIdCol(ast.columns) | ||
) { | ||
@@ -294,0 +320,0 @@ pipeline.push({$unset: '_id'}); |
@@ -15,2 +15,4 @@ const makeProjectionExpressionPartModule = require('./makeProjectionExpressionPart'); | ||
OR: '$or', | ||
IS: '$eq', | ||
'IS NOT': '$ne', | ||
}; | ||
@@ -132,2 +134,6 @@ /** | ||
if (queryPart.type === 'null') { | ||
return null; | ||
} | ||
throw new Error( | ||
@@ -134,0 +140,0 @@ `invalid expression type for array sub select:${queryPart.type}` |
@@ -14,2 +14,3 @@ const makeProjectionExpressionPartModule = require('./makeProjectionExpressionPart'); | ||
* @param {boolean} [includeThis] - include $$this in expresions | ||
* @param {string} [tableAlias] - a table alias to check if it hasn't been specified | ||
* @returns {any} - the mongo query/match | ||
@@ -21,3 +22,4 @@ */ | ||
allowedTypes = [], | ||
includeThis = false | ||
includeThis = false, | ||
tableAlias = '' | ||
) { | ||
@@ -34,7 +36,8 @@ if (allowedTypes.length > 0 && !allowedTypes.includes(queryPart.type)) { | ||
const table = queryPartToUse.table || tableAlias; | ||
if (queryPartToUse.column) { | ||
return ( | ||
(includeThis ? '$$this.' : '') + | ||
(queryPartToUse.table && !ignorePrefix | ||
? `${queryPartToUse.table}.${queryPartToUse.column}` | ||
(table && !ignorePrefix | ||
? `${table}.${queryPartToUse.column}` | ||
: queryPartToUse.column) | ||
@@ -52,3 +55,4 @@ ); | ||
allowedTypes, | ||
includeThis | ||
includeThis, | ||
tableAlias | ||
); | ||
@@ -59,3 +63,4 @@ const right = makeQueryPart( | ||
allowedTypes, | ||
includeThis | ||
includeThis, | ||
tableAlias | ||
); | ||
@@ -83,3 +88,4 @@ if ($check.string(left) && !left.startsWith('$')) { | ||
allowedTypes, | ||
includeThis | ||
includeThis, | ||
tableAlias | ||
), | ||
@@ -90,3 +96,4 @@ makeQueryPart( | ||
allowedTypes, | ||
includeThis | ||
includeThis, | ||
tableAlias | ||
), | ||
@@ -103,3 +110,4 @@ ], | ||
allowedTypes, | ||
includeThis | ||
includeThis, | ||
tableAlias | ||
), | ||
@@ -110,3 +118,4 @@ makeQueryPart( | ||
allowedTypes, | ||
includeThis | ||
includeThis, | ||
tableAlias | ||
), | ||
@@ -113,0 +122,0 @@ ], |
@@ -14,6 +14,9 @@ const getParsedValueFromBinaryExpressionModule = require('./getParsedValueFromBinaryExpression'); | ||
* @param {import('../types').ColumnParseResult} result the result object | ||
* @param {string} [tableAlias] - a table alias to check if it hasn't been specified | ||
* @returns {void} | ||
*/ | ||
function projectColumnParser(column, result) { | ||
function projectColumnParser(column, result, tableAlias = '') { | ||
if (column.expr.type === 'column_ref') { | ||
const columnTable = column.expr.table || tableAlias; | ||
if (column.as && column.as.toUpperCase() === '$$ROOT') { | ||
@@ -36,3 +39,3 @@ result.replaceRoot = { | ||
result.parsedProject.$project[column.as || column.expr.column] = `$${ | ||
column.expr.table ? column.expr.table + '.' : '' | ||
columnTable ? columnTable + '.' : '' | ||
}${column.expr.column}`; | ||
@@ -39,0 +42,0 @@ return; |
{ | ||
"name": "@synatic/sql-to-mongo", | ||
"version": "1.1.4", | ||
"version": "1.1.5", | ||
"description": "Convert SQL to mongo queries or aggregates", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -262,3 +262,3 @@ # sql-to-mongo | ||
--Won't work | ||
select `Address.City` as City from `customers` where `First Name` like 'm%' and absId > 1 | ||
select `Address.City` as City,abs(`id`) as absId from `customers` where `First Name` like 'm%' and absId > 1 | ||
``` | ||
@@ -265,0 +265,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
208925
4406