UNPKG

database-builder

Version:

Library to assist in creating and maintaining SQL commands.

335 lines (334 loc) 15.3 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; 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.ManagedTransaction = void 0; var utils_1 = require("../core/utils"); var transaction_status_1 = require("./transaction-status"); var core_1 = require("../core"); var rxjs_1 = require("rxjs"); var replacement_param_1 = require("../core/replacement-param"); /** * Manages better and homogeneous transaction between providers */ var ManagedTransaction = /** @class */ (function () { function ManagedTransaction(_database, _singleTransactionManager) { this._database = _database; this._singleTransactionManager = _singleTransactionManager; this._status = transaction_status_1.TransactionStatus.OPEN; this._stack = []; this._idTransaction = "transaction_".concat(utils_1.Utils.GUID().replace(/-/g, "_")); } Object.defineProperty(ManagedTransaction.prototype, "id", { /** * return transaction id */ get: function () { return this._idTransaction; }, enumerable: false, configurable: true }); Object.defineProperty(ManagedTransaction.prototype, "status", { /** * Set transaction status */ set: function (value) { this._status = value; }, enumerable: false, configurable: true }); /** * Add command statement in transaction * @param statement command to apply * @param params command params */ ManagedTransaction.prototype.addStatement = function (statement, params) { this.checkTransactionActive(); this._stack.push({ statement: statement, params: params }); }; /** * Add command compilable in transaction * @param compilable command compilable for add in transaction */ ManagedTransaction.prototype.add = function (compilable) { var _this = this; var compiled = compilable.compile(); compiled.forEach(function (c) { return _this.addStatement(c.query, c.params); }); }; /** * @deprecated Será removido, pois não tem utilidade real e não funciona de forma homegenea entre providers * @param executable */ ManagedTransaction.prototype.executeImmediate = function (executable) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: this.checkTransactionActive(); return [4 /*yield*/, this.beginTransaction()]; case 1: _a.sent(); return [4 /*yield*/, this.executeStack()]; case 2: _a.sent(); return [2 /*return*/, executable.execute().toPromise()]; } }); }); }; /** * Commit a transaction */ ManagedTransaction.prototype.commit = function () { if (this._singleTransactionManager) { return this._singleTransactionManager.commitOnStack(this.commitExecuteObservable()); } return this.commitExecuteObservable(); }; /** * Rollback in current transaction */ ManagedTransaction.prototype.rollback = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: if (this._status === transaction_status_1.TransactionStatus.ROLLBACKED) { console.warn("Transaction (id: ".concat(this._idTransaction, ") already rollbacked")); return [2 /*return*/, true]; } this.checkTransactionActive(); this.clearStackTransaction(); if (!(this._status === transaction_status_1.TransactionStatus.STARTED || this._status === transaction_status_1.TransactionStatus.RELEASED)) return [3 /*break*/, 2]; this.addStatement(this.commandRollbackTransaction(), []); return [4 /*yield*/, this.executeStack()]; case 1: _a.sent(); _a.label = 2; case 2: return [2 /*return*/, this.finishTransaction(transaction_status_1.TransactionStatus.ROLLBACKED)]; } }); }); }; ManagedTransaction.prototype.sqlBatch = function (sqlStatements) { return this._database.sqlBatch(sqlStatements); }; ManagedTransaction.prototype.executeSql = function (statement, params) { return this._database.executeSql(statement, params); }; /** * Commit a transaction */ ManagedTransaction.prototype.commitExecuteObservable = function () { var _this = this; return new rxjs_1.Observable(function (observer) { _this.commitExecute() .then(function (result) { observer.next(result); observer.complete(); }).catch(function (error) { observer.error(error); }); }); }; /** * Commit a transaction */ ManagedTransaction.prototype.commitExecute = function () { return __awaiter(this, void 0, void 0, function () { var batch; return __generator(this, function (_a) { switch (_a.label) { case 0: if (this._status === transaction_status_1.TransactionStatus.COMMITTED) { console.warn("Transaction (id: ".concat(this._idTransaction, ") already committed")); return [2 /*return*/, true]; } this.checkParametersAllowedInTransaction(); this.checkTransactionActive(); if (!(this._status === transaction_status_1.TransactionStatus.STARTED || this._status === transaction_status_1.TransactionStatus.RELEASED)) return [3 /*break*/, 2]; this.addStatement(this.commandCommitTransaction(), []); return [4 /*yield*/, this.executeStack()]; case 1: _a.sent(); return [3 /*break*/, 4]; case 2: batch = this.buildSqlBatch(this._stack); this.clearStackTransaction(); this.status = transaction_status_1.TransactionStatus.STARTED; return [4 /*yield*/, this.sqlBatch(batch)]; case 3: _a.sent(); _a.label = 4; case 4: return [2 /*return*/, this.finishTransaction(transaction_status_1.TransactionStatus.COMMITTED)]; } }); }); }; /** * Execute stack in Database */ ManagedTransaction.prototype.executeStack = function () { return __awaiter(this, void 0, void 0, function () { var batch; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!(this._stack.length > 0)) return [3 /*break*/, 2]; batch = this.buildSqlExecute(this._stack); return [4 /*yield*/, this.executeSql(batch.statement, batch.params)]; case 1: _a.sent(); this.clearStackTransaction(); _a.label = 2; case 2: return [2 /*return*/]; } }); }); }; ManagedTransaction.prototype.checkParametersAllowedInTransaction = function () { this._stack.forEach(function (itemStack) { itemStack.params.forEach(function (param, index) { if (param instanceof replacement_param_1.ReplacementParam) { throw new core_1.DatabaseBuilderError("Insert cascading with autoincrement mapper not supported with transaction. (Found in \"".concat(itemStack.statement, "\", params: [").concat(itemStack.params.map(function (x) { return x instanceof replacement_param_1.ReplacementParam ? "[".concat(x.properties.join(","), "]") : x; }).join(","), "], paramIndex: ").concat(index, ")")); } }); }); }; /** * check transaction is active (open, stated, released) and throw error if inactive */ ManagedTransaction.prototype.checkTransactionActive = function () { if (!this.isTransactionActive()) { throw new core_1.DatabaseBuilderError("Transaction (id: ".concat(this._idTransaction, ") is no longer active, and can no longer be used. Current status: ").concat(transaction_status_1.TransactionStatus[this._status])); } }; /** * return true if transaction is active (open, stated, released) */ ManagedTransaction.prototype.isTransactionActive = function () { return this._status === transaction_status_1.TransactionStatus.OPEN || this._status === transaction_status_1.TransactionStatus.STARTED || this._status === transaction_status_1.TransactionStatus.RELEASED; }; /** * Finish transaction and set status * @param status Status for finished transaction */ ManagedTransaction.prototype.finishTransaction = function (status) { this.status = status; this.clearStackTransaction(); return true; }; /** * Clear stack transaction */ ManagedTransaction.prototype.clearStackTransaction = function () { this._stack = []; }; /** * Convert Array commands for SqlBatch format * @param compiled Array commands */ ManagedTransaction.prototype.buildSqlBatch = function (compiled) { return compiled.map(function (x) { var r = x.params.length > 0 ? [x.statement, x.params] : x.statement; return r; }); }; /** * Convert Array commands for SqlExecute format * @param compiled Array commands */ ManagedTransaction.prototype.buildSqlExecute = function (compiled) { return compiled.reduce(function (previous, current) { previous.statement += "".concat(current.statement, ";"); previous.params = __spreadArray(__spreadArray([], previous.params, true), current.params, true); return previous; }, { statement: "", params: [] }); }; /** * Begin transaction */ ManagedTransaction.prototype.beginTransaction = function () { return __awaiter(this, void 0, void 0, function () { var result; return __generator(this, function (_a) { switch (_a.label) { case 0: if (this._status === transaction_status_1.TransactionStatus.STARTED) { return [2 /*return*/, Promise.resolve(void 0)]; } return [4 /*yield*/, this.executeSql("BEGIN TRANSACTION", [])]; case 1: result = _a.sent(); this.status = transaction_status_1.TransactionStatus.STARTED; return [2 /*return*/, result]; } }); }); }; /** * Command commit transaction */ ManagedTransaction.prototype.commandCommitTransaction = function () { return "COMMIT TRANSACTION"; }; /** * Command roolback transaction */ ManagedTransaction.prototype.commandRollbackTransaction = function () { return "ROLLBACK TRANSACTION"; }; return ManagedTransaction; }()); exports.ManagedTransaction = ManagedTransaction;