mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-25 09:45:59 +00:00
custom joins
This commit is contained in:
@@ -8,9 +8,10 @@ import uuidv1 from 'uuid/v1';
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
export interface PerspectiveCustomJoinConfig {
|
export interface PerspectiveCustomJoinConfig {
|
||||||
joinid: string;
|
refNodeDesignerId: string;
|
||||||
|
referenceDesignerId: string;
|
||||||
joinName: string;
|
joinName: string;
|
||||||
baseUniqueName: string;
|
baseDesignerId: string;
|
||||||
conid?: string;
|
conid?: string;
|
||||||
database?: string;
|
database?: string;
|
||||||
refSchemaName?: string;
|
refSchemaName?: string;
|
||||||
@@ -50,6 +51,8 @@ export interface PerspectiveNodeConfig {
|
|||||||
schemaName?: string;
|
schemaName?: string;
|
||||||
pureName: string;
|
pureName: string;
|
||||||
|
|
||||||
|
alias?: string;
|
||||||
|
|
||||||
conid?: string;
|
conid?: string;
|
||||||
database?: string;
|
database?: string;
|
||||||
|
|
||||||
|
|||||||
@@ -952,13 +952,21 @@ export class PerspectiveCustomJoinTreeNode extends PerspectiveTableNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get codeName() {
|
get codeName() {
|
||||||
return this.customJoin.joinid;
|
return this.customJoin.refNodeDesignerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
get customJoinConfig(): PerspectiveCustomJoinConfig {
|
get customJoinConfig(): PerspectiveCustomJoinConfig {
|
||||||
return this.customJoin;
|
return this.customJoin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isChecked() {
|
||||||
|
return this.isCheckedNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleChecked(value?: boolean) {
|
||||||
|
this.toggleCheckedNode(value);
|
||||||
|
}
|
||||||
|
|
||||||
getParentJoinCondition(alias: string, parentAlias: string): Condition[] {
|
getParentJoinCondition(alias: string, parentAlias: string): Condition[] {
|
||||||
return this.customJoin.columns.map(column => {
|
return this.customJoin.columns.map(column => {
|
||||||
const res: Condition = {
|
const res: Condition = {
|
||||||
@@ -1032,15 +1040,15 @@ export function getTableChildPerspectiveNodes(
|
|||||||
setConfig: ChangePerspectiveConfigFunc,
|
setConfig: ChangePerspectiveConfigFunc,
|
||||||
dataProvider: PerspectiveDataProvider,
|
dataProvider: PerspectiveDataProvider,
|
||||||
databaseConfig: PerspectiveDatabaseConfig,
|
databaseConfig: PerspectiveDatabaseConfig,
|
||||||
parentColumn: PerspectiveTreeNode
|
parentNode: PerspectiveTreeNode
|
||||||
) {
|
) {
|
||||||
if (!table) return [];
|
if (!table) return [];
|
||||||
const db = parentColumn.db;
|
const db = parentNode.db;
|
||||||
|
|
||||||
const columnNodes = table.columns.map(col =>
|
const columnNodes = table.columns.map(col =>
|
||||||
findDesignerIdForNode(
|
findDesignerIdForNode(
|
||||||
config,
|
config,
|
||||||
parentColumn,
|
parentNode,
|
||||||
designerId =>
|
designerId =>
|
||||||
new PerspectiveTableColumnNode(
|
new PerspectiveTableColumnNode(
|
||||||
col,
|
col,
|
||||||
@@ -1050,7 +1058,7 @@ export function getTableChildPerspectiveNodes(
|
|||||||
setConfig,
|
setConfig,
|
||||||
dataProvider,
|
dataProvider,
|
||||||
databaseConfig,
|
databaseConfig,
|
||||||
parentColumn,
|
parentNode,
|
||||||
designerId
|
designerId
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1074,7 +1082,7 @@ export function getTableChildPerspectiveNodes(
|
|||||||
dependencies.push(
|
dependencies.push(
|
||||||
findDesignerIdForNode(
|
findDesignerIdForNode(
|
||||||
config,
|
config,
|
||||||
parentColumn,
|
parentNode,
|
||||||
designerId =>
|
designerId =>
|
||||||
new PerspectiveTableReferenceNode(
|
new PerspectiveTableReferenceNode(
|
||||||
fk,
|
fk,
|
||||||
@@ -1085,7 +1093,7 @@ export function getTableChildPerspectiveNodes(
|
|||||||
dataProvider,
|
dataProvider,
|
||||||
databaseConfig,
|
databaseConfig,
|
||||||
isMultiple,
|
isMultiple,
|
||||||
parentColumn,
|
parentNode,
|
||||||
designerId
|
designerId
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1095,6 +1103,60 @@ export function getTableChildPerspectiveNodes(
|
|||||||
}
|
}
|
||||||
res.push(..._sortBy(dependencies, 'title'));
|
res.push(..._sortBy(dependencies, 'title'));
|
||||||
|
|
||||||
|
const customs = [];
|
||||||
|
for (const node of config.nodes) {
|
||||||
|
if (node.designerId == parentNode.parentNode?.designerId || res.find(x => x.designerId == node.designerId)) {
|
||||||
|
// already used as FK
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (const ref of config.references) {
|
||||||
|
if (
|
||||||
|
(ref.sourceId == parentNode.designerId && ref.targetId == node.designerId) ||
|
||||||
|
(ref.targetId == parentNode.designerId && ref.sourceId == node.designerId)
|
||||||
|
) {
|
||||||
|
const newConfig = { ...databaseConfig };
|
||||||
|
if (node.conid) newConfig.conid = node.conid;
|
||||||
|
if (node.database) newConfig.database = node.database;
|
||||||
|
const db = dbs?.[newConfig.conid]?.[newConfig.database];
|
||||||
|
const table = db?.tables?.find(x => x.pureName == node.pureName && x.schemaName == node.schemaName);
|
||||||
|
const view = db?.views?.find(x => x.pureName == node.pureName && x.schemaName == node.schemaName);
|
||||||
|
|
||||||
|
const join: PerspectiveCustomJoinConfig = {
|
||||||
|
refNodeDesignerId: node.designerId,
|
||||||
|
referenceDesignerId: ref.designerId,
|
||||||
|
baseDesignerId: parentNode.designerId,
|
||||||
|
joinName: node.alias || node.pureName,
|
||||||
|
refTableName: node.pureName,
|
||||||
|
refSchemaName: node.schemaName,
|
||||||
|
conid: node.conid,
|
||||||
|
database: node.database,
|
||||||
|
columns:
|
||||||
|
ref.sourceId == parentNode.designerId
|
||||||
|
? ref.columns.map(col => ({ baseColumnName: col.source, refColumnName: col.target }))
|
||||||
|
: ref.columns.map(col => ({ baseColumnName: col.target, refColumnName: col.source })),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (table || view) {
|
||||||
|
customs.push(
|
||||||
|
new PerspectiveCustomJoinTreeNode(
|
||||||
|
join,
|
||||||
|
table || view,
|
||||||
|
dbs,
|
||||||
|
config,
|
||||||
|
setConfig,
|
||||||
|
dataProvider,
|
||||||
|
newConfig,
|
||||||
|
parentNode,
|
||||||
|
node.designerId
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res.push(..._sortBy(customs, 'title'));
|
||||||
|
|
||||||
// const customs = [];
|
// const customs = [];
|
||||||
// for (const join of config.customJoins || []) {
|
// for (const join of config.customJoins || []) {
|
||||||
// if (join.baseUniqueName == parentColumn.uniqueName) {
|
// if (join.baseUniqueName == parentColumn.uniqueName) {
|
||||||
|
|||||||
@@ -219,14 +219,18 @@
|
|||||||
}));
|
}));
|
||||||
updateFromDbInfo();
|
updateFromDbInfo();
|
||||||
} else {
|
} else {
|
||||||
callChange(current => ({
|
callChange(
|
||||||
|
current => ({
|
||||||
...current,
|
...current,
|
||||||
tables: (current.tables || []).filter(x => x.designerId != table.designerId),
|
tables: (current.tables || []).filter(x => x.designerId != table.designerId),
|
||||||
references: (current.references || []).filter(
|
references: (current.references || []).filter(
|
||||||
x => x.sourceId != table.designerId && x.targetId != table.designerId
|
x => x.sourceId != table.designerId && x.targetId != table.designerId
|
||||||
),
|
),
|
||||||
columns: (current.columns || []).filter(x => x.designerId != table.designerId),
|
columns: (current.columns || []).filter(x => x.designerId != table.designerId),
|
||||||
}));
|
}),
|
||||||
|
undefined,
|
||||||
|
{ removeTables: true }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
import { onMount, tick } from 'svelte';
|
import { onMount, tick } from 'svelte';
|
||||||
import {
|
import {
|
||||||
ChangePerspectiveConfigFunc,
|
ChangePerspectiveConfigFunc,
|
||||||
|
createPerspectiveNodeConfig,
|
||||||
PerspectiveConfig,
|
PerspectiveConfig,
|
||||||
PerspectiveCustomJoinConfig,
|
PerspectiveCustomJoinConfig,
|
||||||
PerspectiveTreeNode,
|
PerspectiveTreeNode,
|
||||||
@@ -35,7 +36,6 @@
|
|||||||
|
|
||||||
let conidOverride = editValue?.conid || null;
|
let conidOverride = editValue?.conid || null;
|
||||||
let databaseOverride = editValue?.database || null;
|
let databaseOverride = editValue?.database || null;
|
||||||
let joinid = editValue?.joinid || uuidv1();
|
|
||||||
|
|
||||||
// $: fromDbInfo = useDatabaseInfo({
|
// $: fromDbInfo = useDatabaseInfo({
|
||||||
// conid,
|
// conid,
|
||||||
@@ -68,19 +68,19 @@
|
|||||||
let columns = editValue?.columns || [];
|
let columns = editValue?.columns || [];
|
||||||
// let fromTableName = pureName;
|
// let fromTableName = pureName;
|
||||||
// let fromSchemaName = schemaName;
|
// let fromSchemaName = schemaName;
|
||||||
let fromUniuqeName = editValue?.baseUniqueName || root.uniqueName;
|
let fromDesignerId = editValue?.baseDesignerId || root.designerId;
|
||||||
let refTableName = editValue?.refTableName || null;
|
let refTableName = editValue?.refTableName || null;
|
||||||
let refSchemaName = editValue?.refSchemaName || null;
|
let refSchemaName = editValue?.refSchemaName || null;
|
||||||
let joinName = editValue?.joinName || '';
|
let joinName = editValue?.joinName || '';
|
||||||
|
|
||||||
onMount(() => {
|
// onMount(() => {
|
||||||
if (editValue) return;
|
// if (editValue) return;
|
||||||
let index = 1;
|
// let index = 1;
|
||||||
while (config.customJoins?.find(x => x.joinName == `Custom join ${index}`)) {
|
// while (config.customJoins?.find(x => x.joinName == `Custom join ${index}`)) {
|
||||||
index += 1;
|
// index += 1;
|
||||||
}
|
// }
|
||||||
joinName = `Custom join ${index}`;
|
// joinName = `Custom join ${index}`;
|
||||||
});
|
// });
|
||||||
|
|
||||||
// $: fromTableList = [
|
// $: fromTableList = [
|
||||||
// ..._.sortBy($fromDbInfo?.tables || [], ['schemaName', 'pureName']),
|
// ..._.sortBy($fromDbInfo?.tables || [], ['schemaName', 'pureName']),
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
$: fromTableList = root.getBaseTables();
|
$: fromTableList = root.getBaseTables();
|
||||||
$: fromTableInfo = fromTableList?.find(x => x.node.uniqueName == fromUniuqeName)?.table;
|
$: fromTableInfo = fromTableList?.find(x => x.node.designerId == fromDesignerId)?.table;
|
||||||
|
|
||||||
$: (async () => {
|
$: (async () => {
|
||||||
// without this has svelte problem, doesn't invalidate SelectField options
|
// without this has svelte problem, doesn't invalidate SelectField options
|
||||||
@@ -134,7 +134,7 @@
|
|||||||
|
|
||||||
fromTableOptions = fromTableList.map(tbl => ({
|
fromTableOptions = fromTableList.map(tbl => ({
|
||||||
label: fullNameToLabel(tbl.table),
|
label: fullNameToLabel(tbl.table),
|
||||||
value: tbl.node.uniqueName,
|
value: tbl.node.designerId,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
refTableOptions = refTableList.map(tbl => ({
|
refTableOptions = refTableList.map(tbl => ({
|
||||||
@@ -173,13 +173,13 @@
|
|||||||
<div class="label col-3">Base table</div>
|
<div class="label col-3">Base table</div>
|
||||||
<div class="col-9">
|
<div class="col-9">
|
||||||
<SelectField
|
<SelectField
|
||||||
value={fromUniuqeName}
|
value={fromDesignerId}
|
||||||
isNative
|
isNative
|
||||||
notSelected
|
notSelected
|
||||||
options={fromTableOptions}
|
options={fromTableOptions}
|
||||||
on:change={e => {
|
on:change={e => {
|
||||||
if (e.detail) {
|
if (e.detail) {
|
||||||
fromUniuqeName = e.detail;
|
fromDesignerId = e.detail;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -321,23 +321,48 @@
|
|||||||
<svelte:fragment slot="footer">
|
<svelte:fragment slot="footer">
|
||||||
<FormSubmit
|
<FormSubmit
|
||||||
value={'Save'}
|
value={'Save'}
|
||||||
on:click={async () => {
|
on:click={() => {
|
||||||
const newJoin = {
|
setConfig(cfg => {
|
||||||
joinid,
|
const newNode = createPerspectiveNodeConfig({ pureName: refTableName, schemaName: refSchemaName });
|
||||||
joinName,
|
newNode.designerId = editValue?.refNodeDesignerId || uuidv1();
|
||||||
baseUniqueName: fromUniuqeName,
|
newNode.conid = conidOverride;
|
||||||
refTableName,
|
newNode.database = databaseOverride;
|
||||||
refSchemaName,
|
newNode.position = cfg.nodes.find(x => x.designerId == editValue?.refNodeDesignerId)?.position;
|
||||||
columns,
|
newNode.alias = joinName || refTableName;
|
||||||
conid: conidOverride,
|
|
||||||
database: databaseOverride,
|
const newRef = {
|
||||||
|
designerId: editValue?.referenceDesignerId || uuidv1(),
|
||||||
|
sourceId: fromDesignerId,
|
||||||
|
targetId: newNode.designerId,
|
||||||
|
columns: columns.map(col => ({
|
||||||
|
source: col.baseColumnName,
|
||||||
|
target: col.refColumnName,
|
||||||
|
})),
|
||||||
};
|
};
|
||||||
setConfig(cfg => ({
|
|
||||||
|
return {
|
||||||
...cfg,
|
...cfg,
|
||||||
customJoins: editValue
|
nodes: [...cfg.nodes.filter(x => x.designerId != editValue?.refNodeDesignerId), newNode],
|
||||||
? cfg.customJoins.map(x => (x.joinid == editValue.joinid ? newJoin : x))
|
references: [...cfg.references.filter(x => x.designerId != editValue?.referenceDesignerId), newRef],
|
||||||
: [...(cfg.customJoins || []), newJoin],
|
};
|
||||||
}));
|
});
|
||||||
|
|
||||||
|
// const newJoin = {
|
||||||
|
// joinid,
|
||||||
|
// joinName,
|
||||||
|
// baseDesignerId: fromDesignerId,
|
||||||
|
// refTableName,
|
||||||
|
// refSchemaName,
|
||||||
|
// columns,
|
||||||
|
// conid: conidOverride,
|
||||||
|
// database: databaseOverride,
|
||||||
|
// };
|
||||||
|
// setConfig(cfg => ({
|
||||||
|
// ...cfg,
|
||||||
|
// customJoins: editValue
|
||||||
|
// ? cfg.customJoins.map(x => (x.joinid == editValue.joinid ? newJoin : x))
|
||||||
|
// : [...(cfg.customJoins || []), newJoin],
|
||||||
|
// }));
|
||||||
closeCurrentModal();
|
closeCurrentModal();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { MultipleDatabaseInfo, PerspectiveConfig } from 'dbgate-datalib';
|
import { createPerspectiveNodeConfig, MultipleDatabaseInfo, PerspectiveConfig } from 'dbgate-datalib';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { tick } from 'svelte';
|
import { tick } from 'svelte';
|
||||||
import runCommand from '../commands/runCommand';
|
import runCommand from '../commands/runCommand';
|
||||||
@@ -46,21 +46,43 @@
|
|||||||
}
|
}
|
||||||
const res = {
|
const res = {
|
||||||
...oldValue,
|
...oldValue,
|
||||||
nodes: oldValue.nodes.map(node => {
|
references: newValue.references,
|
||||||
|
nodes: _.compact(
|
||||||
|
oldValue.nodes.map(node => {
|
||||||
const table = newValue.tables?.find(x => x.designerId == node.designerId);
|
const table = newValue.tables?.find(x => x.designerId == node.designerId);
|
||||||
|
|
||||||
|
if (!table && settings?.removeTables) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodeChanged = {
|
||||||
|
...node,
|
||||||
|
alias: table?.alias,
|
||||||
|
};
|
||||||
if (table && (table.left != node.position?.x || table.top != node.position?.y)) {
|
if (table && (table.left != node.position?.x || table.top != node.position?.y)) {
|
||||||
if (!settings?.isCalledFromArrange) {
|
if (!settings?.isCalledFromArrange) {
|
||||||
isArranged = false;
|
isArranged = false;
|
||||||
}
|
}
|
||||||
return {
|
nodeChanged.position = { x: table.left, y: table.top };
|
||||||
...node,
|
|
||||||
position: { x: table.left, y: table.top },
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return node;
|
return nodeChanged;
|
||||||
}),
|
})
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for (const table of newValue.tables) {
|
||||||
|
if (res.nodes.find(x => x.designerId == table.designerId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const newNode = createPerspectiveNodeConfig(table);
|
||||||
|
newNode.designerId = table.designerId;
|
||||||
|
newNode.position = { x: table.left, y: table.top };
|
||||||
|
isArranged = false;
|
||||||
|
res.nodes.push(newNode);
|
||||||
|
}
|
||||||
|
|
||||||
res.isArranged = isArranged;
|
res.isArranged = isArranged;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -81,10 +103,10 @@
|
|||||||
showTableCloseButton: true,
|
showTableCloseButton: true,
|
||||||
allowColumnOperations: true,
|
allowColumnOperations: true,
|
||||||
allowCreateRefByDrag: true,
|
allowCreateRefByDrag: true,
|
||||||
allowTableAlias: true,
|
|
||||||
allowScrollColumns: true,
|
allowScrollColumns: true,
|
||||||
canSelectColumns: true,
|
canSelectColumns: true,
|
||||||
canCheckTables: true,
|
canCheckTables: true,
|
||||||
|
allowTableAlias: true,
|
||||||
arrangeAlg: 'tree',
|
arrangeAlg: 'tree',
|
||||||
referenceMenu: ({ designer, reference, onChangeReference, onRemoveReference }) => {
|
referenceMenu: ({ designer, reference, onChangeReference, onRemoveReference }) => {
|
||||||
return [{ text: 'Remove', onClick: () => onRemoveReference(reference) }];
|
return [{ text: 'Remove', onClick: () => onRemoveReference(reference) }];
|
||||||
|
|||||||
@@ -89,7 +89,8 @@ export function getPerspectiveNodeMenu(props: PerspectiveNodeMenuProps) {
|
|||||||
onClick: () =>
|
onClick: () =>
|
||||||
setConfig(cfg => ({
|
setConfig(cfg => ({
|
||||||
...cfg,
|
...cfg,
|
||||||
customJoins: (cfg.customJoins || []).filter(x => x.joinid != customJoin.joinid),
|
nodes: (cfg.nodes || []).filter(x => x.designerId != customJoin.refNodeDesignerId),
|
||||||
|
references: (cfg.references || []).filter(x => x.designerId != customJoin.referenceDesignerId),
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
customJoin && {
|
customJoin && {
|
||||||
|
|||||||
Reference in New Issue
Block a user