recreate object warning

This commit is contained in:
Jan Prochazka 2021-09-16 10:48:46 +02:00
parent 3ca0810756
commit e715a95cc0
8 changed files with 75 additions and 19 deletions

View File

@ -30,7 +30,7 @@ async function testDatabaseDiff(conn, driver, mangle, createObject = null) {
mangle(structure2); mangle(structure2);
structure2 = extendDatabaseInfo(structure2); structure2 = extendDatabaseInfo(structure2);
const sql = getAlterDatabaseScript(structure1, structure2, {}, structure2, driver); const { sql } = getAlterDatabaseScript(structure1, structure2, {}, structure2, driver);
console.log('RUNNING ALTER SQL', driver.engine, ':', sql); console.log('RUNNING ALTER SQL', driver.engine, ':', sql);
await driver.script(conn, sql); await driver.script(conn, sql);

View File

@ -46,7 +46,7 @@ async function testTableDiff(conn, driver, mangle) {
mangle(tget(structure2)); mangle(tget(structure2));
structure2 = extendDatabaseInfo(structure2); structure2 = extendDatabaseInfo(structure2);
const sql = getAlterTableScript(tget(structure1), tget(structure2), {}, structure2, driver); const { sql } = getAlterTableScript(tget(structure1), tget(structure2), {}, structure2, driver);
console.log('RUNNING ALTER SQL', driver.engine, ':', sql); console.log('RUNNING ALTER SQL', driver.engine, ':', sql);
await driver.script(conn, sql); await driver.script(conn, sql);

View File

@ -104,6 +104,12 @@ type AlterOperation =
| AlterOperation_RecreateTable; | AlterOperation_RecreateTable;
export class AlterPlan { export class AlterPlan {
recreates = {
tables: 0,
constraints: 0,
sqlObjects: 0,
};
public operations: AlterOperation[] = []; public operations: AlterOperation[] = [];
constructor(public db: DatabaseInfo, public dialect: SqlDialect) {} constructor(public db: DatabaseInfo, public dialect: SqlDialect) {}
@ -209,6 +215,7 @@ export class AlterPlan {
table, table,
operations, operations,
}); });
this.recreates.tables += 1;
} }
run(processor: AlterProcessor) { run(processor: AlterProcessor) {
@ -270,6 +277,10 @@ export class AlterPlan {
return opRes; return opRes;
}), }),
]; ];
if (constraints.length > 0) {
this.recreates.constraints += 1;
}
return res; return res;
} }
@ -289,6 +300,7 @@ export class AlterPlan {
} }
if (op.operationType == 'changeConstraint') { if (op.operationType == 'changeConstraint') {
this.recreates.constraints += 1;
const opDrop: AlterOperation = { const opDrop: AlterOperation = {
operationType: 'dropConstraint', operationType: 'dropConstraint',
oldObject: op.oldObject, oldObject: op.oldObject,
@ -356,6 +368,7 @@ export class AlterPlan {
const table = this.db.tables.find( const table = this.db.tables.find(
x => x.pureName == op[objectField].pureName && x.schemaName == op[objectField].schemaName x => x.pureName == op[objectField].pureName && x.schemaName == op[objectField].schemaName
); );
this.recreates.tables += 1;
return [ return [
{ {
operationType: 'recreateTable', operationType: 'recreateTable',

View File

@ -348,6 +348,7 @@ export function createAlterDatabasePlan(
} else { } else {
if (newobj == null) plan.dropSqlObject(oldobj); if (newobj == null) plan.dropSqlObject(oldobj);
else if (newobj.createSql != oldobj.createSql) { else if (newobj.createSql != oldobj.createSql) {
plan.recreates.sqlObjects += 1;
plan.dropSqlObject(oldobj); plan.dropSqlObject(oldobj);
plan.createSqlObject(newobj); plan.createSqlObject(newobj);
} }
@ -372,13 +373,16 @@ export function getAlterTableScript(
opts: DbDiffOptions, opts: DbDiffOptions,
db: DatabaseInfo, db: DatabaseInfo,
driver: EngineDriver driver: EngineDriver
): string { ) {
const plan = createAlterTablePlan(oldTable, newTable, opts, db, driver); const plan = createAlterTablePlan(oldTable, newTable, opts, db, driver);
const dmp = driver.createDumper(); const dmp = driver.createDumper();
if (!driver.dialect.disableExplicitTransaction) dmp.beginTransaction(); if (!driver.dialect.disableExplicitTransaction) dmp.beginTransaction();
plan.run(dmp); plan.run(dmp);
if (!driver.dialect.disableExplicitTransaction) dmp.commitTransaction(); if (!driver.dialect.disableExplicitTransaction) dmp.commitTransaction();
return dmp.s; return {
sql: dmp.s,
recreates: plan.recreates,
};
} }
export function getAlterDatabaseScript( export function getAlterDatabaseScript(
@ -387,11 +391,14 @@ export function getAlterDatabaseScript(
opts: DbDiffOptions, opts: DbDiffOptions,
db: DatabaseInfo, db: DatabaseInfo,
driver: EngineDriver driver: EngineDriver
): string { ) {
const plan = createAlterDatabasePlan(oldDb, newDb, opts, db, driver); const plan = createAlterDatabasePlan(oldDb, newDb, opts, db, driver);
const dmp = driver.createDumper(); const dmp = driver.createDumper();
if (!driver.dialect.disableExplicitTransaction) dmp.beginTransaction(); if (!driver.dialect.disableExplicitTransaction) dmp.beginTransaction();
plan.run(dmp); plan.run(dmp);
if (!driver.dialect.disableExplicitTransaction) dmp.commitTransaction(); if (!driver.dialect.disableExplicitTransaction) dmp.commitTransaction();
return dmp.s; return {
sql: dmp.s,
recreates: plan.recreates,
};
} }

View File

@ -3,6 +3,8 @@
import { getFormContext } from './FormProviderCore.svelte'; import { getFormContext } from './FormProviderCore.svelte';
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
export let disabled;
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
const { submitActionRef } = getFormContext(); const { submitActionRef } = getFormContext();
@ -13,8 +15,10 @@
} }
submitActionRef.set(() => { submitActionRef.set(() => {
handleClick(); if (!disabled) {
handleClick();
}
}); });
</script> </script>
<FormStyledButton type="submit" on:click={handleClick} {...$$props} /> <FormStyledButton type="submit" {disabled} on:click={handleClick} {...$$props} />

View File

@ -1,7 +1,11 @@
<script> <script>
import _ from 'lodash';
import FormStyledButton from '../elements/FormStyledButton.svelte'; import FormStyledButton from '../elements/FormStyledButton.svelte';
import FormCheckboxField from '../forms/FormCheckboxField.svelte';
import FormProvider from '../forms/FormProvider.svelte'; import FormProvider from '../forms/FormProvider.svelte';
import FormSubmit from '../forms/FormSubmit.svelte'; import FormSubmit from '../forms/FormSubmit.svelte';
import FormValues from '../forms/FormValues.svelte';
import FontIcon from '../icons/FontIcon.svelte';
import SqlEditor from '../query/SqlEditor.svelte'; import SqlEditor from '../query/SqlEditor.svelte';
import ModalBase from './ModalBase.svelte'; import ModalBase from './ModalBase.svelte';
@ -10,6 +14,11 @@
export let sql; export let sql;
export let onConfirm; export let onConfirm;
export let engine; export let engine;
export let recreates;
$: isRecreated = _.sum(_.values(recreates || {})) > 0;
$: console.log('recreates', recreates);
</script> </script>
<FormProvider> <FormProvider>
@ -20,15 +29,32 @@
<SqlEditor {engine} value={sql} readOnly /> <SqlEditor {engine} value={sql} readOnly />
</div> </div>
{#if isRecreated}
<div class="form-margin">
<div>
<FontIcon icon="img warn" /> This operation is not directly supported by SQL engine. DbGate can emulate it, but
please check the generated SQL script.
</div>
<FormCheckboxField
templateProps={{ noMargin: true }}
label="Allow recreate (don't use on production databases)"
name="allowRecreate"
/>
</div>
{/if}
<div slot="footer"> <div slot="footer">
<FormSubmit <FormValues let:values>
value="OK" <FormSubmit
on:click={() => { value="OK"
closeCurrentModal(); disabled={isRecreated && !values.allowRecreate}
onConfirm(); on:click={() => {
}} closeCurrentModal();
/> onConfirm();
<FormStyledButton type="button" value="Close" on:click={closeCurrentModal} /> }}
/>
<FormStyledButton type="button" value="Close" on:click={closeCurrentModal} />
</FormValues>
</div> </div>
</ModalBase> </ModalBase>
</FormProvider> </FormProvider>
@ -39,4 +65,8 @@
height: 30vh; height: 30vh;
width: 40vw; width: 40vw;
} }
.form-margin {
margin: var(--dim-large-form-margin);
}
</style> </style>

View File

@ -102,7 +102,7 @@
function doSave(createTableName) { function doSave(createTableName) {
const driver = findEngineDriver($connection, $extensions); const driver = findEngineDriver($connection, $extensions);
const sql = getAlterTableScript( const { sql, recreates } = getAlterTableScript(
$editorValue.base, $editorValue.base,
fillConstraintNames($editorValue.current, driver.dialect), fillConstraintNames($editorValue.current, driver.dialect),
{}, {},
@ -112,6 +112,7 @@
showModal(ConfirmSqlModal, { showModal(ConfirmSqlModal, {
sql, sql,
recreates,
onConfirm: () => { onConfirm: () => {
handleConfirmSql(sql, createTableName); handleConfirmSql(sql, createTableName);
}, },

View File

@ -1,4 +1,4 @@
import _ from 'lodash' import _ from 'lodash';
import { findEngineDriver, generateDbPairingId, getAlterDatabaseScript } from 'dbgate-tools'; import { findEngineDriver, generateDbPairingId, getAlterDatabaseScript } from 'dbgate-tools';
import InputTextModal from '../modals/InputTextModal.svelte'; import InputTextModal from '../modals/InputTextModal.svelte';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
@ -15,10 +15,11 @@ export async function alterDatabaseDialog(conid, database, updateFunc) {
const dbUpdated = _.cloneDeep(db); const dbUpdated = _.cloneDeep(db);
updateFunc(dbUpdated); updateFunc(dbUpdated);
const sql = getAlterDatabaseScript(db, dbUpdated, {}, db, driver); const { sql, recreates } = getAlterDatabaseScript(db, dbUpdated, {}, db, driver);
showModal(ConfirmSqlModal, { showModal(ConfirmSqlModal, {
sql, sql,
recreates,
onConfirm: async () => { onConfirm: async () => {
const resp = await axiosInstance.request({ const resp = await axiosInstance.request({
url: 'database-connections/run-script', url: 'database-connections/run-script',