change structure generates data commands

This commit is contained in:
Jan Prochazka 2023-02-16 13:14:56 +01:00
parent cd1267b464
commit edf0637a35
8 changed files with 127 additions and 24 deletions

View File

@ -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[];

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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

View File

@ -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}

View File

@ -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],

View File

@ -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}