mirror of
https://github.com/dbgate/dbgate
synced 2024-11-07 20:26:23 +00:00
used transaction for save table data
This commit is contained in:
parent
722789ca01
commit
e9a01a1ffd
@ -171,11 +171,11 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
runScript_meta: true,
|
runScript_meta: true,
|
||||||
async runScript({ conid, database, sql }, req) {
|
async runScript({ conid, database, sql, useTransaction }, req) {
|
||||||
testConnectionPermission(conid, req);
|
testConnectionPermission(conid, req);
|
||||||
logger.info({ conid, database, sql }, 'Processing script');
|
logger.info({ conid, database, sql }, 'Processing script');
|
||||||
const opened = await this.ensureOpened(conid, database);
|
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;
|
return res;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -158,12 +158,12 @@ function resolveAnalysedPromises() {
|
|||||||
afterAnalyseCallbacks = [];
|
afterAnalyseCallbacks = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleRunScript({ msgid, sql }, skipReadonlyCheck = false) {
|
async function handleRunScript({ msgid, sql, useTransaction }, skipReadonlyCheck = false) {
|
||||||
await waitConnected();
|
await waitConnected();
|
||||||
const driver = requireEngineDriver(storedConnection);
|
const driver = requireEngineDriver(storedConnection);
|
||||||
try {
|
try {
|
||||||
if (!skipReadonlyCheck) ensureExecuteCustomScript(driver);
|
if (!skipReadonlyCheck) ensureExecuteCustomScript(driver);
|
||||||
await driver.script(systemConnection, sql);
|
await driver.script(systemConnection, sql, { useTransaction });
|
||||||
process.send({ msgtype: 'response', msgid });
|
process.send({ msgtype: 'response', msgid });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
process.send({ msgtype: 'response', msgid, errorMessage: err.message });
|
process.send({ msgtype: 'response', msgid, errorMessage: err.message });
|
||||||
|
@ -533,6 +533,10 @@ export class SqlDumper implements AlterProcessor {
|
|||||||
this.putCmd('^commit');
|
this.putCmd('^commit');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rollbackTransaction() {
|
||||||
|
this.putCmd('^rollback');
|
||||||
|
}
|
||||||
|
|
||||||
alterProlog() {}
|
alterProlog() {}
|
||||||
alterEpilog() {}
|
alterEpilog() {}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import _compact from 'lodash/compact';
|
|||||||
import { SqlDumper } from './SqlDumper';
|
import { SqlDumper } from './SqlDumper';
|
||||||
import { splitQuery } from 'dbgate-query-splitter';
|
import { splitQuery } from 'dbgate-query-splitter';
|
||||||
import { dumpSqlSelect } from 'dbgate-sqltree';
|
import { dumpSqlSelect } from 'dbgate-sqltree';
|
||||||
|
import { EngineDriver, RunScriptOptions } from 'dbgate-types';
|
||||||
|
|
||||||
const dialect = {
|
const dialect = {
|
||||||
limitSelect: true,
|
limitSelect: true,
|
||||||
@ -19,6 +20,12 @@ const dialect = {
|
|||||||
defaultSchemaName: null,
|
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 = {
|
export const driverBase = {
|
||||||
analyserClass: null,
|
analyserClass: null,
|
||||||
dumperClass: SqlDumper,
|
dumperClass: SqlDumper,
|
||||||
@ -41,12 +48,25 @@ export const driverBase = {
|
|||||||
const analyser = new this.analyserClass(pool, this, version);
|
const analyser = new this.analyserClass(pool, this, version);
|
||||||
return analyser.incrementalAnalysis(structure);
|
return analyser.incrementalAnalysis(structure);
|
||||||
},
|
},
|
||||||
createDumper(options = null) {
|
createDumper(options = null): SqlDumper {
|
||||||
return new this.dumperClass(this, options);
|
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'))) {
|
for (const sqlItem of splitQuery(sql, this.getQuerySplitterOptions('script'))) {
|
||||||
|
try {
|
||||||
await this.query(pool, sqlItem, { discardResult: true });
|
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() {
|
getNewObjectTemplates() {
|
||||||
@ -113,5 +133,5 @@ export const driverBase = {
|
|||||||
return this.readQuery(pool, dmp.s, structure);
|
return this.readQuery(pool, dmp.s, structure);
|
||||||
},
|
},
|
||||||
showConnectionField: (field, values) => false,
|
showConnectionField: (field, values) => false,
|
||||||
showConnectionTab: (field) => true,
|
showConnectionTab: field => true,
|
||||||
};
|
};
|
||||||
|
6
packages/types/engines.d.ts
vendored
6
packages/types/engines.d.ts
vendored
@ -12,6 +12,10 @@ export interface StreamOptions {
|
|||||||
info?: (info) => void;
|
info?: (info) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RunScriptOptions {
|
||||||
|
useTransaction: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface QueryOptions {
|
export interface QueryOptions {
|
||||||
discardResult?: boolean;
|
discardResult?: boolean;
|
||||||
}
|
}
|
||||||
@ -130,7 +134,7 @@ export interface EngineDriver {
|
|||||||
createDatabase(pool: any, name: string): Promise;
|
createDatabase(pool: any, name: string): Promise;
|
||||||
dropDatabase(pool: any, name: string): Promise;
|
dropDatabase(pool: any, name: string): Promise;
|
||||||
getQuerySplitterOptions(usage: 'stream' | 'script' | 'editor'): any;
|
getQuerySplitterOptions(usage: 'stream' | 'script' | 'editor'): any;
|
||||||
script(pool: any, sql: string): Promise;
|
script(pool: any, sql: string, options?: RunScriptOptions): Promise;
|
||||||
getNewObjectTemplates(): NewObjectTemplate[];
|
getNewObjectTemplates(): NewObjectTemplate[];
|
||||||
// direct call of pool method, only some methods could be supported, on only some drivers
|
// direct call of pool method, only some methods could be supported, on only some drivers
|
||||||
callMethod(pool, method, args);
|
callMethod(pool, method, args);
|
||||||
|
@ -121,7 +121,7 @@
|
|||||||
const [changeSetStore, dispatchChangeSet] = createUndoReducer(createChangeSet());
|
const [changeSetStore, dispatchChangeSet] = createUndoReducer(createChangeSet());
|
||||||
|
|
||||||
async function handleConfirmSql(sql) {
|
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 || {};
|
const { errorMessage } = resp || {};
|
||||||
if (errorMessage) {
|
if (errorMessage) {
|
||||||
showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage });
|
showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage });
|
||||||
|
Loading…
Reference in New Issue
Block a user