designer prevents creating cycles

This commit is contained in:
Jan Prochazka
2020-12-29 12:36:54 +01:00
parent 3f318fdef5
commit 0055f03c49
3 changed files with 40 additions and 11 deletions

View File

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

View File

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

View File

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