diff --git a/packages/datalib/src/ChangeSet.ts b/packages/datalib/src/ChangeSet.ts index 4e564af30..0238061a3 100644 --- a/packages/datalib/src/ChangeSet.ts +++ b/packages/datalib/src/ChangeSet.ts @@ -10,6 +10,7 @@ import { Expression, } from 'dbgate-sqltree'; import type { NamedObjectInfo, DatabaseInfo, TableInfo } from 'dbgate-types'; +import { JsonDataObjectUpdateCommand } from 'dbgate-tools'; export interface ChangeSetItem { pureName: string; @@ -21,15 +22,9 @@ export interface ChangeSetItem { fields?: { [column: string]: string }; } -export interface ChangeSetDataUpdateCommand { - type: 'renameField' | 'deleteField' | 'setField'; - field: string; - value?: any; -} - export interface ChangeSet { structure?: TableInfo; - dataUpdateCommands?: ChangeSetDataUpdateCommand[]; + dataUpdateCommands?: JsonDataObjectUpdateCommand[]; setColumnMode?: 'fixed' | 'variable'; inserts: ChangeSetItem[]; updates: ChangeSetItem[]; diff --git a/packages/tools/src/schemaEditorTools.ts b/packages/tools/src/schemaEditorTools.ts index 5c5c92657..b3a4b8f80 100644 --- a/packages/tools/src/schemaEditorTools.ts +++ b/packages/tools/src/schemaEditorTools.ts @@ -10,6 +10,14 @@ import type { UniqueInfo, } from 'dbgate-types'; import _ from 'lodash'; +import { parseSqlDefaultValue } from './stringTools'; + +export interface JsonDataObjectUpdateCommand { + type: 'renameField' | 'deleteField' | 'setField' | 'setFieldIfNull'; + oldField?: string; + newField?: string; + value?: any; +} export interface EditorColumnInfo extends ColumnInfo { isPrimaryKey?: boolean; @@ -23,6 +31,41 @@ export function fillEditorColumnInfo(column: ColumnInfo, table: TableInfo): Edit }; } +export function processJsonDataUpdateCommands(obj: any, commands: JsonDataObjectUpdateCommand[] = []) { + for (const cmd of commands) { + switch (cmd.type) { + case 'deleteField': + obj = { + ...obj, + }; + delete obj[cmd.oldField]; + break; + case 'renameField': + obj = { + ...obj, + }; + obj[cmd.newField] = obj[cmd.oldField]; + delete obj[cmd.oldField]; + break; + case 'setField': + obj = { + ...obj, + }; + obj[cmd.newField] = cmd.value; + break; + case 'setFieldIfNull': + obj = { + ...obj, + }; + if (obj[cmd.newField] == null) { + obj[cmd.newField] = cmd.value; + } + break; + } + } + return obj; +} + function processPrimaryKey(table: TableInfo, oldColumn: EditorColumnInfo, newColumn: EditorColumnInfo): TableInfo { if (!oldColumn?.isPrimaryKey && newColumn?.isPrimaryKey) { let primaryKey = table?.primaryKey; @@ -71,7 +114,11 @@ function processPrimaryKey(table: TableInfo, oldColumn: EditorColumnInfo, newCol return table; } -export function editorAddColumn(table: TableInfo, column: EditorColumnInfo): TableInfo { +function defineDataCommand(table: TableInfo, cmd: () => JsonDataObjectUpdateCommand) { + table['__addDataCommands'] = [...(table['__addDataCommands'] || []), cmd()]; +} + +export function editorAddColumn(table: TableInfo, column: EditorColumnInfo, addDataCommand?: boolean): TableInfo { let res = { ...table, columns: [...(table?.columns || []), { ...column, pairingId: uuidv1() }], @@ -79,10 +126,18 @@ export function editorAddColumn(table: TableInfo, column: EditorColumnInfo): Tab res = processPrimaryKey(res, null, column); + if (addDataCommand && column.defaultValue) { + defineDataCommand(res, () => ({ + type: 'setField', + field: column.columnName, + value: parseSqlDefaultValue(column.defaultValue), + })); + } + return res; } -export function editorModifyColumn(table: TableInfo, column: EditorColumnInfo): TableInfo { +export function editorModifyColumn(table: TableInfo, column: EditorColumnInfo, addDataCommand?: boolean): TableInfo { const oldColumn = table?.columns?.find(x => x.pairingId == column.pairingId); let res = { @@ -91,10 +146,26 @@ export function editorModifyColumn(table: TableInfo, column: EditorColumnInfo): }; res = processPrimaryKey(res, fillEditorColumnInfo(oldColumn, table), column); + if (addDataCommand && oldColumn.columnName != column.columnName) { + defineDataCommand(res, () => ({ + type: 'renameField', + oldField: oldColumn.columnName, + newField: column.columnName, + })); + } + + if (addDataCommand && !oldColumn.defaultValue && column.defaultValue) { + defineDataCommand(res, () => ({ + type: 'setFieldIfNull', + newField: column.columnName, + value: parseSqlDefaultValue(column.defaultValue), + })); + } + return res; } -export function editorDeleteColumn(table: TableInfo, column: EditorColumnInfo): TableInfo { +export function editorDeleteColumn(table: TableInfo, column: EditorColumnInfo, addDataCommand?: boolean): TableInfo { let res = { ...table, columns: table.columns.filter(col => col.pairingId != column.pairingId), @@ -102,6 +173,13 @@ export function editorDeleteColumn(table: TableInfo, column: EditorColumnInfo): res = processPrimaryKey(res, column, null); + if (addDataCommand) { + defineDataCommand(res, () => ({ + type: 'deleteField', + oldField: column.columnName, + })); + } + return res; } diff --git a/packages/tools/src/stringTools.ts b/packages/tools/src/stringTools.ts index 8705ac370..21be36385 100644 --- a/packages/tools/src/stringTools.ts +++ b/packages/tools/src/stringTools.ts @@ -115,3 +115,15 @@ export function getAsImageSrc(obj) { return null; } + +export function parseSqlDefaultValue(value: string) { + if (!value) return undefined; + if (!_isString(value)) return undefined; + if (value.startsWith("'") && value.endsWith("'")) { + return value.slice(1, -1); + } + if (!isNaN(value as any) && !isNaN(parseFloat(value))) { + return parseFloat(value); + } + return undefined; +} diff --git a/packages/web/src/datagrid/ColumnManager.svelte b/packages/web/src/datagrid/ColumnManager.svelte index 1957f6e9f..b484472a7 100644 --- a/packages/web/src/datagrid/ColumnManager.svelte +++ b/packages/web/src/datagrid/ColumnManager.svelte @@ -1,5 +1,5 @@ @@ -55,9 +57,9 @@ on:click={e => { closeCurrentModal(); if (columnInfo) { - setTableInfo(tbl => editorModifyColumn(tbl, e.detail)); + setTableInfo(tbl => editorModifyColumn(tbl, e.detail, addDataCommand)); } else { - setTableInfo(tbl => editorAddColumn(tbl, e.detail)); + setTableInfo(tbl => editorAddColumn(tbl, e.detail, addDataCommand)); if (onAddNext) onAddNext(); } }} @@ -68,7 +70,7 @@ value="Save" on:click={e => { closeCurrentModal(); - setTableInfo(tbl => editorAddColumn(tbl, e.detail)); + setTableInfo(tbl => editorAddColumn(tbl, e.detail, addDataCommand)); }} /> {/if} @@ -80,7 +82,7 @@ value="Remove" on:click={() => { closeCurrentModal(); - setTableInfo(tbl => editorDeleteColumn(tbl, columnInfo)); + setTableInfo(tbl => editorDeleteColumn(tbl, columnInfo, addDataCommand)); }} /> {/if}