feat: Aurora Data API - Postgres Support (#5651) · typeorm/typeorm@e584297
1+import {QueryRunnerAlreadyReleasedError} from "../../error/QueryRunnerAlreadyReleasedError";
2+import {TransactionAlreadyStartedError} from "../../error/TransactionAlreadyStartedError";
3+import {TransactionNotStartedError} from "../../error/TransactionNotStartedError";
4+import {QueryRunner} from "../../query-runner/QueryRunner";
5+import {IsolationLevel} from "../types/IsolationLevel";
6+import {AuroraDataApiPostgresDriver} from "../postgres/PostgresDriver";
7+import {PostgresQueryRunner} from "../postgres/PostgresQueryRunner";
8+9+class PostgresQueryRunnerWrapper extends PostgresQueryRunner {
10+driver: any;
11+12+constructor(driver: any, mode: "master"|"slave") {
13+super(driver, mode);
14+}
15+}
16+17+/**
18+ * Runs queries on a single postgres database connection.
19+ */
20+export class AuroraDataApiPostgresQueryRunner extends PostgresQueryRunnerWrapper implements QueryRunner {
21+22+// -------------------------------------------------------------------------
23+// Public Implemented Properties
24+// -------------------------------------------------------------------------
25+26+/**
27+ * Database driver used by connection.
28+ */
29+driver: AuroraDataApiPostgresDriver;
30+31+// -------------------------------------------------------------------------
32+// Protected Properties
33+// -------------------------------------------------------------------------
34+35+/**
36+ * Promise used to obtain a database connection for a first time.
37+ */
38+protected databaseConnectionPromise: Promise<any>;
39+40+/**
41+ * Special callback provided by a driver used to release a created connection.
42+ */
43+protected releaseCallback: Function;
44+45+// -------------------------------------------------------------------------
46+// Constructor
47+// -------------------------------------------------------------------------
48+49+constructor(driver: AuroraDataApiPostgresDriver, mode: "master"|"slave" = "master") {
50+super(driver, mode);
51+}
52+53+// -------------------------------------------------------------------------
54+// Public Methods
55+// -------------------------------------------------------------------------
56+57+/**
58+ * Creates/uses database connection from the connection pool to perform further operations.
59+ * Returns obtained database connection.
60+ */
61+connect(): Promise<any> {
62+if (this.databaseConnection)
63+return Promise.resolve(this.databaseConnection);
64+65+if (this.databaseConnectionPromise)
66+return this.databaseConnectionPromise;
67+68+if (this.mode === "slave" && this.driver.isReplicated) {
69+this.databaseConnectionPromise = this.driver.obtainSlaveConnection().then(([ connection, release]: any[]) => {
70+this.driver.connectedQueryRunners.push(this);
71+this.databaseConnection = connection;
72+this.releaseCallback = release;
73+return this.databaseConnection;
74+});
75+76+} else { // master
77+this.databaseConnectionPromise = this.driver.obtainMasterConnection().then(([connection, release]: any[]) => {
78+this.driver.connectedQueryRunners.push(this);
79+this.databaseConnection = connection;
80+this.releaseCallback = release;
81+return this.databaseConnection;
82+});
83+}
84+85+return this.databaseConnectionPromise;
86+}
87+88+/**
89+ * Starts transaction on the current connection.
90+ */
91+async startTransaction(isolationLevel?: IsolationLevel): Promise<void> {
92+if (this.isTransactionActive)
93+throw new TransactionAlreadyStartedError();
94+95+this.isTransactionActive = true;
96+await this.driver.client.startTransaction();
97+}
98+99+/**
100+ * Commits transaction.
101+ * Error will be thrown if transaction was not started.
102+ */
103+async commitTransaction(): Promise<void> {
104+if (!this.isTransactionActive)
105+throw new TransactionNotStartedError();
106+107+await this.driver.client.commitTransaction();
108+this.isTransactionActive = false;
109+}
110+111+/**
112+ * Rollbacks transaction.
113+ * Error will be thrown if transaction was not started.
114+ */
115+async rollbackTransaction(): Promise<void> {
116+if (!this.isTransactionActive)
117+throw new TransactionNotStartedError();
118+119+await this.driver.client.rollbackTransaction();
120+this.isTransactionActive = false;
121+}
122+123+/**
124+ * Executes a given SQL query.
125+ */
126+async query(query: string, parameters?: any[]): Promise<any> {
127+if (this.isReleased)
128+throw new QueryRunnerAlreadyReleasedError();
129+130+const result = await this.driver.client.query(query, parameters);
131+132+if (result.records) {
133+return result.records;
134+}
135+136+return result;
137+}
138+}