mirror of
https://github.com/Fabio286/antares.git
synced 2025-02-17 20:21:02 +01:00
feat: mysql export for trigger, views, schedulers, functions and routines
This commit is contained in:
parent
0de2321920
commit
b2a5b40c03
@ -167,14 +167,12 @@ export default connections => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('export', async (event, { uid, ...rest }) => {
|
ipcMain.handle('export', async (event, { uid, type, tables, ...rest }) => {
|
||||||
if (exporter !== null) return;
|
if (exporter !== null) return;
|
||||||
|
|
||||||
const type = connections[uid]._client;
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'mysql':
|
case 'mysql':
|
||||||
exporter = new MysqlExporter(connections[uid], rest);
|
exporter = new MysqlExporter(connections[uid], tables, rest);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return {
|
return {
|
||||||
|
@ -3,8 +3,9 @@ import path from 'path';
|
|||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
|
|
||||||
export class BaseExporter extends EventEmitter {
|
export class BaseExporter extends EventEmitter {
|
||||||
constructor (options) {
|
constructor (tables, options) {
|
||||||
super();
|
super();
|
||||||
|
this._tables = tables;
|
||||||
this._options = options;
|
this._options = options;
|
||||||
this._isCancelled = false;
|
this._isCancelled = false;
|
||||||
this._outputStream = fs.createWriteStream(this._options.outputFile, {
|
this._outputStream = fs.createWriteStream(this._options.outputFile, {
|
||||||
|
@ -13,28 +13,36 @@ export default class MysqlExporter extends SqlExporter {
|
|||||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||||
SET NAMES utf8mb4;
|
SET NAMES utf8mb4;
|
||||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||||
/*!40101 SET @OLD_SQL_MODE='NO_AUTO_VALUE_ON_ZERO', SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;`;
|
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;`;
|
||||||
|
|
||||||
return dump;
|
return dump;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getFooter () {
|
async getFooter () {
|
||||||
|
const footer = await super.getFooter();
|
||||||
|
|
||||||
return `/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
return `/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;`;
|
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||||
|
|
||||||
|
${footer}
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getCreateTable (tableName) {
|
async getCreateTable (tableName) {
|
||||||
const { rows } = await this._client.raw(`SHOW CREATE TABLE \`${this.schemaName}\`.\`${tableName}\``);
|
const { rows } = await this._client.raw(
|
||||||
|
`SHOW CREATE TABLE \`${this.schemaName}\`.\`${tableName}\``
|
||||||
|
);
|
||||||
|
|
||||||
if (rows.length !== 1)
|
if (rows.length !== 1) return '';
|
||||||
return '';
|
|
||||||
|
|
||||||
return rows[0]['Create Table'] + ';';
|
const col = 'Create View' in rows[0] ? 'Create View' : 'Create Table';
|
||||||
|
|
||||||
|
return rows[0][col] + ';';
|
||||||
}
|
}
|
||||||
|
|
||||||
getDropTable (tableName) {
|
getDropTable (tableName) {
|
||||||
@ -45,54 +53,82 @@ SET NAMES utf8mb4;
|
|||||||
let rowCount = 0;
|
let rowCount = 0;
|
||||||
let sqlStr = '';
|
let sqlStr = '';
|
||||||
|
|
||||||
const countResults = await this._client.raw(`SELECT COUNT(1) as count FROM \`${this.schemaName}\`.\`${tableName}\``);
|
const countResults = await this._client.raw(
|
||||||
if (countResults.rows.length === 1)
|
`SELECT COUNT(1) as count FROM \`${this.schemaName}\`.\`${tableName}\``
|
||||||
rowCount = countResults.rows[0].count;
|
);
|
||||||
|
if (countResults.rows.length === 1) rowCount = countResults.rows[0].count;
|
||||||
|
|
||||||
if (rowCount > 0) {
|
if (rowCount > 0) {
|
||||||
const columns = await this._client.getTableColumns({ table: tableName, schema: this.schemaName });
|
let queryLength = 0;
|
||||||
|
let rowsWritten = 0;
|
||||||
|
const { sqlInsertDivider, sqlInsertAfter } = this._options;
|
||||||
|
const columns = await this._client.getTableColumns({
|
||||||
|
table: tableName,
|
||||||
|
schema: this.schemaName
|
||||||
|
});
|
||||||
const columnNames = columns.map(col => '`' + col.name + '`');
|
const columnNames = columns.map(col => '`' + col.name + '`');
|
||||||
const insertStmt = `INSERT INTO \`${tableName}\` (${columnNames.join(', ')}) VALUES`;
|
const insertStmt = `INSERT INTO \`${tableName}\` (${columnNames.join(
|
||||||
|
', '
|
||||||
|
)}) VALUES`;
|
||||||
|
|
||||||
const tableResult = await this._client.raw(`SELECT ${columnNames.join(', ')} FROM \`${this.schemaName}\`.\`${tableName}\``);
|
const tableResult = await this._client.raw(
|
||||||
|
`SELECT ${columnNames.join(', ')} FROM \`${
|
||||||
|
this.schemaName
|
||||||
|
}\`.\`${tableName}\``
|
||||||
|
);
|
||||||
|
|
||||||
sqlStr += `LOCK TABLES \`${tableName}\` WRITE;\n`;
|
sqlStr += `LOCK TABLES \`${tableName}\` WRITE;\n`;
|
||||||
sqlStr += `/*!40000 ALTER TABLE \`${tableName}\` DISABLE KEYS */;`;
|
sqlStr += `/*!40000 ALTER TABLE \`${tableName}\` DISABLE KEYS */;`;
|
||||||
sqlStr += '\n\n';
|
sqlStr += '\n\n';
|
||||||
|
|
||||||
sqlStr += insertStmt;
|
sqlStr += insertStmt;
|
||||||
sqlStr += '\n';
|
|
||||||
|
|
||||||
for (const row of tableResult.rows) {
|
for (const rowIndex in tableResult.rows) {
|
||||||
sqlStr += '\t(';
|
const row = tableResult.rows[rowIndex];
|
||||||
|
let sqlInsertString = '';
|
||||||
|
|
||||||
|
if (
|
||||||
|
(sqlInsertDivider === 'bytes' &&
|
||||||
|
queryLength >= sqlInsertAfter * 1024) ||
|
||||||
|
(sqlInsertDivider === 'rows' && rowsWritten === sqlInsertAfter)
|
||||||
|
) {
|
||||||
|
sqlInsertString += `;\n${insertStmt}\n\t(`;
|
||||||
|
|
||||||
|
queryLength = 0;
|
||||||
|
rowsWritten = 0;
|
||||||
|
}
|
||||||
|
else if (parseInt(rowIndex) === 0) sqlInsertString += '\n\t(';
|
||||||
|
else sqlInsertString += ',\n\t(';
|
||||||
|
|
||||||
for (const i in columns) {
|
for (const i in columns) {
|
||||||
const column = columns[i];
|
const column = columns[i];
|
||||||
const val = row[column.name];
|
const val = row[column.name];
|
||||||
|
|
||||||
if (val === null)
|
if (val === null) sqlInsertString += 'NULL';
|
||||||
sqlStr += 'NULL';
|
else if (BIT.includes(column.type)) {
|
||||||
|
sqlInsertString += `b'${hexToBinary(
|
||||||
else if (BIT.includes(column.type))
|
Buffer.from(val).toString('hex')
|
||||||
sqlStr += `b'${hexToBinary(Buffer.from(val).toString('hex'))}'`;
|
)}'`;
|
||||||
|
}
|
||||||
else if (BLOB.includes(column.type))
|
else if (BLOB.includes(column.type))
|
||||||
sqlStr += `X'${val.toString('hex').toUpperCase()}'`;
|
sqlInsertString += `X'${val.toString('hex').toUpperCase()}'`;
|
||||||
|
else if (val === '') sqlInsertString += '\'\'';
|
||||||
|
else {
|
||||||
|
sqlInsertString +=
|
||||||
|
typeof val === 'string' ? this.escapeAndQuote(val) : val;
|
||||||
|
}
|
||||||
|
|
||||||
else if (val === '')
|
if (parseInt(i) !== columns.length - 1) sqlInsertString += ', ';
|
||||||
sqlStr += '\'\'';
|
|
||||||
|
|
||||||
else
|
|
||||||
sqlStr += typeof val === 'string' ? this.escapeAndQuote(val) : val;
|
|
||||||
|
|
||||||
if (parseInt(i) !== columns.length - 1)
|
|
||||||
sqlStr += ', ';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlStr += '),\n';
|
sqlInsertString += ')';
|
||||||
|
sqlStr += sqlInsertString;
|
||||||
|
|
||||||
|
queryLength += sqlInsertString.length;
|
||||||
|
rowsWritten++;
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlStr += '\n';
|
sqlStr += ';\n\n';
|
||||||
|
|
||||||
sqlStr += `/*!40000 ALTER TABLE \`${tableName}\` ENABLE KEYS */;\n`;
|
sqlStr += `/*!40000 ALTER TABLE \`${tableName}\` ENABLE KEYS */;\n`;
|
||||||
sqlStr += 'UNLOCK TABLES;';
|
sqlStr += 'UNLOCK TABLES;';
|
||||||
@ -101,6 +137,173 @@ SET NAMES utf8mb4;
|
|||||||
return sqlStr;
|
return sqlStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getViews () {
|
||||||
|
const { rows: views } = await this._client.raw(
|
||||||
|
`SHOW TABLE STATUS FROM \`${this.schemaName}\` WHERE Comment = 'VIEW'`
|
||||||
|
);
|
||||||
|
let sqlString = '';
|
||||||
|
|
||||||
|
for (const view of views) {
|
||||||
|
sqlString += `DROP VIEW IF EXISTS \`${view.Name}\`;\n`;
|
||||||
|
const viewSyntax = await this.getCreateTable(view.Name);
|
||||||
|
sqlString += viewSyntax.replaceAll('`' + this.schemaName + '`.', '');
|
||||||
|
sqlString += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
return sqlString;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getTriggers () {
|
||||||
|
const { rows: triggers } = await this._client.raw(
|
||||||
|
`SHOW TRIGGERS FROM \`${this.schemaName}\``
|
||||||
|
);
|
||||||
|
const generatedTables = this._tables
|
||||||
|
.filter(t => t.includeStructure)
|
||||||
|
.map(t => t.table);
|
||||||
|
|
||||||
|
let sqlString = '';
|
||||||
|
|
||||||
|
for (const trigger of triggers) {
|
||||||
|
const {
|
||||||
|
Trigger: name,
|
||||||
|
Timing: timing,
|
||||||
|
Event: event,
|
||||||
|
Table: table,
|
||||||
|
Statement: statement,
|
||||||
|
sql_mode: sqlMode
|
||||||
|
} = trigger;
|
||||||
|
|
||||||
|
if (!generatedTables.includes(table)) continue;
|
||||||
|
|
||||||
|
const definer = this.getEscapedDefiner(trigger.Definer);
|
||||||
|
sqlString += '/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;;\n';
|
||||||
|
sqlString += `/*!50003 SET SQL_MODE="${sqlMode}" */;\n`;
|
||||||
|
sqlString += 'DELIMITER ;;\n';
|
||||||
|
sqlString += '/*!50003 CREATE*/ ';
|
||||||
|
sqlString += `/*!50017 DEFINER=${definer}*/ `;
|
||||||
|
sqlString += `/*!50003 TRIGGER \`${name}\` ${timing} ${event} ON ${table} FOR EACH ROW ${statement}*/;;\n`;
|
||||||
|
sqlString += 'DELIMITER ;\n';
|
||||||
|
sqlString += '/*!50003 SET SQL_MODE=@OLD_SQL_MODE */;\n\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
return sqlString;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSchedulers () {
|
||||||
|
const { rows: schedulers } = await this._client.raw(
|
||||||
|
`SELECT *, EVENT_SCHEMA AS \`Db\`, EVENT_NAME AS \`Name\` FROM information_schema.\`EVENTS\` WHERE EVENT_SCHEMA = '${this.schemaName}'`
|
||||||
|
);
|
||||||
|
let sqlString = '';
|
||||||
|
|
||||||
|
for (const scheduler of schedulers) {
|
||||||
|
const {
|
||||||
|
EVENT_NAME: name,
|
||||||
|
SQL_MODE: sqlMode,
|
||||||
|
EVENT_TYPE: type,
|
||||||
|
INTERVAL_VALUE: intervalValue,
|
||||||
|
INTERVAL_FIELD: intervalField,
|
||||||
|
STARTS: starts,
|
||||||
|
ENDS: ends,
|
||||||
|
EXECUTE_AT: at,
|
||||||
|
ON_COMPLETION: onCompletion,
|
||||||
|
STATUS: status,
|
||||||
|
EVENT_DEFINITION: definition
|
||||||
|
} = scheduler;
|
||||||
|
|
||||||
|
const definer = this.getEscapedDefiner(scheduler.DEFINER);
|
||||||
|
const comment = this.escapeAndQuote(scheduler.EVENT_COMMENT);
|
||||||
|
|
||||||
|
sqlString += `/*!50106 DROP EVENT IF EXISTS \`${name}\` */;\n`;
|
||||||
|
sqlString += '/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;;\n';
|
||||||
|
sqlString += `/*!50003 SET SQL_MODE='${sqlMode}' */;\n`;
|
||||||
|
sqlString += 'DELIMITER ;;\n';
|
||||||
|
sqlString += '/*!50106 CREATE*/ ';
|
||||||
|
sqlString += `/*!50117 DEFINER=${definer}*/ `;
|
||||||
|
sqlString += `/*!50106 EVENT \`${name}\` ON SCHEDULE `;
|
||||||
|
if (type === 'RECURRING') {
|
||||||
|
sqlString += `EVERY ${intervalValue} ${intervalField} STARTS '${starts}' `;
|
||||||
|
|
||||||
|
if (ends) sqlString += `ENDS '${ends}' `;
|
||||||
|
}
|
||||||
|
else sqlString += `AT '${at}' `;
|
||||||
|
sqlString += `ON COMPLETION ${onCompletion} ${
|
||||||
|
status === 'disabled' ? 'DISABLE' : 'ENABLE'
|
||||||
|
} COMMENT ${comment || '\'\''} DO ${definition}*/;;\n`;
|
||||||
|
sqlString += 'DELIMITER ;\n';
|
||||||
|
sqlString += '/*!50003 SET SQL_MODE=@OLD_SQL_MODE*/;;\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
return sqlString;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getFunctions () {
|
||||||
|
const { rows: functions } = await this._client.raw(
|
||||||
|
`SHOW FUNCTION STATUS WHERE \`Db\` = '${this.schemaName}';`
|
||||||
|
);
|
||||||
|
|
||||||
|
let sqlString = '';
|
||||||
|
|
||||||
|
for (const func of functions) {
|
||||||
|
sqlString += await this.getRoutineSyntax(
|
||||||
|
func.Name,
|
||||||
|
func.Type,
|
||||||
|
func.Definer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sqlString;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRoutines () {
|
||||||
|
const { rows: routines } = await this._client.raw(
|
||||||
|
`SHOW PROCEDURE STATUS WHERE \`Db\` = '${this.schemaName}';`
|
||||||
|
);
|
||||||
|
|
||||||
|
let sqlString = '';
|
||||||
|
|
||||||
|
for (const routine of routines) {
|
||||||
|
sqlString += await this.getRoutineSyntax(
|
||||||
|
routine.Name,
|
||||||
|
routine.Type,
|
||||||
|
routine.Definer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sqlString;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRoutineSyntax (name, type, definer) {
|
||||||
|
const { rows: routines } = await this._client.raw(
|
||||||
|
`SHOW CREATE ${type} \`${this.schemaName}\`.\`${name}\``
|
||||||
|
);
|
||||||
|
|
||||||
|
if (routines.length === 0) return '';
|
||||||
|
|
||||||
|
const routine = routines[0];
|
||||||
|
|
||||||
|
const { sql_mode: sqlMode, 'Create Function': createProcedure } = routine;
|
||||||
|
|
||||||
|
const startOffset = createProcedure.indexOf(type);
|
||||||
|
const procedureBody = createProcedure.substring(startOffset);
|
||||||
|
|
||||||
|
let sqlString = 'DELIMITER ;;\n';
|
||||||
|
sqlString = `/*!50003 DROP ${type} IF EXISTS ${name}*/;;\n`;
|
||||||
|
sqlString += '/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;;\n';
|
||||||
|
sqlString += `/*!50003 SET SQL_MODE="${sqlMode}"*/;;\n`;
|
||||||
|
sqlString += `/*!50003 CREATE*/ /*!50020 DEFINER=${definer}*/ /*!50003 ${procedureBody}*/;;\n`;
|
||||||
|
sqlString += '/*!50003 SET SQL_MODE=@OLD_SQL_MODE*/;;\n';
|
||||||
|
sqlString += 'DELIMITER ;\n';
|
||||||
|
|
||||||
|
return sqlString;
|
||||||
|
}
|
||||||
|
|
||||||
|
getEscapedDefiner (definer) {
|
||||||
|
return definer
|
||||||
|
.split('@')
|
||||||
|
.map(part => '`' + part + '`')
|
||||||
|
.join('@');
|
||||||
|
}
|
||||||
|
|
||||||
escapeAndQuote (value) {
|
escapeAndQuote (value) {
|
||||||
if (!value) return null;
|
if (!value) return null;
|
||||||
return `'${value.replaceAll(/'/g, '\'\'')}'`;
|
return `'${value.replaceAll(/'/g, '\'\'')}'`;
|
||||||
|
@ -3,8 +3,8 @@ import moment from 'moment';
|
|||||||
import { BaseExporter } from '../BaseExporter';
|
import { BaseExporter } from '../BaseExporter';
|
||||||
|
|
||||||
export class SqlExporter extends BaseExporter {
|
export class SqlExporter extends BaseExporter {
|
||||||
constructor (client, options) {
|
constructor (client, tables, options) {
|
||||||
super(options);
|
super(tables, options);
|
||||||
this._client = client;
|
this._client = client;
|
||||||
this._commentChar = '#';
|
this._commentChar = '#';
|
||||||
}
|
}
|
||||||
@ -23,8 +23,15 @@ export class SqlExporter extends BaseExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async dump () {
|
async dump () {
|
||||||
|
const { includes } = this._options;
|
||||||
|
const extraItems = Object.keys(includes).filter(key => includes[key]);
|
||||||
|
const totalTableToProcess = this._tables.filter(
|
||||||
|
t => t.includeStructure || t.includeContent || t.includeDropStatement
|
||||||
|
).length;
|
||||||
|
const processingItemCount = totalTableToProcess + extraItems.length;
|
||||||
|
|
||||||
const exportState = {
|
const exportState = {
|
||||||
totalItems: this._options.items.length,
|
totalItems: processingItemCount,
|
||||||
currentItemIndex: 0,
|
currentItemIndex: 0,
|
||||||
currentItem: '',
|
currentItem: '',
|
||||||
op: ''
|
op: ''
|
||||||
@ -34,13 +41,16 @@ export class SqlExporter extends BaseExporter {
|
|||||||
this.writeString(header);
|
this.writeString(header);
|
||||||
this.writeString('\n\n\n');
|
this.writeString('\n\n\n');
|
||||||
|
|
||||||
for (const item of this._options.items) {
|
for (const item of this._tables) {
|
||||||
// user abort operation
|
// user abort operation
|
||||||
if (this.isCancelled)
|
if (this.isCancelled) return;
|
||||||
return;
|
|
||||||
|
|
||||||
// skip item if not set to output any detail for them
|
// skip item if not set to output any detail for them
|
||||||
if (!item.includeStructure && !item.includeContent && !item.includeDropStatement)
|
if (
|
||||||
|
!item.includeStructure &&
|
||||||
|
!item.includeContent &&
|
||||||
|
!item.includeDropStatement
|
||||||
|
)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
exportState.currentItemIndex++;
|
exportState.currentItemIndex++;
|
||||||
@ -49,7 +59,9 @@ export class SqlExporter extends BaseExporter {
|
|||||||
|
|
||||||
this.emitUpdate(exportState);
|
this.emitUpdate(exportState);
|
||||||
|
|
||||||
const tableHeader = this.buildComment(`Dump of table ${item.table}\n------------------------------------------------------------`);
|
const tableHeader = this.buildComment(
|
||||||
|
`Dump of table ${item.table}\n------------------------------------------------------------`
|
||||||
|
);
|
||||||
this.writeString(tableHeader);
|
this.writeString(tableHeader);
|
||||||
this.writeString('\n\n');
|
this.writeString('\n\n');
|
||||||
|
|
||||||
@ -79,12 +91,38 @@ export class SqlExporter extends BaseExporter {
|
|||||||
this.writeString('\n\n');
|
this.writeString('\n\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const item of extraItems) {
|
||||||
|
const processingMethod = `get${item.charAt(0).toUpperCase() +
|
||||||
|
item.slice(1)}`;
|
||||||
|
exportState.currentItemIndex++;
|
||||||
|
exportState.currentItem = item;
|
||||||
|
exportState.op = 'PROCESSING';
|
||||||
|
this.emitUpdate(exportState);
|
||||||
|
|
||||||
|
if (this[processingMethod]) {
|
||||||
|
const data = await this[processingMethod]();
|
||||||
|
if (data !== '') {
|
||||||
|
const header =
|
||||||
|
this.buildComment(
|
||||||
|
`Dump of ${item}\n------------------------------------------------------------`
|
||||||
|
) + '\n\n';
|
||||||
|
|
||||||
|
this.writeString(header);
|
||||||
|
this.writeString(data);
|
||||||
|
this.writeString('\n\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const footer = await this.getFooter();
|
const footer = await this.getFooter();
|
||||||
this.writeString(footer);
|
this.writeString(footer);
|
||||||
}
|
}
|
||||||
|
|
||||||
buildComment (text) {
|
buildComment (text) {
|
||||||
return text.split('\n').map(txt => `${this._commentChar} ${txt}`).join('\n');
|
return text
|
||||||
|
.split('\n')
|
||||||
|
.map(txt => `${this._commentChar} ${txt}`)
|
||||||
|
.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSqlHeader () {
|
async getSqlHeader () {
|
||||||
@ -105,11 +143,13 @@ Generation time: ${moment().format()}
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getFooter () {
|
async getFooter () {
|
||||||
return '';
|
return this.buildComment(`Dump completed on ${moment().format()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getCreateTable (tableName) {
|
getCreateTable (tableName) {
|
||||||
throw new Error('Sql Exporter must implement the "getCreateTable" method');
|
throw new Error(
|
||||||
|
'Sql Exporter must implement the "getCreateTable" method'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getDropTable (tableName) {
|
getDropTable (tableName) {
|
||||||
@ -117,6 +157,8 @@ Generation time: ${moment().format()}
|
|||||||
}
|
}
|
||||||
|
|
||||||
getTableInsert (tableName) {
|
getTableInsert (tableName) {
|
||||||
throw new Error('Sql Exporter must implement the "getTableInsert" method');
|
throw new Error(
|
||||||
|
'Sql Exporter must implement the "getTableInsert" method'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,111 +37,168 @@
|
|||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="columns mb-2">
|
|
||||||
<div class="column col-auto d-flex p-0 text-italic ">
|
|
||||||
<i class="mdi mdi-file-document-outline mr-2" />
|
|
||||||
{{ filename }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="column col-auto col-ml-auto p-0">
|
|
||||||
<button class="btn btn-dark btn-sm" @click="uncheckAllTables">
|
|
||||||
<i class="mdi mdi-file-tree-outline" />
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-dark btn-sm" @click="checkAllTables">
|
|
||||||
<i class="mdi mdi-file-tree" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="workspace-query-results">
|
<div class="columns export-options">
|
||||||
<div ref="table" class="table table-hover">
|
<div class="column col-8 left">
|
||||||
<div class="thead">
|
<div class="columns mb-2">
|
||||||
<div class="tr">
|
<div class="column col-auto d-flex text-italic ">
|
||||||
<div class="th c-hand" style="width: 50%;">
|
<i class="mdi mdi-file-document-outline mr-2" />
|
||||||
<div class="table-column-title">
|
{{ filename }}
|
||||||
<span>Table</span>
|
</div>
|
||||||
|
|
||||||
|
<div class="column col-auto col-ml-auto ">
|
||||||
|
<button class="btn btn-dark btn-sm" @click="refresh">
|
||||||
|
<i class="mdi mdi-database-refresh" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-dark btn-sm"
|
||||||
|
:disabled="isRefreshing"
|
||||||
|
@click="uncheckAllTables"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-file-tree-outline" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-dark btn-sm"
|
||||||
|
:disabled="isRefreshing"
|
||||||
|
@click="checkAllTables"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-file-tree" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="workspace-query-results">
|
||||||
|
<div ref="table" class="table table-hover">
|
||||||
|
<div class="thead">
|
||||||
|
<div class="tr">
|
||||||
|
<div class="th c-hand" style="width: 50%;">
|
||||||
|
<div class="table-column-title">
|
||||||
|
<span>{{ $t('word.table') }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="th c-hand text-center">
|
||||||
|
<div class="table-column-title">
|
||||||
|
<span>{{ $t('word.structure') }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="th c-hand text-center">
|
||||||
|
<div class="table-column-title">
|
||||||
|
<span>{{ $t('word.content') }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="th c-hand text-center">
|
||||||
|
<div class="table-column-title">
|
||||||
|
<span>{{ $t('word.drop') }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="th c-hand">
|
|
||||||
<div class="table-column-title">
|
<div class="tbody">
|
||||||
<span>Structure</span>
|
<div
|
||||||
</div>
|
v-for="item in tables"
|
||||||
</div>
|
:key="item.name"
|
||||||
<div class="th c-hand">
|
class="tr"
|
||||||
<div class="table-column-title">
|
>
|
||||||
<span>Content</span>
|
<div class="td">
|
||||||
</div>
|
{{ item.table }}
|
||||||
</div>
|
</div>
|
||||||
<div class="th c-hand">
|
<div class="td text-center">
|
||||||
<div class="table-column-title">
|
<label class="form-checkbox m-0 px-2 form-inline">
|
||||||
<span>Drop</span>
|
<input
|
||||||
|
v-model="item.includeStructure"
|
||||||
|
type="checkbox"
|
||||||
|
><i class="form-icon" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="td text-center">
|
||||||
|
<label class="form-checkbox m-0 px-2 form-inline">
|
||||||
|
<input
|
||||||
|
v-model="item.includeContent"
|
||||||
|
type="checkbox"
|
||||||
|
><i class="form-icon" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="td text-center">
|
||||||
|
<label class="form-checkbox m-0 px-2 form-inline">
|
||||||
|
<input
|
||||||
|
v-model="item.includeDropStatement"
|
||||||
|
type="checkbox"
|
||||||
|
><i class="form-icon" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column col-4">
|
||||||
|
<h4>
|
||||||
|
{{ $t('word.options') }}
|
||||||
|
</h4>
|
||||||
|
<span>{{ $t('word.includes') }}:</span>
|
||||||
|
|
||||||
<div class="tbody">
|
<label
|
||||||
<div
|
v-for="(_, key) in options.includes"
|
||||||
v-for="item in tables"
|
:key="key"
|
||||||
:key="item.name"
|
class="form-checkbox"
|
||||||
class="tr"
|
>
|
||||||
>
|
<input v-model="options.includes[key]" type="checkbox"><i class="form-icon" /> {{ $t(`word.${key}`) }}
|
||||||
<div class="td">
|
</label>
|
||||||
{{ item.table }}
|
|
||||||
</div>
|
<div class="mt-4 mb-2">
|
||||||
<div class="td">
|
{{ $t('message.newInserStmtEvery') }}:
|
||||||
<label class="form-checkbox m-0 px-2">
|
</div>
|
||||||
<input
|
<div class="columns">
|
||||||
v-model="item.includeStructure"
|
<div class="column col-6">
|
||||||
type="checkbox"
|
<input
|
||||||
><i class="form-icon" />
|
v-model.number="options.sqlInsertAfter"
|
||||||
</label>
|
type="number"
|
||||||
</div>
|
class="form-input"
|
||||||
<div class="td">
|
value="250"
|
||||||
<label class="form-checkbox m-0 px-2">
|
>
|
||||||
<input
|
</div>
|
||||||
v-model="item.includeContent"
|
<div class="column col-6">
|
||||||
type="checkbox"
|
<select v-model="options.sqlInsertDivider" class="form-select">
|
||||||
><i class="form-icon" />
|
<option value="bytes">
|
||||||
</label>
|
KiB
|
||||||
</div>
|
</option>
|
||||||
<div class="td">
|
<option value="rows">
|
||||||
<label class="form-checkbox m-0 px-2">
|
{{ $t('word.rows') }}
|
||||||
<input
|
</option>
|
||||||
v-model="item.includeDropStatement"
|
</select>
|
||||||
type="checkbox"
|
|
||||||
><i class="form-icon" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="progressPercentage > 0">
|
|
||||||
<progress
|
|
||||||
class="progress"
|
|
||||||
:value="progressPercentage"
|
|
||||||
max="100"
|
|
||||||
/>
|
|
||||||
<p class="empty-subtitle">
|
|
||||||
{{ progressPercentage }}% - {{ progressStatus }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer columns">
|
||||||
<button
|
<div class="column col modal-progress-wrapper text-left">
|
||||||
class="btn btn-primary mr-2"
|
<div v-if="progressPercentage > 0" class="export-progress">
|
||||||
:class="{'loading': isExporting}"
|
<span class="progress-status">
|
||||||
:disabled="isExporting"
|
{{ progressPercentage }}% - {{ progressStatus }}
|
||||||
@click.stop="startExport"
|
</span>
|
||||||
>
|
<progress
|
||||||
{{ $t('word.export') }}
|
class="progress d-block"
|
||||||
</button>
|
:value="progressPercentage"
|
||||||
<button class="btn btn-link" @click.stop="closeModal">
|
max="100"
|
||||||
{{ $t('word.close') }}
|
/>
|
||||||
</button>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column col-auto px-0">
|
||||||
|
<button class="btn btn-link" @click.stop="closeModal">
|
||||||
|
{{ $t('word.close') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-primary mr-2"
|
||||||
|
:class="{'loading': isExporting}"
|
||||||
|
:disabled="isExporting || isRefreshing"
|
||||||
|
autofocus
|
||||||
|
@click.prevent="startExport"
|
||||||
|
>
|
||||||
|
{{ $t('word.export') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -151,6 +208,7 @@
|
|||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
import { mapActions, mapGetters } from 'vuex';
|
import { mapActions, mapGetters } from 'vuex';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import customizations from 'common/customizations';
|
||||||
import Application from '@/ipc-api/Application';
|
import Application from '@/ipc-api/Application';
|
||||||
import Schema from '@/ipc-api/Schema';
|
import Schema from '@/ipc-api/Schema';
|
||||||
|
|
||||||
@ -163,9 +221,15 @@ export default {
|
|||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
isExporting: false,
|
isExporting: false,
|
||||||
|
isRefreshing: false,
|
||||||
progressPercentage: 0,
|
progressPercentage: 0,
|
||||||
progressStatus: '',
|
progressStatus: '',
|
||||||
tables: [],
|
tables: [],
|
||||||
|
options: {
|
||||||
|
includes: {},
|
||||||
|
sqlInsertAfter: 250,
|
||||||
|
sqlInsertDivider: 'bytes'
|
||||||
|
},
|
||||||
basePath: ''
|
basePath: ''
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -194,7 +258,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async created () {
|
async created () {
|
||||||
await this.refreshSchema({ uid: this.currentWorkspace.uid, schema: this.selectedSchema });
|
await this.refresh();
|
||||||
window.addEventListener('keydown', this.onKey);
|
window.addEventListener('keydown', this.onKey);
|
||||||
this.basePath = await Application.getDownloadPathDirectory();
|
this.basePath = await Application.getDownloadPathDirectory();
|
||||||
this.tables = this.schemaItems.map(item => ({
|
this.tables = this.schemaItems.map(item => ({
|
||||||
@ -204,6 +268,14 @@ export default {
|
|||||||
includeDropStatement: true
|
includeDropStatement: true
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const structure = ['views', 'triggers', 'routines', 'functions', 'schedulers', 'triggerFunctions'];
|
||||||
|
|
||||||
|
structure.forEach(feat => {
|
||||||
|
const val = customizations[this.currentWorkspace.client][feat];
|
||||||
|
if (val)
|
||||||
|
this.$set(this.options.includes, feat, true);
|
||||||
|
});
|
||||||
|
|
||||||
ipcRenderer.on('export-progress', this.updateProgress);
|
ipcRenderer.on('export-progress', this.updateProgress);
|
||||||
},
|
},
|
||||||
beforeDestroy () {
|
beforeDestroy () {
|
||||||
@ -216,18 +288,20 @@ export default {
|
|||||||
}),
|
}),
|
||||||
async startExport () {
|
async startExport () {
|
||||||
this.isExporting = true;
|
this.isExporting = true;
|
||||||
const { uid } = this.currentWorkspace;
|
const { uid, client } = this.currentWorkspace;
|
||||||
const params = {
|
const params = {
|
||||||
uid,
|
uid,
|
||||||
|
type: client,
|
||||||
schema: this.selectedSchema,
|
schema: this.selectedSchema,
|
||||||
outputFile: this.dumpFilePath,
|
outputFile: this.dumpFilePath,
|
||||||
items: [...this.tables]
|
tables: [...this.tables],
|
||||||
|
...this.options
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = await Schema.export(params);
|
const result = await Schema.export(params);
|
||||||
if (result) {
|
if (result) {
|
||||||
if (result.status === 'success')
|
if (result.status === 'success')
|
||||||
this.progressStatus = result.response.cancelled ? 'Aborted' : 'Completed!';
|
this.progressStatus = result.response.cancelled ? this.$t('word.aborted') : this.$t('word.completed');
|
||||||
|
|
||||||
else
|
else
|
||||||
this.progressStatus = result.response;
|
this.progressStatus = result.response;
|
||||||
@ -237,7 +311,17 @@ export default {
|
|||||||
},
|
},
|
||||||
updateProgress (event, state) {
|
updateProgress (event, state) {
|
||||||
this.progressPercentage = Number((state.currentItemIndex / state.totalItems * 100).toFixed(1));
|
this.progressPercentage = Number((state.currentItemIndex / state.totalItems * 100).toFixed(1));
|
||||||
this.progressStatus = state.op + ' ' + state.currentItem;
|
switch (state.op) {
|
||||||
|
case 'PROCESSING':
|
||||||
|
this.progressStatus = this.$t('message.processingTableExport', { table: state.currentItem });
|
||||||
|
break;
|
||||||
|
case 'FETCH':
|
||||||
|
this.progressStatus = this.$t('message.fechingTableExport', { table: state.currentItem });
|
||||||
|
break;
|
||||||
|
case 'WRITE':
|
||||||
|
this.progressStatus = this.$t('message.writingTableExport', { table: state.currentItem });
|
||||||
|
break;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async closeModal () {
|
async closeModal () {
|
||||||
let willClose = true;
|
let willClose = true;
|
||||||
@ -261,6 +345,11 @@ export default {
|
|||||||
uncheckAllTables () {
|
uncheckAllTables () {
|
||||||
this.tables = this.tables.map(item => ({ table: item.table, includeStructure: false, includeContent: false, includeDropStatement: false }));
|
this.tables = this.tables.map(item => ({ table: item.table, includeStructure: false, includeContent: false, includeDropStatement: false }));
|
||||||
},
|
},
|
||||||
|
async refresh () {
|
||||||
|
this.isRefreshing = true;
|
||||||
|
await this.refreshSchema({ uid: this.currentWorkspace.uid, schema: this.selectedSchema });
|
||||||
|
this.isRefreshing = false;
|
||||||
|
},
|
||||||
async openPathDialog () {
|
async openPathDialog () {
|
||||||
const result = await Application.showOpenDialog({ properties: ['openDirectory'] });
|
const result = await Application.showOpenDialog({ properties: ['openDirectory'] });
|
||||||
if (result && !result.canceled)
|
if (result && !result.canceled)
|
||||||
@ -271,9 +360,19 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.workspace-query-results {
|
.export-options {
|
||||||
flex: 1 1 auto;
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.left {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-query-results {
|
||||||
|
flex: 1 0 1px;
|
||||||
.table {
|
.table {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
@ -292,13 +391,22 @@ export default {
|
|||||||
|
|
||||||
.modal-container {
|
.modal-container {
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
.modal-body {
|
.modal-body {
|
||||||
height: 60vh;
|
max-height: 60vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
.modal-footer {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-status {
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -122,7 +122,17 @@ module.exports = {
|
|||||||
select: 'Select',
|
select: 'Select',
|
||||||
passphrase: 'Passphrase',
|
passphrase: 'Passphrase',
|
||||||
filter: 'Filter',
|
filter: 'Filter',
|
||||||
change: 'Change'
|
change: 'Change',
|
||||||
|
views: 'Views',
|
||||||
|
triggers: 'Triggers',
|
||||||
|
routines: 'Routines',
|
||||||
|
functions: 'Functions',
|
||||||
|
schedulers: 'Schedulers',
|
||||||
|
includes: 'Includes',
|
||||||
|
drop: 'Drop',
|
||||||
|
rows: 'Rows',
|
||||||
|
completed: 'Completed',
|
||||||
|
aborted: 'Aborted'
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
appWelcome: 'Welcome to Antares SQL Client!',
|
appWelcome: 'Welcome to Antares SQL Client!',
|
||||||
@ -145,10 +155,12 @@ module.exports = {
|
|||||||
downloadingUpdate: 'Downloading update',
|
downloadingUpdate: 'Downloading update',
|
||||||
updateDownloaded: 'Update downloaded',
|
updateDownloaded: 'Update downloaded',
|
||||||
restartToInstall: 'Restart Antares to install',
|
restartToInstall: 'Restart Antares to install',
|
||||||
unableEditFieldWithoutPrimary: 'Unable to edit a field without a primary key in resultset',
|
unableEditFieldWithoutPrimary:
|
||||||
|
'Unable to edit a field without a primary key in resultset',
|
||||||
editCell: 'Edit cell',
|
editCell: 'Edit cell',
|
||||||
deleteRows: 'Delete row | Delete {count} rows',
|
deleteRows: 'Delete row | Delete {count} rows',
|
||||||
confirmToDeleteRows: 'Do you confirm to delete one row? | Do you confirm to delete {count} rows?',
|
confirmToDeleteRows:
|
||||||
|
'Do you confirm to delete one row? | Do you confirm to delete {count} rows?',
|
||||||
notificationsTimeout: 'Notifications timeout',
|
notificationsTimeout: 'Notifications timeout',
|
||||||
uploadFile: 'Upload file',
|
uploadFile: 'Upload file',
|
||||||
addNewRow: 'Add new row',
|
addNewRow: 'Add new row',
|
||||||
@ -176,7 +188,8 @@ module.exports = {
|
|||||||
deleteTable: 'Delete table',
|
deleteTable: 'Delete table',
|
||||||
emptyCorfirm: 'Do you confirm to empty',
|
emptyCorfirm: 'Do you confirm to empty',
|
||||||
unsavedChanges: 'Unsaved changes',
|
unsavedChanges: 'Unsaved changes',
|
||||||
discardUnsavedChanges: 'You have some unsaved changes. Closing this tab these changes will be discarded.',
|
discardUnsavedChanges:
|
||||||
|
'You have some unsaved changes. Closing this tab these changes will be discarded.',
|
||||||
thereAreNoIndexes: 'There are no indexes',
|
thereAreNoIndexes: 'There are no indexes',
|
||||||
thereAreNoForeign: 'There are no foreign keys',
|
thereAreNoForeign: 'There are no foreign keys',
|
||||||
createNewForeign: 'Create new foreign key',
|
createNewForeign: 'Create new foreign key',
|
||||||
@ -249,7 +262,11 @@ module.exports = {
|
|||||||
killProcess: 'Kill process',
|
killProcess: 'Kill process',
|
||||||
closeTab: 'Close tab',
|
closeTab: 'Close tab',
|
||||||
exportSchema: 'Export schema',
|
exportSchema: 'Export schema',
|
||||||
directoryPath: 'Directory path'
|
directoryPath: 'Directory path',
|
||||||
|
newInserStmtEvery: 'New INSERT statement every',
|
||||||
|
processingTableExport: 'Processing {table}',
|
||||||
|
fechingTableExport: 'Fetching {table} data',
|
||||||
|
writingTableExport: 'Writing {table} data'
|
||||||
},
|
},
|
||||||
faker: {
|
faker: {
|
||||||
address: 'Address',
|
address: 'Address',
|
||||||
|
@ -122,7 +122,17 @@ module.exports = {
|
|||||||
select: 'Seleziona',
|
select: 'Seleziona',
|
||||||
passphrase: 'Passphrase',
|
passphrase: 'Passphrase',
|
||||||
filter: 'Filtra',
|
filter: 'Filtra',
|
||||||
change: 'Cambia'
|
change: 'Cambia',
|
||||||
|
views: 'Viste',
|
||||||
|
triggers: 'Trigger',
|
||||||
|
routines: 'Routine',
|
||||||
|
functions: 'Function',
|
||||||
|
schedulers: 'Scheduler',
|
||||||
|
includes: 'Includi',
|
||||||
|
drop: 'Drop',
|
||||||
|
rows: 'Righe',
|
||||||
|
completed: 'Completato',
|
||||||
|
aborted: 'Annullato'
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
appWelcome: 'Benvenuto in Antares SQL Client!',
|
appWelcome: 'Benvenuto in Antares SQL Client!',
|
||||||
@ -145,10 +155,12 @@ module.exports = {
|
|||||||
downloadingUpdate: 'Download dell\'aggiornamento',
|
downloadingUpdate: 'Download dell\'aggiornamento',
|
||||||
updateDownloaded: 'Aggiornamento scaricato',
|
updateDownloaded: 'Aggiornamento scaricato',
|
||||||
restartToInstall: 'Riavvia Antares per installare l\'aggiornamento',
|
restartToInstall: 'Riavvia Antares per installare l\'aggiornamento',
|
||||||
unableEditFieldWithoutPrimary: 'Impossibile modificare il campo senza una primary key nel resultset',
|
unableEditFieldWithoutPrimary:
|
||||||
|
'Impossibile modificare il campo senza una primary key nel resultset',
|
||||||
editCell: 'Modifica cella',
|
editCell: 'Modifica cella',
|
||||||
deleteRows: 'Elimina riga | Elimina {count} righe',
|
deleteRows: 'Elimina riga | Elimina {count} righe',
|
||||||
confirmToDeleteRows: 'Confermi di voler cancellare una riga? | Confermi di voler cancellare {count} righe?',
|
confirmToDeleteRows:
|
||||||
|
'Confermi di voler cancellare una riga? | Confermi di voler cancellare {count} righe?',
|
||||||
notificationsTimeout: 'Timeout Notifiche',
|
notificationsTimeout: 'Timeout Notifiche',
|
||||||
uploadFile: 'Carica file',
|
uploadFile: 'Carica file',
|
||||||
addNewRow: 'Aggiungi nuova riga',
|
addNewRow: 'Aggiungi nuova riga',
|
||||||
@ -176,7 +188,8 @@ module.exports = {
|
|||||||
deleteTable: 'Cancella tabella',
|
deleteTable: 'Cancella tabella',
|
||||||
emptyCorfirm: 'Confermi di voler svuotare',
|
emptyCorfirm: 'Confermi di voler svuotare',
|
||||||
unsavedChanges: 'Modifiche non salvate',
|
unsavedChanges: 'Modifiche non salvate',
|
||||||
discardUnsavedChanges: 'Hai modifiche non salvate. Lasciando questa scheda le modifiche saranno scartate.',
|
discardUnsavedChanges:
|
||||||
|
'Hai modifiche non salvate. Lasciando questa scheda le modifiche saranno scartate.',
|
||||||
thereAreNoIndexes: 'Non ci sono indici',
|
thereAreNoIndexes: 'Non ci sono indici',
|
||||||
thereAreNoForeign: 'Non ci sono chiavi esterne',
|
thereAreNoForeign: 'Non ci sono chiavi esterne',
|
||||||
createNewForeign: 'Crea nuova chiave esterna',
|
createNewForeign: 'Crea nuova chiave esterna',
|
||||||
@ -236,7 +249,11 @@ module.exports = {
|
|||||||
noSchema: 'Nessuno schema',
|
noSchema: 'Nessuno schema',
|
||||||
restorePreviourSession: 'Ripristina sessione precedente',
|
restorePreviourSession: 'Ripristina sessione precedente',
|
||||||
exportSchema: 'Esporta schema',
|
exportSchema: 'Esporta schema',
|
||||||
directoryPath: 'Percorso directory'
|
directoryPath: 'Percorso directory',
|
||||||
|
newInserStmtEvery: 'Nuova istruzione INSERT ogni',
|
||||||
|
processingTableExport: 'Processo {table}',
|
||||||
|
fechingTableExport: 'Ricavo i dati {table}',
|
||||||
|
writingTableExport: 'Scrittura dati {table}'
|
||||||
},
|
},
|
||||||
faker: {
|
faker: {
|
||||||
address: 'Indirizzo',
|
address: 'Indirizzo',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user