diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index f92f04a7c6513..028b2d01e8718 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -11,6 +11,7 @@ ### Bug Fix 1. Mode: Fixes `JDBCRepository` improper handling of H2database in memory mode - [#33281](https://github.com/apache/shardingsphere/issues/33281) +1. SQL Binder: Use Multimap and CaseInsensitiveString to replace CaseInsensitiveMap for supporting mysql multi table join with same table alias - [#33303](https://github.com/apache/shardingsphere/pull/33303) ### Change Log 1. [MILESTONE](https://github.com/apache/shardingsphere/milestone/30) diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/assign/AssignmentSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/assign/AssignmentSegmentBinder.java index 26b129bb909aa..2d47f9c66bec0 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/assign/AssignmentSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/assign/AssignmentSegmentBinder.java @@ -17,6 +17,8 @@ package org.apache.shardingsphere.infra.binder.engine.segment.assign; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; @@ -30,7 +32,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; /** @@ -49,14 +50,15 @@ public final class AssignmentSegmentBinder { * @return bound assignment segment */ public static SetAssignmentSegment bind(final SetAssignmentSegment segment, final SQLStatementBinderContext binderContext, - final Map tableBinderContexts, final Map outerTableBinderContexts) { + final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts) { return new SetAssignmentSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getAssignments().stream() .map(each -> bindColumnAssignmentSegment(each, binderContext, tableBinderContexts, outerTableBinderContexts)).collect(Collectors.toList())); } private static ColumnAssignmentSegment bindColumnAssignmentSegment(final ColumnAssignmentSegment columnAssignmentSegment, final SQLStatementBinderContext binderContext, - final Map tableBinderContexts, - final Map outerTableBinderContexts) { + final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts) { List boundColumns = columnAssignmentSegment.getColumns().stream() .map(each -> ColumnSegmentBinder.bind(each, SegmentType.SET_ASSIGNMENT, binderContext, tableBinderContexts, outerTableBinderContexts)).collect(Collectors.toList()); ExpressionSegment boundValue = ExpressionSegmentBinder.bind(columnAssignmentSegment.getValue(), SegmentType.SET_ASSIGNMENT, binderContext, tableBinderContexts, outerTableBinderContexts); diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/column/InsertColumnsSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/column/InsertColumnsSegmentBinder.java index 1ac6aff5219bd..5f02778d073b8 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/column/InsertColumnsSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/column/InsertColumnsSegmentBinder.java @@ -17,6 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.segment.column; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; @@ -27,8 +30,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.InsertColumnsSegment; import java.util.Collection; -import java.util.Collections; -import java.util.Map; import java.util.stream.Collectors; /** @@ -45,9 +46,10 @@ public final class InsertColumnsSegmentBinder { * @param tableBinderContexts table binder contexts * @return bound insert columns segment */ - public static InsertColumnsSegment bind(final InsertColumnsSegment segment, final SQLStatementBinderContext binderContext, final Map tableBinderContexts) { + public static InsertColumnsSegment bind(final InsertColumnsSegment segment, final SQLStatementBinderContext binderContext, + final Multimap tableBinderContexts) { Collection boundColumns = segment.getColumns().stream() - .map(each -> ColumnSegmentBinder.bind(each, SegmentType.INSERT_COLUMNS, binderContext, tableBinderContexts, Collections.emptyMap())).collect(Collectors.toList()); + .map(each -> ColumnSegmentBinder.bind(each, SegmentType.INSERT_COLUMNS, binderContext, tableBinderContexts, LinkedHashMultimap.create())).collect(Collectors.toList()); return new InsertColumnsSegment(segment.getStartIndex(), segment.getStopIndex(), boundColumns); } } diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/ExpressionSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/ExpressionSegmentBinder.java index 0cb80277d7d6b..5adaf40ff5d11 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/ExpressionSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/ExpressionSegmentBinder.java @@ -17,6 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.segment.expression; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; @@ -38,9 +41,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.NotExpression; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubqueryExpressionSegment; -import java.util.LinkedHashMap; -import java.util.Map; - /** * Expression segment binder. */ @@ -58,7 +58,8 @@ public final class ExpressionSegmentBinder { * @return bound expression segment */ public static ExpressionSegment bind(final ExpressionSegment segment, final SegmentType parentSegmentType, final SQLStatementBinderContext binderContext, - final Map tableBinderContexts, final Map outerTableBinderContexts) { + final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts) { if (segment instanceof BinaryOperationExpression) { return BinaryOperationExpressionBinder.bind((BinaryOperationExpression) segment, parentSegmentType, binderContext, tableBinderContexts, outerTableBinderContexts); } @@ -66,7 +67,7 @@ public static ExpressionSegment bind(final ExpressionSegment segment, final Segm return ExistsSubqueryExpressionBinder.bind((ExistsSubqueryExpression) segment, binderContext, tableBinderContexts); } if (segment instanceof SubqueryExpressionSegment) { - Map newOuterTableBinderContexts = new LinkedHashMap<>(); + Multimap newOuterTableBinderContexts = LinkedHashMultimap.create(); newOuterTableBinderContexts.putAll(outerTableBinderContexts); newOuterTableBinderContexts.putAll(tableBinderContexts); return new SubqueryExpressionSegment(SubquerySegmentBinder.bind(((SubqueryExpressionSegment) segment).getSubquery(), binderContext, newOuterTableBinderContexts)); diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/BinaryOperationExpressionBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/BinaryOperationExpressionBinder.java index 3add920b69474..43cb19973c0df 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/BinaryOperationExpressionBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/BinaryOperationExpressionBinder.java @@ -17,6 +17,8 @@ package org.apache.shardingsphere.infra.binder.engine.segment.expression.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; @@ -26,8 +28,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BinaryOperationExpression; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment; -import java.util.Map; - /** * Binary operation expression binder. */ @@ -45,7 +45,8 @@ public final class BinaryOperationExpressionBinder { * @return bound binary operation expression segment */ public static BinaryOperationExpression bind(final BinaryOperationExpression segment, final SegmentType parentSegmentType, final SQLStatementBinderContext binderContext, - final Map tableBinderContexts, final Map outerTableBinderContexts) { + final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts) { ExpressionSegment boundLeft = ExpressionSegmentBinder.bind(segment.getLeft(), parentSegmentType, binderContext, tableBinderContexts, outerTableBinderContexts); ExpressionSegment boundRight = ExpressionSegmentBinder.bind(segment.getRight(), parentSegmentType, binderContext, tableBinderContexts, outerTableBinderContexts); return new BinaryOperationExpression(segment.getStartIndex(), segment.getStopIndex(), boundLeft, boundRight, segment.getOperator(), segment.getText()); diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ColumnSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ColumnSegmentBinder.java index 527957067bf9d..ca8f52b857264 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ColumnSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ColumnSegmentBinder.java @@ -17,7 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.segment.expression.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; import com.google.common.base.Strings; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.groovy.util.Maps; @@ -71,7 +73,8 @@ public final class ColumnSegmentBinder { * @return bound column segment */ public static ColumnSegment bind(final ColumnSegment segment, final SegmentType parentSegmentType, final SQLStatementBinderContext binderContext, - final Map tableBinderContexts, final Map outerTableBinderContexts) { + final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts) { if (EXCLUDE_BIND_COLUMNS.contains(segment.getIdentifier().getValue().toUpperCase())) { return segment; } @@ -93,12 +96,11 @@ private static ColumnSegment copy(final ColumnSegment segment) { private static Collection getTableSegmentBinderContexts(final ColumnSegment segment, final SegmentType parentSegmentType, final SQLStatementBinderContext binderContext, - final Map tableBinderContexts, - final Map outerTableBinderContexts) { + final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts) { if (segment.getOwner().isPresent()) { - String owner = segment.getOwner().get().getIdentifier().getValue().toLowerCase(); - return findTableBinderContextByOwner(owner, tableBinderContexts, outerTableBinderContexts, binderContext.getExternalTableBinderContexts()) - .map(Collections::singletonList).orElse(Collections.emptyList()); + String owner = segment.getOwner().get().getIdentifier().getValue(); + return getTableBinderContextByOwner(owner, tableBinderContexts, outerTableBinderContexts, binderContext.getExternalTableBinderContexts()); } if (!binderContext.getJoinTableProjectionSegments().isEmpty() && isNeedUseJoinTableProjectionBind(segment, parentSegmentType, binderContext)) { return Collections.singleton(new SimpleTableSegmentBinderContext(binderContext.getJoinTableProjectionSegments())); @@ -106,28 +108,30 @@ private static Collection getTableSegmentBinderContex return tableBinderContexts.values(); } - private static Optional findTableBinderContextByOwner(final String owner, final Map tableBinderContexts, - final Map outerTableBinderContexts, - final Map externalTableBinderContexts) { - if (tableBinderContexts.containsKey(owner)) { - return Optional.of(tableBinderContexts.get(owner)); + private static Collection getTableBinderContextByOwner(final String owner, final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts, + final Multimap externalTableBinderContexts) { + CaseInsensitiveString caseInsensitiveOwner = new CaseInsensitiveString(owner); + if (tableBinderContexts.containsKey(caseInsensitiveOwner)) { + return tableBinderContexts.get(caseInsensitiveOwner); } - if (outerTableBinderContexts.containsKey(owner)) { - return Optional.of(outerTableBinderContexts.get(owner)); + if (outerTableBinderContexts.containsKey(caseInsensitiveOwner)) { + return outerTableBinderContexts.get(caseInsensitiveOwner); } - if (externalTableBinderContexts.containsKey(owner)) { - return Optional.of(externalTableBinderContexts.get(owner)); + if (externalTableBinderContexts.containsKey(caseInsensitiveOwner)) { + return externalTableBinderContexts.get(caseInsensitiveOwner); } - return Optional.empty(); + return Collections.emptyList(); } private static boolean isNeedUseJoinTableProjectionBind(final ColumnSegment segment, final SegmentType parentSegmentType, final SQLStatementBinderContext binderContext) { return SegmentType.PROJECTION == parentSegmentType - || SegmentType.PREDICATE == parentSegmentType && binderContext.getUsingColumnNames().contains(segment.getIdentifier().getValue().toLowerCase()); + || SegmentType.PREDICATE == parentSegmentType && binderContext.getUsingColumnNames().contains(segment.getIdentifier().getValue()); } private static Optional findInputColumnSegment(final ColumnSegment segment, final SegmentType parentSegmentType, final Collection tableBinderContexts, - final Map outerTableBinderContexts, final SQLStatementBinderContext binderContext) { + final Multimap outerTableBinderContexts, + final SQLStatementBinderContext binderContext) { ColumnSegment result = null; boolean isFindInputColumn = false; for (TableSegmentBinderContext each : tableBinderContexts) { @@ -172,13 +176,14 @@ private static Optional findInputColumnSegmentByPivotColumns(fina if (pivotColumnNames.isEmpty()) { return Optional.empty(); } - if (pivotColumnNames.contains(segment.getIdentifier().getValue().toLowerCase())) { + if (pivotColumnNames.contains(segment.getIdentifier().getValue())) { return Optional.of(new ColumnSegment(0, 0, segment.getIdentifier())); } return Optional.empty(); } - private static Optional findInputColumnSegmentFromOuterTable(final ColumnSegment segment, final Map outerTableBinderContexts) { + private static Optional findInputColumnSegmentFromOuterTable(final ColumnSegment segment, + final Multimap outerTableBinderContexts) { ListIterator listIterator = new ArrayList<>(outerTableBinderContexts.values()).listIterator(outerTableBinderContexts.size()); while (listIterator.hasPrevious()) { TableSegmentBinderContext each = listIterator.previous(); @@ -190,7 +195,8 @@ private static Optional findInputColumnSegmentFromOuterTable( return Optional.empty(); } - private static Optional findInputColumnSegmentFromExternalTables(final ColumnSegment segment, final Map externalTableBinderContexts) { + private static Optional findInputColumnSegmentFromExternalTables(final ColumnSegment segment, + final Multimap externalTableBinderContexts) { for (TableSegmentBinderContext each : externalTableBinderContexts.values()) { Optional result = each.findProjectionSegmentByColumnLabel(segment.getIdentifier().getValue()); if (result.isPresent()) { @@ -204,7 +210,7 @@ private static Optional findInputColumnSegmentByVariables(final C if (variableNames.isEmpty()) { return Optional.empty(); } - if (variableNames.contains(segment.getIdentifier().getValue().toLowerCase())) { + if (variableNames.contains(segment.getIdentifier().getValue())) { ColumnSegment result = new ColumnSegment(0, 0, segment.getIdentifier()); result.setVariable(true); return Optional.of(result); @@ -246,7 +252,8 @@ private static ColumnSegmentBoundInfo createColumnSegmentBoundInfo(final ColumnS * @param tableBinderContexts table binder contexts * @return bound using column segment */ - public static ColumnSegment bindUsingColumn(final ColumnSegment segment, final SegmentType parentSegmentType, final Map tableBinderContexts) { + public static ColumnSegment bindUsingColumn(final ColumnSegment segment, final SegmentType parentSegmentType, + final Multimap tableBinderContexts) { ColumnSegment result = copy(segment); List usingInputColumnSegments = findUsingInputColumnSegments(segment.getIdentifier().getValue(), tableBinderContexts.values()); ShardingSpherePreconditions.checkState(usingInputColumnSegments.size() >= 2, diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ExistsSubqueryExpressionBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ExistsSubqueryExpressionBinder.java index 9630e72e03cf8..70026051bccd0 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ExistsSubqueryExpressionBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ExistsSubqueryExpressionBinder.java @@ -17,6 +17,8 @@ package org.apache.shardingsphere.infra.binder.engine.segment.expression.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; @@ -24,8 +26,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExistsSubqueryExpression; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubquerySegment; -import java.util.Map; - /** * Exists subquery expression binder. */ @@ -41,7 +41,7 @@ public final class ExistsSubqueryExpressionBinder { * @return bound exists subquery expression segment */ public static ExistsSubqueryExpression bind(final ExistsSubqueryExpression segment, final SQLStatementBinderContext binderContext, - final Map tableBinderContexts) { + final Multimap tableBinderContexts) { SubquerySegment boundSubquery = SubquerySegmentBinder.bind(segment.getSubquery(), binderContext, tableBinderContexts); ExistsSubqueryExpression result = new ExistsSubqueryExpression(segment.getStartIndex(), segment.getStopIndex(), boundSubquery); result.setNot(segment.isNot()); diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/FunctionExpressionSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/FunctionExpressionSegmentBinder.java index 3db6db5b4b6bc..a169c4b5e9e01 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/FunctionExpressionSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/FunctionExpressionSegmentBinder.java @@ -17,6 +17,8 @@ package org.apache.shardingsphere.infra.binder.engine.segment.expression.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; @@ -25,7 +27,6 @@ import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.FunctionSegment; -import java.util.Map; import java.util.stream.Collectors; /** @@ -45,7 +46,8 @@ public final class FunctionExpressionSegmentBinder { * @return bound function segment */ public static FunctionSegment bind(final FunctionSegment segment, final SegmentType parentSegmentType, final SQLStatementBinderContext binderContext, - final Map tableBinderContexts, final Map outerTableBinderContexts) { + final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts) { FunctionSegment result = new FunctionSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getFunctionName(), segment.getText()); result.setOwner(segment.getOwner()); result.getParameters().addAll(segment.getParameters().stream() diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/InExpressionBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/InExpressionBinder.java index f14e95a74370f..8233c07b324a9 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/InExpressionBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/InExpressionBinder.java @@ -17,6 +17,8 @@ package org.apache.shardingsphere.infra.binder.engine.segment.expression.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; @@ -26,8 +28,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.InExpression; -import java.util.Map; - /** * In expression binder. */ @@ -45,7 +45,8 @@ public final class InExpressionBinder { * @return bound in expression */ public static InExpression bind(final InExpression segment, final SegmentType parentSegmentType, final SQLStatementBinderContext binderContext, - final Map tableBinderContexts, final Map outerTableBinderContexts) { + final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts) { ExpressionSegment boundLeft = ExpressionSegmentBinder.bind(segment.getLeft(), parentSegmentType, binderContext, tableBinderContexts, outerTableBinderContexts); ExpressionSegment boundRight = ExpressionSegmentBinder.bind(segment.getRight(), parentSegmentType, binderContext, tableBinderContexts, outerTableBinderContexts); return new InExpression(segment.getStartIndex(), segment.getStopIndex(), boundLeft, boundRight, segment.isNot()); diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/NotExpressionBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/NotExpressionBinder.java index cc7d608f091f1..b877238d8704a 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/NotExpressionBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/NotExpressionBinder.java @@ -17,6 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.segment.expression.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; @@ -26,9 +29,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.NotExpression; -import java.util.Collections; -import java.util.Map; - /** * Not expression binder. */ @@ -45,8 +45,8 @@ public final class NotExpressionBinder { * @return bound not expression */ public static NotExpression bind(final NotExpression segment, final SegmentType parentSegmentType, - final SQLStatementBinderContext binderContext, final Map tableBinderContexts) { - ExpressionSegment boundExpression = ExpressionSegmentBinder.bind(segment.getExpression(), parentSegmentType, binderContext, tableBinderContexts, Collections.emptyMap()); + final SQLStatementBinderContext binderContext, final Multimap tableBinderContexts) { + ExpressionSegment boundExpression = ExpressionSegmentBinder.bind(segment.getExpression(), parentSegmentType, binderContext, tableBinderContexts, LinkedHashMultimap.create()); return new NotExpression(segment.getStartIndex(), segment.getStopIndex(), boundExpression, segment.getNotSign()); } } diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/SubquerySegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/SubquerySegmentBinder.java index e4723aea035eb..e986c0a0cfd57 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/SubquerySegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/SubquerySegmentBinder.java @@ -17,6 +17,8 @@ package org.apache.shardingsphere.infra.binder.engine.segment.expression.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; @@ -25,8 +27,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubquerySegment; import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.SelectStatement; -import java.util.Map; - /** * Subquery segment binder. */ @@ -41,7 +41,8 @@ public final class SubquerySegmentBinder { * @param outerTableBinderContexts outer table binder contexts * @return bound subquery segment */ - public static SubquerySegment bind(final SubquerySegment segment, final SQLStatementBinderContext binderContext, final Map outerTableBinderContexts) { + public static SubquerySegment bind(final SubquerySegment segment, final SQLStatementBinderContext binderContext, + final Multimap outerTableBinderContexts) { SQLStatementBinderContext selectBinderContext = new SQLStatementBinderContext(segment.getSelect(), binderContext.getMetaData(), binderContext.getCurrentDatabaseName()); selectBinderContext.getExternalTableBinderContexts().putAll(binderContext.getExternalTableBinderContexts()); SelectStatement boundSelectStatement = new SelectStatementBinder(outerTableBinderContexts).bind(segment.getSelect(), selectBinderContext); diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/TableSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/TableSegmentBinder.java index f417d5bc396ea..a29186e97c3ce 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/TableSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/TableSegmentBinder.java @@ -17,6 +17,8 @@ package org.apache.shardingsphere.infra.binder.engine.segment.from; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; @@ -34,8 +36,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SubqueryTableSegment; import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableSegment; -import java.util.Map; - /** * Table segment binder. */ @@ -51,8 +51,8 @@ public final class TableSegmentBinder { * @param outerTableBinderContexts outer table binder contexts * @return bound table segment */ - public static TableSegment bind(final TableSegment segment, final SQLStatementBinderContext binderContext, final Map tableBinderContexts, - final Map outerTableBinderContexts) { + public static TableSegment bind(final TableSegment segment, final SQLStatementBinderContext binderContext, final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts) { if (segment instanceof SimpleTableSegment) { return SimpleTableSegmentBinder.bind((SimpleTableSegment) segment, binderContext, tableBinderContexts); } @@ -66,11 +66,13 @@ public static TableSegment bind(final TableSegment segment, final SQLStatementBi return DeleteMultiTableSegmentBinder.bind((DeleteMultiTableSegment) segment, binderContext, tableBinderContexts); } if (segment instanceof FunctionTableSegment) { - tableBinderContexts.put(segment.getAliasName().orElseGet(() -> ((FunctionTableSegment) segment).getTableFunction().getText()).toLowerCase(), new FunctionTableSegmentBinderContext()); + tableBinderContexts.put(new CaseInsensitiveString(segment.getAliasName().orElseGet(() -> ((FunctionTableSegment) segment).getTableFunction().getText())), + new FunctionTableSegmentBinderContext()); return segment; } if (segment instanceof CollectionTableSegment) { - tableBinderContexts.put(segment.getAliasName().orElseGet(() -> ((CollectionTableSegment) segment).getExpressionSegment().getText()).toLowerCase(), new FunctionTableSegmentBinderContext()); + tableBinderContexts.put(new CaseInsensitiveString(segment.getAliasName().orElseGet(() -> ((CollectionTableSegment) segment).getExpressionSegment().getText())), + new FunctionTableSegmentBinderContext()); return segment; } return segment; diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/DeleteMultiTableSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/DeleteMultiTableSegmentBinder.java index aef146a00b6cd..c1b7e331f81b6 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/DeleteMultiTableSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/DeleteMultiTableSegmentBinder.java @@ -17,6 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.segment.from.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.from.TableSegmentBinder; @@ -24,9 +27,6 @@ import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.DeleteMultiTableSegment; -import java.util.Collections; -import java.util.Map; - /** * Delete multi table segment binder. */ @@ -42,12 +42,12 @@ public final class DeleteMultiTableSegmentBinder { * @return bound delete multi table segment */ public static DeleteMultiTableSegment bind(final DeleteMultiTableSegment segment, - final SQLStatementBinderContext binderContext, final Map tableBinderContexts) { + final SQLStatementBinderContext binderContext, final Multimap tableBinderContexts) { DeleteMultiTableSegment result = new DeleteMultiTableSegment(); result.setStartIndex(segment.getStartIndex()); result.setStopIndex(segment.getStopIndex()); result.getActualDeleteTables().addAll(segment.getActualDeleteTables()); - result.setRelationTable(TableSegmentBinder.bind(segment.getRelationTable(), binderContext, tableBinderContexts, Collections.emptyMap())); + result.setRelationTable(TableSegmentBinder.bind(segment.getRelationTable(), binderContext, tableBinderContexts, LinkedHashMultimap.create())); return result; } } diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/JoinTableSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/JoinTableSegmentBinder.java index 9af254ca17c65..d631ef671395d 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/JoinTableSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/JoinTableSegmentBinder.java @@ -17,6 +17,8 @@ package org.apache.shardingsphere.infra.binder.engine.segment.from.type; +import com.cedarsoftware.util.CaseInsensitiveMap; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; import lombok.AccessLevel; @@ -41,7 +43,6 @@ import java.util.Collection; import java.util.Collections; -import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -62,7 +63,8 @@ public final class JoinTableSegmentBinder { * @return bound join table segment */ public static JoinTableSegment bind(final JoinTableSegment segment, final SQLStatementBinderContext binderContext, - final Map tableBinderContexts, final Map outerTableBinderContexts) { + final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts) { JoinTableSegment result = new JoinTableSegment(); result.setStartIndex(segment.getStartIndex()); result.setStopIndex(segment.getStopIndex()); @@ -71,15 +73,15 @@ public static JoinTableSegment bind(final JoinTableSegment segment, final SQLSta result.setJoinType(segment.getJoinType()); result.setLeft(TableSegmentBinder.bind(segment.getLeft(), binderContext, tableBinderContexts, outerTableBinderContexts)); result.setRight(TableSegmentBinder.bind(segment.getRight(), binderContext, tableBinderContexts, outerTableBinderContexts)); - result.setCondition(ExpressionSegmentBinder.bind(segment.getCondition(), SegmentType.JOIN_ON, binderContext, tableBinderContexts, Collections.emptyMap())); + result.setCondition(ExpressionSegmentBinder.bind(segment.getCondition(), SegmentType.JOIN_ON, binderContext, tableBinderContexts, LinkedHashMultimap.create())); result.setUsing(bindUsingColumns(segment.getUsing(), tableBinderContexts)); - result.getUsing().forEach(each -> binderContext.getUsingColumnNames().add(each.getIdentifier().getValue().toLowerCase())); + result.getUsing().forEach(each -> binderContext.getUsingColumnNames().add(each.getIdentifier().getValue())); Map usingColumnsByNaturalJoin = Collections.emptyMap(); if (result.isNatural()) { usingColumnsByNaturalJoin = getUsingColumnsByNaturalJoin(result, tableBinderContexts); Collection derivedUsingColumns = getDerivedUsingColumns(usingColumnsByNaturalJoin); result.setDerivedUsing(bindUsingColumns(derivedUsingColumns, tableBinderContexts)); - result.getDerivedUsing().forEach(each -> binderContext.getUsingColumnNames().add(each.getIdentifier().getValue().toLowerCase())); + result.getDerivedUsing().forEach(each -> binderContext.getUsingColumnNames().add(each.getIdentifier().getValue())); } result.getDerivedJoinTableProjectionSegments().addAll(getDerivedJoinTableProjectionSegments(result, binderContext.getDatabaseType(), usingColumnsByNaturalJoin, tableBinderContexts)); binderContext.getJoinTableProjectionSegments().addAll(result.getDerivedJoinTableProjectionSegments()); @@ -97,7 +99,7 @@ private static Collection getDerivedUsingColumns(final Map bindUsingColumns(final Collection usingColumns, final Map tableBinderContexts) { + private static List bindUsingColumns(final Collection usingColumns, final Multimap tableBinderContexts) { List result = new LinkedList<>(); for (ColumnSegment each : usingColumns) { result.add(ColumnSegmentBinder.bindUsingColumn(each, SegmentType.JOIN_USING, tableBinderContexts)); @@ -107,7 +109,7 @@ private static List bindUsingColumns(final Collection getDerivedJoinTableProjectionSegments(final JoinTableSegment segment, final DatabaseType databaseType, final Map usingColumnsByNaturalJoin, - final Map tableBinderContexts) { + final Multimap tableBinderContexts) { Collection projectionSegments = getProjectionSegments(segment, databaseType, tableBinderContexts); if (segment.getUsing().isEmpty() && !segment.isNatural()) { return projectionSegments; @@ -122,7 +124,7 @@ private static Collection getDerivedJoinTableProjectionSegmen } private static Collection getProjectionSegments(final JoinTableSegment segment, final DatabaseType databaseType, - final Map tableBinderContexts) { + final Multimap tableBinderContexts) { Collection result = new LinkedList<>(); if (databaseType instanceof MySQLDatabaseType && JoinType.RIGHT.name().equalsIgnoreCase(segment.getJoinType()) && (!segment.getUsing().isEmpty() || segment.isNatural())) { result.addAll(getProjectionSegments(segment.getRight(), tableBinderContexts)); @@ -134,7 +136,7 @@ private static Collection getProjectionSegments(final JoinTab return result; } - private static Collection getProjectionSegments(final TableSegment tableSegment, final Map tableBinderContexts) { + private static Collection getProjectionSegments(final TableSegment tableSegment, final Multimap tableBinderContexts) { Collection result = new LinkedList<>(); if (tableSegment instanceof SimpleTableSegment) { String tableAliasOrName = tableSegment.getAliasName().orElseGet(() -> ((SimpleTableSegment) tableSegment).getTableName().getIdentifier().getValue()); @@ -147,19 +149,20 @@ private static Collection getProjectionSegments(final TableSe return result; } - private static Collection getProjectionSegmentsByTableAliasOrName(final Map tableBinderContexts, final String tableAliasOrName) { - ShardingSpherePreconditions.checkContainsKey(tableBinderContexts, tableAliasOrName.toLowerCase(), + private static Collection getProjectionSegmentsByTableAliasOrName(final Multimap tableBinderContexts, + final String tableAliasOrName) { + ShardingSpherePreconditions.checkContains(tableBinderContexts.keySet(), new CaseInsensitiveString(tableAliasOrName), () -> new IllegalStateException(String.format("Can not find table binder context by table alias or name %s.", tableAliasOrName))); - return tableBinderContexts.get(tableAliasOrName.toLowerCase()).getProjectionSegments(); + return tableBinderContexts.get(new CaseInsensitiveString(tableAliasOrName)).iterator().next().getProjectionSegments(); } - private static Map getUsingColumnsByNaturalJoin(final JoinTableSegment segment, final Map tableBinderContexts) { - Map result = new LinkedHashMap<>(); + private static Map getUsingColumnsByNaturalJoin(final JoinTableSegment segment, final Multimap tableBinderContexts) { + Map result = new CaseInsensitiveMap<>(); Collection leftProjections = getProjectionSegments(segment.getLeft(), tableBinderContexts); - Map rightProjections = new LinkedHashMap<>(); - getProjectionSegments(segment.getRight(), tableBinderContexts).forEach(each -> rightProjections.put(each.getColumnLabel().toLowerCase(), each)); + Map rightProjections = new CaseInsensitiveMap<>(); + getProjectionSegments(segment.getRight(), tableBinderContexts).forEach(each -> rightProjections.put(each.getColumnLabel(), each)); for (ProjectionSegment each : leftProjections) { - String columnLabel = each.getColumnLabel().toLowerCase(); + String columnLabel = each.getColumnLabel(); if (rightProjections.containsKey(columnLabel)) { result.put(columnLabel, each); } @@ -169,14 +172,14 @@ private static Map getUsingColumnsByNaturalJoin(final private static Map getUsingColumns(final Collection projectionSegments, final Collection usingColumns, final String joinType) { Multimap columnLabelProjectionSegments = LinkedHashMultimap.create(); - projectionSegments.forEach(each -> columnLabelProjectionSegments.put(each.getColumnLabel().toLowerCase(), each)); - Map result = new LinkedHashMap<>(); + projectionSegments.forEach(each -> columnLabelProjectionSegments.put(each.getColumnLabel(), each)); + Map result = new CaseInsensitiveMap<>(); for (ColumnSegment each : usingColumns) { - LinkedList groupProjectionSegments = new LinkedList<>(columnLabelProjectionSegments.get(each.getIdentifier().getValue().toLowerCase())); + LinkedList groupProjectionSegments = new LinkedList<>(columnLabelProjectionSegments.get(each.getIdentifier().getValue())); if (!groupProjectionSegments.isEmpty()) { ProjectionSegment targetProjectionSegment = JoinType.RIGHT.name().equalsIgnoreCase(joinType) ? groupProjectionSegments.descendingIterator().next() : groupProjectionSegments.iterator().next(); - result.put(targetProjectionSegment.getColumnLabel().toLowerCase(), targetProjectionSegment); + result.put(targetProjectionSegment.getColumnLabel(), targetProjectionSegment); } } return result; @@ -184,9 +187,9 @@ private static Map getUsingColumns(final Collection

getJoinUsingColumnsByProjectionOrder(final Collection projectionSegments, final Map usingColumns) { - Map result = new LinkedHashMap<>(usingColumns.size(), 1F); + Map result = new CaseInsensitiveMap<>(usingColumns.size(), 1F); for (ProjectionSegment each : projectionSegments) { - String columnLabel = each.getColumnLabel().toLowerCase(); + String columnLabel = each.getColumnLabel(); if (!result.containsKey(columnLabel) && usingColumns.containsKey(columnLabel)) { result.put(columnLabel, each); } @@ -197,7 +200,7 @@ private static Collection getJoinUsingColumnsByProjectionOrde private static Collection getJoinRemainingColumns(final Collection projectionSegments, final Map usingColumns) { Collection result = new LinkedList<>(); for (ProjectionSegment each : projectionSegments) { - if (!usingColumns.containsKey(each.getColumnLabel().toLowerCase())) { + if (!usingColumns.containsKey(each.getColumnLabel())) { result.add(each); } } diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SimpleTableSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SimpleTableSegmentBinder.java index 0fccc86723829..f02b27f33e53c 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SimpleTableSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SimpleTableSegmentBinder.java @@ -17,7 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.segment.from.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; import com.cedarsoftware.util.CaseInsensitiveSet; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; @@ -47,7 +49,6 @@ import java.util.Collection; import java.util.Collections; import java.util.LinkedList; -import java.util.Map; import java.util.Optional; /** @@ -75,7 +76,8 @@ public final class SimpleTableSegmentBinder { * @param tableBinderContexts table binder contexts * @return bound simple table segment */ - public static SimpleTableSegment bind(final SimpleTableSegment segment, final SQLStatementBinderContext binderContext, final Map tableBinderContexts) { + public static SimpleTableSegment bind(final SimpleTableSegment segment, final SQLStatementBinderContext binderContext, + final Multimap tableBinderContexts) { fillPivotColumnNamesInBinderContext(segment, binderContext); IdentifierValue databaseName = getDatabaseName(segment, binderContext); ShardingSpherePreconditions.checkNotNull(databaseName.getValue(), NoDatabaseSelectedException::new); @@ -83,8 +85,8 @@ public static SimpleTableSegment bind(final SimpleTableSegment segment, final SQ IdentifierValue tableName = segment.getTableName().getIdentifier(); checkTableExists(binderContext, databaseName.getValue(), schemaName.getValue(), tableName.getValue()); ShardingSphereSchema schema = binderContext.getMetaData().getDatabase(databaseName.getValue()).getSchema(schemaName.getValue()); - tableBinderContexts.putIfAbsent( - (segment.getAliasName().orElseGet(tableName::getValue)).toLowerCase(), createSimpleTableBinderContext(segment, schema, databaseName, schemaName, binderContext)); + tableBinderContexts.put(new CaseInsensitiveString(segment.getAliasName().orElseGet(tableName::getValue)), + createSimpleTableBinderContext(segment, schema, databaseName, schemaName, binderContext)); TableNameSegment tableNameSegment = new TableNameSegment(segment.getTableName().getStartIndex(), segment.getTableName().getStopIndex(), tableName); SimpleTableSegment result = new SimpleTableSegment(tableNameSegment); segment.getOwner().ifPresent(result::setOwner); @@ -93,7 +95,7 @@ public static SimpleTableSegment bind(final SimpleTableSegment segment, final SQ } private static void fillPivotColumnNamesInBinderContext(final SimpleTableSegment segment, final SQLStatementBinderContext binderContext) { - segment.getPivot().ifPresent(optional -> optional.getPivotColumns().forEach(each -> binderContext.getPivotColumnNames().add(each.getIdentifier().getValue().toLowerCase()))); + segment.getPivot().ifPresent(optional -> optional.getPivotColumns().forEach(each -> binderContext.getPivotColumnNames().add(each.getIdentifier().getValue()))); } private static IdentifierValue getDatabaseName(final SimpleTableSegment segment, final SQLStatementBinderContext binderContext) { diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SubqueryTableSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SubqueryTableSegmentBinder.java index 225f6787e2f6c..e1f8e17040233 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SubqueryTableSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SubqueryTableSegmentBinder.java @@ -17,6 +17,8 @@ package org.apache.shardingsphere.infra.binder.engine.segment.from.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; @@ -30,8 +32,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.SelectStatement; import org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue; -import java.util.Map; - /** * Subquery table segment binder. */ @@ -48,7 +48,8 @@ public final class SubqueryTableSegmentBinder { * @return bound subquery table segment */ public static SubqueryTableSegment bind(final SubqueryTableSegment segment, final SQLStatementBinderContext binderContext, - final Map tableBinderContexts, final Map outerTableBinderContexts) { + final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts) { fillPivotColumnNamesInBinderContext(segment, binderContext); SQLStatementBinderContext subqueryBinderContext = new SQLStatementBinderContext(segment.getSubquery().getSelect(), binderContext.getMetaData(), binderContext.getCurrentDatabaseName()); subqueryBinderContext.getExternalTableBinderContexts().putAll(binderContext.getExternalTableBinderContexts()); @@ -58,12 +59,12 @@ public static SubqueryTableSegment bind(final SubqueryTableSegment segment, fina IdentifierValue subqueryTableName = segment.getAliasSegment().map(AliasSegment::getIdentifier).orElseGet(() -> new IdentifierValue("")); SubqueryTableSegment result = new SubqueryTableSegment(segment.getStartIndex(), segment.getStopIndex(), boundSubquerySegment); segment.getAliasSegment().ifPresent(result::setAlias); - tableBinderContexts.put(subqueryTableName.getValue().toLowerCase(), new SimpleTableSegmentBinderContext( + tableBinderContexts.put(new CaseInsensitiveString(subqueryTableName.getValue()), new SimpleTableSegmentBinderContext( SubqueryTableBindUtils.createSubqueryProjections(boundSubSelect.getProjections().getProjections(), subqueryTableName, binderContext.getDatabaseType()))); return result; } private static void fillPivotColumnNamesInBinderContext(final SubqueryTableSegment segment, final SQLStatementBinderContext binderContext) { - segment.getPivot().ifPresent(optional -> optional.getPivotColumns().forEach(each -> binderContext.getPivotColumnNames().add(each.getIdentifier().getValue().toLowerCase()))); + segment.getPivot().ifPresent(optional -> optional.getPivotColumns().forEach(each -> binderContext.getPivotColumnNames().add(each.getIdentifier().getValue()))); } } diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/lock/LockSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/lock/LockSegmentBinder.java index 520251b876c7b..5ab1ae83f8577 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/lock/LockSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/lock/LockSegmentBinder.java @@ -17,6 +17,8 @@ package org.apache.shardingsphere.infra.binder.engine.segment.lock; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; @@ -25,7 +27,6 @@ import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.LockSegment; -import java.util.Map; import java.util.stream.Collectors; /** @@ -44,7 +45,8 @@ public final class LockSegmentBinder { * @return bound lock segment */ public static LockSegment bind(final LockSegment segment, final SQLStatementBinderContext binderContext, - final Map tableBinderContexts, final Map outerTableBinderContexts) { + final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts) { LockSegment result = new LockSegment(segment.getStartIndex(), segment.getStopIndex()); result.getTables().addAll(segment.getTables()); result.getColumns().addAll(segment.getColumns().stream() diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/ProjectionsSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/ProjectionsSegmentBinder.java index 9a65b2a029dbc..124fbbf15a64e 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/ProjectionsSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/ProjectionsSegmentBinder.java @@ -17,13 +17,16 @@ package org.apache.shardingsphere.infra.binder.engine.segment.projection; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; -import org.apache.shardingsphere.infra.binder.engine.segment.projection.type.ColumnProjectionSegmentBinder; -import org.apache.shardingsphere.infra.binder.engine.segment.projection.type.ShorthandProjectionSegmentBinder; import org.apache.shardingsphere.infra.binder.engine.segment.expression.ExpressionSegmentBinder; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; +import org.apache.shardingsphere.infra.binder.engine.segment.projection.type.ColumnProjectionSegmentBinder; +import org.apache.shardingsphere.infra.binder.engine.segment.projection.type.ShorthandProjectionSegmentBinder; import org.apache.shardingsphere.infra.binder.engine.segment.projection.type.SubqueryProjectionSegmentBinder; import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment; @@ -35,8 +38,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.SubqueryProjectionSegment; import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableSegment; -import java.util.LinkedHashMap; -import java.util.Map; import java.util.stream.Collectors; /** @@ -56,7 +57,8 @@ public final class ProjectionsSegmentBinder { * @return bound projections segment */ public static ProjectionsSegment bind(final ProjectionsSegment segment, final SQLStatementBinderContext binderContext, final TableSegment boundTableSegment, - final Map tableBinderContexts, final Map outerTableBinderContexts) { + final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts) { ProjectionsSegment result = new ProjectionsSegment(segment.getStartIndex(), segment.getStopIndex()); result.setDistinctRow(segment.isDistinctRow()); result.getProjections().addAll(segment.getProjections().stream() @@ -65,7 +67,8 @@ public static ProjectionsSegment bind(final ProjectionsSegment segment, final SQ } private static ProjectionSegment bind(final ProjectionSegment projectionSegment, final SQLStatementBinderContext binderContext, final TableSegment boundTableSegment, - final Map tableBinderContexts, final Map outerTableBinderContexts) { + final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts) { if (projectionSegment instanceof ColumnProjectionSegment) { return ColumnProjectionSegmentBinder.bind((ColumnProjectionSegment) projectionSegment, binderContext, tableBinderContexts); } @@ -73,7 +76,7 @@ private static ProjectionSegment bind(final ProjectionSegment projectionSegment, return ShorthandProjectionSegmentBinder.bind((ShorthandProjectionSegment) projectionSegment, boundTableSegment, tableBinderContexts); } if (projectionSegment instanceof SubqueryProjectionSegment) { - Map newOuterTableBinderContexts = new LinkedHashMap<>(outerTableBinderContexts.size() + tableBinderContexts.size(), 1F); + Multimap newOuterTableBinderContexts = LinkedHashMultimap.create(); newOuterTableBinderContexts.putAll(outerTableBinderContexts); newOuterTableBinderContexts.putAll(tableBinderContexts); return SubqueryProjectionSegmentBinder.bind((SubqueryProjectionSegment) projectionSegment, binderContext, newOuterTableBinderContexts); diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/ColumnProjectionSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/ColumnProjectionSegmentBinder.java index b7193465ed9cd..371105638533c 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/ColumnProjectionSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/ColumnProjectionSegmentBinder.java @@ -17,6 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.segment.projection.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; @@ -26,9 +29,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ColumnProjectionSegment; -import java.util.Collections; -import java.util.Map; - /** * Column projection segment binder. */ @@ -44,8 +44,8 @@ public final class ColumnProjectionSegmentBinder { * @return bound column projection segment */ public static ColumnProjectionSegment bind(final ColumnProjectionSegment segment, - final SQLStatementBinderContext binderContext, final Map tableBinderContexts) { - ColumnSegment boundColumn = ColumnSegmentBinder.bind(segment.getColumn(), SegmentType.PROJECTION, binderContext, tableBinderContexts, Collections.emptyMap()); + final SQLStatementBinderContext binderContext, final Multimap tableBinderContexts) { + ColumnSegment boundColumn = ColumnSegmentBinder.bind(segment.getColumn(), SegmentType.PROJECTION, binderContext, tableBinderContexts, LinkedHashMultimap.create()); ColumnProjectionSegment result = new ColumnProjectionSegment(boundColumn); segment.getAliasSegment().ifPresent(result::setAlias); result.setVisible(segment.isVisible()); diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/ShorthandProjectionSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/ShorthandProjectionSegmentBinder.java index bfb7bfd9c53e4..65394bf10e584 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/ShorthandProjectionSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/ShorthandProjectionSegmentBinder.java @@ -17,6 +17,8 @@ package org.apache.shardingsphere.infra.binder.engine.segment.projection.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; @@ -29,7 +31,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableSegment; import java.util.Collection; -import java.util.Map; /** * Shorthand projection segment binder. @@ -46,7 +47,7 @@ public final class ShorthandProjectionSegmentBinder { * @return bound shorthand projection segment */ public static ShorthandProjectionSegment bind(final ShorthandProjectionSegment segment, final TableSegment boundTableSegment, - final Map tableBinderContexts) { + final Multimap tableBinderContexts) { ShorthandProjectionSegment result = copy(segment); if (segment.getOwner().isPresent()) { expandVisibleColumns(getProjectionSegmentsByTableAliasOrName(tableBinderContexts, segment.getOwner().get().getIdentifier().getValue()), result); @@ -63,10 +64,11 @@ private static ShorthandProjectionSegment copy(final ShorthandProjectionSegment return result; } - private static Collection getProjectionSegmentsByTableAliasOrName(final Map tableBinderContexts, final String tableAliasOrName) { - ShardingSpherePreconditions.checkContainsKey(tableBinderContexts, tableAliasOrName.toLowerCase(), + private static Collection getProjectionSegmentsByTableAliasOrName(final Multimap tableBinderContexts, + final String tableAliasOrName) { + ShardingSpherePreconditions.checkContains(tableBinderContexts.keySet(), new CaseInsensitiveString(tableAliasOrName), () -> new IllegalStateException(String.format("Can not find table binder context by table alias or name %s.", tableAliasOrName))); - return tableBinderContexts.get(tableAliasOrName.toLowerCase()).getProjectionSegments(); + return tableBinderContexts.get(new CaseInsensitiveString(tableAliasOrName)).iterator().next().getProjectionSegments(); } private static void expandVisibleColumns(final Collection projectionSegments, final ShorthandProjectionSegment segment) { @@ -77,7 +79,7 @@ private static void expandVisibleColumns(final Collection pro } } - private static void expandNoOwnerProjections(final TableSegment boundTableSegment, final Map tableBinderContexts, + private static void expandNoOwnerProjections(final TableSegment boundTableSegment, final Multimap tableBinderContexts, final ShorthandProjectionSegment segment) { if (boundTableSegment instanceof SimpleTableSegment) { String tableAliasOrName = boundTableSegment.getAliasName().orElseGet(() -> ((SimpleTableSegment) boundTableSegment).getTableName().getIdentifier().getValue()); diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/SubqueryProjectionSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/SubqueryProjectionSegmentBinder.java index 55219433df3f9..4feba0cb9b1df 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/SubqueryProjectionSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/SubqueryProjectionSegmentBinder.java @@ -17,6 +17,8 @@ package org.apache.shardingsphere.infra.binder.engine.segment.projection.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.expression.type.SubquerySegmentBinder; @@ -25,8 +27,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubquerySegment; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.SubqueryProjectionSegment; -import java.util.Map; - /** * Subquery projection segment binder. */ @@ -42,7 +42,7 @@ public final class SubqueryProjectionSegmentBinder { * @return bound subquery projection segment */ public static SubqueryProjectionSegment bind(final SubqueryProjectionSegment segment, - final SQLStatementBinderContext binderContext, final Map tableBinderContexts) { + final SQLStatementBinderContext binderContext, final Multimap tableBinderContexts) { SubquerySegment boundSubquerySegment = SubquerySegmentBinder.bind(segment.getSubquery(), binderContext, tableBinderContexts); SubqueryProjectionSegment result = new SubqueryProjectionSegment(boundSubquerySegment, segment.getText()); segment.getAliasSegment().ifPresent(result::setAlias); diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/where/WhereSegmentBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/where/WhereSegmentBinder.java index 34776635fc05c..8c96935e7e874 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/where/WhereSegmentBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/where/WhereSegmentBinder.java @@ -17,6 +17,8 @@ package org.apache.shardingsphere.infra.binder.engine.segment.where; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.Multimap; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; @@ -25,8 +27,6 @@ import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.WhereSegment; -import java.util.Map; - /** * Where segment binder. */ @@ -43,7 +43,8 @@ public final class WhereSegmentBinder { * @return bound where segment */ public static WhereSegment bind(final WhereSegment segment, final SQLStatementBinderContext binderContext, - final Map tableBinderContexts, final Map outerTableBinderContexts) { + final Multimap tableBinderContexts, + final Multimap outerTableBinderContexts) { return new WhereSegment(segment.getStartIndex(), segment.getStopIndex(), ExpressionSegmentBinder.bind(segment.getExpr(), SegmentType.PREDICATE, binderContext, tableBinderContexts, outerTableBinderContexts)); } diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/SQLStatementBinderContext.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/SQLStatementBinderContext.java index 1ac3e373c8e59..10d28175fa81e 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/SQLStatementBinderContext.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/SQLStatementBinderContext.java @@ -17,7 +17,10 @@ package org.apache.shardingsphere.infra.binder.engine.statement; -import com.cedarsoftware.util.CaseInsensitiveMap; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.cedarsoftware.util.CaseInsensitiveSet; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; @@ -27,9 +30,7 @@ import org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement; import java.util.Collection; -import java.util.HashSet; import java.util.LinkedList; -import java.util.Map; /** * SQL statement binder context. @@ -46,18 +47,18 @@ public final class SQLStatementBinderContext { private final Collection variableNames; - private final Collection usingColumnNames = new HashSet<>(); + private final Collection usingColumnNames = new CaseInsensitiveSet<>(); private final Collection joinTableProjectionSegments = new LinkedList<>(); - private final Map externalTableBinderContexts = new CaseInsensitiveMap<>(); + private final Multimap externalTableBinderContexts = LinkedHashMultimap.create(); - private final Collection pivotColumnNames = new HashSet<>(); + private final Collection pivotColumnNames = new CaseInsensitiveSet<>(); public SQLStatementBinderContext(final SQLStatement sqlStatement, final ShardingSphereMetaData metaData, final String currentDatabaseName) { this.metaData = metaData; this.currentDatabaseName = currentDatabaseName; databaseType = sqlStatement.getDatabaseType(); - variableNames = sqlStatement.getVariableNames(); + variableNames = new CaseInsensitiveSet<>(sqlStatement.getVariableNames()); } } diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/DeleteStatementBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/DeleteStatementBinder.java index 72c218a2d1b43..663c8f5bb45d4 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/DeleteStatementBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/DeleteStatementBinder.java @@ -17,6 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.statement.dml; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import lombok.SneakyThrows; import org.apache.shardingsphere.infra.binder.engine.segment.from.TableSegmentBinder; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; @@ -25,10 +28,6 @@ import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.DeleteStatement; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - /** * Delete statement binder. */ @@ -37,9 +36,9 @@ public final class DeleteStatementBinder implements SQLStatementBinder tableBinderContexts = new LinkedHashMap<>(); - result.setTable(TableSegmentBinder.bind(sqlStatement.getTable(), binderContext, tableBinderContexts, Collections.emptyMap())); - sqlStatement.getWhere().ifPresent(optional -> result.setWhere(WhereSegmentBinder.bind(optional, binderContext, tableBinderContexts, Collections.emptyMap()))); + Multimap tableBinderContexts = LinkedHashMultimap.create(); + result.setTable(TableSegmentBinder.bind(sqlStatement.getTable(), binderContext, tableBinderContexts, LinkedHashMultimap.create())); + sqlStatement.getWhere().ifPresent(optional -> result.setWhere(WhereSegmentBinder.bind(optional, binderContext, tableBinderContexts, LinkedHashMultimap.create()))); return result; } diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/InsertStatementBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/InsertStatementBinder.java index af5d970e61fce..5d2ac4a1780a5 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/InsertStatementBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/InsertStatementBinder.java @@ -17,6 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.statement.dml; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import lombok.SneakyThrows; import org.apache.shardingsphere.infra.binder.engine.segment.column.InsertColumnsSegmentBinder; import org.apache.shardingsphere.infra.binder.engine.segment.expression.type.SubquerySegmentBinder; @@ -30,8 +33,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.InsertStatement; import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.Map; import java.util.stream.Collectors; /** @@ -42,7 +43,7 @@ public final class InsertStatementBinder implements SQLStatementBinder tableBinderContexts = new LinkedHashMap<>(); + Multimap tableBinderContexts = LinkedHashMultimap.create(); sqlStatement.getTable().ifPresent(optional -> result.setTable(SimpleTableSegmentBinder.bind(optional, binderContext, tableBinderContexts))); if (sqlStatement.getInsertColumns().isPresent() && !sqlStatement.getInsertColumns().get().getColumns().isEmpty()) { result.setInsertColumns(InsertColumnsSegmentBinder.bind(sqlStatement.getInsertColumns().get(), binderContext, tableBinderContexts)); diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinder.java index b2cff322e1f7a..c0a5da62a6d5c 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinder.java @@ -17,6 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.statement.dml; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import org.apache.shardingsphere.infra.binder.engine.segment.combine.CombineSegmentBinder; @@ -30,9 +33,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableSegment; import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.SelectStatement; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; import java.util.Optional; /** @@ -41,16 +41,16 @@ @RequiredArgsConstructor public final class SelectStatementBinder implements SQLStatementBinder { - private final Map outerTableBinderContexts; + private final Multimap outerTableBinderContexts; public SelectStatementBinder() { - outerTableBinderContexts = Collections.emptyMap(); + outerTableBinderContexts = LinkedHashMultimap.create(); } @Override public SelectStatement bind(final SelectStatement sqlStatement, final SQLStatementBinderContext binderContext) { SelectStatement result = copy(sqlStatement); - Map tableBinderContexts = new LinkedHashMap<>(); + Multimap tableBinderContexts = LinkedHashMultimap.create(); Optional boundTableSegment = sqlStatement.getFrom().map(optional -> TableSegmentBinder.bind(optional, binderContext, tableBinderContexts, outerTableBinderContexts)); boundTableSegment.ifPresent(result::setFrom); result.setProjections(ProjectionsSegmentBinder.bind(sqlStatement.getProjections(), binderContext, boundTableSegment.orElse(null), tableBinderContexts, outerTableBinderContexts)); diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/UpdateStatementBinder.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/UpdateStatementBinder.java index 29427181e2627..2747106952de2 100644 --- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/UpdateStatementBinder.java +++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/UpdateStatementBinder.java @@ -17,6 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.statement.dml; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import lombok.SneakyThrows; import org.apache.shardingsphere.infra.binder.engine.segment.assign.AssignmentSegmentBinder; import org.apache.shardingsphere.infra.binder.engine.segment.from.TableSegmentBinder; @@ -26,10 +29,6 @@ import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.UpdateStatement; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - /** * Update statement binder. */ @@ -38,11 +37,11 @@ public final class UpdateStatementBinder implements SQLStatementBinder tableBinderContexts = new LinkedHashMap<>(); - result.setTable(TableSegmentBinder.bind(sqlStatement.getTable(), binderContext, tableBinderContexts, Collections.emptyMap())); - sqlStatement.getFrom().ifPresent(optional -> result.setFrom(TableSegmentBinder.bind(optional, binderContext, tableBinderContexts, Collections.emptyMap()))); - sqlStatement.getAssignmentSegment().ifPresent(optional -> result.setSetAssignment(AssignmentSegmentBinder.bind(optional, binderContext, tableBinderContexts, Collections.emptyMap()))); - sqlStatement.getWhere().ifPresent(optional -> result.setWhere(WhereSegmentBinder.bind(optional, binderContext, tableBinderContexts, Collections.emptyMap()))); + Multimap tableBinderContexts = LinkedHashMultimap.create(); + result.setTable(TableSegmentBinder.bind(sqlStatement.getTable(), binderContext, tableBinderContexts, LinkedHashMultimap.create())); + sqlStatement.getFrom().ifPresent(optional -> result.setFrom(TableSegmentBinder.bind(optional, binderContext, tableBinderContexts, LinkedHashMultimap.create()))); + sqlStatement.getAssignmentSegment().ifPresent(optional -> result.setSetAssignment(AssignmentSegmentBinder.bind(optional, binderContext, tableBinderContexts, LinkedHashMultimap.create()))); + sqlStatement.getWhere().ifPresent(optional -> result.setWhere(WhereSegmentBinder.bind(optional, binderContext, tableBinderContexts, LinkedHashMultimap.create()))); return result; } diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/assign/AssignmentSegmentBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/assign/AssignmentSegmentBinderTest.java index fecf5ab378196..fa22c44ee1dcf 100644 --- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/assign/AssignmentSegmentBinderTest.java +++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/assign/AssignmentSegmentBinderTest.java @@ -17,6 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.segment.assign; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.type.SimpleTableSegmentBinderContext; import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; @@ -33,7 +36,6 @@ import java.util.Collection; import java.util.Collections; import java.util.LinkedList; -import java.util.Map; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -51,9 +53,9 @@ void assertBindAssignmentSegment() { ColumnSegment columnSegment = new ColumnSegment(0, 0, new IdentifierValue("order_id")); assignments.add(new ColumnAssignmentSegment(0, 0, Collections.singletonList(columnSegment), new LiteralExpressionSegment(0, 0, 1))); SetAssignmentSegment setAssignmentSegment = new SetAssignmentSegment(0, 0, assignments); - Map tableBinderContexts = Collections.singletonMap( - "t_order", new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundOrderIdColumn)))); - SetAssignmentSegment actual = AssignmentSegmentBinder.bind(setAssignmentSegment, mock(SQLStatementBinderContext.class), tableBinderContexts, Collections.emptyMap()); + Multimap tableBinderContexts = LinkedHashMultimap.create(); + tableBinderContexts.put(new CaseInsensitiveString("t_order"), new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundOrderIdColumn)))); + SetAssignmentSegment actual = AssignmentSegmentBinder.bind(setAssignmentSegment, mock(SQLStatementBinderContext.class), tableBinderContexts, LinkedHashMultimap.create()); assertThat(actual, not(setAssignmentSegment)); assertThat(actual.getAssignments().iterator().next(), not(setAssignmentSegment.getAssignments().iterator().next())); assertThat(actual.getAssignments().iterator().next().getColumns().iterator().next().getColumnBoundInfo().getOriginalTable().getValue(), is("t_order")); diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/BinaryOperationExpressionBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/BinaryOperationExpressionBinderTest.java index 10026b292b38d..25a9d68ca57ba 100644 --- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/BinaryOperationExpressionBinderTest.java +++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/BinaryOperationExpressionBinderTest.java @@ -17,14 +17,13 @@ package org.apache.shardingsphere.infra.binder.engine.segment.expression.type; +import com.google.common.collect.LinkedHashMultimap; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BinaryOperationExpression; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.LiteralExpressionSegment; import org.junit.jupiter.api.Test; -import java.util.Collections; - import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; @@ -37,8 +36,8 @@ void assertBinaryOperationExpression() { new LiteralExpressionSegment(0, 0, "test"), new LiteralExpressionSegment(0, 0, "test"), "=", "test"); SQLStatementBinderContext binderContext = mock(SQLStatementBinderContext.class); - BinaryOperationExpression actual = BinaryOperationExpressionBinder.bind(binaryOperationExpression, SegmentType.PROJECTION, - binderContext, Collections.emptyMap(), Collections.emptyMap()); + BinaryOperationExpression actual = + BinaryOperationExpressionBinder.bind(binaryOperationExpression, SegmentType.PROJECTION, binderContext, LinkedHashMultimap.create(), LinkedHashMultimap.create()); assertThat(actual.getLeft().getText(), is("test")); assertThat(actual.getRight().getText(), is("test")); assertThat(actual.getOperator(), is("=")); diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ColumnSegmentBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ColumnSegmentBinderTest.java index e8851bc18fef1..753dd0b6559c2 100644 --- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ColumnSegmentBinderTest.java +++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ColumnSegmentBinderTest.java @@ -17,47 +17,51 @@ package org.apache.shardingsphere.infra.binder.engine.segment.expression.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.type.SimpleTableSegmentBinderContext; import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.infra.database.core.DefaultDatabase; import org.apache.shardingsphere.infra.database.core.type.DatabaseType; +import org.apache.shardingsphere.infra.exception.kernel.syntax.AmbiguousColumnException; import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData; import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ColumnProjectionSegment; +import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.OwnerSegment; import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.bound.ColumnSegmentBoundInfo; import org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue; import org.junit.jupiter.api.Test; import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.mock; class ColumnSegmentBinderTest { @Test void assertBindWithMultiTablesJoinAndNoOwner() { - Map tableBinderContexts = new LinkedHashMap<>(2, 1F); + Multimap tableBinderContexts = LinkedHashMultimap.create(); ColumnSegment boundOrderIdColumn = new ColumnSegment(0, 0, new IdentifierValue("order_id")); boundOrderIdColumn.setColumnBoundInfo(new ColumnSegmentBoundInfo(new IdentifierValue(DefaultDatabase.LOGIC_NAME), new IdentifierValue(DefaultDatabase.LOGIC_NAME), new IdentifierValue("t_order"), new IdentifierValue("order_id"))); - tableBinderContexts.put("t_order", new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundOrderIdColumn)))); + tableBinderContexts.put(new CaseInsensitiveString("t_order"), new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundOrderIdColumn)))); ColumnSegment boundItemIdColumn = new ColumnSegment(0, 0, new IdentifierValue("item_id")); boundItemIdColumn.setColumnBoundInfo(new ColumnSegmentBoundInfo(new IdentifierValue(DefaultDatabase.LOGIC_NAME), new IdentifierValue(DefaultDatabase.LOGIC_NAME), new IdentifierValue("t_order_item"), new IdentifierValue("item_id"))); - tableBinderContexts.put("t_order_item", new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundItemIdColumn)))); + tableBinderContexts.put(new CaseInsensitiveString("t_order_item"), new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundItemIdColumn)))); ColumnSegment columnSegment = new ColumnSegment(0, 0, new IdentifierValue("order_id")); SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), DefaultDatabase.LOGIC_NAME, TypedSPILoader.getService(DatabaseType.class, "FIXTURE"), Collections.emptySet()); - ColumnSegment actual = ColumnSegmentBinder.bind(columnSegment, SegmentType.JOIN_ON, binderContext, tableBinderContexts, Collections.emptyMap()); + ColumnSegment actual = ColumnSegmentBinder.bind(columnSegment, SegmentType.JOIN_ON, binderContext, tableBinderContexts, LinkedHashMultimap.create()); assertNotNull(actual.getColumnBoundInfo()); assertNull(actual.getOtherUsingColumnBoundInfo()); assertThat(actual.getColumnBoundInfo().getOriginalDatabase().getValue(), is(DefaultDatabase.LOGIC_NAME)); @@ -68,19 +72,61 @@ void assertBindWithMultiTablesJoinAndNoOwner() { @Test void assertBindFromOuterTable() { - Map outerTableBinderContexts = new LinkedHashMap<>(2, 1F); + Multimap outerTableBinderContexts = LinkedHashMultimap.create(); ColumnSegment boundOrderStatusColumn = new ColumnSegment(0, 0, new IdentifierValue("status")); boundOrderStatusColumn.setColumnBoundInfo(new ColumnSegmentBoundInfo(new IdentifierValue(DefaultDatabase.LOGIC_NAME), new IdentifierValue(DefaultDatabase.LOGIC_NAME), new IdentifierValue("t_order"), new IdentifierValue("status"))); - outerTableBinderContexts.put("t_order", new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundOrderStatusColumn)))); + outerTableBinderContexts.put(new CaseInsensitiveString("t_order"), new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundOrderStatusColumn)))); ColumnSegment boundOrderItemStatusColumn = new ColumnSegment(0, 0, new IdentifierValue("status")); boundOrderItemStatusColumn.setColumnBoundInfo(new ColumnSegmentBoundInfo(new IdentifierValue(DefaultDatabase.LOGIC_NAME), new IdentifierValue(DefaultDatabase.LOGIC_NAME), new IdentifierValue("t_order_item"), new IdentifierValue("status"))); - outerTableBinderContexts.put("t_order_item", new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundOrderItemStatusColumn)))); + outerTableBinderContexts.put(new CaseInsensitiveString("t_order_item"), new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundOrderItemStatusColumn)))); SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), DefaultDatabase.LOGIC_NAME, TypedSPILoader.getService(DatabaseType.class, "FIXTURE"), Collections.emptySet()); ColumnSegment columnSegment = new ColumnSegment(0, 0, new IdentifierValue("status")); - ColumnSegment actual = ColumnSegmentBinder.bind(columnSegment, SegmentType.PROJECTION, binderContext, Collections.emptyMap(), outerTableBinderContexts); + ColumnSegment actual = ColumnSegmentBinder.bind(columnSegment, SegmentType.PROJECTION, binderContext, LinkedHashMultimap.create(), outerTableBinderContexts); + assertNotNull(actual.getColumnBoundInfo()); + assertNull(actual.getOtherUsingColumnBoundInfo()); + assertThat(actual.getColumnBoundInfo().getOriginalDatabase().getValue(), is(DefaultDatabase.LOGIC_NAME)); + assertThat(actual.getColumnBoundInfo().getOriginalSchema().getValue(), is(DefaultDatabase.LOGIC_NAME)); + assertThat(actual.getColumnBoundInfo().getOriginalTable().getValue(), is("t_order_item")); + assertThat(actual.getColumnBoundInfo().getOriginalColumn().getValue(), is("status")); + } + + @Test + void assertBindWithSameTableAliasAndSameProjection() { + Multimap tableBinderContexts = LinkedHashMultimap.create(); + ColumnSegment boundOrderColumn = new ColumnSegment(0, 0, new IdentifierValue("status")); + boundOrderColumn.setColumnBoundInfo(new ColumnSegmentBoundInfo(new IdentifierValue(DefaultDatabase.LOGIC_NAME), new IdentifierValue(DefaultDatabase.LOGIC_NAME), + new IdentifierValue("t_order"), new IdentifierValue("status"))); + tableBinderContexts.put(new CaseInsensitiveString("temp"), new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundOrderColumn)))); + ColumnSegment boundOrderItemColumn = new ColumnSegment(0, 0, new IdentifierValue("status")); + boundOrderItemColumn.setColumnBoundInfo(new ColumnSegmentBoundInfo(new IdentifierValue(DefaultDatabase.LOGIC_NAME), new IdentifierValue(DefaultDatabase.LOGIC_NAME), + new IdentifierValue("t_order_item"), new IdentifierValue("status"))); + tableBinderContexts.put(new CaseInsensitiveString("temp"), new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundOrderItemColumn)))); + SQLStatementBinderContext binderContext = + new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), DefaultDatabase.LOGIC_NAME, TypedSPILoader.getService(DatabaseType.class, "FIXTURE"), Collections.emptySet()); + ColumnSegment columnSegment = new ColumnSegment(0, 0, new IdentifierValue("status")); + columnSegment.setOwner(new OwnerSegment(0, 0, new IdentifierValue("temp"))); + assertThrows(AmbiguousColumnException.class, () -> ColumnSegmentBinder.bind(columnSegment, SegmentType.PROJECTION, binderContext, tableBinderContexts, LinkedHashMultimap.create())); + } + + @Test + void assertBindWithSameTableAliasAndDifferentProjection() { + Multimap tableBinderContexts = LinkedHashMultimap.create(); + ColumnSegment boundOrderColumn = new ColumnSegment(0, 0, new IdentifierValue("order_id")); + boundOrderColumn.setColumnBoundInfo(new ColumnSegmentBoundInfo(new IdentifierValue(DefaultDatabase.LOGIC_NAME), new IdentifierValue(DefaultDatabase.LOGIC_NAME), + new IdentifierValue("t_order"), new IdentifierValue("order_id"))); + tableBinderContexts.put(new CaseInsensitiveString("temp"), new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundOrderColumn)))); + ColumnSegment boundOrderItemColumn = new ColumnSegment(0, 0, new IdentifierValue("status")); + boundOrderItemColumn.setColumnBoundInfo(new ColumnSegmentBoundInfo(new IdentifierValue(DefaultDatabase.LOGIC_NAME), new IdentifierValue(DefaultDatabase.LOGIC_NAME), + new IdentifierValue("t_order_item"), new IdentifierValue("status"))); + tableBinderContexts.put(new CaseInsensitiveString("temp"), new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundOrderItemColumn)))); + SQLStatementBinderContext binderContext = + new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), DefaultDatabase.LOGIC_NAME, TypedSPILoader.getService(DatabaseType.class, "FIXTURE"), Collections.emptySet()); + ColumnSegment columnSegment = new ColumnSegment(0, 0, new IdentifierValue("status")); + columnSegment.setOwner(new OwnerSegment(0, 0, new IdentifierValue("temp"))); + ColumnSegment actual = ColumnSegmentBinder.bind(columnSegment, SegmentType.PROJECTION, binderContext, tableBinderContexts, LinkedHashMultimap.create()); assertNotNull(actual.getColumnBoundInfo()); assertNull(actual.getOtherUsingColumnBoundInfo()); assertThat(actual.getColumnBoundInfo().getOriginalDatabase().getValue(), is(DefaultDatabase.LOGIC_NAME)); diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ExistsSubqueryExpressionBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ExistsSubqueryExpressionBinderTest.java index ef7e2c55fddd4..69b32b38daad7 100644 --- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ExistsSubqueryExpressionBinderTest.java +++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/ExistsSubqueryExpressionBinderTest.java @@ -17,6 +17,7 @@ package org.apache.shardingsphere.infra.binder.engine.segment.expression.type; +import com.google.common.collect.LinkedHashMultimap; import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.infra.database.core.DefaultDatabase; import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData; @@ -41,7 +42,7 @@ void assertBindExistsSubqueryExpression() { selectStatement.setProjections(new ProjectionsSegment(0, 0)); ExistsSubqueryExpression existsSubqueryExpression = new ExistsSubqueryExpression(0, 0, new SubquerySegment(0, 0, selectStatement, "t_test")); SQLStatementBinderContext binderContext = new SQLStatementBinderContext(mock(ShardingSphereMetaData.class), DefaultDatabase.LOGIC_NAME, new MockedDatabaseType(), Collections.emptyList()); - ExistsSubqueryExpression actual = ExistsSubqueryExpressionBinder.bind(existsSubqueryExpression, binderContext, Collections.emptyMap()); + ExistsSubqueryExpression actual = ExistsSubqueryExpressionBinder.bind(existsSubqueryExpression, binderContext, LinkedHashMultimap.create()); assertThat(actual.getStartIndex(), is(existsSubqueryExpression.getStartIndex())); assertThat(actual.getStopIndex(), is(existsSubqueryExpression.getStopIndex())); assertThat(actual.getText(), is("t_test")); diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/FunctionExpressionSegmentBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/FunctionExpressionSegmentBinderTest.java index 3a45fb63ae432..885d7f8a9cec4 100644 --- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/FunctionExpressionSegmentBinderTest.java +++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/FunctionExpressionSegmentBinderTest.java @@ -17,6 +17,7 @@ package org.apache.shardingsphere.infra.binder.engine.segment.expression.type; +import com.google.common.collect.LinkedHashMultimap; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.infra.database.core.DefaultDatabase; @@ -36,7 +37,7 @@ class FunctionExpressionSegmentBinderTest { void assertBindFunctionExpressionSegment() { FunctionSegment functionSegment = new FunctionSegment(0, 0, "CONCAT", "('%','abc','%')"); SQLStatementBinderContext binderContext = new SQLStatementBinderContext(new ShardingSphereMetaData(), DefaultDatabase.LOGIC_NAME, new MockedDatabaseType(), Collections.emptyList()); - FunctionSegment actual = FunctionExpressionSegmentBinder.bind(functionSegment, SegmentType.PROJECTION, binderContext, Collections.emptyMap(), Collections.emptyMap()); + FunctionSegment actual = FunctionExpressionSegmentBinder.bind(functionSegment, SegmentType.PROJECTION, binderContext, LinkedHashMultimap.create(), LinkedHashMultimap.create()); assertThat(actual.getStartIndex(), is(functionSegment.getStartIndex())); assertThat(actual.getStopIndex(), is(functionSegment.getStopIndex())); assertThat(actual.getFunctionName(), is("CONCAT")); diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/InExpressionBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/InExpressionBinderTest.java index 32a00d0780eac..b815a3e5a35df 100644 --- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/InExpressionBinderTest.java +++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/InExpressionBinderTest.java @@ -17,14 +17,13 @@ package org.apache.shardingsphere.infra.binder.engine.segment.expression.type; +import com.google.common.collect.LinkedHashMultimap; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.InExpression; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.LiteralExpressionSegment; import org.junit.jupiter.api.Test; -import java.util.Collections; - import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -38,7 +37,7 @@ void assertInExpressionBinder() { new LiteralExpressionSegment(0, 0, "left"), new LiteralExpressionSegment(0, 0, "right"), true); SQLStatementBinderContext binderContext = mock(SQLStatementBinderContext.class); - InExpression actual = InExpressionBinder.bind(inExpression, SegmentType.PROJECTION, binderContext, Collections.emptyMap(), Collections.emptyMap()); + InExpression actual = InExpressionBinder.bind(inExpression, SegmentType.PROJECTION, binderContext, LinkedHashMultimap.create(), LinkedHashMultimap.create()); assertThat(actual.getText(), is("leftright")); assertTrue(actual.isNot()); } diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/NotExpressionBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/NotExpressionBinderTest.java index 17e9e48d38f7b..d54bc6b847083 100644 --- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/NotExpressionBinderTest.java +++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/NotExpressionBinderTest.java @@ -17,14 +17,13 @@ package org.apache.shardingsphere.infra.binder.engine.segment.expression.type; +import com.google.common.collect.LinkedHashMultimap; import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType; import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.NotExpression; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.LiteralExpressionSegment; import org.junit.jupiter.api.Test; -import java.util.Collections; - import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; @@ -35,7 +34,7 @@ class NotExpressionBinderTest { void assertBind() { NotExpression notExpression = new NotExpression(0, 10, new LiteralExpressionSegment(0, 0, "test"), true); SQLStatementBinderContext binderContext = mock(SQLStatementBinderContext.class); - NotExpression actual = NotExpressionBinder.bind(notExpression, SegmentType.PROJECTION, binderContext, Collections.emptyMap()); + NotExpression actual = NotExpressionBinder.bind(notExpression, SegmentType.PROJECTION, binderContext, LinkedHashMultimap.create()); assertThat(actual.getNotSign(), is(notExpression.getNotSign())); assertThat(actual.getStartIndex(), is(notExpression.getStartIndex())); assertThat(actual.getStopIndex(), is(notExpression.getStopIndex())); diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/SubquerySegmentBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/SubquerySegmentBinderTest.java index c08d85da16f88..1dd245111b0ee 100644 --- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/SubquerySegmentBinderTest.java +++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/expression/type/SubquerySegmentBinderTest.java @@ -17,6 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.segment.expression.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.type.SimpleTableSegmentBinderContext; import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; @@ -43,8 +46,6 @@ import java.sql.Types; import java.util.Arrays; import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; @@ -73,8 +74,9 @@ void assertBind() { ColumnSegment boundNameColumn = new ColumnSegment(7, 13, new IdentifierValue("user_id")); boundNameColumn.setColumnBoundInfo(new ColumnSegmentBoundInfo( new IdentifierValue(DefaultDatabase.LOGIC_NAME), new IdentifierValue(DefaultDatabase.LOGIC_NAME), new IdentifierValue("t_order_item"), new IdentifierValue("user_id"))); - sqlStatementBinderContext.getExternalTableBinderContexts().put("t_order_item", new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundNameColumn)))); - Map outerTableBinderContexts = new LinkedHashMap<>(); + sqlStatementBinderContext.getExternalTableBinderContexts().put(new CaseInsensitiveString("t_order_item"), + new SimpleTableSegmentBinderContext(Collections.singleton(new ColumnProjectionSegment(boundNameColumn)))); + Multimap outerTableBinderContexts = LinkedHashMultimap.create(); SubquerySegment actual = SubquerySegmentBinder.bind(subquerySegment, sqlStatementBinderContext, outerTableBinderContexts); assertNotNull(actual.getSelect()); assertTrue(actual.getSelect().getFrom().isPresent()); diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/JoinTableSegmentBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/JoinTableSegmentBinderTest.java index 0fab947cb4d32..b8fbed79a2def 100644 --- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/JoinTableSegmentBinderTest.java +++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/JoinTableSegmentBinderTest.java @@ -17,6 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.segment.from.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.infra.database.core.DefaultDatabase; @@ -41,9 +44,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; @@ -67,14 +68,14 @@ void assertBindWithAlias() { when(joinTableSegment.getLeft()).thenReturn(leftTable); when(joinTableSegment.getRight()).thenReturn(rightTable); ShardingSphereMetaData metaData = createMetaData(); - Map tableBinderContexts = new LinkedHashMap<>(); + Multimap tableBinderContexts = LinkedHashMultimap.create(); JoinTableSegment actual = JoinTableSegmentBinder.bind(joinTableSegment, - new SQLStatementBinderContext(metaData, DefaultDatabase.LOGIC_NAME, databaseType, Collections.emptySet()), tableBinderContexts, Collections.emptyMap()); + new SQLStatementBinderContext(metaData, DefaultDatabase.LOGIC_NAME, databaseType, Collections.emptySet()), tableBinderContexts, LinkedHashMultimap.create()); assertThat(actual.getLeft(), instanceOf(SimpleTableSegment.class)); assertThat(actual.getRight(), instanceOf(SimpleTableSegment.class)); assertJoinTableProjectionSegments(actual.getDerivedJoinTableProjectionSegments()); - assertTrue(tableBinderContexts.containsKey("o")); - assertTrue(tableBinderContexts.containsKey("i")); + assertTrue(tableBinderContexts.containsKey(new CaseInsensitiveString("o"))); + assertTrue(tableBinderContexts.containsKey(new CaseInsensitiveString("i"))); } private void assertJoinTableProjectionSegments(final Collection joinTableProjectionSegments) { @@ -105,14 +106,14 @@ void assertBindWithoutAlias() { when(joinTableSegment.getLeft()).thenReturn(leftTable); when(joinTableSegment.getRight()).thenReturn(rightTable); ShardingSphereMetaData metaData = createMetaData(); - Map tableBinderContexts = new LinkedHashMap<>(); + Multimap tableBinderContexts = LinkedHashMultimap.create(); JoinTableSegment actual = JoinTableSegmentBinder.bind(joinTableSegment, new SQLStatementBinderContext(metaData, DefaultDatabase.LOGIC_NAME, databaseType, Collections.emptySet()), - tableBinderContexts, Collections.emptyMap()); + tableBinderContexts, LinkedHashMultimap.create()); assertThat(actual.getLeft(), instanceOf(SimpleTableSegment.class)); assertThat(actual.getRight(), instanceOf(SimpleTableSegment.class)); assertJoinTableProjectionSegments(actual.getDerivedJoinTableProjectionSegments()); - assertTrue(tableBinderContexts.containsKey("t_order")); - assertTrue(tableBinderContexts.containsKey("t_order_item")); + assertTrue(tableBinderContexts.containsKey(new CaseInsensitiveString("t_order"))); + assertTrue(tableBinderContexts.containsKey(new CaseInsensitiveString("t_order_item"))); } @Test @@ -127,14 +128,14 @@ void assertBindWithNaturalJoin() { when(joinTableSegment.isNatural()).thenReturn(true); when(joinTableSegment.getJoinType()).thenReturn(JoinType.RIGHT.name()); ShardingSphereMetaData metaData = createMetaData(); - Map tableBinderContexts = new LinkedHashMap<>(); + Multimap tableBinderContexts = LinkedHashMultimap.create(); JoinTableSegment actual = JoinTableSegmentBinder.bind(joinTableSegment, new SQLStatementBinderContext(metaData, DefaultDatabase.LOGIC_NAME, databaseType, Collections.emptySet()), - tableBinderContexts, Collections.emptyMap()); + tableBinderContexts, LinkedHashMultimap.create()); assertThat(actual.getLeft(), instanceOf(SimpleTableSegment.class)); assertThat(actual.getRight(), instanceOf(SimpleTableSegment.class)); assertJoinTableProjectionSegmentsWithNaturalJoin(actual.getDerivedJoinTableProjectionSegments()); - assertTrue(tableBinderContexts.containsKey("o")); - assertTrue(tableBinderContexts.containsKey("i")); + assertTrue(tableBinderContexts.containsKey(new CaseInsensitiveString("o"))); + assertTrue(tableBinderContexts.containsKey(new CaseInsensitiveString("i"))); } private void assertJoinTableProjectionSegmentsWithNaturalJoin(final Collection joinTableProjectionSegments) { @@ -163,14 +164,14 @@ void assertBindWithJoinUsing() { when(joinTableSegment.getJoinType()).thenReturn(JoinType.RIGHT.name()); when(joinTableSegment.getUsing()).thenReturn(Arrays.asList(new ColumnSegment(0, 0, new IdentifierValue("status")), new ColumnSegment(0, 0, new IdentifierValue("order_id")))); ShardingSphereMetaData metaData = createMetaData(); - Map tableBinderContexts = new LinkedHashMap<>(); + Multimap tableBinderContexts = LinkedHashMultimap.create(); JoinTableSegment actual = JoinTableSegmentBinder.bind(joinTableSegment, new SQLStatementBinderContext(metaData, DefaultDatabase.LOGIC_NAME, databaseType, Collections.emptySet()), - tableBinderContexts, Collections.emptyMap()); + tableBinderContexts, LinkedHashMultimap.create()); assertThat(actual.getLeft(), instanceOf(SimpleTableSegment.class)); assertThat(actual.getRight(), instanceOf(SimpleTableSegment.class)); assertJoinTableProjectionSegmentsWithUsing(actual.getDerivedJoinTableProjectionSegments()); - assertTrue(tableBinderContexts.containsKey("o")); - assertTrue(tableBinderContexts.containsKey("i")); + assertTrue(tableBinderContexts.containsKey(new CaseInsensitiveString("o"))); + assertTrue(tableBinderContexts.containsKey(new CaseInsensitiveString("i"))); } private void assertJoinTableProjectionSegmentsWithUsing(final Collection joinTableProjectionSegments) { @@ -198,17 +199,17 @@ void assertBindWithMultiTableJoin() { when(joinTableSegment.getLeft()).thenReturn(leftTable); when(joinTableSegment.getRight()).thenReturn(rightTable); ShardingSphereMetaData metaData = createMetaData(); - Map tableBinderContexts = new LinkedHashMap<>(); + Multimap tableBinderContexts = LinkedHashMultimap.create(); JoinTableSegment actual = JoinTableSegmentBinder.bind(joinTableSegment, - new SQLStatementBinderContext(metaData, DefaultDatabase.LOGIC_NAME, databaseType, Collections.emptySet()), tableBinderContexts, Collections.emptyMap()); + new SQLStatementBinderContext(metaData, DefaultDatabase.LOGIC_NAME, databaseType, Collections.emptySet()), tableBinderContexts, LinkedHashMultimap.create()); assertThat(actual.getLeft(), instanceOf(JoinTableSegment.class)); assertThat(((JoinTableSegment) actual.getLeft()).getLeft(), instanceOf(SimpleTableSegment.class)); assertThat(((JoinTableSegment) actual.getLeft()).getRight(), instanceOf(SimpleTableSegment.class)); assertThat(actual.getRight(), instanceOf(SimpleTableSegment.class)); assertThat(actual.getDerivedJoinTableProjectionSegments().size(), is(10)); - assertTrue(tableBinderContexts.containsKey("o")); - assertTrue(tableBinderContexts.containsKey("o2")); - assertTrue(tableBinderContexts.containsKey("i")); + assertTrue(tableBinderContexts.containsKey(new CaseInsensitiveString("o"))); + assertTrue(tableBinderContexts.containsKey(new CaseInsensitiveString("o2"))); + assertTrue(tableBinderContexts.containsKey(new CaseInsensitiveString("i"))); } private JoinTableSegment mockLeftJoinSegment() { diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SimpleTableSegmentBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SimpleTableSegmentBinderTest.java index a692cbb1386f2..84c7b7fd20b47 100644 --- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SimpleTableSegmentBinderTest.java +++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SimpleTableSegmentBinderTest.java @@ -17,6 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.segment.from.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.infra.database.core.DefaultDatabase; @@ -34,8 +37,6 @@ import java.sql.Types; import java.util.Arrays; import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.RETURNS_DEEP_STUBS; @@ -50,7 +51,7 @@ class SimpleTableSegmentBinderTest { void assertBindTableNotExists() { SimpleTableSegment simpleTableSegment = new SimpleTableSegment(new TableNameSegment(0, 10, new IdentifierValue("t_not_exists"))); ShardingSphereMetaData metaData = createMetaData(); - Map tableBinderContexts = new LinkedHashMap<>(); + Multimap tableBinderContexts = LinkedHashMultimap.create(); assertThrows(TableNotFoundException.class, () -> SimpleTableSegmentBinder.bind( simpleTableSegment, new SQLStatementBinderContext(metaData, DefaultDatabase.LOGIC_NAME, databaseType, Collections.emptySet()), tableBinderContexts)); } diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SubqueryTableSegmentBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SubqueryTableSegmentBinderTest.java index e0a491760415c..d09954cc63ea6 100644 --- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SubqueryTableSegmentBinderTest.java +++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SubqueryTableSegmentBinderTest.java @@ -17,6 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.segment.from.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.infra.database.core.DefaultDatabase; @@ -43,9 +46,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import java.util.Optional; import static org.hamcrest.CoreMatchers.instanceOf; @@ -72,12 +73,12 @@ void assertBindWithSubqueryTableAlias() { SubqueryTableSegment subqueryTableSegment = new SubqueryTableSegment(0, 0, new SubquerySegment(0, 0, selectStatement, "")); subqueryTableSegment.setAlias(new AliasSegment(0, 0, new IdentifierValue("temp"))); ShardingSphereMetaData metaData = createMetaData(); - Map tableBinderContexts = new LinkedHashMap<>(); + Multimap tableBinderContexts = LinkedHashMultimap.create(); SubqueryTableSegment actual = SubqueryTableSegmentBinder.bind(subqueryTableSegment, new SQLStatementBinderContext(metaData, DefaultDatabase.LOGIC_NAME, databaseType, Collections.emptySet()), - tableBinderContexts, Collections.emptyMap()); + tableBinderContexts, LinkedHashMultimap.create()); assertTrue(actual.getAlias().isPresent()); - assertTrue(tableBinderContexts.containsKey("temp")); - List projectionSegments = new ArrayList<>(tableBinderContexts.get("temp").getProjectionSegments()); + assertTrue(tableBinderContexts.containsKey(new CaseInsensitiveString("temp"))); + List projectionSegments = new ArrayList<>(tableBinderContexts.get(new CaseInsensitiveString("temp")).iterator().next().getProjectionSegments()); assertThat(projectionSegments.size(), is(3)); assertThat(projectionSegments.get(0), instanceOf(ColumnProjectionSegment.class)); assertTrue(((ColumnProjectionSegment) projectionSegments.get(0)).getColumn().getOwner().isPresent()); @@ -106,12 +107,12 @@ void assertBindWithSubqueryProjectionAlias() { SubqueryTableSegment subqueryTableSegment = new SubqueryTableSegment(0, 0, new SubquerySegment(0, 0, selectStatement, "")); subqueryTableSegment.setAlias(new AliasSegment(0, 0, new IdentifierValue("temp"))); ShardingSphereMetaData metaData = createMetaData(); - Map tableBinderContexts = new LinkedHashMap<>(); + Multimap tableBinderContexts = LinkedHashMultimap.create(); SubqueryTableSegment actual = SubqueryTableSegmentBinder.bind(subqueryTableSegment, new SQLStatementBinderContext(metaData, DefaultDatabase.LOGIC_NAME, databaseType, Collections.emptySet()), - tableBinderContexts, Collections.emptyMap()); + tableBinderContexts, LinkedHashMultimap.create()); assertTrue(actual.getAlias().isPresent()); - assertTrue(tableBinderContexts.containsKey("temp")); - List projectionSegments = new ArrayList<>(tableBinderContexts.get("temp").getProjectionSegments()); + assertTrue(tableBinderContexts.containsKey(new CaseInsensitiveString("temp"))); + List projectionSegments = new ArrayList<>(tableBinderContexts.get(new CaseInsensitiveString("temp")).iterator().next().getProjectionSegments()); assertThat(projectionSegments.size(), is(1)); assertThat(projectionSegments.get(0), instanceOf(ColumnProjectionSegment.class)); assertTrue(((ColumnProjectionSegment) projectionSegments.get(0)).getColumn().getOwner().isPresent()); @@ -129,11 +130,11 @@ void assertBindWithoutSubqueryTableAlias() { when(selectStatement.getProjections()).thenReturn(projectionsSegment); SubqueryTableSegment subqueryTableSegment = new SubqueryTableSegment(0, 0, new SubquerySegment(0, 0, selectStatement, "")); ShardingSphereMetaData metaData = createMetaData(); - Map tableBinderContexts = new LinkedHashMap<>(); + Multimap tableBinderContexts = LinkedHashMultimap.create(); SubqueryTableSegment actual = SubqueryTableSegmentBinder.bind(subqueryTableSegment, new SQLStatementBinderContext(metaData, DefaultDatabase.LOGIC_NAME, databaseType, Collections.emptySet()), - tableBinderContexts, Collections.emptyMap()); + tableBinderContexts, LinkedHashMultimap.create()); assertFalse(actual.getAlias().isPresent()); - assertTrue(tableBinderContexts.containsKey("")); + assertTrue(tableBinderContexts.containsKey(new CaseInsensitiveString(""))); } private ShardingSphereMetaData createMetaData() { diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/ShorthandProjectionSegmentBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/ShorthandProjectionSegmentBinderTest.java index 729762dbfc315..329efa58d9ed8 100644 --- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/ShorthandProjectionSegmentBinderTest.java +++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/projection/type/ShorthandProjectionSegmentBinderTest.java @@ -17,6 +17,9 @@ package org.apache.shardingsphere.infra.binder.engine.segment.projection.type; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.type.SimpleTableSegmentBinderContext; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment; @@ -36,8 +39,6 @@ import org.junit.jupiter.api.Test; import java.util.Arrays; -import java.util.Collections; -import java.util.Map; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; @@ -52,8 +53,9 @@ void assertBindWithOwner() { shorthandProjectionSegment.setOwner(new OwnerSegment(0, 0, new IdentifierValue("o"))); ColumnProjectionSegment invisibleColumn = new ColumnProjectionSegment(new ColumnSegment(0, 0, new IdentifierValue("status"))); invisibleColumn.setVisible(false); - Map tableBinderContexts = Collections.singletonMap( - "o", new SimpleTableSegmentBinderContext(Arrays.asList(new ColumnProjectionSegment(new ColumnSegment(0, 0, new IdentifierValue("order_id"))), invisibleColumn))); + Multimap tableBinderContexts = LinkedHashMultimap.create(); + tableBinderContexts.put(new CaseInsensitiveString("o"), + new SimpleTableSegmentBinderContext(Arrays.asList(new ColumnProjectionSegment(new ColumnSegment(0, 0, new IdentifierValue("order_id"))), invisibleColumn))); ShorthandProjectionSegment actual = ShorthandProjectionSegmentBinder.bind(shorthandProjectionSegment, mock(TableSegment.class), tableBinderContexts); assertThat(actual.getActualProjectionSegments().size(), is(1)); ProjectionSegment visibleColumn = actual.getActualProjectionSegments().iterator().next(); @@ -65,8 +67,9 @@ void assertBindWithOwner() { void assertBindWithoutOwnerForSimpleTableSegment() { ColumnProjectionSegment invisibleColumn = new ColumnProjectionSegment(new ColumnSegment(0, 0, new IdentifierValue("status"))); invisibleColumn.setVisible(false); - Map tableBinderContexts = Collections.singletonMap( - "o", new SimpleTableSegmentBinderContext(Arrays.asList(new ColumnProjectionSegment(new ColumnSegment(0, 0, new IdentifierValue("order_id"))), invisibleColumn))); + Multimap tableBinderContexts = LinkedHashMultimap.create(); + tableBinderContexts.put(new CaseInsensitiveString("o"), + new SimpleTableSegmentBinderContext(Arrays.asList(new ColumnProjectionSegment(new ColumnSegment(0, 0, new IdentifierValue("order_id"))), invisibleColumn))); SimpleTableSegment boundTableSegment = new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order"))); boundTableSegment.setAlias(new AliasSegment(0, 0, new IdentifierValue("o"))); ShorthandProjectionSegment actual = ShorthandProjectionSegmentBinder.bind(new ShorthandProjectionSegment(0, 0), boundTableSegment, tableBinderContexts); @@ -80,8 +83,9 @@ void assertBindWithoutOwnerForSimpleTableSegment() { void assertBindWithoutOwnerForSubqueryTableSegment() { ColumnProjectionSegment invisibleColumn = new ColumnProjectionSegment(new ColumnSegment(0, 0, new IdentifierValue("status"))); invisibleColumn.setVisible(false); - Map tableBinderContexts = Collections.singletonMap( - "o", new SimpleTableSegmentBinderContext(Arrays.asList(new ColumnProjectionSegment(new ColumnSegment(0, 0, new IdentifierValue("order_id"))), invisibleColumn))); + Multimap tableBinderContexts = LinkedHashMultimap.create(); + tableBinderContexts.put(new CaseInsensitiveString("o"), + new SimpleTableSegmentBinderContext(Arrays.asList(new ColumnProjectionSegment(new ColumnSegment(0, 0, new IdentifierValue("order_id"))), invisibleColumn))); SubqueryTableSegment boundTableSegment = new SubqueryTableSegment(0, 0, new SubquerySegment(0, 0, mock(MySQLSelectStatement.class), "")); boundTableSegment.setAlias(new AliasSegment(0, 0, new IdentifierValue("o"))); ShorthandProjectionSegment actual = ShorthandProjectionSegmentBinder.bind(new ShorthandProjectionSegment(0, 0), boundTableSegment, tableBinderContexts); @@ -96,7 +100,7 @@ void assertBindWithoutOwnerForJoinTableSegment() { ShorthandProjectionSegment shorthandProjectionSegment = new ShorthandProjectionSegment(0, 0); JoinTableSegment boundTableSegment = new JoinTableSegment(); boundTableSegment.getDerivedJoinTableProjectionSegments().add(new ColumnProjectionSegment(new ColumnSegment(0, 0, new IdentifierValue("order_id")))); - ShorthandProjectionSegment actual = ShorthandProjectionSegmentBinder.bind(shorthandProjectionSegment, boundTableSegment, Collections.emptyMap()); + ShorthandProjectionSegment actual = ShorthandProjectionSegmentBinder.bind(shorthandProjectionSegment, boundTableSegment, LinkedHashMultimap.create()); assertThat(actual.getActualProjectionSegments().size(), is(1)); ProjectionSegment visibleColumn = actual.getActualProjectionSegments().iterator().next(); assertThat(visibleColumn.getColumnLabel(), is("order_id")); diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/where/WhereSegmentBinderTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/where/WhereSegmentBinderTest.java index e488d3723f03a..84815358e6316 100644 --- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/where/WhereSegmentBinderTest.java +++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/where/WhereSegmentBinderTest.java @@ -17,15 +17,15 @@ package org.apache.shardingsphere.infra.binder.engine.segment.where; +import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext; import org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment; import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.WhereSegment; import org.junit.jupiter.api.Test; -import java.util.HashMap; -import java.util.Map; - import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; @@ -36,8 +36,8 @@ class WhereSegmentBinderTest { void assertBind() { SQLStatementBinderContext sqlStatementBinderContext = mock(SQLStatementBinderContext.class); WhereSegment expectedWhereSegment = new WhereSegment(1, 2, mock(ExpressionSegment.class)); - Map tableBinderContexts = new HashMap<>(); - Map outerTableBinderContexts = new HashMap<>(); + Multimap tableBinderContexts = LinkedHashMultimap.create(); + Multimap outerTableBinderContexts = LinkedHashMultimap.create(); WhereSegment actualWhereSegment = WhereSegmentBinder.bind(expectedWhereSegment, sqlStatementBinderContext, tableBinderContexts, outerTableBinderContexts); assertThat(actualWhereSegment.getStopIndex(), is(expectedWhereSegment.getStopIndex())); assertThat(actualWhereSegment.getStartIndex(), is(expectedWhereSegment.getStartIndex()));