@stoqey/sofa
Version:
Couchbase utilities
415 lines • 15.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildIndexExpr = exports.buildWhereClauseExpr = exports.verifyWhereObjectKey = exports.buildWhereExpr = exports.buildSelectExpr = exports.buildSelectArrayExpr = exports.selectBuilder = void 0;
var dictionary_1 = require("./dictionary");
var exceptions_1 = require("../exceptions");
var utils_1 = require("../utils");
// select expressions functions
/**
* Build a SELECT N1QL query from user-specified parameters.
* {@link https://docs.couchbase.com/server/6.5/n1ql/n1ql-language-reference/select-syntax.html}
* @param collection Collection name
* @param select SELECT Clause param
* @param letExpr LET Clause param
* @param where WHERE Clause param
* @param orderBy ORDER BY Clause param
* @param limit LIMIT Clause param
* @param offset OFFSET Clause param
* @param useExpr USE Clause param
*
* @return N1QL SELECT Query
* */
var selectBuilder = function (collection, select, letExpr, where, orderBy, limit, offset, useExpr, groupByExpr, lettingExpr, havingExpr, plainJoinExpr) {
try {
var expr = '';
if (typeof select === 'string') {
expr = select;
}
if (Array.isArray(select)) {
expr = (0, exports.buildSelectArrayExpr)(select);
}
var _collection = collection.indexOf(' ') !== -1
? ("`" + collection).replace(' ', '` ')
: collection.indexOf('`') !== -1
? collection
: "`" + collection + "`";
return "SELECT " + expr + " FROM " + _collection + (plainJoinExpr ? " " + plainJoinExpr + " " : '') + _buildUseKeysExpr(useExpr) + _buildLetExpr(letExpr) + (0, exports.buildWhereExpr)(where) + _buildGroupByExpr(groupByExpr, lettingExpr, havingExpr) + _buildOrderByExpr(orderBy) + _buildLimitExpr(limit) + _buildOffsetExpr(offset);
}
catch (exception) {
if (exception instanceof exceptions_1.WhereClauseException) {
throw exception;
}
throw new exceptions_1.SelectClauseException();
}
};
exports.selectBuilder = selectBuilder;
/**
* @ignore
* */
var _buildAS = function (c) {
return c.hasOwnProperty('as') ? " AS " + c['as'] : '';
};
/**
* @ignore
* */
var _buildField = function (clause) {
if (clause.hasOwnProperty('name')) {
return "" + (0, utils_1.escapeReservedWords)(clause['name']) + _buildAS(clause);
}
return "" + (0, utils_1.escapeReservedWords)(clause);
};
/**
* Create N1QL queries from select array params
* @param clause SELECT Clause param
*
* @return N1QL SELECT Query
* */
var buildSelectArrayExpr = function (clause) {
return "" + clause.map(function (c) { return (0, exports.buildSelectExpr)('', c); }).join(',');
};
exports.buildSelectArrayExpr = buildSelectArrayExpr;
/**
* Recursive function to create N1QL queries.
* @param n1ql N1QL Query String
* @param clause SELECT Clause param
*
* @return N1QL SELECT Query
* */
var buildSelectExpr = function (n1ql, clause) {
try {
if (clause.hasOwnProperty('$field')) {
return _buildField(clause['$field']);
}
var key = Object.keys(clause)[0];
if (dictionary_1.ReturnResultDict.hasOwnProperty(key)) {
return dictionary_1.ReturnResultDict[key] + " " + (0, exports.buildSelectExpr)(n1ql, clause[key]);
}
if (dictionary_1.ResultExprDict.hasOwnProperty(key)) {
return dictionary_1.ResultExprDict[key] + " " + (0, exports.buildSelectExpr)(n1ql, clause[key]);
}
if (dictionary_1.AggDict.hasOwnProperty(key)) {
// todo check if have AS expr inside of Agg function.
return dictionary_1.AggDict[key] + "(" + _buildAggDictExpr(clause, key) + (0, exports.buildSelectExpr)(n1ql, clause[key]) + ")" + _buildAS(clause[key]);
}
throw new exceptions_1.SelectClauseException();
}
catch (_a) {
throw new exceptions_1.SelectClauseException();
}
};
exports.buildSelectExpr = buildSelectExpr;
/**
* @ignore
* */
var _buildAggDictExpr = function (clause, key) {
if (dictionary_1.AggDict.hasOwnProperty(key)) {
if (clause[key].hasOwnProperty('ro')) {
return dictionary_1.ReturnResultDict[clause[key]['ro']] + " ";
}
}
return '';
};
/**
* @ignore
* */
var _buildLetExpr = function (letExpr, clause) {
return Array.isArray(letExpr)
? " " + (clause ? clause : 'LET') + " " + letExpr
.map(function (value) { return (0, utils_1.escapeReservedWords)(value.key) + "=" + value.value; })
.join(',')
: '';
};
/**
* @ignore
* */
var _buildOrderByExpr = function (orderExpr) {
return !!orderExpr
? " ORDER BY " + Object.keys(orderExpr)
.map(function (value) { return (0, utils_1.escapeReservedWords)(value) + " " + orderExpr[value]; })
.join(',')
: '';
};
/**
* @ignore
* */
var _buildLimitExpr = function (limit) {
return Number.isInteger(limit) ? " LIMIT " + limit : '';
};
/**
* @ignore
* */
var _buildOffsetExpr = function (offset) {
return Number.isInteger(offset) ? " OFFSET " + offset : '';
};
/**
* @ignore
* */
var _buildUseKeysExpr = function (useKeys) {
return Array.isArray(useKeys) ? " USE KEYS " + stringifyValues(useKeys) : '';
};
// end select expression functions
//group by expression functions
/**
*@ignore
*/
var _buildGroupByExpr = function (groupByExpr, lettingExpr, havingExpr) {
try {
if ((lettingExpr || havingExpr) && !groupByExpr) {
throw new exceptions_1.QueryGroupByParamsException();
}
if (!groupByExpr) {
return '';
}
return " " + _buildGroupBy(groupByExpr) + _buildLetExpr(lettingExpr, 'LETTING') + (0, exports.buildWhereExpr)(havingExpr, 'HAVING');
}
catch (_a) {
throw new exceptions_1.QueryGroupByParamsException();
}
};
/**
*@ignore
*/
var _buildGroupBy = function (groupByExpr) {
return "GROUP BY " + groupByExpr
.map(function (value) {
return "" + (0, utils_1.escapeReservedWords)(value.expr) + (value.as ? " AS " + value.as : '');
})
.join(',');
};
//end group by expression functions
// where expression functions
/**
* Create WHERE N1QL Expressions.
* {@link https://docs.couchbase.com/server/6.5/n1ql/n1ql-language-reference/where.html}
* @param clause WHERE Clause param
* @return N1QL WHERE Expression
* */
var buildWhereExpr = function (expr, clause) {
return expr ? " " + (clause ? clause : 'WHERE') + " " + (0, exports.buildWhereClauseExpr)('', expr) : '';
};
exports.buildWhereExpr = buildWhereExpr;
/**
* @ignore
*
**/
var verifyWhereObjectKey = function (clause) {
var exist = false;
for (var key in clause) {
if (['$and', '$or', '$not', '$any', '$$every', '$in', '$within'].includes(key)) {
exist = true;
break;
}
}
return exist;
};
exports.verifyWhereObjectKey = verifyWhereObjectKey;
/**
* Recursive function to create WHERE N1QL Expressions.
* @param n1ql N1QL Query String
* @param clause WHERE Clause param
*
* @return N1QL WHERE Expression
* */
var buildWhereClauseExpr = function (n1ql, clause) {
try {
if (!(0, exports.verifyWhereObjectKey)(clause)) {
return _buildFieldClauseExpr(clause);
}
return Object.keys(clause)
.map(function (key) {
var _a;
if (dictionary_1.CollectionSelectOperatorDict[key]) {
return "" + _buildWhereCollectionExpr(key, clause[key]);
}
if (dictionary_1.CollectionInWithinOperatorDict[key]) {
return "" + _buildCollectionInWithinOperator(key, clause[key]);
}
if (Array.isArray(clause[key])) {
var prefix = key === '$not' ? dictionary_1.LogicalOperatorDict[key] + " " : '';
var joinOp = key === '$not' ? " AND " : " " + dictionary_1.LogicalOperatorDict[key] + " ";
return prefix + "(" + clause[key]
.map(function (value) { return (0, exports.buildWhereClauseExpr)(n1ql, value); })
.join(joinOp) + ")";
}
else {
return "" + (0, exports.buildWhereClauseExpr)(n1ql, (_a = {}, _a[key] = clause[key], _a));
}
})
.join(' AND ');
}
catch (exception) {
if (exception instanceof exceptions_1.WhereClauseException) {
throw exception;
}
throw new exceptions_1.WhereClauseException();
}
};
exports.buildWhereClauseExpr = buildWhereClauseExpr;
/**
* @ignore
* */
var _buildFieldClauseExpr = function (field) {
try {
var expr = Object.keys(field).map(function (value) {
if (typeof field[value] === 'object' && !Array.isArray(field[value])) {
return "" + _buildComparisionClauseExpr(value, field[value]);
}
if (!value.includes('$')) {
if (typeof field[value] === 'string') {
return (0, utils_1.escapeReservedWords)(value) + "=" + stringifyValues(field[value]);
}
if (typeof field[value] === 'number' ||
typeof field[value] === 'boolean' ||
Array.isArray(field[value])) {
return (0, utils_1.escapeReservedWords)(value) + "=" + stringifyValues(field[value]);
}
}
throw new exceptions_1.QueryOperatorNotFoundException(value);
});
return expr.join(' AND ');
}
catch (exception) {
if (exception instanceof exceptions_1.WhereClauseException) {
throw exception;
}
throw new exceptions_1.WhereClauseException();
}
};
/**
* @ignore
* */
var _buildComparisionClauseExpr = function (fieldName, comparison) {
try {
var expr = Object.keys(comparison)
.map(function (value) {
if (!!comparison[value]) {
if (dictionary_1.ComparisonEmptyOperatorDict.hasOwnProperty(value)) {
return (0, utils_1.escapeReservedWords)(fieldName) + " " + dictionary_1.ComparisonEmptyOperatorDict[value];
}
if (dictionary_1.ComparisonSingleOperatorDict.hasOwnProperty(value)) {
return "" + (0, utils_1.escapeReservedWords)(fieldName) + dictionary_1.ComparisonSingleOperatorDict[value] + stringifyValues(comparison[value]);
}
if (dictionary_1.ComparisonSingleStringOperatorDict.hasOwnProperty(value)) {
return (0, utils_1.escapeReservedWords)(fieldName) + " " + dictionary_1.ComparisonSingleStringOperatorDict[value] + " " + stringifyValues(comparison[value]);
}
if (dictionary_1.ComparisonMultipleOperatorDict.hasOwnProperty(value) &&
Array.isArray(comparison[value])) {
return (0, utils_1.escapeReservedWords)(fieldName) + " " + dictionary_1.ComparisonMultipleOperatorDict[value] + " " + comparison[value].map(function (v) { return stringifyValues(v); }).join(' AND ');
}
}
throw new exceptions_1.QueryOperatorNotFoundException(value);
})
.join(" AND ");
return Object.keys(comparison).length > 1 ? "(" + expr + ")" : expr;
}
catch (exception) {
if (exception instanceof exceptions_1.WhereClauseException) {
throw exception;
}
throw new exceptions_1.WhereClauseException();
}
};
/**
* @ignore
* */
var _buildCollectionInWithinOperator = function (op, expr, excludeOperator) {
if (!op || !expr.target_expr || !expr.search_expr) {
throw new exceptions_1.InWithinOperatorExceptions();
}
return "" + expr.search_expr + (!excludeOperator && expr.$not ? ' NOT ' : ' ') + dictionary_1.CollectionInWithinOperatorDict[op] + " " + (excludeOperator ? expr.target_expr : stringifyValues(expr.target_expr));
};
var stringifyValues = function (value) {
return JSON.stringify(value).replace(/\\/gi, '');
};
/**
* @ignore
* */
var _buildCollectionInWithIn = function (collection) {
var op = collection.$in ? '$in' : collection.$within ? '$within' : undefined;
if (!op) {
throw new Error('The Collection Operator needs to have the following clauses declared (IN | WITHIN) and SATISFIES.');
}
return "" + _buildCollectionInWithinOperator(op, collection[op], true);
};
/**
* @ignore
* */
var _buildWhereCollectionExpr = function (op, expr) {
return dictionary_1.CollectionSelectOperatorDict[op] + " " + expr.$expr
.map(function (value) { return _buildCollectionInWithIn(value); })
.join(',') + " " + dictionary_1.CollectionSatisfiesOperatorDict['$satisfies'] + " " + (0, exports.buildWhereClauseExpr)('', expr.$satisfied) + " END";
};
// end where expression functions
// index expression functions
/**
* Build a INDEX N1QL query from user-specified parameters.
* {@link https://docs.couchbase.com/server/6.5/n1ql/n1ql-language-reference/createindex.html}
* @param collection Collection name
* @param type INDEX clause types can be 'CREATE' | 'BUILD' | 'DROP' | 'CREATE PRIMARY'
* @param on ON Clause param
* @param where WHERE Clause param
* @param usingGSI use a Global Secondary Index(GSI).
* @param withExpr WITH Clause param
*
* @return N1QL INDEX Query
* */
var buildIndexExpr = function (collection, type, name, on, where, usingGSI, withExpr) {
if (['BUILD', 'CREATE', 'CREATE PRIMARY'].includes(type) && on) {
return type + " INDEX `" + name + "` ON `" + collection + "`(" + buildOnExpr(on) + ")" + (0, exports.buildWhereExpr)(where) + " " + (usingGSI ? 'USING GSI' : '') + " " + buildWithExpr(withExpr);
}
else {
return type + " INDEX `" + collection + "`.`" + name + "`" + (usingGSI ? ' USING GSI' : '');
}
};
exports.buildIndexExpr = buildIndexExpr;
/**
* @ignore
* */
var buildOnExpr = function (on) {
return on
.map(function (value) {
return "" + (0, utils_1.escapeReservedWords)(value.name) + buildOnSortExpr(value);
})
.join(',');
};
/**
* @ignore
* */
var buildOnSortExpr = function (onExpr) {
if (onExpr && onExpr.hasOwnProperty('sort')) {
return "[\"" + onExpr.sort + "\"]";
}
return '';
};
/**
* @ignore
* */
var buildWithExpr = function (withExpr) {
if (withExpr) {
var resultExpr = Object.keys(withExpr)
.map(function (value) {
switch (value) {
case 'nodes':
return buildWithNodesExpr(withExpr[value]);
case 'defer_build':
case 'num_replica':
return "\"" + value + "\": " + withExpr[value];
default:
throw new Error('The WITH clause has an incorrect syntax');
}
})
.join(',');
return !!resultExpr ? "WITH {" + resultExpr + "}" : '';
}
return '';
};
/**
* @ignore
* */
var buildWithNodesExpr = function (withNodesExpr) {
if (withNodesExpr) {
return "\"nodes\": " + stringifyValues(withNodesExpr);
}
};
// end index expression functions
//# sourceMappingURL=builders.js.map