Skip to content

Commit

Permalink
feat(MySQL): manual commit mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Fabio286 committed Feb 15, 2022
1 parent c5eb73e commit 4ed2f9a
Show file tree
Hide file tree
Showing 8 changed files with 266 additions and 62 deletions.
39 changes: 38 additions & 1 deletion src/main/ipc-handlers/schema.js
Expand Up @@ -135,7 +135,7 @@ export default connections => {
}
});

ipcMain.handle('raw-query', async (event, { uid, query, schema, tabUid }) => {
ipcMain.handle('raw-query', async (event, { uid, query, schema, tabUid, autocommit }) => {
if (!query) return;

try {
Expand All @@ -144,6 +144,7 @@ export default connections => {
details: true,
schema,
tabUid,
autocommit,
comments: false
});

Expand All @@ -165,4 +166,40 @@ export default connections => {
return { status: 'error', response: err.toString() };
}
});

ipcMain.handle('commit-tab', async (event, { uid, tabUid }) => {
if (!tabUid) return;

try {
await connections[uid].commitTab(tabUid);
return { status: 'success' };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});

ipcMain.handle('rollback-tab', async (event, { uid, tabUid }) => {
if (!tabUid) return;

try {
await connections[uid].rollbackTab(tabUid);
return { status: 'success' };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});

ipcMain.handle('destroy-connection-to-commit', async (event, { uid, tabUid }) => {
if (!tabUid) return;

try {
await connections[uid].destroyConnectionToCommit(tabUid);
return { status: 'success' };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
};
161 changes: 113 additions & 48 deletions src/main/libs/clients/MySQLClient.js
Expand Up @@ -10,6 +10,7 @@ export class MySQLClient extends AntaresCore {

this._schema = null;
this._runningConnections = new Map();
this._connectionsToCommit = new Map();

this.types = {
0: 'DECIMAL',
Expand Down Expand Up @@ -101,9 +102,10 @@ export class MySQLClient extends AntaresCore {
}

/**
* @memberof MySQLClient
*
* @returns dbConfig
*/
async connect () {
async getDbConfig () {
delete this._params.application_name;

const dbConfig = {
Expand Down Expand Up @@ -134,48 +136,17 @@ export class MySQLClient extends AntaresCore {
}
}

if (!this._poolSize) {
this._connection = await mysql.createConnection(dbConfig);

// ANSI_QUOTES check
const res = await this.getVariable('sql_mode', 'global');
const sqlMode = res?.value.split(',');
const hasAnsiQuotes = sqlMode.includes('ANSI_QUOTES');

if (this._params.readonly)
await this.raw('SET SESSION TRANSACTION READ ONLY');

if (hasAnsiQuotes)
await this.raw(`SET SESSION sql_mode = "${sqlMode.filter(m => m !== 'ANSI_QUOTES').join(',')}"`);
}
else {
this._connection = mysql.createPool({
...dbConfig,
connectionLimit: this._poolSize,
typeCast: (field, next) => {
if (field.type === 'DATETIME')
return field.string();
else
return next();
}
});

// ANSI_QUOTES check
const res = await this.getVariable('sql_mode', 'global');
const sqlMode = res?.value.split(',');
const hasAnsiQuotes = sqlMode.includes('ANSI_QUOTES');

if (hasAnsiQuotes)
await this._connection.query(`SET SESSION sql_mode = "${sqlMode.filter(m => m !== 'ANSI_QUOTES').join(',')}"`);

this._connection.on('connection', connection => {
if (this._params.readonly)
connection.query('SET SESSION TRANSACTION READ ONLY');
return dbConfig;
}

if (hasAnsiQuotes)
connection.query(`SET SESSION sql_mode = "${sqlMode.filter(m => m !== 'ANSI_QUOTES').join(',')}"`);
});
}
/**
* @memberof MySQLClient
*/
async connect () {
if (!this._poolSize)
this._connection = await this.getConnection();
else
this._connection = await this.getConnectionPool();
}

/**
Expand All @@ -186,6 +157,56 @@ export class MySQLClient extends AntaresCore {
if (this._ssh) this._ssh.close();
}

async getConnection () {
const dbConfig = await this.getDbConfig();
const connection = await mysql.createConnection(dbConfig);

// ANSI_QUOTES check
const [res] = await connection.query('SHOW GLOBAL VARIABLES LIKE \'%sql_mode%\'');
const sqlMode = res[0]?.Variable_name?.split(',');
const hasAnsiQuotes = sqlMode.includes('ANSI_QUOTES');

if (this._params.readonly)
await connection.query('SET SESSION TRANSACTION READ ONLY');

if (hasAnsiQuotes)
await connection.query(`SET SESSION sql_mode = "${sqlMode.filter(m => m !== 'ANSI_QUOTES').join(',')}"`);

return connection;
}

async getConnectionPool () {
const dbConfig = await this.getDbConfig();
const connection = mysql.createPool({
...dbConfig,
connectionLimit: this._poolSize,
typeCast: (field, next) => {
if (field.type === 'DATETIME')
return field.string();
else
return next();
}
});

// ANSI_QUOTES check
const [res] = await connection.query('SHOW GLOBAL VARIABLES LIKE \'%sql_mode%\'');
const sqlMode = res[0]?.Variable_name?.split(',');
const hasAnsiQuotes = sqlMode.includes('ANSI_QUOTES');

if (hasAnsiQuotes)
await connection.query(`SET SESSION sql_mode = "${sqlMode.filter(m => m !== 'ANSI_QUOTES').join(',')}"`);

connection.on('connection', connection => {
if (this._params.readonly)
connection.query('SET SESSION TRANSACTION READ ONLY');

if (hasAnsiQuotes)
connection.query(`SET SESSION sql_mode = "${sqlMode.filter(m => m !== 'ANSI_QUOTES').join(',')}"`);
});

return connection;
}

/**
* Executes an USE query
*
Expand Down Expand Up @@ -1276,6 +1297,36 @@ export class MySQLClient extends AntaresCore {
return await this.killProcess(id);
}

/**
*
* @param {string} tabUid
* @returns {Promise<null>}
*/
async commitTab (tabUid) {
const connection = this._connectionsToCommit.get(tabUid);
if (connection)
return await connection.query('COMMIT');
}

/**
*
* @param {string} tabUid
* @returns {Promise<null>}
*/
async rollbackTab (tabUid) {
const connection = this._connectionsToCommit.get(tabUid);
if (connection)
return await connection.query('ROLLBACK');
}

destroyConnectionToCommit (tabUid) {
const connection = this._connectionsToCommit.get(tabUid);
if (connection) {
connection.destroy();
this._connectionsToCommit.delete(tabUid);
}
}

/**
* CREATE TABLE
*
Expand Down Expand Up @@ -1580,6 +1631,7 @@ export class MySQLClient extends AntaresCore {
details: false,
split: true,
comments: true,
autocommit: true,
...args
};

Expand All @@ -1594,8 +1646,21 @@ export class MySQLClient extends AntaresCore {
.filter(Boolean)
.map(q => q.trim())
: [sql];

let connection;
const isPool = typeof this._connection.getConnection === 'function';
const connection = isPool ? await this._connection.getConnection() : this._connection;

if (!args.autocommit && args.tabUid) { // autocommit OFF
if (this._connectionsToCommit.has(args.tabUid))
connection = this._connectionsToCommit.get(args.tabUid);
else {
connection = await this.getConnection();
await connection.query('SET SESSION autocommit=0');
this._connectionsToCommit.set(args.tabUid, connection);
}
}
else// autocommit ON
connection = isPool ? await this._connection.getConnection() : this._connection;

if (args.tabUid && isPool)
this._runningConnections.set(args.tabUid, connection.connection.connectionId);
Expand Down Expand Up @@ -1660,7 +1725,7 @@ export class MySQLClient extends AntaresCore {
});
}
catch (err) {
if (isPool) {
if (isPool && args.autocommit) {
connection.release();
this._runningConnections.delete(args.tabUid);
}
Expand All @@ -1672,7 +1737,7 @@ export class MySQLClient extends AntaresCore {
keysArr = keysArr ? [...keysArr, ...response] : response;
}
catch (err) {
if (isPool) {
if (isPool && args.autocommit) {
connection.release();
this._runningConnections.delete(args.tabUid);
}
Expand All @@ -1690,7 +1755,7 @@ export class MySQLClient extends AntaresCore {
keys: keysArr
});
}).catch((err) => {
if (isPool) {
if (isPool && args.autocommit) {
connection.release();
this._runningConnections.delete(args.tabUid);
}
Expand All @@ -1701,7 +1766,7 @@ export class MySQLClient extends AntaresCore {
resultsArr.push({ rows, report, fields, keys, duration });
}

if (isPool) {
if (isPool && args.autocommit) {
connection.release();
this._runningConnections.delete(args.tabUid);
}
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/components/ModalFakerRows.vue
Expand Up @@ -6,7 +6,7 @@
<div class="modal-title h6">
<div class="d-flex">
<i class="mdi mdi-24px mdi-playlist-plus mr-1" />
<span class="cut-text">{{ $t('message.tableFiller') }}</span>
<span class="cut-text">{{ $tc('message.insertRow', 2) }}</span>
</div>
</div>
<a class="btn btn-clear c-hand" @click.stop="closeModal" />
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/components/TheFooter.vue
Expand Up @@ -11,9 +11,9 @@

<div class="footer-right-elements">
<ul class="footer-elements">
<li class="footer-element footer-link" @click="openOutside('https://www.treedom.net/en/user/fabio-di-stasio/event/antares-for-the-planet')">
<i class="mdi mdi-18px mdi-tree mr-1" />
<small>{{ $t('message.plantATree') }}</small>
<li class="footer-element footer-link" @click="openOutside('https://www.paypal.com/paypalme/fabiodistasio')">
<i class="mdi mdi-18px mdi-coffee mr-1" />
<small>{{ $t('word.donate') }}</small>
</li>
<li class="footer-element footer-link" @click="openOutside('https://github.com/Fabio286/antares/issues')">
<i class="mdi mdi-18px mdi-bug" />
Expand Down

0 comments on commit 4ed2f9a

Please sign in to comment.