This is an automated email from the ASF dual-hosted git repository.
zhaojinchao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 3ba6204888a Enhance sql binder logic to support join using statement
(#28231)
3ba6204888a is described below
commit 3ba6204888a1e9e912ee652933b645aad656a9d9
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Wed Aug 23 15:26:40 2023 +0800
Enhance sql binder logic to support join using statement (#28231)
* Enhance sql binder logic to support join using statement
* Enhance sql binder logic to support join using statement
* fix build error
---
.../route/engine/type/standard/SQLRouteTest.java | 3 ++-
.../SegmentType.java} | 25 ++++------------------
.../expression/ExpressionSegmentBinder.java | 14 ++++++------
.../impl/BinaryOperationExpressionBinder.java | 8 ++++---
.../expression/impl/ColumnSegmentBinder.java | 17 +++++++++++----
.../impl/FunctionExpressionSegmentBinder.java | 6 ++++--
.../expression/impl/InExpressionBinder.java | 9 +++++---
.../expression/impl/NotExpressionBinder.java | 6 ++++--
.../segment/from/impl/JoinTableSegmentBinder.java | 23 +++++++++++++-------
.../impl/ColumnProjectionSegmentBinder.java | 3 ++-
.../binder/segment/where/WhereSegmentBinder.java | 3 ++-
.../statement/SQLStatementBinderContext.java | 3 +++
.../from/impl/JoinTableSegmentBinderTest.java | 4 ++--
13 files changed, 70 insertions(+), 54 deletions(-)
diff --git
a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/SQLRouteTest.java
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/SQLRouteTest.java
index 7d05ef74c3d..cb014c81b54 100644
---
a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/SQLRouteTest.java
+++
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/SQLRouteTest.java
@@ -44,7 +44,8 @@ class SQLRouteTest {
public Stream<? extends Arguments> provideArguments(final
ExtensionContext extensionContext) {
return Stream.of(
Arguments.of("noTableUnicastRandomDataSource", "SELECT 1,
1 + 2", Collections.singletonList(1)),
- Arguments.of("withBroadcastTable", "SELECT user_id, status
from t_order_item a join t_product b on a.product_id = b.product_id where
user_id = ?", Collections.singletonList(1)),
+ Arguments.of("withBroadcastTable", "SELECT a.user_id,
status from t_order_item a join t_product b on a.product_id = b.product_id
where a.user_id = ?",
+ Collections.singletonList(1)),
Arguments.of("allBindingWithBroadcastTable",
"SELECT a.user_id, a.status from t_order a join
t_order_item b on a.order_id = b.order_id join t_product c on b.product_id =
c.product_id where a.user_id = ?",
Collections.singletonList(1)),
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/SQLStatementBinderContext.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/enums/SegmentType.java
similarity index 51%
copy from
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/SQLStatementBinderContext.java
copy to
infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/enums/SegmentType.java
index 999a6a72635..f7b4429de8a 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/SQLStatementBinderContext.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/enums/SegmentType.java
@@ -15,29 +15,12 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.infra.binder.statement;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
-import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
-import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
-
-import java.util.Collection;
-import java.util.LinkedList;
+package org.apache.shardingsphere.infra.binder.enums;
/**
- * SQL statement binder context.
+ * Segment type enum.
*/
-@RequiredArgsConstructor
-@Getter
-public final class SQLStatementBinderContext {
-
- private final ShardingSphereMetaData metaData;
-
- private final String defaultDatabaseName;
-
- private final DatabaseType databaseType;
+public enum SegmentType {
- private final Collection<ProjectionSegment> joinTableProjectionSegments =
new LinkedList<>();
+ PROJECTION, PREDICATE, JOIN
}
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/ExpressionSegmentBinder.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/ExpressionSegmentBinder.java
index 01108f954a4..17ad6ec9e09 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/ExpressionSegmentBinder.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/ExpressionSegmentBinder.java
@@ -19,6 +19,7 @@ package
org.apache.shardingsphere.infra.binder.segment.expression;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.infra.binder.enums.SegmentType;
import
org.apache.shardingsphere.infra.binder.segment.expression.impl.BinaryOperationExpressionBinder;
import
org.apache.shardingsphere.infra.binder.segment.expression.impl.ColumnSegmentBinder;
import
org.apache.shardingsphere.infra.binder.segment.expression.impl.ExistsSubqueryExpressionBinder;
@@ -49,15 +50,16 @@ public final class ExpressionSegmentBinder {
* Bind expression segment with metadata.
*
* @param segment expression segment
+ * @param parentSegmentType parent segment type
* @param statementBinderContext statement binder context
* @param tableBinderContexts table binder contexts
* @param outerTableBinderContexts outer table binder contexts
* @return bounded expression segment
*/
- public static ExpressionSegment bind(final ExpressionSegment segment,
final SQLStatementBinderContext statementBinderContext,
+ public static ExpressionSegment bind(final ExpressionSegment segment,
final SegmentType parentSegmentType, final SQLStatementBinderContext
statementBinderContext,
final Map<String,
TableSegmentBinderContext> tableBinderContexts, final Map<String,
TableSegmentBinderContext> outerTableBinderContexts) {
if (segment instanceof BinaryOperationExpression) {
- return
BinaryOperationExpressionBinder.bind((BinaryOperationExpression) segment,
statementBinderContext, tableBinderContexts, outerTableBinderContexts);
+ return
BinaryOperationExpressionBinder.bind((BinaryOperationExpression) segment,
parentSegmentType, statementBinderContext, tableBinderContexts,
outerTableBinderContexts);
}
if (segment instanceof ExistsSubqueryExpression) {
return
ExistsSubqueryExpressionBinder.bind((ExistsSubqueryExpression) segment,
statementBinderContext, tableBinderContexts);
@@ -66,16 +68,16 @@ public final class ExpressionSegmentBinder {
return
SubqueryExpressionSegmentBinder.bind((SubqueryExpressionSegment) segment,
statementBinderContext, tableBinderContexts);
}
if (segment instanceof InExpression) {
- return InExpressionBinder.bind((InExpression) segment,
statementBinderContext, tableBinderContexts);
+ return InExpressionBinder.bind((InExpression) segment,
parentSegmentType, statementBinderContext, tableBinderContexts);
}
if (segment instanceof NotExpression) {
- return NotExpressionBinder.bind((NotExpression) segment,
statementBinderContext, tableBinderContexts);
+ return NotExpressionBinder.bind((NotExpression) segment,
parentSegmentType, statementBinderContext, tableBinderContexts);
}
if (segment instanceof ColumnSegment) {
- return ColumnSegmentBinder.bind((ColumnSegment) segment,
statementBinderContext, tableBinderContexts, outerTableBinderContexts);
+ return ColumnSegmentBinder.bind((ColumnSegment) segment,
parentSegmentType, statementBinderContext, tableBinderContexts,
outerTableBinderContexts);
}
if (segment instanceof FunctionSegment) {
- return FunctionExpressionSegmentBinder.bind((FunctionSegment)
segment, statementBinderContext, tableBinderContexts, outerTableBinderContexts);
+ return FunctionExpressionSegmentBinder.bind((FunctionSegment)
segment, parentSegmentType, statementBinderContext, tableBinderContexts,
outerTableBinderContexts);
}
// TODO support more ExpressionSegment bind
return segment;
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/BinaryOperationExpressionBinder.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/BinaryOperationExpressionBinder.java
index ef0a6256b95..2b1b60915fa 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/BinaryOperationExpressionBinder.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/BinaryOperationExpressionBinder.java
@@ -19,6 +19,7 @@ package
org.apache.shardingsphere.infra.binder.segment.expression.impl;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.infra.binder.enums.SegmentType;
import
org.apache.shardingsphere.infra.binder.segment.expression.ExpressionSegmentBinder;
import
org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderContext;
import
org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
@@ -37,15 +38,16 @@ public final class BinaryOperationExpressionBinder {
* Bind binary operation expression with metadata.
*
* @param segment binary operation expression segment
+ * @param parentSegmentType parent segment type
* @param statementBinderContext statement binder context
* @param tableBinderContexts table binder contexts
* @param outerTableBinderContexts outer table binder contexts
* @return bounded binary operation expression segment
*/
- public static BinaryOperationExpression bind(final
BinaryOperationExpression segment, final SQLStatementBinderContext
statementBinderContext,
+ public static BinaryOperationExpression bind(final
BinaryOperationExpression segment, final SegmentType parentSegmentType, final
SQLStatementBinderContext statementBinderContext,
final Map<String,
TableSegmentBinderContext> tableBinderContexts, final Map<String,
TableSegmentBinderContext> outerTableBinderContexts) {
- ExpressionSegment boundedLeft =
ExpressionSegmentBinder.bind(segment.getLeft(), statementBinderContext,
tableBinderContexts, outerTableBinderContexts);
- ExpressionSegment boundedRight =
ExpressionSegmentBinder.bind(segment.getRight(), statementBinderContext,
tableBinderContexts, outerTableBinderContexts);
+ ExpressionSegment boundedLeft =
ExpressionSegmentBinder.bind(segment.getLeft(), parentSegmentType,
statementBinderContext, tableBinderContexts, outerTableBinderContexts);
+ ExpressionSegment boundedRight =
ExpressionSegmentBinder.bind(segment.getRight(), parentSegmentType,
statementBinderContext, tableBinderContexts, outerTableBinderContexts);
return new BinaryOperationExpression(segment.getStartIndex(),
segment.getStopIndex(), boundedLeft, boundedRight, segment.getOperator(),
segment.getText());
}
}
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/ColumnSegmentBinder.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/ColumnSegmentBinder.java
index 0356b40deaf..72e038d3a80 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/ColumnSegmentBinder.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/ColumnSegmentBinder.java
@@ -19,6 +19,7 @@ package
org.apache.shardingsphere.infra.binder.segment.expression.impl;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.infra.binder.enums.SegmentType;
import
org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderContext;
import
org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
import org.apache.shardingsphere.infra.exception.AmbiguousColumnException;
@@ -51,36 +52,44 @@ public final class ColumnSegmentBinder {
* Bind column segment with metadata.
*
* @param segment table segment
+ * @param parentSegmentType parent segment type
* @param statementBinderContext statement binder context
* @param tableBinderContexts table binder contexts
* @param outerTableBinderContexts outer table binder contexts
* @return bounded column segment
*/
- public static ColumnSegment bind(final ColumnSegment segment, final
SQLStatementBinderContext statementBinderContext,
+ public static ColumnSegment bind(final ColumnSegment segment, final
SegmentType parentSegmentType, final SQLStatementBinderContext
statementBinderContext,
final Map<String,
TableSegmentBinderContext> tableBinderContexts, final Map<String,
TableSegmentBinderContext> outerTableBinderContexts) {
if
(EXCLUDE_BIND_COLUMNS.contains(segment.getIdentifier().getValue().toUpperCase()))
{
return segment;
}
ColumnSegment result = new ColumnSegment(segment.getStartIndex(),
segment.getStopIndex(), segment.getIdentifier());
segment.getOwner().ifPresent(result::setOwner);
- Collection<TableSegmentBinderContext> tableBinderContextValues =
getTableSegmentBinderContexts(segment, statementBinderContext,
tableBinderContexts, outerTableBinderContexts);
+ Collection<TableSegmentBinderContext> tableBinderContextValues =
+ getTableSegmentBinderContexts(segment, parentSegmentType,
statementBinderContext, tableBinderContexts, outerTableBinderContexts);
Optional<ColumnSegment> inputColumnSegment =
findInputColumnSegment(segment.getIdentifier().getValue(),
tableBinderContextValues);
result.setColumnBoundedInfo(createColumnSegmentBoundedInfo(segment,
inputColumnSegment.orElse(null)));
return result;
}
- private static Collection<TableSegmentBinderContext>
getTableSegmentBinderContexts(final ColumnSegment segment, final
SQLStatementBinderContext statementBinderContext,
+ private static Collection<TableSegmentBinderContext>
getTableSegmentBinderContexts(final ColumnSegment segment, final SegmentType
parentSegmentType,
+
final SQLStatementBinderContext statementBinderContext,
final Map<String, TableSegmentBinderContext> tableBinderContexts,
final Map<String, TableSegmentBinderContext> outerTableBinderContexts) {
if (segment.getOwner().isPresent()) {
return
getTableBinderContextByOwner(segment.getOwner().get().getIdentifier().getValue(),
tableBinderContexts, outerTableBinderContexts);
}
- if
(!statementBinderContext.getJoinTableProjectionSegments().isEmpty()) {
+ if (!statementBinderContext.getJoinTableProjectionSegments().isEmpty()
&& isNeedUseJoinTableProjectionBind(segment, parentSegmentType,
statementBinderContext)) {
return Collections.singleton(new
TableSegmentBinderContext(statementBinderContext.getJoinTableProjectionSegments()));
}
return tableBinderContexts.values();
}
+ private static boolean isNeedUseJoinTableProjectionBind(final
ColumnSegment segment, final SegmentType parentSegmentType, final
SQLStatementBinderContext statementBinderContext) {
+ return SegmentType.PROJECTION == parentSegmentType
+ || SegmentType.PREDICATE == parentSegmentType &&
statementBinderContext.getUsingColumnNames().contains(segment.getIdentifier().getValue().toLowerCase());
+ }
+
private static Collection<TableSegmentBinderContext>
getTableBinderContextByOwner(final String owner, final Map<String,
TableSegmentBinderContext> tableBinderContexts,
final Map<String, TableSegmentBinderContext> outerTableBinderContexts) {
if (tableBinderContexts.containsKey(owner)) {
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/FunctionExpressionSegmentBinder.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/FunctionExpressionSegmentBinder.java
index 7eba90e82b0..4732ea9d195 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/FunctionExpressionSegmentBinder.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/FunctionExpressionSegmentBinder.java
@@ -19,6 +19,7 @@ package
org.apache.shardingsphere.infra.binder.segment.expression.impl;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.infra.binder.enums.SegmentType;
import
org.apache.shardingsphere.infra.binder.segment.expression.ExpressionSegmentBinder;
import
org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderContext;
import
org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
@@ -37,17 +38,18 @@ public final class FunctionExpressionSegmentBinder {
* Bind function expression with metadata.
*
* @param segment function expression segment
+ * @param parentSegmentType parent segment type
* @param statementBinderContext statement binder context
* @param tableBinderContexts table binder contexts
* @param outerTableBinderContexts outer table binder contexts
* @return function segment
*/
- public static FunctionSegment bind(final FunctionSegment segment, final
SQLStatementBinderContext statementBinderContext,
+ public static FunctionSegment bind(final FunctionSegment segment, final
SegmentType parentSegmentType, final SQLStatementBinderContext
statementBinderContext,
final Map<String,
TableSegmentBinderContext> tableBinderContexts, final Map<String,
TableSegmentBinderContext> outerTableBinderContexts) {
FunctionSegment result = new FunctionSegment(segment.getStartIndex(),
segment.getStopIndex(), segment.getFunctionName(), segment.getText());
result.setOwner(segment.getOwner());
for (ExpressionSegment each : segment.getParameters()) {
- result.getParameters().add(ExpressionSegmentBinder.bind(each,
statementBinderContext, tableBinderContexts, outerTableBinderContexts));
+ result.getParameters().add(ExpressionSegmentBinder.bind(each,
parentSegmentType, statementBinderContext, tableBinderContexts,
outerTableBinderContexts));
}
return result;
}
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/InExpressionBinder.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/InExpressionBinder.java
index c9386aa34bf..75ac6c5a3c0 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/InExpressionBinder.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/InExpressionBinder.java
@@ -19,6 +19,7 @@ package
org.apache.shardingsphere.infra.binder.segment.expression.impl;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.infra.binder.enums.SegmentType;
import
org.apache.shardingsphere.infra.binder.segment.expression.ExpressionSegmentBinder;
import
org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderContext;
import
org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
@@ -38,13 +39,15 @@ public final class InExpressionBinder {
* Bind in expression segment with metadata.
*
* @param segment in expression
+ * @param parentSegmentType parent segment type
* @param statementBinderContext statement binder context
* @param tableBinderContexts table binder contexts
* @return bounded in expression
*/
- public static InExpression bind(final InExpression segment, final
SQLStatementBinderContext statementBinderContext, final Map<String,
TableSegmentBinderContext> tableBinderContexts) {
- ExpressionSegment boundedLeft =
ExpressionSegmentBinder.bind(segment.getLeft(), statementBinderContext,
tableBinderContexts, Collections.emptyMap());
- ExpressionSegment boundedRight =
ExpressionSegmentBinder.bind(segment.getRight(), statementBinderContext,
tableBinderContexts, Collections.emptyMap());
+ public static InExpression bind(final InExpression segment, final
SegmentType parentSegmentType, final SQLStatementBinderContext
statementBinderContext,
+ final Map<String,
TableSegmentBinderContext> tableBinderContexts) {
+ ExpressionSegment boundedLeft =
ExpressionSegmentBinder.bind(segment.getLeft(), parentSegmentType,
statementBinderContext, tableBinderContexts, Collections.emptyMap());
+ ExpressionSegment boundedRight =
ExpressionSegmentBinder.bind(segment.getRight(), parentSegmentType,
statementBinderContext, tableBinderContexts, Collections.emptyMap());
return new InExpression(segment.getStartIndex(),
segment.getStopIndex(), boundedLeft, boundedRight, segment.isNot());
}
}
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/NotExpressionBinder.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/NotExpressionBinder.java
index 55f637a5773..f1400e589b9 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/NotExpressionBinder.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/expression/impl/NotExpressionBinder.java
@@ -19,6 +19,7 @@ package
org.apache.shardingsphere.infra.binder.segment.expression.impl;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.infra.binder.enums.SegmentType;
import
org.apache.shardingsphere.infra.binder.segment.expression.ExpressionSegmentBinder;
import
org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderContext;
import
org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
@@ -38,13 +39,14 @@ public final class NotExpressionBinder {
* Bind not expression segment with metadata.
*
* @param segment not expression
+ * @param parentSegmentType parent segment type
* @param statementBinderContext statement binder context
* @param tableBinderContexts table binder contexts
* @return bounded not expression
*/
- public static NotExpression bind(final NotExpression segment, final
SQLStatementBinderContext statementBinderContext,
+ public static NotExpression bind(final NotExpression segment, final
SegmentType parentSegmentType, final SQLStatementBinderContext
statementBinderContext,
final Map<String,
TableSegmentBinderContext> tableBinderContexts) {
- ExpressionSegment boundedExpression =
ExpressionSegmentBinder.bind(segment.getExpression(), statementBinderContext,
tableBinderContexts, Collections.emptyMap());
+ ExpressionSegment boundedExpression =
ExpressionSegmentBinder.bind(segment.getExpression(), parentSegmentType,
statementBinderContext, tableBinderContexts, Collections.emptyMap());
return new NotExpression(segment.getStartIndex(),
segment.getStopIndex(), boundedExpression, segment.getNotSign());
}
}
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/from/impl/JoinTableSegmentBinder.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/from/impl/JoinTableSegmentBinder.java
index 3bce8ffd49a..7a60bcf362e 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/from/impl/JoinTableSegmentBinder.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/from/impl/JoinTableSegmentBinder.java
@@ -17,8 +17,11 @@
package org.apache.shardingsphere.infra.binder.segment.from.impl;
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.Multimap;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.infra.binder.enums.SegmentType;
import
org.apache.shardingsphere.infra.binder.segment.expression.ExpressionSegmentBinder;
import
org.apache.shardingsphere.infra.binder.segment.expression.impl.ColumnSegmentBinder;
import org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinder;
@@ -66,13 +69,15 @@ public final class JoinTableSegmentBinder {
result.setNatural(segment.isNatural());
result.setJoinType(segment.getJoinType());
result.setRight(TableSegmentBinder.bind(segment.getRight(),
statementBinderContext, tableBinderContexts));
-
result.setCondition(ExpressionSegmentBinder.bind(segment.getCondition(),
statementBinderContext, tableBinderContexts, Collections.emptyMap()));
+
result.setCondition(ExpressionSegmentBinder.bind(segment.getCondition(),
SegmentType.JOIN, statementBinderContext, tableBinderContexts,
Collections.emptyMap()));
result.setUsing(bindUsingColumns(segment.getUsing(),
tableBinderContexts));
+ result.getUsing().forEach(each ->
statementBinderContext.getUsingColumnNames().add(each.getIdentifier().getValue().toLowerCase()));
Map<String, ProjectionSegment> usingColumnsByNaturalJoin =
Collections.emptyMap();
if (result.isNatural()) {
usingColumnsByNaturalJoin = getUsingColumnsByNaturalJoin(result,
tableBinderContexts);
Collection<ColumnSegment> derivedUsingColumns =
getDerivedUsingColumns(usingColumnsByNaturalJoin);
result.setDerivedUsing(bindUsingColumns(derivedUsingColumns,
tableBinderContexts));
+ result.getDerivedUsing().forEach(each ->
statementBinderContext.getUsingColumnNames().add(each.getIdentifier().getValue().toLowerCase()));
}
result.getDerivedJoinTableProjectionSegments().addAll(getDerivedJoinTableProjectionSegments(result,
statementBinderContext.getDatabaseType(), usingColumnsByNaturalJoin,
tableBinderContexts));
statementBinderContext.getJoinTableProjectionSegments().addAll(result.getDerivedJoinTableProjectionSegments());
@@ -106,7 +111,7 @@ public final class JoinTableSegmentBinder {
return projectionSegments;
}
Collection<ProjectionSegment> result = new LinkedList<>();
- Map<String, ProjectionSegment> originalUsingColumns =
segment.getUsing().isEmpty() ? usingColumnsByNaturalJoin :
getUsingColumns(projectionSegments, segment.getUsing());
+ Map<String, ProjectionSegment> originalUsingColumns =
segment.getUsing().isEmpty() ? usingColumnsByNaturalJoin :
getUsingColumns(projectionSegments, segment.getUsing(), segment.getJoinType());
Collection<ProjectionSegment> orderedUsingColumns =
databaseType instanceof MySQLDatabaseType ?
getJoinUsingColumnsByProjectionOrder(projectionSegments, originalUsingColumns)
: originalUsingColumns.values();
result.addAll(orderedUsingColumns);
@@ -160,14 +165,16 @@ public final class JoinTableSegmentBinder {
return result;
}
- private static Map<String, ProjectionSegment> getUsingColumns(final
Collection<ProjectionSegment> projectionSegments, final
Collection<ColumnSegment> usingColumns) {
- Map<String, ProjectionSegment> columnLabelProjectionSegments = new
LinkedHashMap<>(projectionSegments.size(), 1F);
- projectionSegments.forEach(each ->
columnLabelProjectionSegments.putIfAbsent(each.getColumnLabel().toLowerCase(),
each));
+ private static Map<String, ProjectionSegment> getUsingColumns(final
Collection<ProjectionSegment> projectionSegments, final
Collection<ColumnSegment> usingColumns, final String joinType) {
+ Multimap<String, ProjectionSegment> columnLabelProjectionSegments =
LinkedHashMultimap.create();
+ projectionSegments.forEach(each ->
columnLabelProjectionSegments.put(each.getColumnLabel().toLowerCase(), each));
Map<String, ProjectionSegment> result = new LinkedHashMap<>();
for (ColumnSegment each : usingColumns) {
- ProjectionSegment projectionSegment =
columnLabelProjectionSegments.get(each.getIdentifier().getValue().toLowerCase());
- if (null != projectionSegment) {
- result.put(projectionSegment.getColumnLabel().toLowerCase(),
projectionSegment);
+ LinkedList<ProjectionSegment> groupProjectionSegments = new
LinkedList<>(columnLabelProjectionSegments.get(each.getIdentifier().getValue().toLowerCase()));
+ if (!groupProjectionSegments.isEmpty()) {
+ ProjectionSegment targetProjectionSegment =
+ JoinType.RIGHT.name().equalsIgnoreCase(joinType) ?
groupProjectionSegments.descendingIterator().next() :
groupProjectionSegments.iterator().next();
+
result.put(targetProjectionSegment.getColumnLabel().toLowerCase(),
targetProjectionSegment);
}
}
return result;
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/impl/ColumnProjectionSegmentBinder.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/impl/ColumnProjectionSegmentBinder.java
index d1ae82549f9..9b462e13815 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/impl/ColumnProjectionSegmentBinder.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/projection/impl/ColumnProjectionSegmentBinder.java
@@ -19,6 +19,7 @@ package
org.apache.shardingsphere.infra.binder.segment.projection.impl;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.infra.binder.enums.SegmentType;
import
org.apache.shardingsphere.infra.binder.segment.expression.impl.ColumnSegmentBinder;
import
org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderContext;
import
org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
@@ -44,7 +45,7 @@ public final class ColumnProjectionSegmentBinder {
*/
public static ColumnProjectionSegment bind(final ColumnProjectionSegment
segment, final SQLStatementBinderContext statementBinderContext,
final Map<String,
TableSegmentBinderContext> tableBinderContexts) {
- ColumnSegment boundedColumn =
ColumnSegmentBinder.bind(segment.getColumn(), statementBinderContext,
tableBinderContexts, Collections.emptyMap());
+ ColumnSegment boundedColumn =
ColumnSegmentBinder.bind(segment.getColumn(), SegmentType.PROJECTION,
statementBinderContext, tableBinderContexts, Collections.emptyMap());
ColumnProjectionSegment result = new
ColumnProjectionSegment(boundedColumn);
segment.getAliasSegment().ifPresent(result::setAlias);
result.setVisible(segment.isVisible());
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/where/WhereSegmentBinder.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/where/WhereSegmentBinder.java
index 129655fbc15..f1e91c24e3f 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/where/WhereSegmentBinder.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/where/WhereSegmentBinder.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.infra.binder.segment.where;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.infra.binder.enums.SegmentType;
import
org.apache.shardingsphere.infra.binder.segment.expression.ExpressionSegmentBinder;
import
org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderContext;
import
org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
@@ -44,6 +45,6 @@ public final class WhereSegmentBinder {
public static WhereSegment bind(final WhereSegment segment, final
SQLStatementBinderContext statementBinderContext,
final Map<String,
TableSegmentBinderContext> tableBinderContexts, final Map<String,
TableSegmentBinderContext> outerTableBinderContexts) {
return new WhereSegment(segment.getStartIndex(),
segment.getStopIndex(),
- ExpressionSegmentBinder.bind(segment.getExpr(),
statementBinderContext, tableBinderContexts, outerTableBinderContexts));
+ ExpressionSegmentBinder.bind(segment.getExpr(),
SegmentType.PREDICATE, statementBinderContext, tableBinderContexts,
outerTableBinderContexts));
}
}
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/SQLStatementBinderContext.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/SQLStatementBinderContext.java
index 999a6a72635..8d1c8df99c1 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/SQLStatementBinderContext.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/statement/SQLStatementBinderContext.java
@@ -24,6 +24,7 @@ import
org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
import java.util.Collection;
+import java.util.HashSet;
import java.util.LinkedList;
/**
@@ -39,5 +40,7 @@ public final class SQLStatementBinderContext {
private final DatabaseType databaseType;
+ private final Collection<String> usingColumnNames = new HashSet<>();
+
private final Collection<ProjectionSegment> joinTableProjectionSegments =
new LinkedList<>();
}
diff --git
a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/from/impl/JoinTableSegmentBinderTest.java
b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/from/impl/JoinTableSegmentBinderTest.java
index 1cbed4b5952..0b8e985b882 100644
---
a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/from/impl/JoinTableSegmentBinderTest.java
+++
b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/from/impl/JoinTableSegmentBinderTest.java
@@ -188,9 +188,9 @@ class JoinTableSegmentBinderTest {
assertThat(actual.size(), is(5));
assertTrue(actual.get(0) instanceof ColumnProjectionSegment);
assertThat(((ColumnProjectionSegment)
actual.get(0)).getColumn().getColumnBoundedInfo().getOriginalColumn().getValue(),
is("status"));
- assertThat(((ColumnProjectionSegment)
actual.get(0)).getColumn().getColumnBoundedInfo().getOriginalTable().getValue(),
is("t_order"));
+ assertThat(((ColumnProjectionSegment)
actual.get(0)).getColumn().getColumnBoundedInfo().getOriginalTable().getValue(),
is("t_order_item"));
assertThat(((ColumnProjectionSegment)
actual.get(1)).getColumn().getColumnBoundedInfo().getOriginalColumn().getValue(),
is("order_id"));
- assertThat(((ColumnProjectionSegment)
actual.get(1)).getColumn().getColumnBoundedInfo().getOriginalTable().getValue(),
is("t_order"));
+ assertThat(((ColumnProjectionSegment)
actual.get(1)).getColumn().getColumnBoundedInfo().getOriginalTable().getValue(),
is("t_order_item"));
assertThat(((ColumnProjectionSegment)
actual.get(2)).getColumn().getColumnBoundedInfo().getOriginalColumn().getValue(),
is("user_id"));
assertThat(((ColumnProjectionSegment)
actual.get(2)).getColumn().getColumnBoundedInfo().getOriginalTable().getValue(),
is("t_order"));
assertThat(((ColumnProjectionSegment)
actual.get(3)).getColumn().getColumnBoundedInfo().getOriginalColumn().getValue(),
is("item_id"));