database-builder
Version:
Library to assist in creating and maintaining SQL commands.
407 lines (406 loc) • 19.6 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueryBuilderBase = void 0;
var union_type_1 = require("../../core/union-type");
var projection_builder_1 = require("../projection-builder");
var utils_1 = require("../../core/utils");
var where_builder_1 = require("../where-builder");
var order_by_1 = require("../../core/enums/order-by");
var having_builder_1 = require("../having-builder");
var projections_helper_1 = require("../../core/projections-helper");
var builder_compiled_1 = require("../../core/builder-compiled");
var column_ref_1 = require("../../core/column-ref");
var sql_base_builder_1 = require("../sql-base-builder");
var mapper_utils_1 = require("../../mapper/mapper-utils");
var core_1 = require("../../core");
var model_utils_1 = require("../../core/model-utils");
var param_filter_1 = require("../../core/param-filter");
var projection_compile_1 = require("../projection-compile");
var query_helper_1 = require("../../core/query-helper");
var QueryBuilderBase = /** @class */ (function (_super) {
__extends(QueryBuilderBase, _super);
function QueryBuilderBase(queryT, mapperTable, alias, _getMapper) {
if (alias === void 0) { alias = void 0; }
var _this = _super.call(this, queryT, utils_1.Utils.getMapperTable(queryT, _getMapper).newable, mapperTable, alias) || this;
_this._getMapper = _getMapper;
_this._groupBy = "";
_this._limit = new builder_compiled_1.BuilderCompiled();
_this._orderBy = "";
_this._having = {
where: "",
params: []
};
_this._projections = [];
// TODO: remove "_joinParams" e utilizar SqlAndParams como é realizado nos projections
_this._joinParams = [];
_this._ignoreQueryFilter = false;
_this.GROUP_BY = " GROUP BY ";
_this.HAVING = " HAVING ";
_this.ORDER_BY = " ORDER BY ";
_this.LIMIT = " LIMIT";
_this.OFFSET = "OFFSET";
_this._joinsQuery = [];
_this._unionsQuery = [];
_this._fromParams = [];
if (utils_1.Utils.isQueryBuilder(queryT)) {
var compiled = queryT.compile();
_this._tablename = "(".concat(compiled.query, ")");
_this._joinParams = _this._joinParams.concat(compiled.params);
}
return _this;
}
Object.defineProperty(QueryBuilderBase.prototype, "alias", {
get: function () {
return this._alias;
},
enumerable: false,
configurable: true
});
Object.defineProperty(QueryBuilderBase.prototype, "tablename", {
get: function () {
return this._tablename;
},
enumerable: false,
configurable: true
});
QueryBuilderBase.prototype.getAlias = function (tKey) {
var tablename = mapper_utils_1.MapperUtils.resolveKey(tKey);
var isThis = this.tablename === tablename;
var resultSearch = this._joinsQuery.filter(function (x) { return x.tablename === tablename; });
if (isThis && resultSearch.length === 0) {
return this.alias;
}
if (resultSearch.length === 1 && !isThis) {
return resultSearch[0].alias;
}
if (resultSearch.length > 1 || isThis) {
throw new core_1.DatabaseBuilderError("It is not possible to find a single alias for table \"".concat(tablename, "\", as there are multiple queries for table \"").concat(tablename, "\". It is necessary use the specific alias."));
}
return void 0;
};
QueryBuilderBase.prototype.clone = function () {
return model_utils_1.ModelUtils.cloneDeep(this._getInstance());
};
QueryBuilderBase.prototype.ref = function (expression, alias) {
if (alias === void 0) { alias = this.alias; }
return new column_ref_1.ColumnRef(utils_1.Utils.getColumn(expression), alias);
};
QueryBuilderBase.prototype.hasAlias = function (alias) {
if (_super.prototype.hasAlias.call(this, alias)) {
return true;
}
// check in joins
for (var key in this._joinsQuery) {
if (this._joinsQuery.hasOwnProperty(key)) {
var joinQuery = this._joinsQuery[key];
if (joinQuery.hasAlias(alias)) {
return true;
}
}
}
return false;
};
QueryBuilderBase.prototype.from = function (query) {
var _this = this;
if (utils_1.Utils.isQueryCompilable(query)) {
return this.from(query.compile());
}
query
.forEach(function (compiled) {
_this._tablename = "(".concat(compiled.query, ")");
_this._fromParams = compiled.params;
});
return this._getInstance();
};
QueryBuilderBase.prototype.unionAll = function (query) {
return this.union(query, union_type_1.UnionType.All);
};
QueryBuilderBase.prototype.union = function (query, type) {
var _this = this;
if (type === void 0) { type = union_type_1.UnionType.None; }
if (utils_1.Utils.isQueryCompilable(query)) {
return this.union(query.compile(), type);
}
query
.forEach(function (compiled) {
_this._unionsQuery.push({ query: compiled, type: type });
});
return this._getInstance();
};
QueryBuilderBase.prototype.createWhere = function () {
return new where_builder_1.WhereBuilder(this._newable, this.alias);
};
QueryBuilderBase.prototype.where = function (whereCallback) {
var instanceWhere = this.createWhere();
whereCallback(instanceWhere);
this.compileWhere(this.whereCompiled, instanceWhere.compile());
return this._getInstance();
};
/**
* Where with expression Lambda
* #Experimental
* @param {LambdaExpression<T>} expression
* @returns {TQuery}
* @memberof QueryBuilderBase
*/
QueryBuilderBase.prototype.whereExp = function (expression) {
var instanceWhere = this.createWhere();
instanceWhere.expression(expression);
this.compileWhere(this.whereCompiled, instanceWhere.compile());
return this._getInstance();
};
QueryBuilderBase.prototype.projection = function (projectionCallback) {
var instanceProjection = this.createProjectionBuilder();
projectionCallback(instanceProjection);
this.buildProjections(instanceProjection.result());
return this._getInstance();
};
QueryBuilderBase.prototype.select = function () {
var expressions = [];
for (var _i = 0; _i < arguments.length; _i++) {
expressions[_i] = arguments[_i];
}
return this.projection(function (projection) { return projection.columns.apply(projection, expressions); });
};
QueryBuilderBase.prototype.orderBy = function (expression, order) {
if (order === void 0) { order = order_by_1.OrderBy.ASC; }
var columnName;
if (utils_1.Utils.isQueryCompiled(expression)) {
return this.orderBy("(".concat(query_helper_1.QueryHelper.compileWithoutParams(expression.query, expression.params), ")"), order);
}
else if (utils_1.Utils.isQueryCompiledArray(expression)) {
return this.orderBy(expression[0], order);
}
else if (utils_1.Utils.isPlanRef(expression)) {
columnName = expression.result();
}
else if (utils_1.Utils.isNumber(expression)) {
columnName = "".concat(expression);
}
else {
columnName = utils_1.Utils.addAlias(utils_1.Utils.getColumn(expression), this._alias);
}
this.compileOrderBy("".concat(columnName, " ").concat(order));
return this._getInstance();
};
QueryBuilderBase.prototype.asc = function (expression) {
return this.orderBy(expression, order_by_1.OrderBy.ASC);
};
QueryBuilderBase.prototype.desc = function (expression) {
return this.orderBy(expression, order_by_1.OrderBy.DESC);
};
QueryBuilderBase.prototype.groupBy = function (expression, havingCallback) {
this.compileGroupBy(utils_1.Utils.addAlias(utils_1.Utils.getColumn(expression), this._alias));
if (havingCallback) {
var whereHaving = new having_builder_1.HavingBuilder(this._newable, "");
havingCallback(whereHaving, new projections_helper_1.ProjectionsHelper(this._newable, this._alias, false));
this.compileHaving(whereHaving.compile());
}
return this._getInstance();
};
QueryBuilderBase.prototype.limit = function (limit, offset) {
this._limit.builder = "".concat(this.LIMIT, " ?");
this._limit.params = [limit];
if (offset) {
this._limit.builder += " ".concat(this.OFFSET, " ?");
this._limit.params.push(offset);
}
return this._getInstance();
};
/**
* Find projection by alias and result index (base 1...N+1)
* @param projectionAlias alias to find the projection
* @returns index (base 1...N+1)
*/
QueryBuilderBase.prototype.getIndexProjection = function (projectionAlias) {
var projectionColumnAlias = utils_1.Utils.getColumn(projectionAlias);
var index = this._projections.findIndex(function (x) { return x.projection.endsWith(" AS ".concat(projectionColumnAlias)); });
if (index > -1) {
return index + 1;
}
throw new core_1.DatabaseBuilderError("Not found projection alias (\"".concat(projectionColumnAlias, "\" in projections (current value: \"").concat(projection_compile_1.ProjectionCompile.compile(this._projections).projection, "\"))"));
};
QueryBuilderBase.prototype.ignoreQueryFilters = function () {
if (this._joinsQuery.length) {
throw new core_1.DatabaseBuilderError("Can't apply 'ignoreQueryFilters' after joining 'join()'");
}
this._ignoreQueryFilter = true;
return this._getInstance();
};
QueryBuilderBase.prototype.enableQueryFilters = function () {
if (this._joinsQuery.length) {
throw new core_1.DatabaseBuilderError("Can't apply 'addQueryFilters' after joining 'join()'");
}
this._ignoreQueryFilter = false;
return this._getInstance();
};
QueryBuilderBase.prototype.setParamsQueryFilter = function (params) {
if (this._joinsQuery.length) {
throw new core_1.DatabaseBuilderError("Can't apply 'setParamsQueryFilter' after joining 'join()'");
}
this._paramsQueryFilter = params;
return this._getInstance();
};
QueryBuilderBase.prototype.compileTable = function () {
return "".concat(this._tablename, " AS ").concat(this._alias);
};
QueryBuilderBase.prototype.compile = function () {
var whereCompiled = this.whereCompile(this.whereCompiled);
var compiled = this.buildBase();
var compiledJoin = this.compileJoin();
return this.buildUnions({
params: compiled.params
.concat(compiledJoin.params)
// .concat(this._joinParams)
.concat(whereCompiled.params)
.concat(this._having.params)
.concat(this._limit.params),
// Template: https://sqlite.org/lang_select.html
query: "".concat(compiled.query).concat(compiledJoin.query).concat(whereCompiled.where).concat(this._groupBy).concat(this._having.where).concat(this._orderBy).concat(this._limit.builder)
});
};
QueryBuilderBase.prototype.whereCompile = function (baseWhereCompiled) {
var _this = this;
var whereCompiled = model_utils_1.ModelUtils.cloneDeep(baseWhereCompiled);
// apply query filter
var queryFilter = model_utils_1.ModelUtils.cloneDeep(this.mapperTable.queryFilter);
if (!this._ignoreQueryFilter && queryFilter && queryFilter.where) {
queryFilter.where = queryFilter.where.replace(new RegExp(utils_1.Utils.REPLACEABLE_ALIAS, "g"), this.alias);
if (queryFilter.params && this._paramsQueryFilter) {
queryFilter.params = queryFilter.params.map(function (param) {
var keyParam = Object.keys(_this._paramsQueryFilter)
.find(function (x) {
var result = param_filter_1.ParamFilter.PATTERN.exec(param);
return result && result.length > 1
? result[1] === x
: false;
});
return utils_1.Utils.isString(param) && keyParam
? utils_1.Utils.isString(_this._paramsQueryFilter[keyParam])
? param.replace(param_filter_1.ParamFilter.PATTERN, _this._paramsQueryFilter[keyParam])
: _this._paramsQueryFilter[keyParam]
: param;
});
}
this.compileWhere(whereCompiled, queryFilter);
}
return whereCompiled;
};
QueryBuilderBase.prototype.createProjectionBuilder = function (addAliasTableToAlias, addAliasDefault) {
return new projection_builder_1.ProjectionBuilder(this._newable, this.alias, addAliasTableToAlias, addAliasDefault, this._getMapper);
};
QueryBuilderBase.prototype.addJoin = function (joinQuery) {
this._joinsQuery.push(joinQuery);
this._joinParams = this._joinParams.concat(joinQuery._getParams());
this.compileWhere(this.whereCompiled, joinQuery._getWhere());
this.buildProjections(joinQuery._getProjections());
this.compileGroupBy(joinQuery._getGroupBy());
this.compileHaving(joinQuery._getHaving());
this.compileOrderBy(joinQuery._getOrderBy());
};
QueryBuilderBase.prototype.setDefaultColumns = function () {
this.projection(function (projection) { return projection.all(); });
};
QueryBuilderBase.prototype.getColumnsCompiled = function () {
if (this._projections.length === 0) {
this.setDefaultColumns();
}
return projection_compile_1.ProjectionCompile.compile(this._projections);
};
QueryBuilderBase.prototype.compileJoin = function () {
var joinsBuild = { query: "", params: [] };
for (var key in this._joinsQuery) {
if (this._joinsQuery.hasOwnProperty(key)) {
var joinQuery = this._joinsQuery[key];
joinsBuild = this.compileTableJoins(joinsBuild, joinQuery);
}
}
return joinsBuild;
};
QueryBuilderBase.prototype.buildBase = function () {
var columnsCompiled = this.getColumnsCompiled();
// let tablenameAndJoins: QueryCompiled = { query: this.compileTable(), params: this._fromParams };
// for (const key in this._joinsQuery) {
// if (this._joinsQuery.hasOwnProperty(key)) {
// const joinQuery = this._joinsQuery[key];
// tablenameAndJoins = this.compileTableJoins(tablenameAndJoins, joinQuery);
// }
// }
// this._joinParams = this._joinParams.concat(tablenameAndJoins.params);
return {
params: columnsCompiled.params.concat(this._fromParams),
query: "SELECT ".concat(columnsCompiled.projection, " FROM ").concat(this.compileTable()),
};
// return {
// params: columnsCompiled.params.concat(tablenameAndJoins.params),
// query: `SELECT ${columnsCompiled.projection} FROM ${tablenameAndJoins.query}`,
// } as QueryCompiled;
};
QueryBuilderBase.prototype.compileGroupBy = function (groupBy, addCommand) {
if (addCommand === void 0) { addCommand = true; }
if (groupBy && groupBy.length) {
this._groupBy += "".concat(this._groupBy.length ? ", " : (addCommand ? this.GROUP_BY : "")).concat(groupBy);
}
};
QueryBuilderBase.prototype.compileHaving = function (having, addCommand) {
if (addCommand === void 0) { addCommand = true; }
if (having && having.where && having.where.length) {
this._having.where += "".concat(this._having.where.length ? " AND " : (addCommand ? this.HAVING : "")).concat(having.where);
this._having.params = this._having.params.concat(having.params);
}
};
QueryBuilderBase.prototype.compileOrderBy = function (orderBy, addCommand) {
if (addCommand === void 0) { addCommand = true; }
if (orderBy && orderBy.length) {
this._orderBy += "".concat(this._orderBy.length ? ", " : (addCommand ? this.ORDER_BY : "")).concat(orderBy);
}
};
QueryBuilderBase.prototype.buildUnions = function (queryBase) {
for (var key in this._unionsQuery) {
if (this._unionsQuery.hasOwnProperty(key)) {
var unionQuery = this._unionsQuery[key];
queryBase.query += " UNION".concat(unionQuery.type === union_type_1.UnionType.All ? " ALL" : "", " ").concat(unionQuery.query.query);
queryBase.params = queryBase.params.concat(unionQuery.query.params);
}
}
return queryBase;
};
QueryBuilderBase.prototype.buildProjections = function (projections) {
if (projections.length > 0) {
this._projections = __spreadArray(__spreadArray([], this._projections, true), projections, true);
}
};
QueryBuilderBase.prototype.compileTableJoins = function (tablesBase, join) {
var onWhereCompiled = join._getOn();
return {
params: tablesBase.params.concat(onWhereCompiled.params).concat(join._getParams()),
query: "".concat(tablesBase.query, " ").concat(join._getTypeJoin(), " JOIN ").concat(join.compileTable(), " ON (").concat(onWhereCompiled.where, ")"),
};
};
return QueryBuilderBase;
}(sql_base_builder_1.SqlBaseBuilder));
exports.QueryBuilderBase = QueryBuilderBase;