This commit is contained in:
Tutur33
2023-11-24 22:35:41 +01:00
parent 3c0b507a93
commit 7644b2a0f7
45165 changed files with 4803356 additions and 3 deletions
+162
View File
@@ -0,0 +1,162 @@
/// <reference path="../../adonis-typings/index.d.ts" />
/// <reference types="@adonisjs/events/build/adonis-typings" />
/// <reference types="@adonisjs/profiler/build/adonis-typings/profiler" />
/// <reference types="node" />
import { Knex } from 'knex';
import { EventEmitter } from 'events';
import { EmitterContract } from '@ioc:Adonis/Core/Event';
import { ProfilerRowContract } from '@ioc:Adonis/Core/Profiler';
import { IsolationLevels, DialectContract, TransactionClientContract } from '@ioc:Adonis/Lucid/Database';
import { RawBuilder } from '../Database/StaticBuilder/Raw';
import { ReferenceBuilder } from '../Database/StaticBuilder/Reference';
/**
* Transaction uses a dedicated connection from the connection pool
* and executes queries inside a given transaction.
*/
export declare class TransactionClient extends EventEmitter implements TransactionClientContract {
knexClient: Knex.Transaction;
dialect: DialectContract;
connectionName: string;
debug: boolean;
emitter: EmitterContract;
/**
* Always true
*/
isTransaction: true;
/**
* Transactions are always in write mode, since they always needs
* the primary connection
*/
mode: 'dual';
/**
* The profiler to be used for profiling queries
*/
profiler?: ProfilerRowContract;
private hooks;
constructor(knexClient: Knex.Transaction, dialect: DialectContract, connectionName: string, debug: boolean, emitter: EmitterContract);
/**
* Whether or not transaction has been completed
*/
get isCompleted(): boolean;
/**
* Returns schema instance for the write client
*/
get schema(): Knex.SchemaBuilder;
/**
* Returns the read client. Which is just a single client in case
* of transactions
*/
getReadClient(): Knex.Transaction<any, any[]>;
/**
* Returns the write client. Which is just a single client in case
* of transactions
*/
getWriteClient(): Knex.Transaction<any, any[]>;
/**
* Truncate tables inside a transaction
*/
truncate(table: string, cascade?: boolean): Promise<void>;
/**
* Get columns info inside a transaction. You won't need it here, however
* added for API compatibility with the [[QueryClient]] class
*/
columnsInfo(table: string, column?: string): Promise<any>;
/**
* Returns an array of table names
*/
getAllTables(schemas?: string[]): Promise<string[]>;
/**
* Returns an array of all views names
*/
getAllViews(schemas?: string[]): Promise<string[]>;
/**
* Returns an array of all types names
*/
getAllTypes(schemas?: string[]): Promise<string[]>;
/**
* Drop all tables inside database
*/
dropAllTables(schemas?: string[]): Promise<void>;
/**
* Drop all views inside the database
*/
dropAllViews(schemas?: string[]): Promise<void>;
/**
* Drop all custom types inside the database
*/
dropAllTypes(schemas?: string[]): Promise<void>;
/**
* Get a new query builder instance
*/
knexQuery(): Knex.QueryBuilder;
/**
* Returns the knex raw query builder instance. The query builder is always
* created from the `write` client, so before executing the query, you
* may want to decide which client to use.
*/
knexRawQuery(sql: string, bindings?: any): Knex.Raw;
/**
* Returns a query builder instance for a given model. The `connection`
* and `profiler` is passed down to the model, so that it continue
* using the same options
*/
modelQuery(model: any): any;
/**
* Get a new query builder instance
*/
query(): any;
/**
* Get a new insert query builder instance
*/
insertQuery(): any;
/**
* Execute raw query on transaction
*/
rawQuery(sql: any, bindings?: any): any;
/**
* Returns an instance of raw builder. This raw builder queries
* cannot be executed. Use `rawQuery`, if you want to execute
* queries raw queries.
*/
raw(sql: string, bindings?: any): RawBuilder;
/**
* Returns reference builder.
*/
ref(reference: string): ReferenceBuilder;
/**
* Returns another instance of transaction with save point
*/
transaction(callback?: {
isolationLevel?: IsolationLevels;
} | ((trx: TransactionClientContract) => Promise<any>), options?: {
isolationLevel?: IsolationLevels;
}): Promise<any>;
/**
* Same as [[Transaction.query]] but also selects the table
*/
from(table: any): any;
/**
* Same as [[Transaction.insertTable]] but also selects the table
*/
table(table: any): any;
/**
* Register after commit or rollback hook
*/
after(event: 'rollback' | 'commit', handler: () => void | Promise<void>): this;
/**
* Commit the transaction
*/
commit(): Promise<void>;
/**
* Rollback the transaction
*/
rollback(): Promise<void>;
/**
* Get advisory lock on the selected connection
*/
getAdvisoryLock(key: string, timeout?: number): any;
/**
* Release advisory lock
*/
releaseAdvisoryLock(key: string): any;
}
+329
View File
@@ -0,0 +1,329 @@
"use strict";
/*
* @adonisjs/lucid
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.TransactionClient = void 0;
const events_1 = require("events");
const hooks_1 = require("@poppinss/hooks");
const QueryBuilder_1 = require("../Orm/QueryBuilder");
const Raw_1 = require("../Database/StaticBuilder/Raw");
const Raw_2 = require("../Database/QueryBuilder/Raw");
const Insert_1 = require("../Database/QueryBuilder/Insert");
const Reference_1 = require("../Database/StaticBuilder/Reference");
const Database_1 = require("../Database/QueryBuilder/Database");
/**
* Transaction uses a dedicated connection from the connection pool
* and executes queries inside a given transaction.
*/
class TransactionClient extends events_1.EventEmitter {
constructor(knexClient, dialect, connectionName, debug, emitter) {
super();
Object.defineProperty(this, "knexClient", {
enumerable: true,
configurable: true,
writable: true,
value: knexClient
});
Object.defineProperty(this, "dialect", {
enumerable: true,
configurable: true,
writable: true,
value: dialect
});
Object.defineProperty(this, "connectionName", {
enumerable: true,
configurable: true,
writable: true,
value: connectionName
});
Object.defineProperty(this, "debug", {
enumerable: true,
configurable: true,
writable: true,
value: debug
});
Object.defineProperty(this, "emitter", {
enumerable: true,
configurable: true,
writable: true,
value: emitter
});
/**
* Always true
*/
Object.defineProperty(this, "isTransaction", {
enumerable: true,
configurable: true,
writable: true,
value: true
});
/**
* Transactions are always in write mode, since they always needs
* the primary connection
*/
Object.defineProperty(this, "mode", {
enumerable: true,
configurable: true,
writable: true,
value: 'dual'
});
/**
* The profiler to be used for profiling queries
*/
Object.defineProperty(this, "profiler", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "hooks", {
enumerable: true,
configurable: true,
writable: true,
value: new hooks_1.Hooks()
});
/**
* Lucid models listens for transaction events to delete the reference. During
* testing, it is common to generate more than 10 model instances and hence
* the max listeners limit needs to be removed
*/
this.setMaxListeners(Infinity);
}
/**
* Whether or not transaction has been completed
*/
get isCompleted() {
return this.knexClient.isCompleted();
}
/**
* Returns schema instance for the write client
*/
get schema() {
return this.getWriteClient().schema;
}
/**
* Returns the read client. Which is just a single client in case
* of transactions
*/
getReadClient() {
return this.knexClient;
}
/**
* Returns the write client. Which is just a single client in case
* of transactions
*/
getWriteClient() {
return this.knexClient;
}
/**
* Truncate tables inside a transaction
*/
async truncate(table, cascade = false) {
await this.dialect.truncate(table, cascade);
}
/**
* Get columns info inside a transaction. You won't need it here, however
* added for API compatibility with the [[QueryClient]] class
*/
async columnsInfo(table, column) {
const query = this.knexClient.select(table);
const result = await (column ? query.columnInfo(column) : query.columnInfo());
return result;
}
/**
* Returns an array of table names
*/
async getAllTables(schemas) {
return this.dialect.getAllTables(schemas);
}
/**
* Returns an array of all views names
*/
async getAllViews(schemas) {
return this.dialect.getAllViews(schemas);
}
/**
* Returns an array of all types names
*/
async getAllTypes(schemas) {
return this.dialect.getAllTypes(schemas);
}
/**
* Drop all tables inside database
*/
async dropAllTables(schemas) {
return this.dialect.dropAllTables(schemas || ['public']);
}
/**
* Drop all views inside the database
*/
async dropAllViews(schemas) {
return this.dialect.dropAllViews(schemas || ['public']);
}
/**
* Drop all custom types inside the database
*/
async dropAllTypes(schemas) {
return this.dialect.dropAllTypes(schemas || ['public']);
}
/**
* Get a new query builder instance
*/
knexQuery() {
return this.knexClient.queryBuilder();
}
/**
* Returns the knex raw query builder instance. The query builder is always
* created from the `write` client, so before executing the query, you
* may want to decide which client to use.
*/
knexRawQuery(sql, bindings) {
return bindings ? this.knexClient.raw(sql, bindings) : this.knexClient.raw(sql);
}
/**
* Returns a query builder instance for a given model. The `connection`
* and `profiler` is passed down to the model, so that it continue
* using the same options
*/
modelQuery(model) {
return new QueryBuilder_1.ModelQueryBuilder(this.knexQuery(), model, this);
}
/**
* Get a new query builder instance
*/
query() {
return new Database_1.DatabaseQueryBuilder(this.knexQuery(), this);
}
/**
* Get a new insert query builder instance
*/
insertQuery() {
return new Insert_1.InsertQueryBuilder(this.knexQuery(), this);
}
/**
* Execute raw query on transaction
*/
rawQuery(sql, bindings) {
return new Raw_2.RawQueryBuilder(this.knexClient.raw(sql, bindings), this);
}
/**
* Returns an instance of raw builder. This raw builder queries
* cannot be executed. Use `rawQuery`, if you want to execute
* queries raw queries.
*/
raw(sql, bindings) {
return new Raw_1.RawBuilder(sql, bindings);
}
/**
* Returns reference builder.
*/
ref(reference) {
return new Reference_1.ReferenceBuilder(reference, this.knexClient.client);
}
/**
* Returns another instance of transaction with save point
*/
async transaction(callback, options) {
const trx = await this.knexClient.transaction(options);
const transaction = new TransactionClient(trx, this.dialect, this.connectionName, this.debug, this.emitter);
/**
* Always make sure to pass the profiler down the chain
*/
transaction.profiler = this.profiler?.create('trx:begin', { state: 'begin' });
/**
* Self managed transaction
*/
if (typeof callback === 'function') {
try {
const response = await callback(transaction);
!transaction.isCompleted && (await transaction.commit());
return response;
}
catch (error) {
await transaction.rollback();
throw error;
}
}
return transaction;
}
/**
* Same as [[Transaction.query]] but also selects the table
*/
from(table) {
return this.query().from(table);
}
/**
* Same as [[Transaction.insertTable]] but also selects the table
*/
table(table) {
return this.insertQuery().table(table);
}
/**
* Register after commit or rollback hook
*/
after(event, handler) {
this.hooks.add('after', event, handler);
return this;
}
/**
* Commit the transaction
*/
async commit() {
try {
await this.knexClient.commit();
this.profiler?.end({ state: 'commit' });
this.emit('commit', this);
this.removeAllListeners();
}
catch (error) {
this.profiler?.end({ state: 'commit' });
this.removeAllListeners();
throw error;
}
try {
await this.hooks.exec('after', 'commit');
this.hooks.clear('after');
}
catch { }
}
/**
* Rollback the transaction
*/
async rollback() {
try {
await this.knexClient.rollback();
this.profiler?.end({ state: 'rollback' });
this.emit('rollback', this);
this.removeAllListeners();
}
catch (error) {
this.profiler?.end({ state: 'rollback' });
this.removeAllListeners();
throw error;
}
try {
await this.hooks.exec('after', 'rollback');
this.hooks.clear('after');
}
catch { }
}
/**
* Get advisory lock on the selected connection
*/
getAdvisoryLock(key, timeout) {
return this.dialect.getAdvisoryLock(key, timeout);
}
/**
* Release advisory lock
*/
releaseAdvisoryLock(key) {
return this.dialect.releaseAdvisoryLock(key);
}
}
exports.TransactionClient = TransactionClient;