mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-26 15:36:28 +00:00
change structure generates data commands
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
|||||||
Expression,
|
Expression,
|
||||||
} from 'dbgate-sqltree';
|
} from 'dbgate-sqltree';
|
||||||
import type { NamedObjectInfo, DatabaseInfo, TableInfo } from 'dbgate-types';
|
import type { NamedObjectInfo, DatabaseInfo, TableInfo } from 'dbgate-types';
|
||||||
|
import { JsonDataObjectUpdateCommand } from 'dbgate-tools';
|
||||||
|
|
||||||
export interface ChangeSetItem {
|
export interface ChangeSetItem {
|
||||||
pureName: string;
|
pureName: string;
|
||||||
@@ -21,15 +22,9 @@ export interface ChangeSetItem {
|
|||||||
fields?: { [column: string]: string };
|
fields?: { [column: string]: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChangeSetDataUpdateCommand {
|
|
||||||
type: 'renameField' | 'deleteField' | 'setField';
|
|
||||||
field: string;
|
|
||||||
value?: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ChangeSet {
|
export interface ChangeSet {
|
||||||
structure?: TableInfo;
|
structure?: TableInfo;
|
||||||
dataUpdateCommands?: ChangeSetDataUpdateCommand[];
|
dataUpdateCommands?: JsonDataObjectUpdateCommand[];
|
||||||
setColumnMode?: 'fixed' | 'variable';
|
setColumnMode?: 'fixed' | 'variable';
|
||||||
inserts: ChangeSetItem[];
|
inserts: ChangeSetItem[];
|
||||||
updates: ChangeSetItem[];
|
updates: ChangeSetItem[];
|
||||||
|
|||||||
@@ -10,6 +10,14 @@ import type {
|
|||||||
UniqueInfo,
|
UniqueInfo,
|
||||||
} from 'dbgate-types';
|
} from 'dbgate-types';
|
||||||
import _ from 'lodash';
|
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 {
|
export interface EditorColumnInfo extends ColumnInfo {
|
||||||
isPrimaryKey?: boolean;
|
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 {
|
function processPrimaryKey(table: TableInfo, oldColumn: EditorColumnInfo, newColumn: EditorColumnInfo): TableInfo {
|
||||||
if (!oldColumn?.isPrimaryKey && newColumn?.isPrimaryKey) {
|
if (!oldColumn?.isPrimaryKey && newColumn?.isPrimaryKey) {
|
||||||
let primaryKey = table?.primaryKey;
|
let primaryKey = table?.primaryKey;
|
||||||
@@ -71,7 +114,11 @@ function processPrimaryKey(table: TableInfo, oldColumn: EditorColumnInfo, newCol
|
|||||||
return table;
|
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 = {
|
let res = {
|
||||||
...table,
|
...table,
|
||||||
columns: [...(table?.columns || []), { ...column, pairingId: uuidv1() }],
|
columns: [...(table?.columns || []), { ...column, pairingId: uuidv1() }],
|
||||||
@@ -79,10 +126,18 @@ export function editorAddColumn(table: TableInfo, column: EditorColumnInfo): Tab
|
|||||||
|
|
||||||
res = processPrimaryKey(res, null, column);
|
res = processPrimaryKey(res, null, column);
|
||||||
|
|
||||||
|
if (addDataCommand && column.defaultValue) {
|
||||||
|
defineDataCommand(res, () => ({
|
||||||
|
type: 'setField',
|
||||||
|
field: column.columnName,
|
||||||
|
value: parseSqlDefaultValue(column.defaultValue),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
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);
|
const oldColumn = table?.columns?.find(x => x.pairingId == column.pairingId);
|
||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
@@ -91,10 +146,26 @@ export function editorModifyColumn(table: TableInfo, column: EditorColumnInfo):
|
|||||||
};
|
};
|
||||||
res = processPrimaryKey(res, fillEditorColumnInfo(oldColumn, table), column);
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function editorDeleteColumn(table: TableInfo, column: EditorColumnInfo): TableInfo {
|
export function editorDeleteColumn(table: TableInfo, column: EditorColumnInfo, addDataCommand?: boolean): TableInfo {
|
||||||
let res = {
|
let res = {
|
||||||
...table,
|
...table,
|
||||||
columns: table.columns.filter(col => col.pairingId != column.pairingId),
|
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);
|
res = processPrimaryKey(res, column, null);
|
||||||
|
|
||||||
|
if (addDataCommand) {
|
||||||
|
defineDataCommand(res, () => ({
|
||||||
|
type: 'deleteField',
|
||||||
|
oldField: column.columnName,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,3 +115,15 @@ export function getAsImageSrc(obj) {
|
|||||||
|
|
||||||
return null;
|
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">
|
<script lang="ts">
|
||||||
import _, { indexOf, range } from 'lodash';
|
import _, { add, indexOf, range } from 'lodash';
|
||||||
import { ChangeSet, DisplayColumn, GridDisplay } from 'dbgate-datalib';
|
import { ChangeSet, DisplayColumn, GridDisplay } from 'dbgate-datalib';
|
||||||
import { filterName } from 'dbgate-tools';
|
import { filterName } from 'dbgate-tools';
|
||||||
import CloseSearchButton from '../buttons/CloseSearchButton.svelte';
|
import CloseSearchButton from '../buttons/CloseSearchButton.svelte';
|
||||||
@@ -113,19 +113,29 @@
|
|||||||
$: tableInfo = display?.editableStructure;
|
$: tableInfo = display?.editableStructure;
|
||||||
$: setTableInfo = updFunc => {
|
$: setTableInfo = updFunc => {
|
||||||
const structure = updFunc(display?.editableStructure);
|
const structure = updFunc(display?.editableStructure);
|
||||||
|
let added = [];
|
||||||
|
if (structure['__addDataCommands']) {
|
||||||
|
added = structure['__addDataCommands'];
|
||||||
|
delete structure['__addDataCommands'];
|
||||||
|
}
|
||||||
dispatchChangeSet({
|
dispatchChangeSet({
|
||||||
type: 'set',
|
type: 'set',
|
||||||
value: {
|
value: {
|
||||||
...changeSetState?.value,
|
...changeSetState?.value,
|
||||||
|
dataUpdateCommands: [...(changeSetState?.value?.dataUpdateCommands || []), ...added],
|
||||||
structure,
|
structure,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
tick().then(() => display.reload());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$: addDataCommand = allowChangeChangeSetStructure;
|
||||||
|
|
||||||
function handleAddColumn() {
|
function handleAddColumn() {
|
||||||
showModal(ColumnEditorModal, {
|
showModal(ColumnEditorModal, {
|
||||||
setTableInfo,
|
setTableInfo,
|
||||||
tableInfo,
|
tableInfo,
|
||||||
|
addDataCommand,
|
||||||
onAddNext: async () => {
|
onAddNext: async () => {
|
||||||
await tick();
|
await tick();
|
||||||
handleAddColumn();
|
handleAddColumn();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
import { createEventDispatcher } from 'svelte';
|
import { createEventDispatcher } from 'svelte';
|
||||||
import { showModal } from '../modals/modalTools';
|
import { showModal } from '../modals/modalTools';
|
||||||
import ColumnEditorModal from '../tableeditor/ColumnEditorModal.svelte';
|
import ColumnEditorModal from '../tableeditor/ColumnEditorModal.svelte';
|
||||||
|
import { editorDeleteColumn } from 'dbgate-tools';
|
||||||
|
|
||||||
export let column;
|
export let column;
|
||||||
export let display;
|
export let display;
|
||||||
@@ -21,9 +22,10 @@
|
|||||||
export let columnIndex = -1;
|
export let columnIndex = -1;
|
||||||
|
|
||||||
export let allowChangeChangeSetStructure = false;
|
export let allowChangeChangeSetStructure = false;
|
||||||
|
$: addDataCommand = allowChangeChangeSetStructure;
|
||||||
|
|
||||||
function handleEditColumn() {
|
function handleEditColumn() {
|
||||||
showModal(ColumnEditorModal, { columnInfo, tableInfo, setTableInfo });
|
showModal(ColumnEditorModal, { columnInfo, tableInfo, setTableInfo, addDataCommand });
|
||||||
}
|
}
|
||||||
|
|
||||||
function exchange(array, i1, i2) {
|
function exchange(array, i1, i2) {
|
||||||
@@ -85,11 +87,7 @@
|
|||||||
<span class="icon" on:click={handleEditColumn}>
|
<span class="icon" on:click={handleEditColumn}>
|
||||||
<FontIcon icon="icon edit" />
|
<FontIcon icon="icon edit" />
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span class="icon" on:click={() => setTableInfo(info => editorDeleteColumn(info, columnInfo, addDataCommand))}>
|
||||||
class="icon"
|
|
||||||
on:click={() =>
|
|
||||||
setTableInfo(info => ({ ...info, columns: info.columns.filter(x => x.pairingId != columnInfo?.pairingId) }))}
|
|
||||||
>
|
|
||||||
<FontIcon icon="icon delete" />
|
<FontIcon icon="icon delete" />
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createGridCache, createGridConfig, JslGridDisplay } from 'dbgate-datalib';
|
import { createGridCache, createGridConfig, JslGridDisplay } from 'dbgate-datalib';
|
||||||
import { generateTablePairingId } from 'dbgate-tools';
|
import { generateTablePairingId, processJsonDataUpdateCommands } from 'dbgate-tools';
|
||||||
import { writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
import JslFormView from '../formview/JslFormView.svelte';
|
import JslFormView from '../formview/JslFormView.svelte';
|
||||||
import { apiOff, apiOn, useApiCall } from '../utility/api';
|
import { apiOff, apiOn, useApiCall } from '../utility/api';
|
||||||
@@ -45,9 +45,11 @@
|
|||||||
}
|
}
|
||||||
$: $effect;
|
$: $effect;
|
||||||
|
|
||||||
|
$: infoWithPairingId = generateTablePairingId($info);
|
||||||
|
|
||||||
$: display = new JslGridDisplay(
|
$: display = new JslGridDisplay(
|
||||||
jslid,
|
jslid,
|
||||||
(allowChangeChangeSetStructure && changeSetState?.value?.structure) || generateTablePairingId($info),
|
(allowChangeChangeSetStructure && changeSetState?.value?.structure) || infoWithPairingId,
|
||||||
$config,
|
$config,
|
||||||
config.update,
|
config.update,
|
||||||
$cache,
|
$cache,
|
||||||
@@ -75,5 +77,8 @@
|
|||||||
{changeSetStore}
|
{changeSetStore}
|
||||||
{dispatchChangeSet}
|
{dispatchChangeSet}
|
||||||
{allowChangeChangeSetStructure}
|
{allowChangeChangeSetStructure}
|
||||||
|
preprocessLoadedRow={changeSetState?.value?.dataUpdateCommands
|
||||||
|
? row => processJsonDataUpdateCommands(row, changeSetState?.value?.dataUpdateCommands)
|
||||||
|
: null}
|
||||||
/>
|
/>
|
||||||
{/key}
|
{/key}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
export let selectedCellsPublished;
|
export let selectedCellsPublished;
|
||||||
export let rowCountLoaded = null;
|
export let rowCountLoaded = null;
|
||||||
|
|
||||||
|
export let preprocessLoadedRow = null;
|
||||||
|
|
||||||
// export let griderFactory;
|
// export let griderFactory;
|
||||||
|
|
||||||
export let loadedRows = [];
|
export let loadedRows = [];
|
||||||
@@ -65,7 +67,8 @@
|
|||||||
errorMessage = nextRows.errorMessage;
|
errorMessage = nextRows.errorMessage;
|
||||||
} else {
|
} else {
|
||||||
if (allRowCount == null) handleLoadRowCount();
|
if (allRowCount == null) handleLoadRowCount();
|
||||||
loadedRows = [...loadedRows, ...nextRows];
|
|
||||||
|
loadedRows = [...loadedRows, ...(preprocessLoadedRow ? nextRows.map(preprocessLoadedRow) : nextRows)];
|
||||||
isLoadedAll = nextRows.length === 0;
|
isLoadedAll = nextRows.length === 0;
|
||||||
// const loadedInfo = {
|
// const loadedInfo = {
|
||||||
// loadedRows: [...loadedRows, ...nextRows],
|
// loadedRows: [...loadedRows, ...nextRows],
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
export let tableInfo = null;
|
export let tableInfo = null;
|
||||||
export let onAddNext;
|
export let onAddNext;
|
||||||
export let driver = null;
|
export let driver = null;
|
||||||
|
|
||||||
|
export let addDataCommand = false;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<FormProvider initialValues={fillEditorColumnInfo(columnInfo || {}, tableInfo)}>
|
<FormProvider initialValues={fillEditorColumnInfo(columnInfo || {}, tableInfo)}>
|
||||||
@@ -55,9 +57,9 @@
|
|||||||
on:click={e => {
|
on:click={e => {
|
||||||
closeCurrentModal();
|
closeCurrentModal();
|
||||||
if (columnInfo) {
|
if (columnInfo) {
|
||||||
setTableInfo(tbl => editorModifyColumn(tbl, e.detail));
|
setTableInfo(tbl => editorModifyColumn(tbl, e.detail, addDataCommand));
|
||||||
} else {
|
} else {
|
||||||
setTableInfo(tbl => editorAddColumn(tbl, e.detail));
|
setTableInfo(tbl => editorAddColumn(tbl, e.detail, addDataCommand));
|
||||||
if (onAddNext) onAddNext();
|
if (onAddNext) onAddNext();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@@ -68,7 +70,7 @@
|
|||||||
value="Save"
|
value="Save"
|
||||||
on:click={e => {
|
on:click={e => {
|
||||||
closeCurrentModal();
|
closeCurrentModal();
|
||||||
setTableInfo(tbl => editorAddColumn(tbl, e.detail));
|
setTableInfo(tbl => editorAddColumn(tbl, e.detail, addDataCommand));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -80,7 +82,7 @@
|
|||||||
value="Remove"
|
value="Remove"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
closeCurrentModal();
|
closeCurrentModal();
|
||||||
setTableInfo(tbl => editorDeleteColumn(tbl, columnInfo));
|
setTableInfo(tbl => editorDeleteColumn(tbl, columnInfo, addDataCommand));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user