used transaction for save table data

This commit is contained in:
Jan Prochazka 2023-02-05 19:17:46 +01:00
parent 722789ca01
commit e9a01a1ffd
6 changed files with 38 additions and 10 deletions

View File

@ -171,11 +171,11 @@ module.exports = {
},
runScript_meta: true,
async runScript({ conid, database, sql }, req) {
async runScript({ conid, database, sql, useTransaction }, req) {
testConnectionPermission(conid, req);
logger.info({ conid, database, sql }, 'Processing script');
const opened = await this.ensureOpened(conid, database);
const res = await this.sendRequest(opened, { msgtype: 'runScript', sql });
const res = await this.sendRequest(opened, { msgtype: 'runScript', sql, useTransaction });
return res;
},

View File

@ -158,12 +158,12 @@ function resolveAnalysedPromises() {
afterAnalyseCallbacks = [];
}
async function handleRunScript({ msgid, sql }, skipReadonlyCheck = false) {
async function handleRunScript({ msgid, sql, useTransaction }, skipReadonlyCheck = false) {
await waitConnected();
const driver = requireEngineDriver(storedConnection);
try {
if (!skipReadonlyCheck) ensureExecuteCustomScript(driver);
await driver.script(systemConnection, sql);
await driver.script(systemConnection, sql, { useTransaction });
process.send({ msgtype: 'response', msgid });
} catch (err) {
process.send({ msgtype: 'response', msgid, errorMessage: err.message });

View File

@ -533,6 +533,10 @@ export class SqlDumper implements AlterProcessor {
this.putCmd('^commit');
}
rollbackTransaction() {
this.putCmd('^rollback');
}
alterProlog() {}
alterEpilog() {}

View File

@ -2,6 +2,7 @@ import _compact from 'lodash/compact';
import { SqlDumper } from './SqlDumper';
import { splitQuery } from 'dbgate-query-splitter';
import { dumpSqlSelect } from 'dbgate-sqltree';
import { EngineDriver, RunScriptOptions } from 'dbgate-types';
const dialect = {
limitSelect: true,
@ -19,6 +20,12 @@ const dialect = {
defaultSchemaName: null,
};
export async function runCommandOnDriver(pool, driver: EngineDriver, cmd: (dmp: SqlDumper) => void) {
const dmp = driver.createDumper();
cmd(dmp as any);
await driver.query(pool, dmp.s, { discardResult: true });
}
export const driverBase = {
analyserClass: null,
dumperClass: SqlDumper,
@ -41,12 +48,25 @@ export const driverBase = {
const analyser = new this.analyserClass(pool, this, version);
return analyser.incrementalAnalysis(structure);
},
createDumper(options = null) {
createDumper(options = null): SqlDumper {
return new this.dumperClass(this, options);
},
async script(pool, sql) {
async script(pool, sql, options: RunScriptOptions) {
if (options?.useTransaction) {
runCommandOnDriver(pool, this, dmp => dmp.beginTransaction());
}
for (const sqlItem of splitQuery(sql, this.getQuerySplitterOptions('script'))) {
await this.query(pool, sqlItem, { discardResult: true });
try {
await this.query(pool, sqlItem, { discardResult: true });
} catch (err) {
if (options?.useTransaction) {
runCommandOnDriver(pool, this, dmp => dmp.rollbackTransaction());
}
throw err;
}
}
if (options?.useTransaction) {
runCommandOnDriver(pool, this, dmp => dmp.commitTransaction());
}
},
getNewObjectTemplates() {
@ -113,5 +133,5 @@ export const driverBase = {
return this.readQuery(pool, dmp.s, structure);
},
showConnectionField: (field, values) => false,
showConnectionTab: (field) => true,
showConnectionTab: field => true,
};

View File

@ -12,6 +12,10 @@ export interface StreamOptions {
info?: (info) => void;
}
export interface RunScriptOptions {
useTransaction: boolean;
}
export interface QueryOptions {
discardResult?: boolean;
}
@ -130,7 +134,7 @@ export interface EngineDriver {
createDatabase(pool: any, name: string): Promise;
dropDatabase(pool: any, name: string): Promise;
getQuerySplitterOptions(usage: 'stream' | 'script' | 'editor'): any;
script(pool: any, sql: string): Promise;
script(pool: any, sql: string, options?: RunScriptOptions): Promise;
getNewObjectTemplates(): NewObjectTemplate[];
// direct call of pool method, only some methods could be supported, on only some drivers
callMethod(pool, method, args);

View File

@ -121,7 +121,7 @@
const [changeSetStore, dispatchChangeSet] = createUndoReducer(createChangeSet());
async function handleConfirmSql(sql) {
const resp = await apiCall('database-connections/run-script', { conid, database, sql });
const resp = await apiCall('database-connections/run-script', { conid, database, sql, useTransaction: true });
const { errorMessage } = resp || {};
if (errorMessage) {
showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage });