UNPKG

docorm

Version:

Persistence layer with ORM features for JSON documents

169 lines 6.03 kB
import _ from 'lodash'; export function queryExpressionIsCoalesce(expression) { return (expression.coalesce !== undefined); } export function queryExpressionIsConstant(expression) { return (expression.constant !== undefined) && !Array.isArray(expression.constant); } export function queryExpressionIsConstantList(expression) { return (expression.constant !== undefined) && Array.isArray(expression.constant); } export function queryExpressionIsFunction(expression) { return (expression.function !== undefined); } export function queryExpressionIsOperator(expression) { return (expression.operator !== undefined); } export function queryExpressionIsFullText(expression) { return (expression.text == 'default'); } export function queryExpressionIsPath(expression) { return expression.path !== undefined; } export function queryExpressionIsRange(expression) { return expression.range !== undefined; } export function queryClauseIsBetween(clause) { return clause.operator == 'between'; } export function queryClauseIsComparison(clause) { const operator = clause.operator; return !queryClauseIsFullTextSearch(clause) && [undefined, '=', '<', '>', '<=', '>=', '!='].includes(operator); } export function queryClauseIsIn(clause) { return clause.operator == 'in'; } export function queryClauseIsFullTextSearch(clause) { const l = clause.l; const r = clause.r; return clause.operator == 'contains' && queryExpressionIsFullText(l) && (queryExpressionIsConstant(r) || queryExpressionIsPath(r)); } export function queryClauseIsSimple(clause) { return queryClauseIsBetween(clause) || queryClauseIsComparison(clause) || queryClauseIsIn(clause) || queryClauseIsFullTextSearch(clause); } export function queryClauseIsAnd(clause) { return clause.and != null; } export function queryClauseIsOr(clause) { return clause.or != null; } export function queryClauseIsNot(clause) { return clause.not != null; } export function calculateExpression(context, expression) { if (queryExpressionIsCoalesce(expression)) { for (const subexpression of expression.coalesce) { if (subexpression != null) { return subexpression; } } return null; } else if (queryExpressionIsConstant(expression)) { return expression.constant; } else if (queryExpressionIsConstantList(expression)) { return expression.constant; } else if (queryExpressionIsFullText(expression)) { return expression.text; } else if (queryExpressionIsFunction(expression)) { throw 'Functions are not supported in query expressions outside a database context.'; } else if (queryExpressionIsOperator(expression)) { throw 'Operators are not supported in query expressions outside a database context.'; } else if (queryExpressionIsPath(expression)) { return _.get(context, expression.path); // TODO Should we support type enforcement when the optional sqlType property is present? } else if (queryExpressionIsRange(expression)) { return expression.range; } } export function applyQuery(x, query) { if (query === true) { return true; } else if (query === false) { return false; } else if (queryClauseIsAnd(query)) { for (const subclause of query.and) { if (!applyQuery(x, subclause)) { return false; } return true; } } else if (queryClauseIsOr(query)) { for (const subclause of query.or) { if (applyQuery(x, subclause)) { return true; } return false; } } else if (queryClauseIsNot(query)) { return !applyQuery(x, query.not); } else { // queryClauseIsSimple if (queryClauseIsBetween(query)) { const left = calculateExpression(x, query.l); const right = calculateExpression(x, query.r); if (!_.isArray(right) || right.length != 2) { throw 'For "between" queries, the right side must be a range (an array of size 2).'; } if (typeof left == 'number') { if (typeof right[0] != 'number' || typeof right[1] != 'number') { throw 'For "between" queries, the range must consist of numbers if the left side is a number.'; } return right[0] <= left && left <= right[1]; } else if (typeof left == 'string') { return right[0].toString() <= left && left <= right[1].toString(); } else { return right[0] <= left && left <= right[1]; } } else if (queryClauseIsComparison(query)) { const left = calculateExpression(x, query.l); const right = calculateExpression(x, query.r); switch (query.operator) { case '<': return left < right; case '>': return left > right; case '<=': return left <= right; case '>=': return left >= right; case '!=': return left != right; case '=': default: return left == right; } } else if (queryClauseIsIn(query)) { const left = calculateExpression(x, query.l); const right = calculateExpression(x, query.r); if (!_.isArray(right)) { throw 'For "in" queries, the right side must be an array.'; } return right.includes(left); } else if (queryClauseIsFullTextSearch(query)) { throw 'Full text search queries are not supported outside a database context.'; } } return false; } //# sourceMappingURL=queries.js.map