mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-05-02 13:43:58 +00:00
designer prevents creating cycles
This commit is contained in:
@@ -6,6 +6,7 @@ import _ from 'lodash';
|
|||||||
import useTheme from '../theme/useTheme';
|
import useTheme from '../theme/useTheme';
|
||||||
import DesignerReference from './DesignerReference';
|
import DesignerReference from './DesignerReference';
|
||||||
import cleanupDesignColumns from './cleanupDesignColumns';
|
import cleanupDesignColumns from './cleanupDesignColumns';
|
||||||
|
import { isConnectedByReference } from './generateDesignedQuery';
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@@ -130,7 +131,7 @@ export default function Designer({ value, onChange }) {
|
|||||||
designerId: uuidv1(),
|
designerId: uuidv1(),
|
||||||
sourceId: source.designerId,
|
sourceId: source.designerId,
|
||||||
targetId: target.designerId,
|
targetId: target.designerId,
|
||||||
joinType: 'INNER JOIN',
|
joinType: isConnectedByReference(current, source, target, null) ? 'CROSS JOIN' : 'INNER JOIN',
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
source: source.columnName,
|
source: source.columnName,
|
||||||
@@ -172,6 +173,7 @@ export default function Designer({ value, onChange }) {
|
|||||||
reference={ref}
|
reference={ref}
|
||||||
onChangeReference={changeReference}
|
onChangeReference={changeReference}
|
||||||
onRemoveReference={removeReference}
|
onRemoveReference={removeReference}
|
||||||
|
designer={value}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{(tables || []).map((table) => (
|
{(tables || []).map((table) => (
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import _ from 'lodash';
|
|||||||
import useTheme from '../theme/useTheme';
|
import useTheme from '../theme/useTheme';
|
||||||
import { useShowMenu } from '../modals/showMenu';
|
import { useShowMenu } from '../modals/showMenu';
|
||||||
import { DropDownMenuDivider, DropDownMenuItem } from '../modals/DropDownMenu';
|
import { DropDownMenuDivider, DropDownMenuItem } from '../modals/DropDownMenu';
|
||||||
|
import { isConnectedByReference } from './generateDesignedQuery';
|
||||||
|
|
||||||
const StyledSvg = styled.svg`
|
const StyledSvg = styled.svg`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -37,18 +38,22 @@ const ReferenceText = styled.span`
|
|||||||
background-color: ${(props) => props.theme.designer_background};
|
background-color: ${(props) => props.theme.designer_background};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
function ReferenceContextMenu({ remove, setJoinType }) {
|
function ReferenceContextMenu({ remove, setJoinType, isConnected }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DropDownMenuItem onClick={remove}>Remove</DropDownMenuItem>
|
<DropDownMenuItem onClick={remove}>Remove</DropDownMenuItem>
|
||||||
<DropDownMenuDivider />
|
{!isConnected && (
|
||||||
<DropDownMenuItem onClick={() => setJoinType('INNER JOIN')}>Set INNER JOIN</DropDownMenuItem>
|
<>
|
||||||
<DropDownMenuItem onClick={() => setJoinType('LEFT JOIN')}>Set LEFT JOIN</DropDownMenuItem>
|
<DropDownMenuDivider />
|
||||||
<DropDownMenuItem onClick={() => setJoinType('RIGHT JOIN')}>Set RIGHT JOIN</DropDownMenuItem>
|
<DropDownMenuItem onClick={() => setJoinType('INNER JOIN')}>Set INNER JOIN</DropDownMenuItem>
|
||||||
<DropDownMenuItem onClick={() => setJoinType('FULL OUTER JOIN')}>Set FULL OUTER JOIN</DropDownMenuItem>
|
<DropDownMenuItem onClick={() => setJoinType('LEFT JOIN')}>Set LEFT JOIN</DropDownMenuItem>
|
||||||
<DropDownMenuItem onClick={() => setJoinType('CROSS JOIN')}>Set CROSS JOIN</DropDownMenuItem>
|
<DropDownMenuItem onClick={() => setJoinType('RIGHT JOIN')}>Set RIGHT JOIN</DropDownMenuItem>
|
||||||
<DropDownMenuItem onClick={() => setJoinType('WHERE EXISTS')}>Set WHERE EXISTS</DropDownMenuItem>
|
<DropDownMenuItem onClick={() => setJoinType('FULL OUTER JOIN')}>Set FULL OUTER JOIN</DropDownMenuItem>
|
||||||
<DropDownMenuItem onClick={() => setJoinType('WHERE NOT EXISTS')}>Set WHERE NOT EXISTS</DropDownMenuItem>
|
<DropDownMenuItem onClick={() => setJoinType('CROSS JOIN')}>Set CROSS JOIN</DropDownMenuItem>
|
||||||
|
<DropDownMenuItem onClick={() => setJoinType('WHERE EXISTS')}>Set WHERE EXISTS</DropDownMenuItem>
|
||||||
|
<DropDownMenuItem onClick={() => setJoinType('WHERE NOT EXISTS')}>Set WHERE NOT EXISTS</DropDownMenuItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -59,6 +64,7 @@ export default function DesignerReference({
|
|||||||
changeToken,
|
changeToken,
|
||||||
onRemoveReference,
|
onRemoveReference,
|
||||||
onChangeReference,
|
onChangeReference,
|
||||||
|
designer,
|
||||||
}) {
|
}) {
|
||||||
const { designerId, sourceId, targetId, columns, joinType } = reference;
|
const { designerId, sourceId, targetId, columns, joinType } = reference;
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
@@ -104,6 +110,7 @@ export default function DesignerReference({
|
|||||||
event.pageY,
|
event.pageY,
|
||||||
<ReferenceContextMenu
|
<ReferenceContextMenu
|
||||||
remove={() => onRemoveReference({ designerId })}
|
remove={() => onRemoveReference({ designerId })}
|
||||||
|
isConnected={isConnectedByReference(designer, { designerId: sourceId }, { designerId: targetId }, reference)}
|
||||||
setJoinType={(joinType) => {
|
setJoinType={(joinType) => {
|
||||||
onChangeReference({
|
onChangeReference({
|
||||||
...reference,
|
...reference,
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ class DesignerComponent {
|
|||||||
get parentTables() {
|
get parentTables() {
|
||||||
return this.parentComponent ? this.parentComponent.myAndParentTables : [];
|
return this.parentComponent ? this.parentComponent.myAndParentTables : [];
|
||||||
}
|
}
|
||||||
|
get thisAndSubComponentsTables() {
|
||||||
|
return [...this.tables, ..._.flatten(this.subComponents.map((x) => x.thisAndSubComponentsTables))];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function referenceIsConnecting(
|
function referenceIsConnecting(
|
||||||
@@ -221,7 +224,6 @@ function findPrimaryTable(tables: DesignerTableInfo[]) {
|
|||||||
return _.minBy(tables, (x) => x.top);
|
return _.minBy(tables, (x) => x.top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getReferenceConditions(reference: DesignerReferenceInfo, designer: DesignerInfo): Condition[] {
|
function getReferenceConditions(reference: DesignerReferenceInfo, designer: DesignerInfo): Condition[] {
|
||||||
const sourceTable = designer.tables.find((x) => x.designerId == reference.sourceId);
|
const sourceTable = designer.tables.find((x) => x.designerId == reference.sourceId);
|
||||||
const targetTable = designer.tables.find((x) => x.designerId == reference.targetId);
|
const targetTable = designer.tables.find((x) => x.designerId == reference.targetId);
|
||||||
@@ -260,3 +262,21 @@ export default function generateDesignedQuery(designer: DesignerInfo, engine: En
|
|||||||
dumpSqlSelect(dmp, select);
|
dumpSqlSelect(dmp, select);
|
||||||
return dmp.s;
|
return dmp.s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isConnectedByReference(
|
||||||
|
designer: DesignerInfo,
|
||||||
|
table1: { designerId: string },
|
||||||
|
table2: { designerId: string },
|
||||||
|
withoutRef: { designerId: string }
|
||||||
|
) {
|
||||||
|
const creator = new DesignerComponentCreator({
|
||||||
|
...designer,
|
||||||
|
references: withoutRef
|
||||||
|
? designer.references.filter((x) => x.designerId != withoutRef.designerId)
|
||||||
|
: designer.references,
|
||||||
|
});
|
||||||
|
const arrays = creator.components.map((x) => x.thisAndSubComponentsTables);
|
||||||
|
const array1 = arrays.find((a) => a.find((x) => x.designerId == table1.designerId));
|
||||||
|
const array2 = arrays.find((a) => a.find((x) => x.designerId == table2.designerId));
|
||||||
|
return array1 == array2;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user