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"));


Reply via email to