This is an automated email from the ASF dual-hosted git repository.

zhangliang 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 408dfc91de2 Add more test cases on SegmentBinder (#37152)
408dfc91de2 is described below

commit 408dfc91de29f3d997213f16d184411fb6d2328e
Author: Liang Zhang <[email protected]>
AuthorDate: Fri Nov 21 00:14:29 2025 +0800

    Add more test cases on SegmentBinder (#37152)
---
 .../dml/column/InsertColumnsSegmentBinderTest.java | 68 +++++++++++++++
 .../dml/combine/CombineSegmentBinderTest.java      | 98 ++++++++++++++++++++++
 .../type/BinaryOperationExpressionBinderTest.java  | 39 ++++++---
 .../type/ExistsSubqueryExpressionBinderTest.java   | 43 +++++-----
 .../type/FunctionExpressionSegmentBinderTest.java  | 67 ++++++++++++---
 .../expression/type/InExpressionBinderTest.java    | 36 ++++++--
 .../type/DeleteMultiTableSegmentBinderTest.java    | 68 +++++++++++++++
 7 files changed, 370 insertions(+), 49 deletions(-)

diff --git 
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/column/InsertColumnsSegmentBinderTest.java
 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/column/InsertColumnsSegmentBinderTest.java
new file mode 100644
index 00000000000..e020c63b0da
--- /dev/null
+++ 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/column/InsertColumnsSegmentBinderTest.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.infra.binder.engine.segment.dml.column;
+
+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.dml.expression.type.ColumnSegmentBinder;
+import 
org.apache.shardingsphere.infra.binder.engine.segment.dml.from.context.TableSegmentBinderContext;
+import 
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.InsertColumnsSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.AutoMockExtension;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockSettings;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(AutoMockExtension.class)
+@StaticMockSettings(ColumnSegmentBinder.class)
+class InsertColumnsSegmentBinderTest {
+    
+    @Test
+    void assertBind() {
+        ColumnSegment firstColumn = new ColumnSegment(0, 1, new 
IdentifierValue("order_id"));
+        ColumnSegment secondColumn = new ColumnSegment(2, 3, new 
IdentifierValue("user_id"));
+        InsertColumnsSegment segment = new InsertColumnsSegment(5, 8, 
Arrays.asList(firstColumn, secondColumn));
+        ColumnSegment boundFirstColumn = new ColumnSegment(0, 1, new 
IdentifierValue("order_id"));
+        ColumnSegment boundSecondColumn = new ColumnSegment(2, 3, new 
IdentifierValue("user_id"));
+        SQLStatementBinderContext binderContext = 
mock(SQLStatementBinderContext.class);
+        Multimap<CaseInsensitiveString, TableSegmentBinderContext> 
tableBinderContexts = LinkedHashMultimap.create();
+        when(ColumnSegmentBinder.bind(eq(firstColumn), 
eq(SegmentType.INSERT_COLUMNS), eq(binderContext), eq(tableBinderContexts), 
any(Multimap.class))).thenReturn(boundFirstColumn);
+        when(ColumnSegmentBinder.bind(eq(secondColumn), 
eq(SegmentType.INSERT_COLUMNS), eq(binderContext), eq(tableBinderContexts), 
any(Multimap.class))).thenReturn(boundSecondColumn);
+        InsertColumnsSegment actual = InsertColumnsSegmentBinder.bind(segment, 
binderContext, tableBinderContexts);
+        assertThat(actual.getStartIndex(), is(5));
+        assertThat(actual.getStopIndex(), is(8));
+        Collection<ColumnSegment> actualColumns = actual.getColumns();
+        assertThat(actualColumns.size(), is(2));
+        assertThat(actualColumns.iterator().next(), is(boundFirstColumn));
+        assertThat(actualColumns.stream().skip(1).findFirst().orElse(null), 
is(boundSecondColumn));
+    }
+}
diff --git 
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/combine/CombineSegmentBinderTest.java
 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/combine/CombineSegmentBinderTest.java
new file mode 100644
index 00000000000..325fa19de6b
--- /dev/null
+++ 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/combine/CombineSegmentBinderTest.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.infra.binder.engine.segment.dml.combine;
+
+import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString;
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.Multimap;
+import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import 
org.apache.shardingsphere.infra.binder.engine.segment.dml.from.context.TableSegmentBinderContext;
+import 
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
+import 
org.apache.shardingsphere.infra.binder.engine.statement.dml.SelectStatementBinder;
+import org.apache.shardingsphere.infra.hint.HintValueContext;
+import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import org.apache.shardingsphere.sql.parser.statement.core.enums.CombineType;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.combine.CombineSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubquerySegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement;
+import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedConstruction;
+import org.mockito.invocation.InvocationOnMock;
+
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static org.hamcrest.CoreMatchers.hasItems;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockConstruction;
+import static org.mockito.Mockito.when;
+
+class CombineSegmentBinderTest {
+    
+    @Test
+    void assertBind() {
+        SelectStatement leftSelect = new 
SelectStatement(mock(DatabaseType.class));
+        SelectStatement rightSelect = new 
SelectStatement(mock(DatabaseType.class));
+        SubquerySegment leftSegment = new SubquerySegment(1, 5, leftSelect, 
"LEFT");
+        SubquerySegment rightSegment = new SubquerySegment(6, 10, rightSelect, 
"RIGHT");
+        CombineSegment segment = new CombineSegment(0, 20, leftSegment, 
CombineType.UNION, rightSegment);
+        SQLStatementBinderContext binderContext = new 
SQLStatementBinderContext(
+                mock(ShardingSphereMetaData.class, RETURNS_DEEP_STUBS), 
"foo_db", new HintValueContext(), mock(SQLStatement.class));
+        Multimap<CaseInsensitiveString, TableSegmentBinderContext> 
externalContexts = binderContext.getExternalTableBinderContexts();
+        CaseInsensitiveString tableKey = new CaseInsensitiveString("t_order");
+        externalContexts.put(tableKey, mock(TableSegmentBinderContext.class));
+        Collection<String> cteAliases = 
binderContext.getCommonTableExpressionsSegmentsUniqueAliases();
+        cteAliases.add("existing_cte");
+        Multimap<CaseInsensitiveString, TableSegmentBinderContext> 
outerTableBinderContexts = LinkedHashMultimap.create();
+        SelectStatement boundLeftSelect = new 
SelectStatement(mock(DatabaseType.class));
+        SelectStatement boundRightSelect = new 
SelectStatement(mock(DatabaseType.class));
+        AtomicReference<SQLStatementBinderContext> capturedLeftContext = new 
AtomicReference<>();
+        AtomicReference<SQLStatementBinderContext> capturedRightContext = new 
AtomicReference<>();
+        try (MockedConstruction<SelectStatementBinder> ignore = 
mockConstruction(SelectStatementBinder.class, (mock, context) -> {
+            when(mock.bind(eq(leftSelect), 
any(SQLStatementBinderContext.class))).thenAnswer(invocation -> {
+                
capturedLeftContext.set(getSqlStatementBinderContext(invocation, "left_cte"));
+                return boundLeftSelect;
+            });
+            when(mock.bind(eq(rightSelect), 
any(SQLStatementBinderContext.class))).thenAnswer(invocation -> {
+                
capturedRightContext.set(getSqlStatementBinderContext(invocation, "right_cte"));
+                return boundRightSelect;
+            });
+        })) {
+            CombineSegment actual = CombineSegmentBinder.bind(segment, 
binderContext, outerTableBinderContexts);
+            assertThat(actual.getStartIndex(), is(0));
+            assertThat(actual.getStopIndex(), is(20));
+            assertThat(actual.getLeft().getSelect(), is(boundLeftSelect));
+            assertThat(actual.getRight().getSelect(), is(boundRightSelect));
+        }
+        
assertThat(capturedLeftContext.get().getExternalTableBinderContexts().get(tableKey).iterator().next(),
 is(externalContexts.get(tableKey).iterator().next()));
+        
assertThat(capturedRightContext.get().getExternalTableBinderContexts().get(tableKey).iterator().next(),
 is(externalContexts.get(tableKey).iterator().next()));
+        
assertThat(binderContext.getCommonTableExpressionsSegmentsUniqueAliases(), 
hasItems("existing_cte", "left_cte", "right_cte"));
+    }
+    
+    private static SQLStatementBinderContext 
getSqlStatementBinderContext(final InvocationOnMock invocation, final String 
commonTableExpressionsSegmentsUniqueAlias) {
+        SQLStatementBinderContext subqueryContext = invocation.getArgument(1);
+        
subqueryContext.getCommonTableExpressionsSegmentsUniqueAliases().add(commonTableExpressionsSegmentsUniqueAlias);
+        return subqueryContext;
+    }
+}
diff --git 
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/BinaryOperationExpressionBinderTest.java
 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/BinaryOperationExpressionBinderTest.java
index ceb8fa6c931..eacfaaa5e36 100644
--- 
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/BinaryOperationExpressionBinderTest.java
+++ 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/BinaryOperationExpressionBinderTest.java
@@ -17,30 +17,47 @@
 
 package 
org.apache.shardingsphere.infra.binder.engine.segment.dml.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.dml.expression.ExpressionSegmentBinder;
+import 
org.apache.shardingsphere.infra.binder.engine.segment.dml.from.context.TableSegmentBinderContext;
 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.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.AutoMockExtension;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockSettings;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+@ExtendWith(AutoMockExtension.class)
+@StaticMockSettings(ExpressionSegmentBinder.class)
 class BinaryOperationExpressionBinderTest {
     
     @Test
-    void assertBinaryOperationExpression() {
-        BinaryOperationExpression binaryOperationExpression = new 
BinaryOperationExpression(0, 0,
-                new LiteralExpressionSegment(0, 0, "test"),
-                new LiteralExpressionSegment(0, 0, "test"), "=", "test");
+    void assertBind() {
+        ExpressionSegment leftSegment = mock(ExpressionSegment.class);
+        ExpressionSegment rightSegment = mock(ExpressionSegment.class);
+        BinaryOperationExpression segment = new BinaryOperationExpression(3, 
9, leftSegment, rightSegment, "+", "a + b");
+        ExpressionSegment boundLeftSegment = mock(ExpressionSegment.class);
+        ExpressionSegment boundRightSegment = mock(ExpressionSegment.class);
         SQLStatementBinderContext binderContext = 
mock(SQLStatementBinderContext.class);
-        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("="));
-        assertThat(actual.getText(), is("test"));
+        Multimap<CaseInsensitiveString, TableSegmentBinderContext> 
tableBinderContexts = LinkedHashMultimap.create();
+        Multimap<CaseInsensitiveString, TableSegmentBinderContext> 
outerTableBinderContexts = LinkedHashMultimap.create();
+        when(ExpressionSegmentBinder.bind(leftSegment, SegmentType.PREDICATE, 
binderContext, tableBinderContexts, 
outerTableBinderContexts)).thenReturn(boundLeftSegment);
+        when(ExpressionSegmentBinder.bind(rightSegment, SegmentType.PREDICATE, 
binderContext, tableBinderContexts, 
outerTableBinderContexts)).thenReturn(boundRightSegment);
+        BinaryOperationExpression actual = 
BinaryOperationExpressionBinder.bind(segment, SegmentType.PREDICATE, 
binderContext, tableBinderContexts, outerTableBinderContexts);
+        assertThat(actual.getStartIndex(), is(3));
+        assertThat(actual.getStopIndex(), is(9));
+        assertThat(actual.getLeft(), is(boundLeftSegment));
+        assertThat(actual.getRight(), is(boundRightSegment));
+        assertThat(actual.getOperator(), is("+"));
+        assertThat(actual.getText(), is("a + b"));
     }
 }
diff --git 
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ExistsSubqueryExpressionBinderTest.java
 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ExistsSubqueryExpressionBinderTest.java
index 3e0c70d97f8..f52dd49e630 100644
--- 
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ExistsSubqueryExpressionBinderTest.java
+++ 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ExistsSubqueryExpressionBinderTest.java
@@ -17,38 +17,43 @@
 
 package 
org.apache.shardingsphere.infra.binder.engine.segment.dml.expression.type;
 
+import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString;
 import com.google.common.collect.LinkedHashMultimap;
-import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import com.google.common.collect.Multimap;
+import 
org.apache.shardingsphere.infra.binder.engine.segment.dml.from.context.TableSegmentBinderContext;
 import 
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
-import org.apache.shardingsphere.infra.hint.HintValueContext;
-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.expr.ExistsSubqueryExpression;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubquerySegment;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionsSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.AutoMockExtension;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockSettings;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+@ExtendWith(AutoMockExtension.class)
+@StaticMockSettings(SubquerySegmentBinder.class)
 class ExistsSubqueryExpressionBinderTest {
     
-    private final DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "FIXTURE");
-    
     @Test
-    void assertBindExistsSubqueryExpression() {
-        SelectStatement selectStatement = new SelectStatement(databaseType);
-        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), "foo_db", new 
HintValueContext(), mock());
-        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"));
-        assertThat(actual.getSubquery().getStartIndex(), 
is(existsSubqueryExpression.getSubquery().getStartIndex()));
-        assertThat(actual.getSubquery().getStopIndex(), 
is(existsSubqueryExpression.getSubquery().getStopIndex()));
-        assertThat(actual.getSubquery().getText(), is("t_test"));
+    void assertBind() {
+        SubquerySegment subquerySegment = new SubquerySegment(0, 5, 
mock(SelectStatement.class), "SELECT 1");
+        ExistsSubqueryExpression segment = new ExistsSubqueryExpression(1, 10, 
subquerySegment);
+        segment.setNot(true);
+        SubquerySegment boundSubquerySegment = new SubquerySegment(0, 5, 
mock(SelectStatement.class), "SELECT 1");
+        SQLStatementBinderContext binderContext = 
mock(SQLStatementBinderContext.class);
+        Multimap<CaseInsensitiveString, TableSegmentBinderContext> 
tableBinderContexts = LinkedHashMultimap.create();
+        when(SubquerySegmentBinder.bind(eq(subquerySegment), 
eq(binderContext), eq(tableBinderContexts))).thenReturn(boundSubquerySegment);
+        ExistsSubqueryExpression actual = 
ExistsSubqueryExpressionBinder.bind(segment, binderContext, 
tableBinderContexts);
+        assertThat(actual.getStartIndex(), is(1));
+        assertThat(actual.getStopIndex(), is(10));
+        assertThat(actual.getSubquery(), is(boundSubquerySegment));
+        assertTrue(actual.isNot());
     }
 }
diff --git 
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/FunctionExpressionSegmentBinderTest.java
 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/FunctionExpressionSegmentBinderTest.java
index d3b0cdef1db..0c3a82164d5 100644
--- 
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/FunctionExpressionSegmentBinderTest.java
+++ 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/FunctionExpressionSegmentBinderTest.java
@@ -17,28 +17,75 @@
 
 package 
org.apache.shardingsphere.infra.binder.engine.segment.dml.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.dml.expression.ExpressionSegmentBinder;
+import 
org.apache.shardingsphere.infra.binder.engine.segment.dml.from.context.TableSegmentBinderContext;
 import 
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
-import org.apache.shardingsphere.infra.hint.HintValueContext;
-import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.FunctionSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.OwnerSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.WindowItemSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.AutoMockExtension;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockSettings;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.util.Iterator;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+@ExtendWith(AutoMockExtension.class)
+@StaticMockSettings(ExpressionSegmentBinder.class)
 class FunctionExpressionSegmentBinderTest {
     
     @Test
-    void assertBindFunctionExpressionSegment() {
-        FunctionSegment functionSegment = new FunctionSegment(0, 0, "CONCAT", 
"('%','abc','%')");
-        SQLStatementBinderContext binderContext = new 
SQLStatementBinderContext(new ShardingSphereMetaData(), "foo_db", new 
HintValueContext(), mock());
-        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"));
-        assertThat(actual.getText(), is("('%','abc','%')"));
+    void assertBindSkipsParameterForXmlElement() {
+        FunctionSegment functionSegment = new FunctionSegment(0, 5, 
"XMLELEMENT", "XMLELEMENT()");
+        OwnerSegment ownerSegment = new OwnerSegment(0, 0, new 
IdentifierValue("schema"));
+        functionSegment.setOwner(ownerSegment);
+        WindowItemSegment windowItemSegment = new WindowItemSegment(0, 0);
+        functionSegment.setWindow(windowItemSegment);
+        ExpressionSegment skippedParameter = mock(ExpressionSegment.class);
+        ExpressionSegment parameterToBind = mock(ExpressionSegment.class);
+        functionSegment.getParameters().add(skippedParameter);
+        functionSegment.getParameters().add(parameterToBind);
+        ExpressionSegment boundParameter = mock(ExpressionSegment.class);
+        SQLStatementBinderContext binderContext = 
mock(SQLStatementBinderContext.class);
+        Multimap<CaseInsensitiveString, TableSegmentBinderContext> 
tableBinderContexts = LinkedHashMultimap.create();
+        Multimap<CaseInsensitiveString, TableSegmentBinderContext> 
outerTableBinderContexts = LinkedHashMultimap.create();
+        when(ExpressionSegmentBinder.bind(parameterToBind, 
SegmentType.PROJECTION, binderContext, tableBinderContexts, 
outerTableBinderContexts)).thenReturn(boundParameter);
+        FunctionSegment actual = 
FunctionExpressionSegmentBinder.bind(functionSegment, SegmentType.PROJECTION, 
binderContext, tableBinderContexts, outerTableBinderContexts);
+        Iterator<ExpressionSegment> parameters = 
actual.getParameters().iterator();
+        assertThat(parameters.next(), is(skippedParameter));
+        assertThat(parameters.next(), is(boundParameter));
+        assertThat(actual.getOwner(), is(ownerSegment));
+        assertThat(actual.getWindow().orElse(null), is(windowItemSegment));
+    }
+    
+    @Test
+    void assertBindWithoutSkip() {
+        FunctionSegment functionSegment = new FunctionSegment(3, 8, "ABS", 
"ABS()");
+        ExpressionSegment firstParameter = mock(ExpressionSegment.class);
+        ExpressionSegment secondParameter = mock(ExpressionSegment.class);
+        functionSegment.getParameters().add(firstParameter);
+        functionSegment.getParameters().add(secondParameter);
+        ExpressionSegment boundFirstParameter = mock(ExpressionSegment.class);
+        ExpressionSegment boundSecondParameter = mock(ExpressionSegment.class);
+        SQLStatementBinderContext binderContext = 
mock(SQLStatementBinderContext.class);
+        Multimap<CaseInsensitiveString, TableSegmentBinderContext> 
tableBinderContexts = LinkedHashMultimap.create();
+        Multimap<CaseInsensitiveString, TableSegmentBinderContext> 
outerTableBinderContexts = LinkedHashMultimap.create();
+        when(ExpressionSegmentBinder.bind(firstParameter, 
SegmentType.PROJECTION, binderContext, tableBinderContexts, 
outerTableBinderContexts)).thenReturn(boundFirstParameter);
+        when(ExpressionSegmentBinder.bind(secondParameter, 
SegmentType.PROJECTION, binderContext, tableBinderContexts, 
outerTableBinderContexts)).thenReturn(boundSecondParameter);
+        FunctionSegment actual = 
FunctionExpressionSegmentBinder.bind(functionSegment, SegmentType.PROJECTION, 
binderContext, tableBinderContexts, outerTableBinderContexts);
+        Iterator<ExpressionSegment> parameters = 
actual.getParameters().iterator();
+        assertThat(parameters.next(), is(boundFirstParameter));
+        assertThat(parameters.next(), is(boundSecondParameter));
     }
 }
diff --git 
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/InExpressionBinderTest.java
 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/InExpressionBinderTest.java
index bd544e3376d..f0a11bcaae2 100644
--- 
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/InExpressionBinderTest.java
+++ 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/InExpressionBinderTest.java
@@ -17,28 +17,46 @@
 
 package 
org.apache.shardingsphere.infra.binder.engine.segment.dml.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.dml.expression.ExpressionSegmentBinder;
+import 
org.apache.shardingsphere.infra.binder.engine.segment.dml.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.expr.InExpression;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.LiteralExpressionSegment;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.AutoMockExtension;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockSettings;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+@ExtendWith(AutoMockExtension.class)
+@StaticMockSettings(ExpressionSegmentBinder.class)
 class InExpressionBinderTest {
     
     @Test
-    void assertInExpressionBinder() {
-        InExpression inExpression = new InExpression(0, 10,
-                new LiteralExpressionSegment(0, 0, "left"),
-                new LiteralExpressionSegment(0, 0, "right"), true);
+    void assertBind() {
+        ExpressionSegment leftSegment = mock(ExpressionSegment.class);
+        ExpressionSegment rightSegment = mock(ExpressionSegment.class);
+        InExpression segment = new InExpression(5, 10, leftSegment, 
rightSegment, true);
+        ExpressionSegment boundLeftSegment = mock(ExpressionSegment.class);
+        ExpressionSegment boundRightSegment = mock(ExpressionSegment.class);
         SQLStatementBinderContext binderContext = 
mock(SQLStatementBinderContext.class);
-        InExpression actual = InExpressionBinder.bind(inExpression, 
SegmentType.PROJECTION, binderContext, LinkedHashMultimap.create(), 
LinkedHashMultimap.create());
-        assertThat(actual.getText(), is("left NOT IN right"));
-        assertTrue(actual.isNot());
+        Multimap<CaseInsensitiveString, TableSegmentBinderContext> 
tableBinderContexts = LinkedHashMultimap.create();
+        Multimap<CaseInsensitiveString, TableSegmentBinderContext> 
outerTableBinderContexts = LinkedHashMultimap.create();
+        when(ExpressionSegmentBinder.bind(leftSegment, SegmentType.PREDICATE, 
binderContext, tableBinderContexts, 
outerTableBinderContexts)).thenReturn(boundLeftSegment);
+        when(ExpressionSegmentBinder.bind(rightSegment, SegmentType.PREDICATE, 
binderContext, tableBinderContexts, 
outerTableBinderContexts)).thenReturn(boundRightSegment);
+        InExpression actual = InExpressionBinder.bind(segment, 
SegmentType.PREDICATE, binderContext, tableBinderContexts, 
outerTableBinderContexts);
+        assertThat(actual.getStartIndex(), is(5));
+        assertThat(actual.getStopIndex(), is(10));
+        assertThat(actual.getLeft(), is(boundLeftSegment));
+        assertThat(actual.getRight(), is(boundRightSegment));
+        assertThat(actual.isNot(), is(true));
     }
 }
diff --git 
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/from/type/DeleteMultiTableSegmentBinderTest.java
 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/from/type/DeleteMultiTableSegmentBinderTest.java
new file mode 100644
index 00000000000..e2eb6bd5ddd
--- /dev/null
+++ 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/from/type/DeleteMultiTableSegmentBinderTest.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.infra.binder.engine.segment.dml.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.dml.from.TableSegmentBinder;
+import 
org.apache.shardingsphere.infra.binder.engine.segment.dml.from.context.TableSegmentBinderContext;
+import 
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableNameSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.DeleteMultiTableSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.AutoMockExtension;
+import 
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockSettings;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(AutoMockExtension.class)
+@StaticMockSettings(TableSegmentBinder.class)
+class DeleteMultiTableSegmentBinderTest {
+    
+    @Test
+    void assertBind() {
+        DeleteMultiTableSegment segment = new DeleteMultiTableSegment();
+        segment.setStartIndex(10);
+        segment.setStopIndex(20);
+        SimpleTableSegment firstDeleteTable = new SimpleTableSegment(new 
TableNameSegment(0, 0, new IdentifierValue("t_order")));
+        SimpleTableSegment secondDeleteTable = new SimpleTableSegment(new 
TableNameSegment(0, 0, new IdentifierValue("t_order_item")));
+        segment.getActualDeleteTables().add(firstDeleteTable);
+        segment.getActualDeleteTables().add(secondDeleteTable);
+        TableSegment relationTable = new SimpleTableSegment(new 
TableNameSegment(0, 0, new IdentifierValue("relation_table")));
+        segment.setRelationTable(relationTable);
+        SQLStatementBinderContext binderContext = 
mock(SQLStatementBinderContext.class);
+        Multimap<CaseInsensitiveString, TableSegmentBinderContext> 
tableBinderContexts = LinkedHashMultimap.create();
+        TableSegment boundRelationTable = mock(TableSegment.class);
+        when(TableSegmentBinder.bind(eq(relationTable), eq(binderContext), 
eq(tableBinderContexts), any(Multimap.class))).thenReturn(boundRelationTable);
+        DeleteMultiTableSegment actual = 
DeleteMultiTableSegmentBinder.bind(segment, binderContext, tableBinderContexts);
+        assertThat(actual.getStartIndex(), is(10));
+        assertThat(actual.getStopIndex(), is(20));
+        assertThat(actual.getActualDeleteTables(), 
is(segment.getActualDeleteTables()));
+        assertThat(actual.getRelationTable(), is(boundRelationTable));
+    }
+}


Reply via email to