UNPKG

ts-sql-query

Version:

Type-safe SQL query builder like QueryDSL or JOOQ in Java or Linq in .Net for TypeScript with MariaDB, MySql, Oracle, PostgreSql, Sqlite and SqlServer support.

451 lines (450 loc) 16 kB
"use strict"; var _a, _b, _c; Object.defineProperty(exports, "__esModule", { value: true }); exports.PrismaQueryRunner = void 0; const AbstractQueryRunner_1 = require("./AbstractQueryRunner"); function isPrisma3(connection) { return connection.$executeRawUnsafe; } class PrismaQueryRunner extends AbstractQueryRunner_1.AbstractQueryRunner { constructor(connection, config = { interactiveTransactions: false }) { super(); this.transactionLevel = 0; this.config = config; this.connection = connection; switch (connection._activeProvider) { case 'postgresql': this.database = 'postgreSql'; break; case 'mysql': this.database = 'mySql'; break; case 'sqlite': this.database = 'sqlite'; break; case 'sqlserver': this.database = 'sqlServer'; break; default: throw new Error('Unknown Prisma provider of name ' + connection._activeProvider); } try { if (connection.$transaction) { this.transaction = undefined; } } catch { // This is running in an interactiveTransaction this.transaction = connection; this.transactionLevel = 1; } if (config.forUseInTransaction) { this.transactionLevel = 1; } } useDatabase(database) { if (database !== this.database) { if (this.database === 'mySql' && database === 'mariaDB') { // @ts-ignore this.database = database; } else if (this.database === 'mariaDB' && database === 'mySql') { // @ts-ignore this.database = database; } else if (this.database === 'mySql' || this.database === 'mariaDB') { throw new Error('Unsupported database: ' + database + '. The current connection used in PrismaQueryRunner only supports mySql or mariaDB databases'); } else { throw new Error('Unsupported database: ' + database + '. The current connection used in PrismaQueryRunner only supports ' + this.database + ' databases'); } } } getNativeRunner() { return this.connection; } getCurrentNativeTransaction() { return this.transaction; } execute(fn) { return fn(this.connection, this.transaction); } executeQueryReturning(query, params) { const connection = this.transaction || this.connection; let result; if (isPrisma3(connection)) { result = connection.$queryRawUnsafe(query, ...params); } else { result = connection.$queryRaw(query, ...params); } return this.wrapPrismaPromise(result); } executeMutation(query, params) { const connection = this.transaction || this.connection; let result; if (isPrisma3(connection)) { result = connection.$executeRawUnsafe(query, ...params); } else { result = connection.$executeRaw(query, ...params); } return this.wrapPrismaPromise(result); } executeInsertReturningLastInsertedId(query, params = []) { if (this.database === 'mySql' || this.database === 'mariaDB') { if (this.containsInsertReturningClause(query, params)) { return super.executeInsertReturningLastInsertedId(query, params); } return this.executeCombined(() => this.executeInsert(query, params), () => this.executeSelectOneColumnOneRow('select last_insert_id()', [])).then(([_count, id]) => id); } if (this.database === 'sqlite') { if (this.containsInsertReturningClause(query, params)) { return super.executeInsertReturningLastInsertedId(query, params); } return this.executeCombined(() => this.executeInsert(query, params), () => this.executeSelectOneColumnOneRow('select last_insert_rowid()', [])).then(([_count, id]) => id); } return super.executeInsertReturningLastInsertedId(query, params); } executeBeginTransaction() { if (isPrisma3(this.connection)) { return Promise.reject(new Error('Low level transaction management is not supported by Prisma.')); } return Promise.reject(new Error('Long running transactions are not supported by Prisma. See https://github.com/prisma/prisma/issues/1844')); } executeCommit() { if (isPrisma3(this.connection)) { return Promise.reject(new Error('Low level transaction management is not supported by Prisma.')); } return Promise.reject(new Error('Long running transactions are not supported by Prisma. See https://github.com/prisma/prisma/issues/1844')); } executeRollback() { if (isPrisma3(this.connection)) { return Promise.reject(new Error('Low level transaction management is not supported by Prisma.')); } return Promise.reject(new Error('Long running transactions are not supported by Prisma. See https://github.com/prisma/prisma/issues/1844')); } isTransactionActive() { return this.transactionLevel > 0; } executeInTransaction(fn, _outermostQueryRunner) { if (this.config.interactiveTransactions) { if (this.transaction) { throw new Error('Nested interactive transaction is not supported by Prisma'); } return this.connection.$transaction((interactiveTransactions) => { // @ts-ignore this.transaction = interactiveTransactions; this.transactionLevel++; const promises = fn(); let result; if (Array.isArray(promises)) { result = Promise.all(promises); } else { result = promises; } return result.finally(() => { this.transactionLevel--; // @ts-ignore this.transaction = undefined; }); }, this.config.interactiveTransactionsOptions); } this.transactionLevel++; try { let promises = fn(); const unwrap = !Array.isArray(promises); if (!Array.isArray(promises)) { promises = [promises]; } let result = this.connection.$transaction(promises); if (unwrap) { result = result.then(([value]) => { return value; }); } return result; } finally { this.transactionLevel--; } } addParam(params, value) { const index = params.length; let result; switch (this.database) { case 'mariaDB': result = '?'; break; case 'mySql': result = '?'; break; case 'noopDB': result = '$' + index; break; case 'oracle': result = ':' + index; break; case 'postgreSql': result = '$' + (index + 1); break; case 'sqlite': result = '?'; break; case 'sqlServer': result = '@P' + (index + 1); break; default: throw new Error('Unknown database ' + this.database); } params.push(value); return result; } createResolvedPromise(result) { if (this.transaction) { Promise.resolve(result); } if (this.transactionLevel <= 0) { return Promise.resolve(result); } else { return new ResolvedPrismaPromise(result); } } executeCombined(fn1, fn2) { if (this.transaction) { return fn1().then((r1) => { return fn2().then((r2) => { return [r1, r2]; }); }); } if (this.transactionLevel <= 0) { this.transactionLevel++; let p1, p2; try { p1 = fn1(); p2 = fn2(); } finally { this.transactionLevel--; } return this.connection.$transaction([ p1, p2 ]); } return new CombinedPrismaPromise(fn1(), fn2()); } lowLevelTransactionManagementSupported() { return false; } wrapPrismaPromise(promise) { if (this.transaction) { // Use a real Promise instead of Prisma proxy to avoid issues due then with one param is not properly managed return new Promise((resolve, reject) => { promise.then(resolve, reject); }); } if (this.transactionLevel <= 0) { return promise; } else { return new PrismaPromise(promise); } } } exports.PrismaQueryRunner = PrismaQueryRunner; class PrismaPromise { constructor(next) { this[_a] = "PrismaPromise"; this.next = next; } then(onfulfilled, onrejected, transactionId) { // Note: Prisma 4 doesn't require transactionId, it can be removed if (transactionId !== undefined) { if (this.onfinally) { return this.next.then((r) => { this.onfinally(); return r; }, (e) => { this.onfinally(); throw e; }, transactionId).then(onfulfilled, onrejected); } else { return this.next.then(this.onfulfilled || ((r) => { return r; }), this.onrejected || ((e) => { throw e; }), transactionId).then(onfulfilled, onrejected); } } this.onfulfilled = onfulfilled; this.onrejected = onrejected; return new PrismaPromise(this); } catch(onrejected) { this.onrejected = onrejected; return new PrismaPromise(this); } finally(onfinally) { this.onfinally = onfinally; return new PrismaPromise(this); } requestTransaction(transactionId, lock) { return this.next.requestTransaction(transactionId, lock).then((result) => { if (typeof result === 'function') { return () => { if (this.onfinally) { return result().finally(this.onfinally); } else { return result().then(this.onfulfilled, this.onrejected); } }; } else { // Prisma 4 if (this.onfinally) { return Promise.resolve(result).finally(this.onfinally); } else { return Promise.resolve(result).then(this.onfulfilled, this.onrejected); } } }); } } _a = Symbol.toStringTag; class ResolvedPrismaPromise { constructor(value) { this[_b] = "PrismaPromise"; this.value = value; } then(onfulfilled, onrejected, transactionId) { // Note: Prisma 4 doesn't require transactionId, it can be removed if (transactionId !== undefined) { if (this.onfinally) { return Promise.resolve(this.value).finally(this.onfinally).then(onfulfilled, onrejected); } else { return Promise.resolve(this.value).then(this.onfulfilled, this.onrejected).then(onfulfilled, onrejected); } } this.onfulfilled = onfulfilled; this.onrejected = onrejected; return new PrismaPromise(this); } catch(onrejected) { this.onrejected = onrejected; return new PrismaPromise(this); } finally(onfinally) { this.onfinally = onfinally; return new PrismaPromise(this); } requestTransaction(_transactionId, _lock) { return Promise.resolve(() => { if (this.onfinally) { return Promise.resolve(this.value).finally(this.onfinally); } else { return Promise.resolve(this.value).then(this.onfulfilled, this.onrejected); } }); } } _b = Symbol.toStringTag; class CombinedPrismaPromise { constructor(next1, next2) { this[_c] = "PrismaPromise"; this.next1 = next1; this.next2 = next2; } then(onfulfilled, onrejected, transactionId) { // Note: Prisma 4 doesn't require transactionId, it can be removed if (transactionId !== undefined) { if (this.onfinally) { return Promise.all([ this.next1.then((r) => { return r; }, (e) => { throw e; }, transactionId), this.next2.then((r) => { return r; }, (e) => { throw e; }, transactionId) ]).finally(this.onfinally).then(onfulfilled, onrejected); } else { return Promise.all([ this.next1.then((r) => { return r; }, (e) => { throw e; }, transactionId), this.next2.then((r) => { return r; }, (e) => { throw e; }, transactionId) ]).then(this.onfulfilled, this.onrejected).then(onfulfilled, onrejected); } } this.onfulfilled = onfulfilled; this.onrejected = onrejected; return new PrismaPromise(this); } catch(onrejected) { this.onrejected = onrejected; return new PrismaPromise(this); } finally(onfinally) { this.onfinally = onfinally; return new PrismaPromise(this); } requestTransaction(transactionId, lock) { const rt1 = this.next1.requestTransaction(transactionId, lock); const rt2 = this.next2.requestTransaction(transactionId, lock); return Promise.all([rt1, rt2]).then(([pfn1, pfn2]) => { if (typeof pfn1 === 'function') { const fn1 = pfn1; const fn2 = pfn2; return (() => { if (this.onfinally) { return Promise.all([ fn1(), fn2() ]).finally(this.onfinally); } else { return Promise.all([ fn1(), fn2() ]).then(this.onfulfilled, this.onrejected); } }); } else { // Prisma 4 if (this.onfinally) { return Promise.all([ pfn1, pfn2 ]).finally(this.onfinally); } else { return Promise.all([ pfn1, pfn2 ]).then(this.onfulfilled, this.onrejected); } } }); } } _c = Symbol.toStringTag;