ts-db-helper
Version:
Simple ORM based on TypeScript
208 lines • 7.99 kB
JavaScript
import { QueryError } from '../../errors/query.error';
import { QueryManager } from '../../managers/query-manager';
import { Observable } from 'rxjs/Observable';
import { ModelManager } from '../../managers/model-manager';
import { DbQuery } from '../db-query.model';
import 'rxjs/add/observable/combineLatest';
import 'rxjs/add/operator/map';
/**
* @public
* @class QueryInsert
*
* @description
* For design reasons this class should not be used directly. Use this class with {@link Insert} function.
* Prefer use of save() method instead of Insert for a single entry.
* Insert optimize multiple entry insertion with bulk mecanisme for example.
*
* @param T @extends DbHelperModel a model declared with table and column annotations
*
* @example
* ```typescript
* // Create new model instance
* const todo = new Todo();
* // manipulates todo instance and then insert it
* Insert(todo).exec().subscribe((qr: QueryResult<any>) => {
* // do something after insertion
* }, (err) => {
* // manage error
* });
*
* // it is simplier to use the save methode for a single entry
* todo.save()
*
* // Insertion should be used for multiple model insertion
* const todos = <Todo[]>[];
* // provide and edi.subscribe((qr: QueryResult<any>) => {
* // do something after insertion
* }, (err) => {
* // manage error
* });t new entries
* Insert(todos).exec().subscribe((qr: QueryResult<any>) => {
* // do something after insertion
* }, (err) => {
* // manage error
* });
* ```
*
* @author Olivier Margarit
* @since 0.1
*/
var QueryInsert = /** @class */ (function () {
/**
* @public
* @constructor should not be use directly, see class header
*
* @param {T | Array<T>} model DbHelper model or list of models
*/
function QueryInsert(model) {
this.model = model;
/**
* @private
* @constant {string} type statement type
*/
this.type = 'INSERT';
}
/**
* @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.
*/
QueryInsert.prototype.build = function () {
var table;
var dbQuery = new DbQuery();
if (Array.isArray(this.model)) {
if (this.model.length) {
table = ModelManager.getInstance().getModel(this.model[0]);
}
else {
return dbQuery;
}
}
else {
table = ModelManager.getInstance().getModel(this.model);
}
dbQuery.table = table.name;
dbQuery.type = this.type;
var columns = [];
for (var _i = 0, _a = table.columnList; _i < _a.length; _i++) {
var column = _a[_i];
columns.push(column.name);
}
dbQuery.query += this.type + ' INTO ' + table.name + ' (`' + columns.join('`, `') + '`) VALUES ';
var items = Array.isArray(this.model) ? this.model : [this.model];
var valuesStrings = [];
var parameters = [];
for (var _b = 0, items_1 = items; _b < items_1.length; _b++) {
var item = items_1[_b];
var interrogationMarks = [];
for (var _c = 0, _d = table.columnList; _c < _d.length; _c++) {
var column = _d[_c];
var value = item.getColumnValue(column.name);
if (value === undefined) {
parameters.push(null);
item.setFieldValue(column.field, null);
}
else {
parameters.push(value);
}
interrogationMarks.push('?');
}
valuesStrings.push('(' + interrogationMarks.join(', ') + ')');
}
dbQuery.query += valuesStrings.join(', ');
dbQuery.params = dbQuery.params.concat(parameters);
return dbQuery;
};
/**
* @public
* @method exec to execute the query and asynchronously retreive result.
*
* @return {Observable<QueryResult<any>>} observable to subscribe and manage results
*/
QueryInsert.prototype.exec = function () {
var _this = this;
var observable = null;
if (Array.isArray(this.model)) {
// check if array is to big for insertion
var table = void 0;
if (this.model.length) {
table = ModelManager.getInstance().getModel(this.model[0]);
}
else {
throw (new QueryError('Try to insert empty array', '', ''));
}
var maxItemNumberPerRequest = Math.floor(QueryInsert.SQLITE_PRAMS_LIMIT / table.columnList.length);
var numberOfParts = Math.floor(this.model.length / maxItemNumberPerRequest) + 1;
if (numberOfParts > 1) {
// Array is to big, subsequent insert queries will be created and executed
var observables = [];
for (var i = 0; i < numberOfParts; i += 1) {
var start = i * maxItemNumberPerRequest;
var nextIndex = start + maxItemNumberPerRequest;
var end = nextIndex < this.model.length ? nextIndex : this.model.length;
if (start >= end) {
break;
}
var insert = (new QueryInsert(this.model.slice(start, end)));
observables.push(insert.exec());
}
observable = Observable.combineLatest(observables).map(function (qrs) {
var rowsAffected = 0;
var insertId;
for (var _i = 0, qrs_1 = qrs; _i < qrs_1.length; _i++) {
var qr = qrs_1[_i];
rowsAffected += qr.rowsAffected;
if (qr && qr.insertId || qr.insertId === 0) {
insertId = Math.max(insertId ? insertId : 0, qr.insertId);
}
}
return {
rowsAffected: rowsAffected,
insertId: insertId,
rows: {
length: 0,
item: function (i) {
return null;
},
toArray: function () {
return [];
}
}
};
});
}
}
if (!observable) {
// this is not a too big array, so the query can simply be executed
observable = QueryManager.getInstance().query(this.build());
observable.map(function (qr) {
if (Array.isArray(_this.model)) {
for (var _i = 0, _a = _this.model; _i < _a.length; _i++) {
var model = _a[_i];
model.$$inserted = true;
model.$$isModified = false;
}
}
else {
_this.model.$$inserted = true;
_this.model.$$isModified = false;
}
return qr;
});
}
return observable;
};
/**
* @private
* @static
* @constant {number} SQLITE_PRAMS_LIMIT is a standard SQLite driver limit
* this parameter will probably be customizable in a futrue
* release
*/
QueryInsert.SQLITE_PRAMS_LIMIT = 999;
return QueryInsert;
}());
export { QueryInsert };
//# sourceMappingURL=query-insert.model.js.map