ts-db-helper
Version:
Simple ORM based on TypeScript
362 lines • 12.5 kB
JavaScript
import { DbColumn } from '../structure/db-column.model';
import { ModelResult } from './model-result.model';
import { DbTable } from '../structure/db-table.model';
import { QueryManager } from '../../managers/query-manager';
import { ModelManager } from '../../managers/model-manager';
import { DbQuery } from '../db-query.model';
import { ClauseGroup } from './clause-group.model';
/**
* @public
* @class QuerySelect
*
* @description
* For design reasons this class should not be used directly. Use this class with {@link Select} function.
*
* @param T @extends DbHelperModel a model declared with table and column annotations
*
* @example
* ```typescript
* // select todos
* Select(Todo).where({isDone: false}}).exec().subscribe((qr: QueryResult<Todo>) => {
* // do something with the result...
* }, (err) => {
* // do something with the error...
* });
* ```
*
* @author Olivier Margarit
* @since 0.1
*/
var QuerySelect = /** @class */ (function () {
/**
* @public
* @constructor should not be use directly, see class header
*
* @param {{new(): T}} model extention
*/
function QuerySelect(model) {
this.model = model;
/**
* @private
* @constant {string} type query type
*/
this.type = 'SELECT';
/**
* @private
* @property {Array<IJoin>} joins list of join for the query
*/
this.joins = [];
/**
* @private
* @property size, the number of element returned by the select query
*/
this.size = 1000;
/**
* @private
* @property {number} page the paginated number of the query select
*/
this.page = 0;
/**
* @private
* @property {string} alias the query alias to prevent column collision
*/
this.alias = '';
}
/**
* @public
* @method copy method to copy QuerySelect
*
* @return {QuerySelect<T>} the query select copy
*
* @since 0.2
*/
QuerySelect.prototype.copy = function () {
var q = (new QuerySelect(this.model)).where(this.whereClauses).join(this.joins).groupBy(this.grpBy).orderBy(this.ordrBy);
if (this.proj) {
q.projection(this.proj);
}
return q;
};
/**
* @public
* @method projection customize the select column of the QueryResult
* for performance optimization if needed.
*
* @param {Array<string>} proj the projection
*
* @return {QuerySelect<T>} this instance to chain query instructions
*/
QuerySelect.prototype.projection = function (proj) {
this.proj = proj;
return this;
};
/**
* @public
* @method join add query join to query select
*
* @param {IJoin|Array<IJoin>} joinQuery join query or list of join queries
*
* @return {QuerySelect<T>} the instance itself to chain operation
*/
QuerySelect.prototype.join = function (joinQuery) {
var joins;
if (!Array.isArray(joinQuery)) {
joins = [joinQuery];
}
else {
joins = joinQuery;
}
for (var _i = 0, joins_1 = joins; _i < joins_1.length; _i++) {
var jq = joins_1[_i];
if (!jq) {
continue;
}
if (!jq.alias) {
jq.alias = 'join_' + this.joins.length;
}
this.joins.push(jq);
}
return this;
};
/**
* @public
* @method where is the method to add clauses to the where statement of the query
* see {@link Clause} or {@link ClauseGroup} or {@link CompositeClause}
*
* @param {Clause|Clause[]|CompositeClause|ClauseGroup|{[index: string]: any}} clauses where clauses
*
* @return {QuerySelect<T>} this instance to chain query instructions
*/
QuerySelect.prototype.where = function (clauses) {
if (!this.whereClauses) {
this.whereClauses = new ClauseGroup();
}
this.whereClauses.add(clauses);
return this;
};
/**
* @public
* @method groupBy add group by instructions to the query
*
* @param {string} group string whith the column to group by
*
* @return {QuerySelect<T>} this instance to chain query instructions
*/
QuerySelect.prototype.groupBy = function (group) {
this.grpBy = group;
return this;
};
/**
* @public
* @method orderBy add order by instructions to the query
*
* @param {string} order string whith the column to order by
*
* @return {QuerySelect<T>} this instance to chain query instructions
*/
QuerySelect.prototype.orderBy = function (order) {
this.ordrBy = order;
return this;
};
/**
* @public
* @method setPage set the page result for pagination
*
* @param {number} page page number of the result
*
* @return {QuerySelect<T>} this instance to chain query instructions
*/
QuerySelect.prototype.setPage = function (page) {
this.page = page;
return this;
};
/**
* @public
* @method setSize set the size of the page result for pagination
*
* @param {number} size page size number of the result
*
* @return {QuerySelect<T>} this instance to chain query instructions
*/
QuerySelect.prototype.setSize = function (size) {
this.size = size;
return this;
};
QuerySelect.prototype.getSize = function () {
return this.size;
};
QuerySelect.prototype.getPage = function () {
return this.page;
};
/**
* @public
* @method getProjectedTable get virtual table representing the result table expected
*
* @return {DbTable} the virtual table
*/
QuerySelect.prototype.getProjectedTable = function () {
var srcTable = ModelManager.getInstance().getModel(this.model);
var table = new DbTable();
table.name = srcTable.name;
table.modelName = srcTable.modelName;
if (this.proj) {
var projection = this.proj.slice();
for (var _i = 0, _a = srcTable.columnList; _i < _a.length; _i++) {
var column = _a[_i];
var index = projection.indexOf(column.name);
if (index >= 0) {
table.columns[column.name] = column;
table.fields[column.field] = column;
table.columnList.push(column);
projection.slice(index, 1);
}
}
for (var _b = 0, projection_1 = projection; _b < projection_1.length; _b++) {
var name = projection_1[_b];
var dbColumn = new DbColumn(name);
dbColumn.field = name;
table.columns[dbColumn.name] = dbColumn;
table.columnList.push(dbColumn);
table.fields[dbColumn.field] = dbColumn;
}
}
else {
for (var _c = 0, _d = srcTable.columnList; _c < _d.length; _c++) {
var column = _d[_c];
table.columnList.push(column);
table.columns[column.name] = column;
table.fields[column.field] = column;
}
if (table.columns.hasOwnProperty('rowid')) {
var rowidColumn = new DbColumn('rowid');
rowidColumn.indexed = true;
rowidColumn.autoIncrement = true;
rowidColumn.field = '$$rowid';
rowidColumn.type = 'integer';
table.columns[rowidColumn.name] = rowidColumn;
table.columnList.push(rowidColumn);
table.fields[rowidColumn.field] = rowidColumn;
}
}
if (this.joins) {
for (var _e = 0, _f = this.joins; _e < _f.length; _e++) {
var joinQuery = _f[_e];
var joinTable = joinQuery.getProjectedTable();
for (var _g = 0, _h = joinTable.columnList; _g < _h.length; _g++) {
var column = _h[_g];
var joinColumn = column.fromAlias(joinQuery.alias);
table.columnList.push(joinColumn);
table.columns[joinColumn.name] = joinColumn;
table.fields[joinColumn.field] = joinColumn;
}
}
}
return table;
};
/**
* @private
* @method getJoinProjection get the projection of join query
*
* @return {string} the projection
*/
QuerySelect.prototype.getJoinProjection = function () {
var joinProjection = '';
if (this.joins) {
var columns = [];
for (var _i = 0, _a = this.joins; _i < _a.length; _i++) {
var joinQuery = _a[_i];
var joinTable = joinQuery.getProjectedTable();
for (var _b = 0, _c = joinTable.columnList; _b < _c.length; _b++) {
var column = _c[_b];
columns.push(joinQuery.alias + '.' + column.name);
}
}
joinProjection = columns.join(', ');
}
return joinProjection;
};
/**
* @public
* @method build should be removed to be a part of the private API
*
* @return {DbQuery} of the query with the string part and
* clauses params.
*/
QuerySelect.prototype.build = function () {
var dbQuery = new DbQuery();
dbQuery.page = this.page;
dbQuery.size = this.size;
dbQuery.table = ModelManager.getInstance().getModel(this.model).name;
dbQuery.type = this.type;
dbQuery.query += this.type;
if (this.proj) {
dbQuery.query += ' ';
for (var i = 0; i < this.proj.length; i++) {
var item = this.proj[i];
if (item.trim().indexOf('(') >= 0) {
dbQuery.query += item;
}
else {
dbQuery.query += ' `' + item + '`';
}
if (i < this.proj.length - 1) {
dbQuery.query += ', ';
}
}
}
else if (QueryManager.getInstance().supportRowid) {
dbQuery.query += ' rowid, *';
}
else {
dbQuery.query += ' *';
}
if (this.joins && this.joins.length && !this.proj) {
dbQuery.query += ', ' + this.getJoinProjection();
}
dbQuery.query += ' FROM ' + dbQuery.table;
for (var _i = 0, _a = this.joins; _i < _a.length; _i++) {
var joinQuery = _a[_i];
dbQuery.append(joinQuery.build());
}
if (this.whereClauses) {
var w = this.whereClauses.build();
if (w && w.content) {
dbQuery.query += ' WHERE';
dbQuery.append(w);
}
}
if (this.grpBy) {
dbQuery.query += ' GROUP BY ' + this.grpBy;
}
if (this.ordrBy) {
dbQuery.query += ' ORDER BY ' + this.ordrBy;
}
return dbQuery;
};
/**
* @public
* @method exec to execute the query and asynchronously retreive result.
*
* @return {Observable<QueryResult<T>>} observable to subscribe and retrieve typed result
*/
QuerySelect.prototype.exec = function () {
var _this = this;
return QueryManager.getInstance().query(this.build()).map(function (qr) {
return new ModelResult(qr, _this.model, _this.proj);
});
};
/**
* @public
* @method exec to execute the query and asynchronously retreive result.
*
* @return {Observable<QueryResult<any>>} observable to subscribe and retrieve result
*
* @since 0.2
*/
QuerySelect.prototype.execRaw = function () {
return QueryManager.getInstance().query(this.build());
};
return QuerySelect;
}());
export { QuerySelect };
//# sourceMappingURL=query-select.model.js.map