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.
534 lines (533 loc) • 22.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MockQueryRunner = void 0;
class MockQueryRunner {
constructor(queryExecutor, databaseOrConfig = 'noopDB') {
this.count = 0;
this.queryExecutor = queryExecutor;
if (typeof databaseOrConfig === 'string') {
databaseOrConfig = { database: databaseOrConfig };
}
this.database = databaseOrConfig.database || 'noopDB';
this.promise = databaseOrConfig.promise || Promise;
}
useDatabase(database) {
// @ts-ignore
this.database = database;
}
getNativeRunner() {
return null;
}
getCurrentNativeTransaction() {
return undefined;
}
execute(fn) {
return fn(null);
}
executeSelectOneRow(query, params = []) {
try {
const index = this.count++;
const result = this.queryExecutor('selectOneRow', query, params, index);
if (!isPlainObjectOrNoValue(result)) {
throw new Error('Invalid test case result for a selectOneRow with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or a plain object');
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeSelectManyRows(query, params = []) {
try {
const index = this.count++;
let result = this.queryExecutor('selectManyRows', query, params, index);
if (result === undefined || result === null) {
result = [];
}
if (!Array.isArray(result)) {
throw new Error('Invalid test case result for a selectManyRows with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or an Array of plain object');
}
for (let i = 0; i < result.length; i++) {
if (!isPlainObject(result[i])) {
throw new Error('Invalid test case result for a selectManyRows with index ' + index + '. The returned array by the mock function provided to the MockQueryRunner contains a no plain object at position ' + i);
}
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeSelectOneColumnOneRow(query, params = []) {
// undefined result means no value returned by the database
try {
return this.promise.resolve(this.queryExecutor('selectOneColumnOneRow', query, params, this.count++));
}
catch (e) {
return this.promise.reject(e);
}
}
executeSelectOneColumnManyRows(query, params = []) {
try {
const index = this.count++;
let result = this.queryExecutor('selectOneColumnManyRows', query, params, index);
if (result === undefined || result === null) {
result = [];
}
if (!Array.isArray(result)) {
throw new Error('Invalid test case result for a selectOneColumnManyRows with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or an Array');
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeInsert(query, params = []) {
try {
const index = this.count++;
let result = this.queryExecutor('insert', query, params, index);
if (result === undefined || result === null) {
result = 1;
}
if (typeof result !== 'number') {
throw new Error('Invalid test case result for an insert with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or a number');
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeInsertReturningLastInsertedId(query, params = []) {
try {
return this.promise.resolve(this.queryExecutor('insertReturningLastInsertedId', query, params, this.count++));
}
catch (e) {
return this.promise.reject(e);
}
}
executeInsertReturningMultipleLastInsertedId(query, params = []) {
try {
const index = this.count++;
let result = this.queryExecutor('insertReturningMultipleLastInsertedId', query, params, index);
if (result === undefined || result === null) {
result = [];
}
if (!Array.isArray(result)) {
throw new Error('Invalid test case result for an insertReturningMultipleLastInsertedId with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or an Array');
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeInsertReturningOneRow(query, params = []) {
try {
const index = this.count++;
const result = this.queryExecutor('insertReturningOneRow', query, params, index);
if (!isPlainObjectOrNoValue(result)) {
throw new Error('Invalid test case result for a insertReturningOneRow with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or a plain object');
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeInsertReturningManyRows(query, params = []) {
try {
const index = this.count++;
let result = this.queryExecutor('insertReturningManyRows', query, params, index);
if (result === undefined || result === null) {
result = [];
}
if (!Array.isArray(result)) {
throw new Error('Invalid test case result for a insertReturningManyRows with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or an Array of plain object');
}
for (let i = 0; i < result.length; i++) {
if (!isPlainObject(result[i])) {
throw new Error('Invalid test case result for a insertReturningManyRows with index ' + index + '. The returned array by the mock function provided to the MockQueryRunner contains a no plain object at position ' + i);
}
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeInsertReturningOneColumnOneRow(query, params = []) {
// undefined result means no value returned by the database
try {
return this.promise.resolve(this.queryExecutor('insertReturningOneColumnOneRow', query, params, this.count++));
}
catch (e) {
return this.promise.reject(e);
}
}
executeInsertReturningOneColumnManyRows(query, params = []) {
try {
const index = this.count++;
let result = this.queryExecutor('insertReturningOneColumnManyRows', query, params, index);
if (result === undefined || result === null) {
result = [];
}
if (!Array.isArray(result)) {
throw new Error('Invalid test case result for a insertReturningOneColumnManyRows with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or an Array');
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeUpdate(query, params = []) {
try {
const index = this.count++;
let result = this.queryExecutor('update', query, params, index);
if (result === undefined || result === null) {
result = 0;
}
if (typeof result !== 'number') {
throw new Error('Invalid test case result for an update with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or a number');
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeUpdateReturningOneRow(query, params = []) {
try {
const index = this.count++;
const result = this.queryExecutor('updateReturningOneRow', query, params, index);
if (!isPlainObjectOrNoValue(result)) {
throw new Error('Invalid test case result for a updateReturningOneRow with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or a plain object');
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeUpdateReturningManyRows(query, params = []) {
try {
const index = this.count++;
let result = this.queryExecutor('updateReturningManyRows', query, params, index);
if (result === undefined || result === null) {
result = [];
}
if (!Array.isArray(result)) {
throw new Error('Invalid test case result for a updateReturningManyRows with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or an Array of plain object');
}
for (let i = 0; i < result.length; i++) {
if (!isPlainObject(result[i])) {
throw new Error('Invalid test case result for a updateReturningManyRows with index ' + index + '. The returned array by the mock function provided to the MockQueryRunner contains a no plain object at position ' + i);
}
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeUpdateReturningOneColumnOneRow(query, params = []) {
// undefined result means no value returned by the database
try {
return this.promise.resolve(this.queryExecutor('updateReturningOneColumnOneRow', query, params, this.count++));
}
catch (e) {
return this.promise.reject(e);
}
}
executeUpdateReturningOneColumnManyRows(query, params = []) {
try {
const index = this.count++;
let result = this.queryExecutor('updateReturningOneColumnManyRows', query, params, index);
if (result === undefined || result === null) {
result = [];
}
if (!Array.isArray(result)) {
throw new Error('Invalid test case result for a updateReturningOneColumnManyRows with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or an Array');
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeDelete(query, params = []) {
try {
const index = this.count++;
let result = this.queryExecutor('delete', query, params, index);
if (result === undefined || result === null) {
result = 0;
}
if (typeof result !== 'number') {
throw new Error('Invalid test case result for a delete with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or a number');
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeDeleteReturningOneRow(query, params = []) {
try {
const index = this.count++;
const result = this.queryExecutor('deleteReturningOneRow', query, params, index);
if (!isPlainObjectOrNoValue(result)) {
throw new Error('Invalid test case result for a deleteReturningOneRow with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or a plain object');
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeDeleteReturningManyRows(query, params = []) {
try {
const index = this.count++;
let result = this.queryExecutor('deleteReturningManyRows', query, params, index);
if (result === undefined || result === null) {
result = [];
}
if (!Array.isArray(result)) {
throw new Error('Invalid test case result for a deleteReturningManyRows with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or an Array of plain object');
}
for (let i = 0; i < result.length; i++) {
if (!isPlainObject(result[i])) {
throw new Error('Invalid test case result for a deleteReturningManyRows with index ' + index + '. The returned array by the mock function provided to the MockQueryRunner contains a no plain object at position ' + i);
}
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeDeleteReturningOneColumnOneRow(query, params = []) {
// undefined result means no value returned by the database
try {
return this.promise.resolve(this.queryExecutor('deleteReturningOneColumnOneRow', query, params, this.count++));
}
catch (e) {
return this.promise.reject(e);
}
}
executeDeleteReturningOneColumnManyRows(query, params = []) {
try {
const index = this.count++;
let result = this.queryExecutor('deleteReturningOneColumnManyRows', query, params, index);
if (result === undefined || result === null) {
result = [];
}
if (!Array.isArray(result)) {
throw new Error('Invalid test case result for a deleteReturningOneColumnManyRows with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined or an Array');
}
return this.promise.resolve(result);
}
catch (e) {
return this.promise.reject(e);
}
}
executeProcedure(query, params = []) {
try {
const index = this.count++;
const result = this.queryExecutor('executeProcedure', query, params, index);
if (result !== undefined && result !== null) {
throw new Error('Invalid test case result for an executeProcedure with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null or undefined');
}
return this.promise.resolve(undefined);
}
catch (e) {
return this.promise.reject(e);
}
}
executeFunction(query, params = []) {
try {
return this.promise.resolve(this.queryExecutor('executeFunction', query, params, this.count++));
}
catch (e) {
return this.promise.reject(e);
}
}
executeBeginTransaction() {
try {
const index = this.count++;
const result = this.queryExecutor('beginTransaction', 'begin transaction', [], index);
if (result !== undefined && result !== null) {
throw new Error('Invalid test case result for a beginTransaction with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null or undefined');
}
return this.promise.resolve(undefined);
}
catch (e) {
return this.promise.reject(e);
}
}
executeCommit() {
try {
const index = this.count++;
const result = this.queryExecutor('commit', 'commit', [], index);
if (result !== undefined && result !== null) {
throw new Error('Invalid test case result for a commit with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null or undefined');
}
return this.promise.resolve(undefined);
}
catch (e) {
return this.promise.reject(e);
}
}
executeRollback() {
try {
const index = this.count++;
const result = this.queryExecutor('rollback', 'rollback', [], index);
if (result !== undefined && result !== null) {
throw new Error('Invalid test case result for a commit with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null or undefined');
}
return this.promise.resolve(undefined);
}
catch (e) {
return this.promise.reject(e);
}
}
isTransactionActive() {
const index = this.count++;
let result = this.queryExecutor('isTransactionActive', '', [], index);
if (result !== undefined && result !== null) {
result = false;
}
if (typeof result !== 'boolean') {
throw new Error('Invalid test case result for an isTransactionActive with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null, undefined, or a boolean');
}
return result;
}
executeDatabaseSchemaModification(query, params = []) {
try {
const index = this.count++;
const result = this.queryExecutor('executeDatabaseSchemaModification', query, params, index);
if (result !== undefined && result !== null) {
throw new Error('Invalid test case result for a executeDatabaseSchemaModification with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null or undefined');
}
return this.promise.resolve(undefined);
}
catch (e) {
return this.promise.reject(e);
}
}
executeConnectionConfiguration(query, params = []) {
try {
const index = this.count++;
const result = this.queryExecutor('executeConnectionConfiguration', query, params, index);
if (result !== undefined && result !== null) {
throw new Error('Invalid test case result for a executeConnectionConfiguration with index ' + index + '. Your mock function provided to the MockQueryRunner must returns null or undefined');
}
return this.promise.resolve(undefined);
}
catch (e) {
return this.promise.reject(e);
}
}
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 = '@' + index;
break;
default:
throw new Error('Unknown database ' + this.database);
}
params.push(value);
return result;
}
addOutParam(params, name) {
if (this.database !== 'oracle') {
throw new Error('Unsupported output parameters');
}
const index = params.length;
if (name) {
params.push({ dir: 3003 /*oracledb.BIND_OUT*/, as: name }); // See https://github.com/oracle/node-oracledb/blob/master/lib/oracledb.js
}
else {
params.push({ dir: 3003 /*oracledb.BIND_OUT*/ }); // See https://github.com/oracle/node-oracledb/blob/master/lib/oracledb.js
}
return ':' + index;
}
executeInTransaction(fn, outermostQueryRunner) {
return outermostQueryRunner.executeBeginTransaction().then(() => {
let result = fn();
if (Array.isArray(result)) {
result = this.createAllPromise(result);
}
return result.then((r) => {
return outermostQueryRunner.executeCommit().then(() => {
return r;
});
}, (e) => {
return outermostQueryRunner.executeRollback().then(() => {
throw e;
}, () => {
// Throw the innermost error
throw e;
});
});
});
}
executeCombined(fn1, fn2) {
return fn1().then((r1) => {
return fn2().then((r2) => {
return [r1, r2];
});
});
}
createResolvedPromise(result) {
return this.promise.resolve(result);
}
createAllPromise(promises) {
return this.promise.all(promises);
}
isMocked() {
return true;
}
lowLevelTransactionManagementSupported() {
return true;
}
}
exports.MockQueryRunner = MockQueryRunner;
function isPlainObject(value) {
if (!value && typeof value !== 'object') {
return false;
}
const prototype = Object.getPrototypeOf(value);
return prototype === null || prototype === Object.prototype;
}
function isPlainObjectOrNoValue(value) {
if (value === null || value === undefined) {
return true;
}
if (typeof value !== 'object') {
return false;
}
const prototype = Object.getPrototypeOf(value);
return prototype === null || prototype === Object.prototype;
}