mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-29 15:43:59 +00:00
alter table
This commit is contained in:
@@ -248,10 +248,13 @@ export class AlterPlan {
|
|||||||
|
|
||||||
if (op.operationType == 'dropTable') {
|
if (op.operationType == 'dropTable') {
|
||||||
return [
|
return [
|
||||||
...(op.oldObject.dependencies || []).map(oldObject => ({
|
...(op.oldObject.dependencies || []).map(oldObject => {
|
||||||
|
const opRes: AlterOperation = {
|
||||||
operationType: 'dropConstraint',
|
operationType: 'dropConstraint',
|
||||||
oldObject,
|
oldObject,
|
||||||
})),
|
};
|
||||||
|
return opRes;
|
||||||
|
}),
|
||||||
op,
|
op,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { ColumnInfo, DatabaseInfo, DatabaseInfoObjects, TableInfo } from 'dbgate-types';
|
import _ from 'lodash';
|
||||||
|
import { ColumnInfo, ColumnReference, DatabaseInfo, DatabaseInfoObjects, TableInfo } from 'dbgate-types';
|
||||||
|
|
||||||
export function fullNameFromString(name) {
|
export function fullNameFromString(name) {
|
||||||
const m = name.match(/\[([^\]]+)\]\.\[([^\]]+)\]/);
|
const m = name.match(/\[([^\]]+)\]\.\[([^\]]+)\]/);
|
||||||
@@ -68,3 +69,28 @@ export function makeUniqueColumnNames(res: ColumnInfo[]) {
|
|||||||
usedNames.add(res[i].columnName);
|
usedNames.add(res[i].columnName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function columnsConstraintName(prefix: string, table: TableInfo, columns: ColumnReference[]) {
|
||||||
|
return `${prefix}_${table.pureName}_${columns.map(x => x.columnName.replace(' ', '_')).join('_')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fillConstraintNames(table: TableInfo) {
|
||||||
|
if (!table) return table;
|
||||||
|
const res = _.cloneDeep(table);
|
||||||
|
if (res.primaryKey && !res.primaryKey.constraintName) {
|
||||||
|
res.primaryKey.constraintName = `PK_${res.pureName}`;
|
||||||
|
}
|
||||||
|
for (const fk of res.foreignKeys) {
|
||||||
|
if (fk.constraintName) continue;
|
||||||
|
fk.constraintName = columnsConstraintName('FK', res, fk.columns);
|
||||||
|
}
|
||||||
|
for (const ix of res.indexes) {
|
||||||
|
if (ix.constraintName) continue;
|
||||||
|
ix.constraintName = columnsConstraintName('IX', res, ix.columns);
|
||||||
|
}
|
||||||
|
for (const uq of res.uniques) {
|
||||||
|
if (uq.constraintName) continue;
|
||||||
|
uq.constraintName = columnsConstraintName('UQ', res, uq.columns);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
import uuidv1 from 'uuid/v1';
|
import uuidv1 from 'uuid/v1';
|
||||||
import _omit from 'lodash/omit';
|
import _omit from 'lodash/omit';
|
||||||
import { ColumnInfo, ConstraintInfo, ForeignKeyInfo, PrimaryKeyInfo, TableInfo } from 'dbgate-types';
|
import {
|
||||||
|
ColumnInfo,
|
||||||
|
ConstraintInfo,
|
||||||
|
ForeignKeyInfo,
|
||||||
|
IndexInfo,
|
||||||
|
PrimaryKeyInfo,
|
||||||
|
TableInfo,
|
||||||
|
UniqueInfo,
|
||||||
|
} from 'dbgate-types';
|
||||||
|
|
||||||
export interface EditorColumnInfo extends ColumnInfo {
|
export interface EditorColumnInfo extends ColumnInfo {
|
||||||
isPrimaryKey?: boolean;
|
isPrimaryKey?: boolean;
|
||||||
@@ -8,7 +16,7 @@ export interface EditorColumnInfo extends ColumnInfo {
|
|||||||
|
|
||||||
export function fillEditorColumnInfo(column: ColumnInfo, table: TableInfo): EditorColumnInfo {
|
export function fillEditorColumnInfo(column: ColumnInfo, table: TableInfo): EditorColumnInfo {
|
||||||
return {
|
return {
|
||||||
isPrimaryKey: !!(table?.primaryKey && table.primaryKey.columns.find(x => x.columnName == column.columnName)),
|
isPrimaryKey: !!table?.primaryKey?.columns?.find(x => x.columnName == column.columnName),
|
||||||
dataType: column ? undefined : 'int',
|
dataType: column ? undefined : 'int',
|
||||||
...column,
|
...column,
|
||||||
};
|
};
|
||||||
@@ -118,6 +126,26 @@ export function editorAddConstraint(table: TableInfo, constraint: ConstraintInfo
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (constraint.constraintType == 'index') {
|
||||||
|
res.indexes = [
|
||||||
|
...(res.indexes || []),
|
||||||
|
{
|
||||||
|
pairingId: uuidv1(),
|
||||||
|
...constraint,
|
||||||
|
} as IndexInfo,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constraint.constraintType == 'unique') {
|
||||||
|
res.uniques = [
|
||||||
|
...(res.uniques || []),
|
||||||
|
{
|
||||||
|
pairingId: uuidv1(),
|
||||||
|
...constraint,
|
||||||
|
} as UniqueInfo,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,6 +167,14 @@ export function editorModifyConstraint(table: TableInfo, constraint: ConstraintI
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (constraint.constraintType == 'index') {
|
||||||
|
res.indexes = table.indexes.map(fk => (fk.pairingId == constraint.pairingId ? { ...fk, ...constraint } : fk));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constraint.constraintType == 'unique') {
|
||||||
|
res.uniques = table.uniques.map(fk => (fk.pairingId == constraint.pairingId ? { ...fk, ...constraint } : fk));
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,11 +10,13 @@
|
|||||||
export let title;
|
export let title;
|
||||||
export let clickable;
|
export let clickable;
|
||||||
export let onRemove = null;
|
export let onRemove = null;
|
||||||
|
export let onAddNew = null;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ObjectListControl
|
<ObjectListControl
|
||||||
{collection}
|
{collection}
|
||||||
{title}
|
{title}
|
||||||
|
{onAddNew}
|
||||||
{clickable}
|
{clickable}
|
||||||
on:clickrow
|
on:clickrow
|
||||||
columns={[
|
columns={[
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import FontIcon from '../icons/FontIcon.svelte';
|
||||||
|
|
||||||
|
import Link from './Link.svelte';
|
||||||
|
|
||||||
import TableControl from './TableControl.svelte';
|
import TableControl from './TableControl.svelte';
|
||||||
|
|
||||||
export let title;
|
export let title;
|
||||||
@@ -6,13 +10,16 @@
|
|||||||
export let columns;
|
export let columns;
|
||||||
export let showIfEmpty = false;
|
export let showIfEmpty = false;
|
||||||
export let clickable;
|
export let clickable;
|
||||||
|
export let onAddNew;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if collection?.length > 0 || showIfEmpty}
|
{#if collection?.length > 0 || showIfEmpty}
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<span class="title">{title}</span>
|
<span class="title mr-1">{title}</span>
|
||||||
|
{#if onAddNew}
|
||||||
|
<Link onClick={onAddNew}><FontIcon icon="icon add" /> Add new</Link>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<TableControl
|
<TableControl
|
||||||
@@ -78,5 +85,4 @@
|
|||||||
.body {
|
.body {
|
||||||
margin: 20px;
|
margin: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
export let onAddNext;
|
export let onAddNext;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<FormProvider initialValues={fillEditorColumnInfo(columnInfo, tableInfo)}>
|
<FormProvider initialValues={fillEditorColumnInfo(columnInfo || {}, tableInfo)}>
|
||||||
<ModalBase {...$$restProps}>
|
<ModalBase {...$$restProps}>
|
||||||
<svelte:fragment slot="header"
|
<svelte:fragment slot="header"
|
||||||
>{columnInfo ? 'Edit column' : `Add column ${(tableInfo?.columns || []).length + 1}`}</svelte:fragment
|
>{columnInfo ? 'Edit column' : `Add column ${(tableInfo?.columns || []).length + 1}`}</svelte:fragment
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
{#each columns as column, index}
|
{#each columns as column, index}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="label col-3">Column {index + 1}</div>
|
<div class="label col-3">Column {index + 1}</div>
|
||||||
<div class="col-6">
|
<div class={$$slots.column ? 'col-3' : 'col-6'}>
|
||||||
{#key column.columnName}
|
{#key column.columnName}
|
||||||
<SelectField
|
<SelectField
|
||||||
value={column.columnName}
|
value={column.columnName}
|
||||||
@@ -73,6 +73,11 @@
|
|||||||
/>
|
/>
|
||||||
{/key}
|
{/key}
|
||||||
</div>
|
</div>
|
||||||
|
{#if $$slots.column}
|
||||||
|
<div class="col-3">
|
||||||
|
<slot name="column" {column} setColumns={changeFunc => (columns = changeFunc(columns))} {index} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
<div class="col-3 button">
|
<div class="col-3 button">
|
||||||
<FormStyledButton
|
<FormStyledButton
|
||||||
value="Delete"
|
value="Delete"
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import SelectField from '../forms/SelectField.svelte';
|
||||||
|
|
||||||
import ColumnsConstraintEditorModal from './ColumnsConstraintEditorModal.svelte';
|
import ColumnsConstraintEditorModal from './ColumnsConstraintEditorModal.svelte';
|
||||||
|
|
||||||
export let constraintInfo;
|
export let constraintInfo;
|
||||||
export let setTableInfo;
|
export let setTableInfo;
|
||||||
export let tableInfo;
|
export let tableInfo;
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ColumnsConstraintEditorModal
|
<ColumnsConstraintEditorModal
|
||||||
@@ -14,4 +15,27 @@
|
|||||||
{constraintInfo}
|
{constraintInfo}
|
||||||
{setTableInfo}
|
{setTableInfo}
|
||||||
{tableInfo}
|
{tableInfo}
|
||||||
/>
|
>
|
||||||
|
<svelte:fragment slot="column" let:column let:setColumns let:index>
|
||||||
|
<SelectField
|
||||||
|
value={column.isDescending ? 'desc' : 'asc'}
|
||||||
|
isNative
|
||||||
|
options={[
|
||||||
|
{ label: 'ASC', value: 'asc' },
|
||||||
|
{ label: 'DESC', value: 'desc' },
|
||||||
|
]}
|
||||||
|
on:change={e => {
|
||||||
|
setColumns(columns =>
|
||||||
|
columns.map((col, i) =>
|
||||||
|
i == index
|
||||||
|
? {
|
||||||
|
...col,
|
||||||
|
isDescending: e.detail == 'desc',
|
||||||
|
}
|
||||||
|
: col
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</svelte:fragment>
|
||||||
|
</ColumnsConstraintEditorModal>
|
||||||
|
|||||||
@@ -33,6 +33,17 @@
|
|||||||
testEnabled: () => getCurrentEditor()?.writable(),
|
testEnabled: () => getCurrentEditor()?.writable(),
|
||||||
onClick: () => getCurrentEditor().addForeignKey(),
|
onClick: () => getCurrentEditor().addForeignKey(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
registerCommand({
|
||||||
|
id: 'tableEditor.addINdex',
|
||||||
|
category: 'Table editor',
|
||||||
|
name: 'Add index',
|
||||||
|
icon: 'icon add-key',
|
||||||
|
toolbar: true,
|
||||||
|
isRelatedToTab: true,
|
||||||
|
testEnabled: () => getCurrentEditor()?.writable(),
|
||||||
|
onClick: () => getCurrentEditor().addIndex(),
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -99,6 +110,14 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function addIndex() {
|
||||||
|
showModal(IndexEditorModal, {
|
||||||
|
setTableInfo,
|
||||||
|
tableInfo,
|
||||||
|
dbInfo,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
$: columns = tableInfo?.columns;
|
$: columns = tableInfo?.columns;
|
||||||
$: primaryKey = tableInfo?.primaryKey;
|
$: primaryKey = tableInfo?.primaryKey;
|
||||||
$: foreignKeys = tableInfo?.foreignKeys;
|
$: foreignKeys = tableInfo?.foreignKeys;
|
||||||
@@ -118,6 +137,7 @@
|
|||||||
showIfEmpty
|
showIfEmpty
|
||||||
clickable={writable()}
|
clickable={writable()}
|
||||||
on:clickrow={e => showModal(ColumnEditorModal, { columnInfo: e.detail, tableInfo, setTableInfo })}
|
on:clickrow={e => showModal(ColumnEditorModal, { columnInfo: e.detail, tableInfo, setTableInfo })}
|
||||||
|
onAddNew={addColumn}
|
||||||
columns={[
|
columns={[
|
||||||
{
|
{
|
||||||
fieldName: 'notNull',
|
fieldName: 'notNull',
|
||||||
@@ -173,6 +193,7 @@
|
|||||||
<ObjectListControl
|
<ObjectListControl
|
||||||
collection={_.compact([primaryKey])}
|
collection={_.compact([primaryKey])}
|
||||||
title="Primary key"
|
title="Primary key"
|
||||||
|
onAddNew={primaryKey ? null : addPrimaryKey}
|
||||||
clickable={writable()}
|
clickable={writable()}
|
||||||
on:clickrow={e => showModal(PrimaryKeyEditorModal, { constraintInfo: e.detail, tableInfo, setTableInfo })}
|
on:clickrow={e => showModal(PrimaryKeyEditorModal, { constraintInfo: e.detail, tableInfo, setTableInfo })}
|
||||||
columns={[
|
columns={[
|
||||||
@@ -199,6 +220,7 @@
|
|||||||
|
|
||||||
<ObjectListControl
|
<ObjectListControl
|
||||||
collection={indexes}
|
collection={indexes}
|
||||||
|
onAddNew={addIndex}
|
||||||
title={`Indexes (${indexes?.length || 0})`}
|
title={`Indexes (${indexes?.length || 0})`}
|
||||||
clickable={writable()}
|
clickable={writable()}
|
||||||
on:clickrow={e => showModal(IndexEditorModal, { constraintInfo: e.detail, tableInfo, setTableInfo })}
|
on:clickrow={e => showModal(IndexEditorModal, { constraintInfo: e.detail, tableInfo, setTableInfo })}
|
||||||
@@ -226,6 +248,7 @@
|
|||||||
|
|
||||||
<ForeignKeyObjectListControl
|
<ForeignKeyObjectListControl
|
||||||
collection={foreignKeys}
|
collection={foreignKeys}
|
||||||
|
onAddNew={addForeignKey}
|
||||||
title={`Foreign keys (${foreignKeys?.length || 0})`}
|
title={`Foreign keys (${foreignKeys?.length || 0})`}
|
||||||
clickable={writable()}
|
clickable={writable()}
|
||||||
onRemove={row => setTableInfo(tbl => editorDeleteConstraint(tbl, row))}
|
onRemove={row => setTableInfo(tbl => editorDeleteConstraint(tbl, row))}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { findEngineDriver, generateTablePairingId, getAlterTableScript } from 'dbgate-tools';
|
import { fillConstraintNames, findEngineDriver, generateTablePairingId, getAlterTableScript } from 'dbgate-tools';
|
||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import registerCommand from '../commands/registerCommand';
|
import registerCommand from '../commands/registerCommand';
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
|
|
||||||
function doSave(createTableName) {
|
function doSave(createTableName) {
|
||||||
const driver = findEngineDriver($connection, $extensions);
|
const driver = findEngineDriver($connection, $extensions);
|
||||||
const sql = getAlterTableScript($editorValue.base, $editorValue.current, {}, $dbInfo, driver);
|
const sql = getAlterTableScript($editorValue.base, fillConstraintNames($editorValue.current), {}, $dbInfo, driver);
|
||||||
|
|
||||||
showModal(ConfirmSqlModal, {
|
showModal(ConfirmSqlModal, {
|
||||||
sql,
|
sql,
|
||||||
|
|||||||
Reference in New Issue
Block a user