This is an automated email from the ASF dual-hosted git repository. xxyu pushed a commit to branch kylin5 in repository https://gitbox.apache.org/repos/asf/kylin.git
commit 2502c156320934204b333d3c746f820ad1963ecf Author: Jiale He <jialeheb...@gmail.com> AuthorDate: Wed Feb 1 17:41:37 2023 +0800 KYLIN-5521 fix JoinsGraph --- .../apache/kylin/metadata/model/JoinsGraph.java | 610 --------------------- .../kylin/metadata/model/graph/JoinsGraph.java | 2 +- .../kylin/metadata/model/JoinsGraphTest.java | 4 +- 3 files changed, 4 insertions(+), 612 deletions(-) diff --git a/src/core-metadata/src/main/java/org/apache/kylin/metadata/model/JoinsGraph.java b/src/core-metadata/src/main/java/org/apache/kylin/metadata/model/JoinsGraph.java deleted file mode 100644 index acd810fbec..0000000000 --- a/src/core-metadata/src/main/java/org/apache/kylin/metadata/model/JoinsGraph.java +++ /dev/null @@ -1,610 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.kylin.metadata.model; - -import java.io.Serializable; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; - -import org.apache.commons.collections.CollectionUtils; -import org.apache.kylin.common.KylinConfig; -import org.apache.kylin.common.util.Pair; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -import lombok.Getter; -import lombok.NonNull; -import lombok.Setter; - -public class JoinsGraph implements Serializable { - - public class Edge implements Serializable { - - @Getter - private final JoinDesc join; - private final ColumnDesc[] leftCols; - private final ColumnDesc[] rightCols; - private final NonEquiJoinCondition nonEquiJoinCondition; - - private Edge(JoinDesc join) { - this.join = join; - - leftCols = new ColumnDesc[join.getForeignKeyColumns().length]; - int i = 0; - for (TblColRef colRef : join.getForeignKeyColumns()) { - leftCols[i++] = colRef.getColumnDesc(); - } - - rightCols = new ColumnDesc[join.getPrimaryKeyColumns().length]; - i = 0; - for (TblColRef colRef : join.getPrimaryKeyColumns()) { - rightCols[i++] = colRef.getColumnDesc(); - } - - nonEquiJoinCondition = join.getNonEquiJoinCondition(); - } - - public boolean isJoinMatched(JoinDesc other) { - return join.equals(other); - } - - public boolean isNonEquiJoin() { - return nonEquiJoinCondition != null; - } - - public boolean isLeftJoin() { - return !join.isLeftOrInnerJoin() && join.isLeftJoin(); - } - - public boolean isLeftOrInnerJoin() { - return join.isLeftOrInnerJoin(); - } - - public boolean isInnerJoin() { - return !join.isLeftOrInnerJoin() && join.isInnerJoin(); - } - - private TableRef left() { - return join.getFKSide(); - } - - private TableRef right() { - return join.getPKSide(); - } - - private boolean isFkSide(TableRef tableRef) { - return join.getFKSide().equals(tableRef); - } - - private boolean isPkSide(TableRef tableRef) { - return join.getPKSide().equals(tableRef); - } - - private TableRef other(TableRef tableRef) { - if (left().equals(tableRef)) { - return right(); - } else if (right().equals(tableRef)) { - return left(); - } - throw new IllegalArgumentException("table " + tableRef + " is not on the edge " + this); - } - - @Override - public boolean equals(Object that) { - if (that == null) - return false; - - if (this.getClass() != that.getClass()) - return false; - - return joinEdgeMatcher.matches(this, (Edge) that); - } - - @Override - public int hashCode() { - if (this.isLeftJoin()) { - return Objects.hash(isLeftJoin(), leftCols, rightCols); - } else { - if (Arrays.hashCode(leftCols) < Arrays.hashCode(rightCols)) { - return Objects.hash(isLeftJoin(), leftCols, rightCols); - } else { - return Objects.hash(isLeftJoin(), rightCols, leftCols); - } - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("Edge: "); - sb.append(left()) - .append(isLeftJoin() ? " LEFT JOIN " - : isLeftOrInnerJoin() ? " LEFT OR INNER JOIN " : " INNER JOIN ") - .append(right()).append(" ON ") - .append(Arrays.toString(Arrays.stream(leftCols).map(ColumnDesc::getName).toArray())).append(" = ") - .append(Arrays.toString(Arrays.stream(rightCols).map(ColumnDesc::getName).toArray())); - return sb.toString(); - } - } - - private Edge edgeOf(JoinDesc join) { - return new Edge(join); - } - - private static final IJoinEdgeMatcher DEFAULT_JOIN_EDGE_MATCHER = new DefaultJoinEdgeMatcher(); - @Setter - private IJoinEdgeMatcher joinEdgeMatcher = DEFAULT_JOIN_EDGE_MATCHER; - - /** - * compare: - * 1. JoinType - * 2. Columns on both sides - */ - public interface IJoinEdgeMatcher extends Serializable { - boolean matches(@NonNull Edge join1, @NonNull Edge join2); - } - - public static class DefaultJoinEdgeMatcher implements IJoinEdgeMatcher { - @Override - public boolean matches(@NonNull Edge join1, @NonNull Edge join2) { - if (join1.isLeftJoin() != join2.isLeftJoin() && !join1.isLeftOrInnerJoin() && !join2.isLeftOrInnerJoin()) { - return false; - } - - if (!Objects.equals(join1.nonEquiJoinCondition, join2.nonEquiJoinCondition)) { - return false; - } - - if (join1.isLeftJoin()) { - return columnDescEquals(join1.leftCols, join2.leftCols) - && columnDescEquals(join1.rightCols, join2.rightCols); - } else { - return (columnDescEquals(join1.leftCols, join2.leftCols) - && columnDescEquals(join1.rightCols, join2.rightCols)) - || (columnDescEquals(join1.leftCols, join2.rightCols) - && columnDescEquals(join1.rightCols, join2.leftCols)); - } - } - - private boolean columnDescEquals(ColumnDesc[] a, ColumnDesc[] b) { - if (a.length != b.length) { - return false; - } - - List<ColumnDesc> oneList = Lists.newArrayList(a); - List<ColumnDesc> anotherList = Lists.newArrayList(b); - - for (ColumnDesc obj : oneList) { - anotherList.removeIf(dual -> columnDescEquals(obj, dual)); - } - return anotherList.isEmpty(); - } - - protected boolean columnDescEquals(ColumnDesc a, ColumnDesc b) { - return Objects.equals(a, b); - } - } - - @Getter - private final TableRef center; - private final Map<String, TableRef> nodes = new HashMap<>(); - private final Set<Edge> edges = new HashSet<>(); - private final Map<TableRef, List<Edge>> edgesFromNode = new HashMap<>(); - private final Map<TableRef, List<Edge>> edgesToNode = new HashMap<>(); - - /** - * For model there's always a center, if there's only one tableScan it's the center. - * Otherwise the center is not determined, it's a linked graph, hard to tell the center. - */ - public JoinsGraph(TableRef root, List<JoinDesc> joins) { - this.center = root; - addNode(root); - - for (JoinDesc join : joins) { - Preconditions.checkState(Arrays.stream(join.getForeignKeyColumns()).allMatch(TblColRef::isQualified)); - Preconditions.checkState(Arrays.stream(join.getPrimaryKeyColumns()).allMatch(TblColRef::isQualified)); - addAsEdge(join); - } - - validate(joins); - } - - private void addNode(TableRef table) { - Preconditions.checkNotNull(table); - String alias = table.getAlias(); - TableRef node = nodes.get(alias); - if (node != null) { - Preconditions.checkArgument(node.equals(table), "[%s]'s Alias \"%s\" has conflict with [%s].", table, alias, - node); - } else { - nodes.put(alias, table); - } - } - - private void addAsEdge(JoinDesc join) { - TableRef fkTable = join.getFKSide(); - TableRef pkTable = join.getPKSide(); - addNode(pkTable); - - Edge edge = edgeOf(join); - edgesFromNode.computeIfAbsent(fkTable, fk -> Lists.newArrayList()); - edgesFromNode.get(fkTable).add(edge); - edgesToNode.computeIfAbsent(pkTable, pk -> Lists.newArrayList()); - edgesToNode.get(pkTable).add(edge); - if (!edge.isLeftJoin()) { - // inner join is reversible - edgesFromNode.computeIfAbsent(pkTable, pk -> Lists.newArrayList()); - edgesFromNode.get(pkTable).add(edge); - edgesToNode.computeIfAbsent(fkTable, fk -> Lists.newArrayList()); - edgesToNode.get(fkTable).add(edge); - } - edges.add(edge); - } - - public void setJoinToLeftOrInner(JoinDesc join) { - if (!join.isLeftJoin()) { - join.setLeftOrInner(true); - return; - } - - join.setLeftOrInner(true); - TableRef fkTable = join.getFKSide(); - TableRef pkTable = join.getPKSide(); - Edge edge = edges.stream().filter(e -> e.isJoinMatched(join)).findFirst().orElse(null); - if (edge == null) { - return; - } - edgesFromNode.computeIfAbsent(pkTable, pk -> Lists.newArrayList()); - edgesFromNode.get(pkTable).add(edge); - edgesToNode.computeIfAbsent(fkTable, fk -> Lists.newArrayList()); - edgesToNode.get(fkTable).add(edge); - } - - private void validate(List<JoinDesc> joins) { - for (JoinDesc join : joins) { - TableRef fkTable = join.getFKSide(); - Preconditions.checkNotNull(nodes.get(fkTable.getAlias())); - Preconditions.checkState(nodes.get(fkTable.getAlias()).equals(fkTable)); - } - Preconditions.checkState(nodes.size() == joins.size() + 1); - } - - public boolean match(JoinsGraph pattern, Map<String, String> matchAlias) { - return match(pattern, matchAlias, false); - } - - public boolean match(JoinsGraph pattern, Map<String, String> matchAlias, boolean matchPatial) { - return match(pattern, matchAlias, matchPatial, false); - } - - public boolean match(JoinsGraph pattern, Map<String, String> matchAlias, boolean matchPatial, - boolean matchPartialNonEquiJoin) { - if (pattern == null || pattern.center == null) { - throw new IllegalArgumentException("pattern(model) should have a center: " + pattern); - } - - List<TableRef> candidatesOfQCenter = searchCenterByIdentity(pattern.center); - if (CollectionUtils.isEmpty(candidatesOfQCenter)) { - return false; - } - - for (TableRef queryCenter : candidatesOfQCenter) { - // query <-> pattern - Map<TableRef, TableRef> trialMatch = Maps.newHashMap(); - trialMatch.put(queryCenter, pattern.center); - - if (!checkInnerJoinNum(pattern, queryCenter, pattern.center, matchPatial)) { - continue; - } - - AtomicReference<Map<TableRef, TableRef>> finalMatchRef = new AtomicReference<>(); - innerMatch(pattern, trialMatch, matchPatial, finalMatchRef); - if (finalMatchRef.get() != null - && (matchPartialNonEquiJoin || checkNonEquiJoinMatches(finalMatchRef.get(), pattern))) { - matchAlias.clear(); - matchAlias.putAll(finalMatchRef.get().entrySet().stream() - .collect(Collectors.toMap(e -> e.getKey().getAlias(), e -> e.getValue().getAlias()))); - return true; - } - } - return false; - } - - public static JoinsGraph normalizeJoinGraph(JoinsGraph joinsGraph) { - for (Edge edge : joinsGraph.edges) { - if (!edge.isLeftJoin() || edge.isLeftOrInnerJoin()) { - TableRef leftTable = edge.left(); - List<Edge> edgeList = joinsGraph.edgesToNode.get(leftTable); - if (CollectionUtils.isEmpty(edgeList)) { - continue; - } - for (Edge targetEdge : edgeList) { - if (!edge.equals(targetEdge) && leftTable.equals(targetEdge.right()) - && !targetEdge.isLeftOrInnerJoin()) { - joinsGraph.setJoinToLeftOrInner(targetEdge.join); - normalizeJoinGraph(joinsGraph); - } - } - } - } - return joinsGraph; - } - - public List<TableRef> getAllTblRefNodes() { - return Lists.newArrayList(nodes.values()); - } - - /** - * check if any non-equi join is missed in the pattern - * if so, we cannot match the current graph with the the pattern graph. - * set `kylin.query.match-partial-non-equi-join-model` to skip this checking - * @param matches - * @return - */ - private boolean checkNonEquiJoinMatches(Map<TableRef, TableRef> matches, JoinsGraph pattern) { - HashSet<TableRef> patternGraphTables = new HashSet<>(pattern.nodes.values()); - - for (TableRef patternTable : patternGraphTables) { - List<Edge> outgoingEdges = pattern.getEdgesByFKSide(patternTable); - // for all outgoing non-equi join edges - // if there is no match found for the right side table in the current graph - // return false - for (Edge outgoingEdge : outgoingEdges) { - if (outgoingEdge.isNonEquiJoin()) { - if (!matches.containsValue(patternTable) || !matches.containsValue(outgoingEdge.right())) { - return false; - } - } - } - } - return true; - } - - private boolean isAllJoinInner(JoinsGraph joinsGraph, TableRef tableRef) { - List<Edge> edgesFromNode = joinsGraph.edgesFromNode.get(tableRef); - List<Edge> edgesToNode = joinsGraph.edgesToNode.get(tableRef); - - if (edgesFromNode == null) { - return false; - } - - if (edgesToNode == null) { - return false; - } - - if (edgesToNode.size() != edgesFromNode.size()) { - return false; - } - - for (Edge edge : edgesFromNode) { - if (edge.join.isLeftJoin()) { - return false; - } - } - - return true; - } - - private boolean checkInnerJoinNum(JoinsGraph pattern, TableRef queryTableRef, TableRef patternTableRef, - boolean matchPartial) { - if (matchPartial) { - return true; - } - // fully match: unmatched if extra inner join edge on either graph - // matched if: query graph join count: model graph join count: - // 1) inner join <= inner join - // 2) inner join + left or inner join >= inner join - List<Edge> innerQueryEdges = this.edgesFrom(queryTableRef).stream().filter(Edge::isInnerJoin) - .collect(Collectors.toList()); - List<Edge> notLeftQueryEdges = this.edgesFrom(queryTableRef).stream().filter(e -> !e.isLeftJoin()) - .collect(Collectors.toList()); - List<Edge> innerPatternEdges = pattern.edgesFrom(patternTableRef).stream().filter(Edge::isInnerJoin) - .collect(Collectors.toList()); - - // if all joins are inner joins, compare sum of both sides - if (isAllJoinInner(this, queryTableRef) && isAllJoinInner(pattern, patternTableRef)) { - int cntInnerQueryEdges = innerQueryEdges.size(); - int cntNotLeftQueryEdges = notLeftQueryEdges.size(); - int cntInnerPatternEdges = innerPatternEdges.size(); - return cntInnerQueryEdges <= cntInnerPatternEdges && cntNotLeftQueryEdges >= cntInnerPatternEdges; - } - - // if not all joins are inner, compare left side and right side separately - // Calculate join count in query graph - int cntLeftSideInnerQueryEdges = (int) innerQueryEdges.stream() - .filter(edge -> edge.right().equals(queryTableRef)).count(); - int cntRightSideInnerQueryEdges = (int) innerQueryEdges.stream() - .filter(edge -> edge.left().equals(queryTableRef)).count(); - int cntLeftSideNotLeftQueryEdges = (int) notLeftQueryEdges.stream() - .filter(edge -> edge.right().equals(queryTableRef)).count(); - int cntRightSideNotLeftQueryEdges = (int) notLeftQueryEdges.stream() - .filter(edge -> edge.left().equals(queryTableRef)).count(); - // Calculate join count in model graph - int cntLeftSideInnerPatternEdges = (int) innerPatternEdges.stream() - .filter(edge -> edge.right().equals(patternTableRef)).count(); - int cntRightSideInnerPatternEdges = (int) innerPatternEdges.stream() - .filter(edge -> edge.left().equals(patternTableRef)).count(); - - boolean isLeftEqual = cntLeftSideInnerQueryEdges <= cntLeftSideInnerPatternEdges - && cntLeftSideNotLeftQueryEdges >= cntLeftSideInnerPatternEdges; - boolean isRightEqual = cntRightSideInnerQueryEdges <= cntRightSideInnerPatternEdges - && cntRightSideNotLeftQueryEdges >= cntRightSideInnerPatternEdges; - return isLeftEqual && isRightEqual; - } - - private void innerMatch(JoinsGraph pattern, Map<TableRef, TableRef> trialMatches, boolean matchPartial, - AtomicReference<Map<TableRef, TableRef>> finalMatch) { - if (trialMatches.size() == nodes.size()) { - //match is found - finalMatch.set(trialMatches); - return; - } - - Preconditions.checkState(nodes.size() > trialMatches.size()); - Optional<Pair<Edge, TableRef>> toMatch = trialMatches.keySet().stream() - .map(t -> edgesFrom(t).stream().filter(e -> !trialMatches.containsKey(e.other(t))).findFirst() - .map(edge -> new Pair<>(edge, edge.other(t))).orElse(null)) - .filter(Objects::nonNull).findFirst(); - - Preconditions.checkState(toMatch.isPresent()); - Edge toMatchQueryEdge = toMatch.get().getFirst(); - TableRef toMatchQueryNode = toMatch.get().getSecond(); - TableRef matchedQueryNode = toMatchQueryEdge.other(toMatchQueryNode); - TableRef matchedPatternNode = trialMatches.get(matchedQueryNode); - - List<TableRef> toMatchPatternNodeCandidates = Lists.newArrayList(); - for (Edge patternEdge : pattern.edgesFrom(matchedPatternNode)) { - TableRef toMatchPatternNode = patternEdge.other(matchedPatternNode); - if (!toMatchQueryNode.getTableIdentity().equals(toMatchPatternNode.getTableIdentity()) - || !toMatchQueryEdge.equals(patternEdge) || trialMatches.containsValue(toMatchPatternNode) - || !checkInnerJoinNum(pattern, toMatchQueryNode, toMatchPatternNode, matchPartial)) { - continue; - } - toMatchPatternNodeCandidates.add(toMatchPatternNode); - } - - for (TableRef toMatchPatternNode : toMatchPatternNodeCandidates) { - Map<TableRef, TableRef> newTrialMatches = Maps.newHashMap(); - newTrialMatches.putAll(trialMatches); - newTrialMatches.put(toMatchQueryNode, toMatchPatternNode); - innerMatch(pattern, newTrialMatches, matchPartial, finalMatch); - if (finalMatch.get() != null) { - //get out of recursive invoke chain straightly - return; - } - } - } - - public List<Edge> unmatched(JoinsGraph pattern) { - List<Edge> unmatched = Lists.newArrayList(); - Set<Edge> all = edgesFromNode.values().stream().flatMap(List::stream).collect(Collectors.toSet()); - for (Edge edge : all) { - List<JoinDesc> joins = getJoinsPathByPKSide(edge.right()); - JoinsGraph subGraph = new JoinsGraph(center, joins); - if (subGraph.match(pattern, Maps.newHashMap())) { - continue; - } - unmatched.add(edge); - } - return unmatched; - } - - private List<TableRef> searchCenterByIdentity(final TableRef table) { - // special case: several same nodes in a JoinGraph - return nodes.values().stream().filter(node -> node.getTableIdentity().equals(table.getTableIdentity())) - .filter(node -> { - List<JoinDesc> path2Center = getJoinsPathByPKSide(node); - return path2Center.stream().noneMatch(JoinDesc::isLeftJoin); - }).collect(Collectors.toList()); - } - - private List<Edge> edgesFrom(TableRef thisSide) { - return edgesFromNode.getOrDefault(thisSide, Lists.newArrayList()); - } - - public Map<String, String> matchAlias(JoinsGraph joinsGraph, KylinConfig kylinConfig) { - Map<String, String> matchAlias = Maps.newHashMap(); - match(joinsGraph, matchAlias, kylinConfig.isQueryMatchPartialInnerJoinModel(), - kylinConfig.partialMatchNonEquiJoins()); - return matchAlias; - } - - public Map<String, String> matchAlias(JoinsGraph joinsGraph, boolean matchPartial) { - Map<String, String> matchAlias = Maps.newHashMap(); - match(joinsGraph, matchAlias, matchPartial); - return matchAlias; - } - - public List<Edge> getEdgesByFKSide(TableRef table) { - if (!edgesFromNode.containsKey(table)) { - return Lists.newArrayList(); - } - return edgesFromNode.get(table).stream().filter(e -> e.isFkSide(table)).collect(Collectors.toList()); - } - - private Edge getEdgeByPKSide(TableRef table) { - if (!edgesToNode.containsKey(table)) { - return null; - } - List<Edge> edgesByPkSide = edgesToNode.get(table).stream().filter(e -> e.isPkSide(table)) - .collect(Collectors.toList()); - if (edgesByPkSide.isEmpty()) { - return null; - } - Preconditions.checkState(edgesByPkSide.size() == 1, "%s is allowed to be Join PK side once", table); - return edgesByPkSide.get(0); - } - - public JoinDesc getJoinByPKSide(TableRef table) { - Edge edge = getEdgeByPKSide(table); - return edge != null ? edge.join : null; - } - - private List<JoinDesc> getJoinsPathByPKSide(TableRef table) { - List<JoinDesc> pathToRoot = Lists.newArrayList(); - TableRef pkSide = table; // start from leaf - while (pkSide != null) { - JoinDesc subJoin = getJoinByPKSide(pkSide); - if (subJoin != null) { - pathToRoot.add(subJoin); - pkSide = subJoin.getFKSide(); - } else { - pkSide = null; - } - } - return Lists.reverse(pathToRoot); - } - - public JoinsGraph getSubgraphByAlias(Set<String> aliasSets) { - TableRef subGraphRoot = this.center; - Set<JoinDesc> subGraphJoin = Sets.newHashSet(); - for (String alias : aliasSets) { - subGraphJoin.addAll(getJoinsPathByPKSide(nodes.get(alias))); - } - return new JoinsGraph(subGraphRoot, Lists.newArrayList(subGraphJoin)); - } - - @Override - public String toString() { - StringBuilder graphStrBuilder = new StringBuilder(); - graphStrBuilder.append("Root: ").append(center); - List<Edge> nextEdges = getEdgesByFKSide(center); - nextEdges.forEach(e -> buildGraphStr(graphStrBuilder, e, 1)); - return graphStrBuilder.toString(); - } - - private void buildGraphStr(StringBuilder sb, @NonNull Edge edge, int indent) { - sb.append('\n'); - for (int i = 0; i < indent; i++) { - sb.append(" "); - } - sb.append(edge); - List<Edge> nextEdges = getEdgesByFKSide(edge.right()); - nextEdges.forEach(e -> buildGraphStr(sb, e, indent + 1)); - } -} diff --git a/src/core-metadata/src/main/java/org/apache/kylin/metadata/model/graph/JoinsGraph.java b/src/core-metadata/src/main/java/org/apache/kylin/metadata/model/graph/JoinsGraph.java index 67f8e26bfc..b6342fd476 100644 --- a/src/core-metadata/src/main/java/org/apache/kylin/metadata/model/graph/JoinsGraph.java +++ b/src/core-metadata/src/main/java/org/apache/kylin/metadata/model/graph/JoinsGraph.java @@ -355,7 +355,7 @@ public class JoinsGraph implements Serializable { } for (Edge targetEdge : edgeList) { if (!edge.equals(targetEdge) && fkSide.equals(targetEdge.pkSide()) - && !targetEdge.isLeftOrInnerJoin()) { + && !targetEdge.isLeftOrInnerJoin() && targetEdge.isLeftJoin()) { setJoinToLeftOrInner(targetEdge.join); normalize(); } diff --git a/src/core-metadata/src/test/java/org/apache/kylin/metadata/model/JoinsGraphTest.java b/src/core-metadata/src/test/java/org/apache/kylin/metadata/model/JoinsGraphTest.java index 65ad1e25da..65a359e63f 100644 --- a/src/core-metadata/src/test/java/org/apache/kylin/metadata/model/JoinsGraphTest.java +++ b/src/core-metadata/src/test/java/org/apache/kylin/metadata/model/JoinsGraphTest.java @@ -29,6 +29,8 @@ import org.apache.kylin.common.KylinConfig; import org.apache.kylin.common.exception.KylinException; import org.apache.kylin.common.util.NLocalFileMetadataTestCase; import org.apache.kylin.common.util.Unsafe; +import org.apache.kylin.metadata.model.graph.DefaultJoinEdgeMatcher; +import org.apache.kylin.metadata.model.graph.JoinsGraph; import org.apache.kylin.metadata.project.NProjectManager; import org.junit.Assert; import org.junit.Before; @@ -349,7 +351,7 @@ public class JoinsGraphTest extends NLocalFileMetadataTestCase { public void testColumnDescEquals() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { NTableMetadataManager manager = NTableMetadataManager.getInstance(getTestConfig(), "default"); TableDesc tableDesc = manager.getTableDesc("DEFAULT.TEST_KYLIN_FACT"); - JoinsGraph.DefaultJoinEdgeMatcher matcher = new JoinsGraph.DefaultJoinEdgeMatcher(); + DefaultJoinEdgeMatcher matcher = new DefaultJoinEdgeMatcher(); ColumnDesc one = new ColumnDesc(); one.setTable(tableDesc); one.setName("one");