mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-18 00:56:02 +00:00
SYNC: restore table fixes & backup table tests
This commit is contained in:
committed by
Diflow
parent
ef23f0d18e
commit
ec06a7d861
@@ -103,13 +103,70 @@ describe('Transactions', () => {
|
|||||||
|
|
||||||
describe('Backup table', () => {
|
describe('Backup table', () => {
|
||||||
multiTest({ skipMongo: true }, (connectionName, databaseName, engine, options = {}) => {
|
multiTest({ skipMongo: true }, (connectionName, databaseName, engine, options = {}) => {
|
||||||
|
const implicitTransactions = options.implicitTransactions ?? false;
|
||||||
|
|
||||||
cy.contains(connectionName).click();
|
cy.contains(connectionName).click();
|
||||||
if (databaseName) cy.contains(databaseName).click();
|
if (databaseName) cy.contains(databaseName).click();
|
||||||
cy.contains('customers').rightclick();
|
cy.contains('addresses').rightclick();
|
||||||
cy.contains('Create table backup').click();
|
cy.contains('Create table backup').click();
|
||||||
cy.testid('ConfirmSqlModal_okButton').click();
|
cy.testid('ConfirmSqlModal_okButton').click();
|
||||||
cy.contains('customers (').click();
|
cy.testid('app-object-group-items-table-backups').contains('addresses').click();
|
||||||
cy.contains('Rows: 8').should('be.visible');
|
cy.contains('Rows: 12').should('be.visible');
|
||||||
|
cy.testid('app-object-group-items-tables').contains('addresses').click();
|
||||||
|
|
||||||
|
cy.contains('Ridgewood').click();
|
||||||
|
cy.testid('TableDataTab_deleteSelectedRows').click();
|
||||||
|
cy.contains('Rosewood').click();
|
||||||
|
cy.testid('TableDataTab_deleteSelectedRows').click();
|
||||||
|
|
||||||
|
cy.contains('Vermont').click();
|
||||||
|
cy.get('body').realType('Wermont{enter}');
|
||||||
|
|
||||||
|
cy.testid('TableDataTab_insertNewRow').click();
|
||||||
|
cy.get('body').realType('Modranska{enter}');
|
||||||
|
cy.realPress(['ArrowLeft']);
|
||||||
|
cy.realPress(['ArrowLeft']);
|
||||||
|
cy.get('body').realType('13{enter}');
|
||||||
|
cy.realPress(['ArrowRight']);
|
||||||
|
cy.get('body').realType('1{enter}');
|
||||||
|
cy.realPress(['ArrowRight']);
|
||||||
|
cy.realPress(['ArrowRight']);
|
||||||
|
cy.realPress(['ArrowRight']);
|
||||||
|
cy.get('body').realType('Prague{enter}');
|
||||||
|
cy.realPress(['ArrowRight']);
|
||||||
|
cy.get('body').realType('CZ{enter}');
|
||||||
|
cy.realPress(['ArrowRight']);
|
||||||
|
cy.get('body').realType('10000{enter}');
|
||||||
|
cy.realPress(['ArrowRight']);
|
||||||
|
cy.get('body').realType('111222333{enter}');
|
||||||
|
|
||||||
|
cy.testid('TableDataTab_save').click();
|
||||||
|
cy.testid('ConfirmSqlModal_okButton').click();
|
||||||
|
cy.contains('Rows: 11').should('be.visible'); // wait for save
|
||||||
|
|
||||||
|
cy.testid('app-object-group-items-table-backups').contains('addresses').rightclick();
|
||||||
|
cy.contains('restore script').click();
|
||||||
|
cy.contains('UPDATE'); // wait for query
|
||||||
|
cy.testid('QueryTab_executeButton').click();
|
||||||
|
cy.contains('Query execution finished');
|
||||||
|
|
||||||
|
if (implicitTransactions) {
|
||||||
|
cy.testid('QueryTab_commitTransactionButton').click();
|
||||||
|
cy.contains('Commit Transaction finished');
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.realPress('F1');
|
||||||
|
cy.realType('Close all');
|
||||||
|
cy.realPress('Enter');
|
||||||
|
// cy.testid('CloseTabModal_buttonConfirm').click();
|
||||||
|
cy.wait(1000);
|
||||||
|
|
||||||
|
cy.testid('app-object-group-items-tables').contains('addresses').click();
|
||||||
|
|
||||||
|
// check whether data was successfully restored
|
||||||
|
cy.contains('Rows: 12').should('be.visible');
|
||||||
|
cy.contains('Ridgewood');
|
||||||
|
cy.contains('Vermont');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
<svelte:fragment slot="footer">
|
<svelte:fragment slot="footer">
|
||||||
<FormSubmit
|
<FormSubmit
|
||||||
value={_t('datagrid.closeTabs.close', { defaultMessage: 'Close tabs' })}
|
value={_t('datagrid.closeTabs.close', { defaultMessage: 'Close tabs' })}
|
||||||
|
data-testid="CloseTabModal_buttonConfirm"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
closeCurrentModal();
|
closeCurrentModal();
|
||||||
onConfirm();
|
onConfirm();
|
||||||
@@ -52,6 +53,7 @@
|
|||||||
<FormStyledButton
|
<FormStyledButton
|
||||||
type="button"
|
type="button"
|
||||||
value={_t('common.cancel', { defaultMessage: 'Cancel' })}
|
value={_t('common.cancel', { defaultMessage: 'Cancel' })}
|
||||||
|
data-testid="CloseTabModal_buttonCancel"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
closeCurrentModal();
|
closeCurrentModal();
|
||||||
onCancel();
|
onCancel();
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ export function createTableRestoreScript(backupTable: TableInfo, originalTable:
|
|||||||
);
|
);
|
||||||
const valueColumns = _.difference(bothColumns, keyColumns);
|
const valueColumns = _.difference(bothColumns, keyColumns);
|
||||||
|
|
||||||
|
if (keyColumns.length === 0) {
|
||||||
|
throw new Error('Cannot create restore script: no key columns found');
|
||||||
|
}
|
||||||
|
|
||||||
function makeColumnCond(colName: string, operator: '=' | '<>' | '<' | '>' | '<=' | '>=' = '='): Condition {
|
function makeColumnCond(colName: string, operator: '=' | '<>' | '<' | '>' | '<=' | '>=' = '='): Condition {
|
||||||
return {
|
return {
|
||||||
conditionType: 'binary',
|
conditionType: 'binary',
|
||||||
@@ -30,6 +34,30 @@ export function createTableRestoreScript(backupTable: TableInfo, originalTable:
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function makeNullNotNullCond(colName: string, isCond1: boolean): Condition {
|
||||||
|
return {
|
||||||
|
conditionType: 'and',
|
||||||
|
conditions: [
|
||||||
|
{
|
||||||
|
conditionType: 'isNull',
|
||||||
|
expr: {
|
||||||
|
exprType: 'column',
|
||||||
|
columnName: colName,
|
||||||
|
source: isCond1 ? { name: originalTable } : { alias: 'bak' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
conditionType: 'isNotNull',
|
||||||
|
expr: {
|
||||||
|
exprType: 'column',
|
||||||
|
columnName: colName,
|
||||||
|
source: isCond1 ? { alias: 'bak' } : { name: originalTable },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function putTitle(title: string) {
|
function putTitle(title: string) {
|
||||||
dmp.putRaw('\n\n');
|
dmp.putRaw('\n\n');
|
||||||
dmp.comment(`******************** ${title} ********************`);
|
dmp.comment(`******************** ${title} ********************`);
|
||||||
@@ -45,50 +73,56 @@ export function createTableRestoreScript(backupTable: TableInfo, originalTable:
|
|||||||
dmp.comment(`Follows UPDATE, DELETE, INSERT statements to restore data`);
|
dmp.comment(`Follows UPDATE, DELETE, INSERT statements to restore data`);
|
||||||
dmp.putRaw('\n');
|
dmp.putRaw('\n');
|
||||||
|
|
||||||
const update: Update = {
|
if (valueColumns.length > 0) {
|
||||||
commandType: 'update',
|
const update: Update = {
|
||||||
from: { name: originalTable },
|
commandType: 'update',
|
||||||
fields: valueColumns.map(colName => ({
|
from: { name: originalTable },
|
||||||
exprType: 'select',
|
fields: valueColumns.map(colName => ({
|
||||||
select: {
|
exprType: 'select',
|
||||||
commandType: 'select',
|
select: {
|
||||||
from: { name: backupTable, alias: 'bak' },
|
commandType: 'select',
|
||||||
columns: [
|
from: { name: backupTable, alias: 'bak' },
|
||||||
{
|
columns: [
|
||||||
exprType: 'column',
|
|
||||||
columnName: colName,
|
|
||||||
source: { alias: 'bak' },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
where: {
|
|
||||||
conditionType: 'and',
|
|
||||||
conditions: keyColumns.map(colName => makeColumnCond(colName)),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
targetColumn: colName,
|
|
||||||
})),
|
|
||||||
where: {
|
|
||||||
conditionType: 'exists',
|
|
||||||
subQuery: {
|
|
||||||
commandType: 'select',
|
|
||||||
from: { name: backupTable, alias: 'bak' },
|
|
||||||
selectAll: true,
|
|
||||||
where: {
|
|
||||||
conditionType: 'and',
|
|
||||||
conditions: [
|
|
||||||
...keyColumns.map(keyColName => makeColumnCond(keyColName)),
|
|
||||||
{
|
{
|
||||||
conditionType: 'or',
|
exprType: 'column',
|
||||||
conditions: valueColumns.map(colName => makeColumnCond(colName, '<>')),
|
columnName: colName,
|
||||||
|
source: { alias: 'bak' },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
where: {
|
||||||
|
conditionType: 'and',
|
||||||
|
conditions: keyColumns.map(colName => makeColumnCond(colName)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
targetColumn: colName,
|
||||||
|
})),
|
||||||
|
where: {
|
||||||
|
conditionType: 'exists',
|
||||||
|
subQuery: {
|
||||||
|
commandType: 'select',
|
||||||
|
from: { name: backupTable, alias: 'bak' },
|
||||||
|
selectAll: true,
|
||||||
|
where: {
|
||||||
|
conditionType: 'and',
|
||||||
|
conditions: [
|
||||||
|
...keyColumns.map(keyColName => makeColumnCond(keyColName)),
|
||||||
|
{
|
||||||
|
conditionType: 'or',
|
||||||
|
conditions: valueColumns.flatMap(colName => [
|
||||||
|
makeColumnCond(colName, '<>'),
|
||||||
|
makeNullNotNullCond(colName, true),
|
||||||
|
makeNullNotNullCond(colName, false),
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
};
|
||||||
};
|
putTitle('UPDATE');
|
||||||
putTitle('UPDATE');
|
dumpSqlUpdate(dmp, update);
|
||||||
dumpSqlUpdate(dmp, update);
|
dmp.endCommand();
|
||||||
dmp.endCommand();
|
}
|
||||||
|
|
||||||
const delcmd: Delete = {
|
const delcmd: Delete = {
|
||||||
commandType: 'delete',
|
commandType: 'delete',
|
||||||
@@ -127,6 +161,14 @@ export function createTableRestoreScript(backupTable: TableInfo, originalTable:
|
|||||||
};
|
};
|
||||||
|
|
||||||
putTitle('INSERT');
|
putTitle('INSERT');
|
||||||
|
|
||||||
|
const autoinc = originalTable.columns.find(x => x.autoIncrement);
|
||||||
|
if (autoinc) {
|
||||||
|
dmp.allowIdentityInsert(originalTable, true);
|
||||||
|
}
|
||||||
dumpSqlInsert(dmp, insert);
|
dumpSqlInsert(dmp, insert);
|
||||||
dmp.endCommand();
|
dmp.endCommand();
|
||||||
|
if (autoinc) {
|
||||||
|
dmp.allowIdentityInsert(originalTable, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user