123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- /*
- * Copyright (c) 2015-present, Vitaly Tomilov
- *
- * See the LICENSE file at the top-level directory of this distribution
- * for licensing information.
- *
- * Removal or modification of this copyright notice is prohibited.
- */
- const {InnerState} = require('./inner-state');
- const {addInspection} = require('./utils');
- const {assert} = require('./assert');
- /**
- * @enum {number}
- * @alias txMode.isolationLevel
- * @readonly
- * @summary Transaction Isolation Level.
- * @description
- * The type is available from the {@link txMode} namespace.
- *
- * @see $[Transaction Isolation]
- */
- const isolationLevel = {
- /** Isolation level not specified. */
- none: 0,
- /** ISOLATION LEVEL SERIALIZABLE */
- serializable: 1,
- /** ISOLATION LEVEL REPEATABLE READ */
- repeatableRead: 2,
- /** ISOLATION LEVEL READ COMMITTED */
- readCommitted: 3
- // From the official documentation: http://www.postgresql.org/docs/9.5/static/sql-set-transaction.html
- // The SQL standard defines one additional level, READ UNCOMMITTED. In PostgreSQL READ UNCOMMITTED is treated as READ COMMITTED.
- // => skipping `READ UNCOMMITTED`.
- };
- /**
- * @class txMode.TransactionMode
- * @description
- * Constructs a complete transaction-opening `BEGIN` command, from these options:
- * - isolation level
- * - access mode
- * - deferrable mode
- *
- * The type is available from the {@link txMode} namespace.
- *
- * @param {} [options]
- * Transaction Mode options.
- *
- * @param {txMode.isolationLevel} [options.tiLevel]
- * Transaction Isolation Level.
- *
- * @param {boolean} [options.readOnly]
- * Sets transaction access mode based on the read-only flag:
- * - `undefined` - access mode not specified (default)
- * - `true` - access mode is set to `READ ONLY`
- * - `false` - access mode is set to `READ WRITE`
- *
- * @param {boolean} [options.deferrable]
- * Sets transaction deferrable mode based on the boolean value:
- * - `undefined` - deferrable mode not specified (default)
- * - `true` - mode is set to `DEFERRABLE`
- * - `false` - mode is set to `NOT DEFERRABLE`
- *
- * It is used only when `tiLevel`=`isolationLevel.serializable`
- * and `readOnly`=`true`, or else it is ignored.
- *
- * @returns {txMode.TransactionMode}
- *
- * @see $[BEGIN], {@link txMode.isolationLevel}
- *
- * @example
- *
- * const {TransactionMode, isolationLevel} = pgp.txMode;
- *
- * // Create a reusable transaction mode (serializable + read-only + deferrable):
- * const mode = new TransactionMode({
- * tiLevel: isolationLevel.serializable,
- * readOnly: true,
- * deferrable: true
- * });
- *
- * db.tx({mode}, t => {
- * return t.any('SELECT * FROM table');
- * })
- * .then(data => {
- * // success;
- * })
- * .catch(error => {
- * // error
- * });
- *
- * // Instead of the default BEGIN, such transaction will start with:
- *
- * // BEGIN ISOLATION LEVEL SERIALIZABLE READ ONLY DEFERRABLE
- *
- */
- class TransactionMode extends InnerState {
- constructor(options) {
- options = assert(options, ['tiLevel', 'deferrable', 'readOnly']);
- const {readOnly, deferrable} = options;
- let {tiLevel} = options;
- let level, accessMode, deferrableMode, begin = 'begin';
- tiLevel = (tiLevel > 0) ? parseInt(tiLevel) : 0;
- if (tiLevel > 0 && tiLevel < 4) {
- const values = ['serializable', 'repeatable read', 'read committed'];
- level = 'isolation level ' + values[tiLevel - 1];
- }
- if (readOnly) {
- accessMode = 'read only';
- } else {
- if (readOnly !== undefined) {
- accessMode = 'read write';
- }
- }
- // From the official documentation: http://www.postgresql.org/docs/9.5/static/sql-set-transaction.html
- // The DEFERRABLE transaction property has no effect unless the transaction is also SERIALIZABLE and READ ONLY
- if (tiLevel === isolationLevel.serializable && readOnly) {
- if (deferrable) {
- deferrableMode = 'deferrable';
- } else {
- if (deferrable !== undefined) {
- deferrableMode = 'not deferrable';
- }
- }
- }
- if (level) {
- begin += ' ' + level;
- }
- if (accessMode) {
- begin += ' ' + accessMode;
- }
- if (deferrableMode) {
- begin += ' ' + deferrableMode;
- }
- super({begin, capBegin: begin.toUpperCase()});
- }
- /**
- * @method txMode.TransactionMode#begin
- * @description
- * Returns a complete BEGIN statement, according to all the parameters passed into the class.
- *
- * This method is primarily for internal use by the library.
- *
- * @param {boolean} [cap=false]
- * Indicates whether the returned SQL must be capitalized.
- *
- * @returns {string}
- */
- begin(cap) {
- return cap ? this._inner.capBegin : this._inner.begin;
- }
- }
- addInspection(TransactionMode, function () {
- return this.begin(true);
- });
- /**
- * @namespace txMode
- * @description
- * Transaction Mode namespace, available as `pgp.txMode`, before and after initializing the library.
- *
- * Extends the default `BEGIN` with Transaction Mode parameters:
- * - isolation level
- * - access mode
- * - deferrable mode
- *
- * @property {function} TransactionMode
- * {@link txMode.TransactionMode TransactionMode} class constructor.
- *
- * @property {txMode.isolationLevel} isolationLevel
- * Transaction Isolation Level enumerator
- *
- * @see $[BEGIN]
- */
- module.exports = {
- isolationLevel,
- TransactionMode
- };
|