mirror of
https://github.com/dbgate/dbgate
synced 2024-11-07 20:26:23 +00:00
change structure generates data commands
This commit is contained in:
parent
cd1267b464
commit
edf0637a35
@ -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[];
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import _, { indexOf, range } from 'lodash';
|
||||
import _, { add, indexOf, range } from 'lodash';
|
||||
import { ChangeSet, DisplayColumn, GridDisplay } from 'dbgate-datalib';
|
||||
import { filterName } from 'dbgate-tools';
|
||||
import CloseSearchButton from '../buttons/CloseSearchButton.svelte';
|
||||
@ -113,19 +113,29 @@
|
||||
$: tableInfo = display?.editableStructure;
|
||||
$: setTableInfo = updFunc => {
|
||||
const structure = updFunc(display?.editableStructure);
|
||||
let added = [];
|
||||
if (structure['__addDataCommands']) {
|
||||
added = structure['__addDataCommands'];
|
||||
delete structure['__addDataCommands'];
|
||||
}
|
||||
dispatchChangeSet({
|
||||
type: 'set',
|
||||
value: {
|
||||
...changeSetState?.value,
|
||||
dataUpdateCommands: [...(changeSetState?.value?.dataUpdateCommands || []), ...added],
|
||||
structure,
|
||||
},
|
||||
});
|
||||
tick().then(() => display.reload());
|
||||
};
|
||||
|
||||
$: addDataCommand = allowChangeChangeSetStructure;
|
||||
|
||||
function handleAddColumn() {
|
||||
showModal(ColumnEditorModal, {
|
||||
setTableInfo,
|
||||
tableInfo,
|
||||
addDataCommand,
|
||||
onAddNext: async () => {
|
||||
await tick();
|
||||
handleAddColumn();
|
||||
|
@ -6,6 +6,7 @@
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { showModal } from '../modals/modalTools';
|
||||
import ColumnEditorModal from '../tableeditor/ColumnEditorModal.svelte';
|
||||
import { editorDeleteColumn } from 'dbgate-tools';
|
||||
|
||||
export let column;
|
||||
export let display;
|
||||
@ -21,9 +22,10 @@
|
||||
export let columnIndex = -1;
|
||||
|
||||
export let allowChangeChangeSetStructure = false;
|
||||
$: addDataCommand = allowChangeChangeSetStructure;
|
||||
|
||||
function handleEditColumn() {
|
||||
showModal(ColumnEditorModal, { columnInfo, tableInfo, setTableInfo });
|
||||
showModal(ColumnEditorModal, { columnInfo, tableInfo, setTableInfo, addDataCommand });
|
||||
}
|
||||
|
||||
function exchange(array, i1, i2) {
|
||||
@ -85,11 +87,7 @@
|
||||
<span class="icon" on:click={handleEditColumn}>
|
||||
<FontIcon icon="icon edit" />
|
||||
</span>
|
||||
<span
|
||||
class="icon"
|
||||
on:click={() =>
|
||||
setTableInfo(info => ({ ...info, columns: info.columns.filter(x => x.pairingId != columnInfo?.pairingId) }))}
|
||||
>
|
||||
<span class="icon" on:click={() => setTableInfo(info => editorDeleteColumn(info, columnInfo, addDataCommand))}>
|
||||
<FontIcon icon="icon delete" />
|
||||
</span>
|
||||
<span
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { createGridCache, createGridConfig, JslGridDisplay } from 'dbgate-datalib';
|
||||
import { generateTablePairingId } from 'dbgate-tools';
|
||||
import { generateTablePairingId, processJsonDataUpdateCommands } from 'dbgate-tools';
|
||||
import { writable } from 'svelte/store';
|
||||
import JslFormView from '../formview/JslFormView.svelte';
|
||||
import { apiOff, apiOn, useApiCall } from '../utility/api';
|
||||
@ -45,9 +45,11 @@
|
||||
}
|
||||
$: $effect;
|
||||
|
||||
$: infoWithPairingId = generateTablePairingId($info);
|
||||
|
||||
$: display = new JslGridDisplay(
|
||||
jslid,
|
||||
(allowChangeChangeSetStructure && changeSetState?.value?.structure) || generateTablePairingId($info),
|
||||
(allowChangeChangeSetStructure && changeSetState?.value?.structure) || infoWithPairingId,
|
||||
$config,
|
||||
config.update,
|
||||
$cache,
|
||||
@ -75,5 +77,8 @@
|
||||
{changeSetStore}
|
||||
{dispatchChangeSet}
|
||||
{allowChangeChangeSetStructure}
|
||||
preprocessLoadedRow={changeSetState?.value?.dataUpdateCommands
|
||||
? row => processJsonDataUpdateCommands(row, changeSetState?.value?.dataUpdateCommands)
|
||||
: null}
|
||||
/>
|
||||
{/key}
|
||||
|
@ -15,6 +15,8 @@
|
||||
export let selectedCellsPublished;
|
||||
export let rowCountLoaded = null;
|
||||
|
||||
export let preprocessLoadedRow = null;
|
||||
|
||||
// export let griderFactory;
|
||||
|
||||
export let loadedRows = [];
|
||||
@ -65,7 +67,8 @@
|
||||
errorMessage = nextRows.errorMessage;
|
||||
} else {
|
||||
if (allRowCount == null) handleLoadRowCount();
|
||||
loadedRows = [...loadedRows, ...nextRows];
|
||||
|
||||
loadedRows = [...loadedRows, ...(preprocessLoadedRow ? nextRows.map(preprocessLoadedRow) : nextRows)];
|
||||
isLoadedAll = nextRows.length === 0;
|
||||
// const loadedInfo = {
|
||||
// loadedRows: [...loadedRows, ...nextRows],
|
||||
|
@ -17,6 +17,8 @@
|
||||
export let tableInfo = null;
|
||||
export let onAddNext;
|
||||
export let driver = null;
|
||||
|
||||
export let addDataCommand = false;
|
||||
</script>
|
||||
|
||||
<FormProvider initialValues={fillEditorColumnInfo(columnInfo || {}, tableInfo)}>
|
||||
@ -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}
|
||||
|
Loading…
Reference in New Issue
Block a user