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
JavaScript
"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;