UNPKG

database-builder

Version:

Library to assist in creating and maintaining SQL commands.

407 lines (406 loc) 19.6 kB
"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;