2022-09-30 16:42:13 +00:00
|
|
|
import {Awaitable, Collection, ErrorWithContext} from '../../util'
|
|
|
|
import {QueryResult, QueryRow} from '../types'
|
2021-06-03 03:36:25 +00:00
|
|
|
import {SQLDialect} from '../dialect/SQLDialect'
|
|
|
|
import {AppClass} from '../../lifecycle/AppClass'
|
2021-06-05 13:36:35 +00:00
|
|
|
import {Inject, Injectable} from '../../di'
|
|
|
|
import {QueryExecutedEvent} from './event/QueryExecutedEvent'
|
2021-07-25 14:15:01 +00:00
|
|
|
import {Schema} from '../schema/Schema'
|
2022-01-27 01:37:54 +00:00
|
|
|
import {Bus} from '../../support/bus'
|
2022-09-30 16:42:13 +00:00
|
|
|
import {ModelField} from '../model/Field'
|
2021-06-02 01:59:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Error thrown when a connection is used before it is ready.
|
|
|
|
* @extends Error
|
|
|
|
*/
|
|
|
|
export class ConnectionNotReadyError extends ErrorWithContext {
|
|
|
|
constructor(name = '', context: {[key: string]: any} = {}) {
|
|
|
|
super(`The connection ${name} is not ready and cannot execute queries.`)
|
|
|
|
this.context = context
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Abstract base class for database connections.
|
|
|
|
* @abstract
|
|
|
|
*/
|
2021-06-05 13:36:35 +00:00
|
|
|
@Injectable()
|
2021-06-02 01:59:40 +00:00
|
|
|
export abstract class Connection extends AppClass {
|
2021-06-05 13:36:35 +00:00
|
|
|
@Inject()
|
2022-01-27 01:37:54 +00:00
|
|
|
protected readonly bus!: Bus
|
2021-06-02 01:59:40 +00:00
|
|
|
|
|
|
|
constructor(
|
|
|
|
/**
|
|
|
|
* The name of this connection
|
|
|
|
* @type string
|
|
|
|
*/
|
|
|
|
public readonly name: string,
|
|
|
|
/**
|
|
|
|
* This connection's config object
|
|
|
|
*/
|
|
|
|
public readonly config: any = {},
|
2021-06-03 03:36:25 +00:00
|
|
|
) {
|
|
|
|
super()
|
|
|
|
}
|
2021-06-02 01:59:40 +00:00
|
|
|
|
|
|
|
public abstract dialect(): SQLDialect
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Open the connection.
|
|
|
|
* @return Promise<void>
|
|
|
|
*/
|
|
|
|
public abstract init(): Promise<void>
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Execute an SQL query and get the result.
|
|
|
|
* @param {string} query
|
|
|
|
* @return Promise<QueryResult>
|
|
|
|
*/
|
|
|
|
public abstract query(query: string): Promise<QueryResult>
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Close the connection.
|
|
|
|
* @return Promise<void>
|
|
|
|
*/
|
|
|
|
public abstract close(): Promise<void>
|
|
|
|
|
2021-07-25 14:15:01 +00:00
|
|
|
/**
|
|
|
|
* Get a Schema on this connection.
|
|
|
|
* @param name
|
|
|
|
*/
|
|
|
|
public abstract schema(name?: string): Schema
|
2021-06-05 13:36:35 +00:00
|
|
|
|
2021-08-24 04:51:53 +00:00
|
|
|
/**
|
|
|
|
* Execute all queries logged to this connection during the closure
|
|
|
|
* as a transaction in the database.
|
|
|
|
* @param closure
|
|
|
|
*/
|
|
|
|
public abstract asTransaction<T>(closure: () => Awaitable<T>): Awaitable<T>
|
|
|
|
|
2022-09-30 16:42:13 +00:00
|
|
|
/**
|
|
|
|
* Normalize a query row before it is used by the framework.
|
|
|
|
* This helps account for differences in return values from the dialects.
|
|
|
|
* @param row
|
|
|
|
* @param fields
|
|
|
|
*/
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
|
public normalizeRow(row: QueryRow, fields: Collection<ModelField>): QueryRow {
|
|
|
|
return row
|
|
|
|
}
|
|
|
|
|
2021-06-05 13:36:35 +00:00
|
|
|
/**
|
|
|
|
* Fire a QueryExecutedEvent for the given query string.
|
|
|
|
* @param query
|
|
|
|
* @protected
|
|
|
|
*/
|
|
|
|
protected async queryExecuted(query: string): Promise<void> {
|
|
|
|
const event = new QueryExecutedEvent(this.name, this, query)
|
2022-01-27 01:37:54 +00:00
|
|
|
await this.bus.push(event)
|
2021-06-05 13:36:35 +00:00
|
|
|
}
|
2021-06-02 01:59:40 +00:00
|
|
|
}
|