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 9727439ae68 Add EnumerableScanTest, EnumerableScanTest and 
LogicalScanTest (#37334)
9727439ae68 is described below

commit 9727439ae68c119fbc3f8f02b746079a5cb9b7c1
Author: Liang Zhang <[email protected]>
AuthorDate: Thu Dec 11 00:10:54 2025 +0800

    Add EnumerableScanTest, EnumerableScanTest and LogicalScanTest (#37334)
    
    * Add EnumerableScanTest, EnumerableScanTest and LogicalScanTest
    
    * Add EnumerableScanTest, EnumerableScanTest and LogicalScanTest
---
 .../rel/operator/logical/LogicalScanTest.java      | 200 +++++++++++++++++++++
 .../operator/physical/EnumerableModifyTest.java    |  98 ++++++++++
 .../rel/operator/physical/EnumerableScanTest.java  | 156 ++++++++++++++++
 3 files changed, 454 insertions(+)

diff --git 
a/kernel/sql-federation/compiler/src/test/java/org/apache/shardingsphere/sqlfederation/compiler/rel/operator/logical/LogicalScanTest.java
 
b/kernel/sql-federation/compiler/src/test/java/org/apache/shardingsphere/sqlfederation/compiler/rel/operator/logical/LogicalScanTest.java
new file mode 100644
index 00000000000..357e44c6cfd
--- /dev/null
+++ 
b/kernel/sql-federation/compiler/src/test/java/org/apache/shardingsphere/sqlfederation/compiler/rel/operator/logical/LogicalScanTest.java
@@ -0,0 +1,200 @@
+/*
+ * 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.sqlfederation.compiler.rel.operator.logical;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
+import org.apache.calcite.linq4j.tree.Expressions;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptSchema;
+import org.apache.calcite.plan.RelOptTable;
+import org.apache.calcite.plan.volcano.VolcanoPlanner;
+import org.apache.calcite.prepare.RelOptTableImpl;
+import org.apache.calcite.rel.AbstractRelNode;
+import org.apache.calcite.rel.RelWriter;
+import org.apache.calcite.rel.core.TableScan;
+import org.apache.calcite.rel.externalize.RelWriterImpl;
+import org.apache.calcite.rel.hint.RelHint;
+import org.apache.calcite.rel.logical.LogicalFilter;
+import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.rel.logical.LogicalTableScan;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.schema.Schema;
+import org.apache.calcite.schema.Statistics;
+import org.apache.calcite.schema.ModifiableTable;
+import org.apache.calcite.schema.TranslatableTable;
+import org.apache.calcite.sql.SqlExplainLevel;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.internal.configuration.plugins.Plugins;
+import org.mockito.plugins.MemberAccessor;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.Objects;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.withSettings;
+
+class LogicalScanTest {
+    
+    private RelDataType rowType;
+    
+    private RelOptCluster cluster;
+    
+    private LogicalTableScan tableScan;
+    
+    private RexBuilder rexBuilder;
+    
+    @BeforeEach
+    void setUp() {
+        RelDataTypeFactory typeFactory = new JavaTypeFactoryImpl();
+        rexBuilder = new RexBuilder(typeFactory);
+        cluster = RelOptCluster.create(new VolcanoPlanner(), rexBuilder);
+        rowType = typeFactory.builder().add("col", 
SqlTypeName.INTEGER).build();
+        TranslatableTable federationTable = mock(TranslatableTable.class, 
withSettings().extraInterfaces(ModifiableTable.class));
+        when(federationTable.getRowType(typeFactory)).thenReturn(rowType);
+        when(federationTable.getStatistic()).thenReturn(Statistics.of(1D, 
ImmutableList.of()));
+        
when(federationTable.getJdbcTableType()).thenReturn(Schema.TableType.TABLE);
+        when(federationTable.toRel(any(RelOptTable.ToRelContext.class), 
any(RelOptTable.class))).thenAnswer(invocation -> LogicalTableScan.create(
+                invocation.getArgument(0, 
RelOptTable.ToRelContext.class).getCluster(), invocation.getArgument(1, 
RelOptTable.class), ImmutableList.of()));
+        RelOptSchema relOptSchema = mock(RelOptSchema.class);
+        when(relOptSchema.getTypeFactory()).thenReturn(typeFactory);
+        RelOptTable relOptTable = RelOptTableImpl.create(relOptSchema, 
rowType, ImmutableList.of("test", "tbl"), federationTable, each -> 
Expressions.constant(federationTable));
+        
when(relOptSchema.getTableForMember(anyList())).thenReturn(relOptTable);
+        tableScan = LogicalTableScan.create(cluster, relOptTable, 
Collections.emptyList());
+    }
+    
+    @Test
+    void assertPushDownFilter() {
+        LogicalFilter logicalFilter = LogicalFilter.create(tableScan, 
rexBuilder.makeLiteral(true));
+        LogicalScan logicalScan = new LogicalScan(tableScan, "MySQL");
+        logicalScan.pushDown(logicalFilter);
+        assertThat(logicalScan.getRowType(), is(logicalFilter.getRowType()));
+    }
+    
+    @Test
+    void assertPushDownProject() {
+        LogicalProject logicalProject = LogicalProject.create(
+                tableScan, Collections.emptyList(), 
Collections.singletonList(rexBuilder.makeInputRef(rowType, 0)), 
Collections.singletonList("col"), Collections.emptySet());
+        LogicalScan logicalScan = new LogicalScan(tableScan, "MySQL");
+        logicalScan.pushDown(logicalProject);
+        assertThat(logicalScan.getRowType(), is(logicalProject.getRowType()));
+    }
+    
+    @Test
+    void assertPeek() {
+        assertNotNull(new LogicalScan(tableScan, "MySQL").peek());
+    }
+    
+    @Test
+    void assertExplainTerms() {
+        LogicalScan logicalScan = new LogicalScan(tableScan, "MySQL");
+        StringWriter writer = new StringWriter();
+        RelWriter relWriter = new RelWriterImpl(new PrintWriter(writer), 
SqlExplainLevel.EXPPLAN_ATTRIBUTES, false);
+        logicalScan.explainTerms(relWriter);
+        relWriter.done(logicalScan);
+        assertTrue(writer.toString().contains("pushDownRelBuilder"));
+    }
+    
+    @Test
+    void assertDeepEqualsSelf() {
+        LogicalScan logicalScan = new LogicalScan(tableScan, "MySQL");
+        assertTrue(logicalScan.deepEquals(logicalScan));
+    }
+    
+    @Test
+    void assertDeepEqualsWithNull() {
+        assertFalse(new LogicalScan(tableScan, "MySQL").deepEquals(null));
+    }
+    
+    @Test
+    void assertDeepEqualsWithDifferentInstanceWithoutSharedBuilder() {
+        assertFalse(new LogicalScan(tableScan, "MySQL").deepEquals(new 
LogicalScan(tableScan, "MySQL")));
+    }
+    
+    @Test
+    void assertDeepEqualsWithSharedBuilder() throws 
ReflectiveOperationException {
+        LogicalScan logicalScan = new LogicalScan(tableScan, "MySQL");
+        LogicalScan sharedBuilder = new LogicalScan(tableScan, "MySQL");
+        MemberAccessor memberAccessor = Plugins.getMemberAccessor();
+        Field builderField = 
LogicalScan.class.getDeclaredField("pushDownRelBuilder");
+        Object pushDownRelBuilder = memberAccessor.get(builderField, 
logicalScan);
+        memberAccessor.set(builderField, sharedBuilder, pushDownRelBuilder);
+        assertTrue(logicalScan.deepEquals(sharedBuilder));
+    }
+    
+    @Test
+    void assertDeepEqualsWithDifferentClass() {
+        assertFalse(new LogicalScan(tableScan, "MySQL").deepEquals(new 
Object()));
+    }
+    
+    @Test
+    void assertDeepEqualsWithDifferentDatabase() throws 
ReflectiveOperationException {
+        LogicalScan logicalScan = new LogicalScan(tableScan, "MySQL");
+        LogicalScan differentDatabase = new LogicalScan(tableScan, 
"PostgreSQL");
+        MemberAccessor memberAccessor = Plugins.getMemberAccessor();
+        Field builderField = 
LogicalScan.class.getDeclaredField("pushDownRelBuilder");
+        memberAccessor.set(builderField, differentDatabase, 
memberAccessor.get(builderField, logicalScan));
+        assertFalse(logicalScan.deepEquals(differentDatabase));
+    }
+    
+    @Test
+    void assertDeepEqualsWithDifferentHints() throws 
ReflectiveOperationException {
+        LogicalScan logicalScan = new LogicalScan(tableScan, "MySQL");
+        LogicalScan differentHints = new LogicalScan(tableScan, "MySQL");
+        MemberAccessor memberAccessor = Plugins.getMemberAccessor();
+        Field builderField = 
LogicalScan.class.getDeclaredField("pushDownRelBuilder");
+        memberAccessor.set(builderField, differentHints, 
memberAccessor.get(builderField, logicalScan));
+        memberAccessor.set(TableScan.class.getDeclaredField("hints"), 
differentHints, ImmutableList.of(RelHint.builder("h").build()));
+        assertFalse(logicalScan.deepEquals(differentHints));
+    }
+    
+    @Test
+    void assertDeepEqualsWithDifferentRowType() throws 
ReflectiveOperationException {
+        LogicalScan logicalScan = new LogicalScan(tableScan, "MySQL");
+        LogicalScan differentRowType = new LogicalScan(tableScan, "MySQL");
+        MemberAccessor memberAccessor = Plugins.getMemberAccessor();
+        Field builderField = 
LogicalScan.class.getDeclaredField("pushDownRelBuilder");
+        memberAccessor.set(builderField, differentRowType, 
memberAccessor.get(builderField, logicalScan));
+        RelDataTypeFactory typeFactory = cluster.getTypeFactory();
+        RelDataType anotherRowType = typeFactory.builder().add("col", 
SqlTypeName.BIGINT).build();
+        memberAccessor.set(AbstractRelNode.class.getDeclaredField("rowType"), 
differentRowType, anotherRowType);
+        assertFalse(logicalScan.deepEquals(differentRowType));
+    }
+    
+    @Test
+    void assertDeepHashCode() {
+        LogicalScan logicalScan = new LogicalScan(tableScan, "MySQL");
+        int expectedHashCode = Objects.hash(logicalScan.getTraitSet(), 
"MySQL", logicalScan.getPushDownRelBuilder(), logicalScan.getHints(), 
logicalScan.getRowType());
+        assertThat(logicalScan.deepHashCode(), is(expectedHashCode));
+    }
+}
diff --git 
a/kernel/sql-federation/compiler/src/test/java/org/apache/shardingsphere/sqlfederation/compiler/rel/operator/physical/EnumerableModifyTest.java
 
b/kernel/sql-federation/compiler/src/test/java/org/apache/shardingsphere/sqlfederation/compiler/rel/operator/physical/EnumerableModifyTest.java
new file mode 100644
index 00000000000..30b85d0ddfd
--- /dev/null
+++ 
b/kernel/sql-federation/compiler/src/test/java/org/apache/shardingsphere/sqlfederation/compiler/rel/operator/physical/EnumerableModifyTest.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.sqlfederation.compiler.rel.operator.physical;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.adapter.enumerable.EnumerableRel;
+import org.apache.calcite.adapter.enumerable.EnumerableRelImplementor;
+import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
+import org.apache.calcite.linq4j.tree.Expressions;
+import org.apache.calcite.plan.ConventionTraitDef;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptSchema;
+import org.apache.calcite.plan.RelOptTable;
+import org.apache.calcite.plan.volcano.VolcanoPlanner;
+import org.apache.calcite.prepare.Prepare;
+import org.apache.calcite.prepare.RelOptTableImpl;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.TableModify;
+import org.apache.calcite.rel.logical.LogicalTableScan;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.schema.Schema;
+import org.apache.calcite.schema.Statistics;
+import org.apache.calcite.sql.type.SqlTypeName;
+import 
org.apache.shardingsphere.sqlfederation.compiler.metadata.schema.SQLFederationTable;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class EnumerableModifyTest {
+    
+    private RelOptCluster cluster;
+    
+    private RelOptTable relOptTable;
+    
+    private RelNode input;
+    
+    private Prepare.CatalogReader catalogReader;
+    
+    @BeforeEach
+    void setUp() {
+        RelDataTypeFactory typeFactory = new JavaTypeFactoryImpl();
+        RexBuilder rexBuilder = new RexBuilder(typeFactory);
+        VolcanoPlanner planner = new VolcanoPlanner();
+        planner.addRelTraitDef(ConventionTraitDef.INSTANCE);
+        cluster = RelOptCluster.create(planner, rexBuilder);
+        RelDataType rowType = typeFactory.builder().add("col", 
SqlTypeName.INTEGER).build();
+        SQLFederationTable federationTable = mock(SQLFederationTable.class);
+        when(federationTable.getRowType(typeFactory)).thenReturn(rowType);
+        
when(federationTable.toRel(org.mockito.ArgumentMatchers.any(RelOptTable.ToRelContext.class),
 org.mockito.ArgumentMatchers.any(RelOptTable.class))).thenAnswer(
+                invocation -> 
LogicalTableScan.create(invocation.getArgument(0, 
RelOptTable.ToRelContext.class).getCluster(), invocation.getArgument(1, 
RelOptTable.class), Collections.emptyList()));
+        when(federationTable.getStatistic()).thenReturn(Statistics.of(1D, 
ImmutableList.of()));
+        
when(federationTable.getJdbcTableType()).thenReturn(Schema.TableType.TABLE);
+        RelOptSchema schema = mock(RelOptSchema.class);
+        when(schema.getTypeFactory()).thenReturn(typeFactory);
+        relOptTable = RelOptTableImpl.create(schema, rowType, 
ImmutableList.of("test", "tbl"), federationTable, each -> 
Expressions.constant(federationTable));
+        input = LogicalTableScan.create(cluster, relOptTable, 
Collections.emptyList());
+        catalogReader = mock(Prepare.CatalogReader.class);
+    }
+    
+    @Test
+    void assertCopy() {
+        EnumerableModify enumerableModify = new EnumerableModify(cluster, 
cluster.traitSet(), relOptTable, catalogReader, input, 
TableModify.Operation.INSERT, null, null, false);
+        EnumerableModify copied = (EnumerableModify) 
enumerableModify.copy(cluster.traitSet(), Collections.singletonList(input));
+        assertThat(copied.getTable(), is(relOptTable));
+        assertThat(copied.getInput(), is(input));
+        assertThat(copied.getCluster(), is(cluster));
+    }
+    
+    @Test
+    void assertImplement() {
+        EnumerableModify enumerableModify = new EnumerableModify(cluster, 
cluster.traitSet(), relOptTable, catalogReader, input, 
TableModify.Operation.DELETE, null, null, false);
+        assertThrows(UnsupportedOperationException.class, () -> 
enumerableModify.implement(mock(EnumerableRelImplementor.class), 
EnumerableRel.Prefer.ARRAY));
+    }
+}
diff --git 
a/kernel/sql-federation/compiler/src/test/java/org/apache/shardingsphere/sqlfederation/compiler/rel/operator/physical/EnumerableScanTest.java
 
b/kernel/sql-federation/compiler/src/test/java/org/apache/shardingsphere/sqlfederation/compiler/rel/operator/physical/EnumerableScanTest.java
new file mode 100644
index 00000000000..1d14304540c
--- /dev/null
+++ 
b/kernel/sql-federation/compiler/src/test/java/org/apache/shardingsphere/sqlfederation/compiler/rel/operator/physical/EnumerableScanTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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.sqlfederation.compiler.rel.operator.physical;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.DataContext;
+import org.apache.calcite.adapter.enumerable.EnumerableConvention;
+import org.apache.calcite.adapter.enumerable.EnumerableRel;
+import org.apache.calcite.adapter.enumerable.EnumerableRelImplementor;
+import org.apache.calcite.adapter.enumerable.JavaRowFormat;
+import org.apache.calcite.adapter.enumerable.PhysType;
+import org.apache.calcite.adapter.enumerable.PhysTypeImpl;
+import org.apache.calcite.adapter.java.JavaTypeFactory;
+import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
+import org.apache.calcite.linq4j.Linq4j;
+import org.apache.calcite.linq4j.tree.BlockStatement;
+import org.apache.calcite.linq4j.tree.Blocks;
+import org.apache.calcite.linq4j.tree.Expressions;
+import org.apache.calcite.plan.ConventionTraitDef;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptSchema;
+import org.apache.calcite.plan.RelOptTable;
+import org.apache.calcite.plan.volcano.VolcanoPlanner;
+import org.apache.calcite.prepare.RelOptTableImpl;
+import org.apache.calcite.rel.RelWriter;
+import org.apache.calcite.rel.externalize.RelWriterImpl;
+import org.apache.calcite.rel.logical.LogicalTableScan;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.schema.Schema;
+import org.apache.calcite.schema.Statistics;
+import org.apache.calcite.sql.SqlExplainLevel;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.sql.util.SqlString;
+import 
org.apache.shardingsphere.sqlfederation.compiler.metadata.schema.SQLFederationTable;
+import 
org.apache.shardingsphere.sqlfederation.compiler.sql.dialect.SQLDialectFactory;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Collections;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class EnumerableScanTest {
+    
+    private RelOptCluster cluster;
+    
+    private RelDataType rowType;
+    
+    private RelOptTable relOptTable;
+    
+    @BeforeEach
+    void setUp() {
+        JavaTypeFactoryImpl typeFactory = new JavaTypeFactoryImpl();
+        VolcanoPlanner planner = new VolcanoPlanner();
+        planner.addRelTraitDef(ConventionTraitDef.INSTANCE);
+        cluster = RelOptCluster.create(planner, new RexBuilder(typeFactory));
+        rowType = typeFactory.builder().add("col", 
SqlTypeName.INTEGER).build();
+        SQLFederationTable federationTable = mock(SQLFederationTable.class);
+        when(federationTable.getRowType(typeFactory)).thenReturn(rowType);
+        when(federationTable.toRel(any(RelOptTable.ToRelContext.class), 
any(RelOptTable.class))).thenAnswer(
+                invocation -> 
LogicalTableScan.create(invocation.getArgument(0, 
RelOptTable.ToRelContext.class).getCluster(), invocation.getArgument(1, 
RelOptTable.class), Collections.emptyList()));
+        when(federationTable.getStatistic()).thenReturn(Statistics.of(1D, 
ImmutableList.of()));
+        
when(federationTable.getJdbcTableType()).thenReturn(Schema.TableType.TABLE);
+        when(federationTable.implement(any(DataContext.class), any(), 
any(int[].class))).thenReturn(Linq4j.emptyEnumerable());
+        RelOptSchema schema = mock(RelOptSchema.class);
+        when(schema.getTypeFactory()).thenReturn(typeFactory);
+        relOptTable = RelOptTableImpl.create(schema, rowType, 
ImmutableList.of("test", "tbl"), federationTable, each -> 
Expressions.constant(federationTable));
+    }
+    
+    @Test
+    void assertConstructorWithPushDownNodeSetsFields() {
+        LogicalTableScan pushDownNode = LogicalTableScan.create(cluster, 
relOptTable, Collections.emptyList());
+        EnumerableScan scan = new EnumerableScan(cluster, cluster.traitSet(), 
relOptTable, pushDownNode, "MySQL");
+        assertNotNull(scan.getSqlString());
+        assertThat(scan.getPushDownRowType(), is(pushDownNode.getRowType()));
+        assertThat(scan.getTraitSet().getConvention(), 
is(EnumerableConvention.INSTANCE));
+    }
+    
+    @Test
+    void assertCopyKeepsSqlAndRowType() {
+        SqlString sqlString = new 
SqlString(SQLDialectFactory.getSQLDialect("MySQL"), "SELECT 1");
+        EnumerableScan copied = (EnumerableScan) new EnumerableScan(cluster, 
cluster.traitSet(), relOptTable, sqlString, rowType).copy(cluster.traitSet(), 
Collections.emptyList());
+        assertThat(copied.getSqlString(), is(sqlString));
+        assertThat(copied.getPushDownRowType(), is(rowType));
+    }
+    
+    @Test
+    void assertExplainTerms() {
+        SqlString sqlString = new 
SqlString(SQLDialectFactory.getSQLDialect("MySQL"), "SELECT 1");
+        EnumerableScan scan = new EnumerableScan(cluster, cluster.traitSet(), 
relOptTable, sqlString, rowType);
+        StringWriter writer = new StringWriter();
+        RelWriter relWriter = new RelWriterImpl(new PrintWriter(writer), 
SqlExplainLevel.EXPPLAN_ATTRIBUTES, false);
+        scan.explainTerms(relWriter);
+        relWriter.done(scan);
+        assertThat(writer.toString(), containsString("sql="));
+        assertThat(writer.toString(), containsString("dynamicParameters"));
+    }
+    
+    @Test
+    void assertDeriveRowType() {
+        SqlString sqlString = new 
SqlString(SQLDialectFactory.getSQLDialect("MySQL"), "SELECT 1");
+        assertThat(new EnumerableScan(cluster, cluster.traitSet(), 
relOptTable, sqlString, rowType).deriveRowType(), is(rowType));
+    }
+    
+    @Test
+    void assertImplementWithoutDynamicParameters() {
+        EnumerableRelImplementor implementor = 
mock(EnumerableRelImplementor.class);
+        when(implementor.getTypeFactory()).thenReturn((JavaTypeFactory) 
cluster.getTypeFactory());
+        
when(implementor.getRootExpression()).thenReturn(Expressions.parameter(DataContext.class,
 "root"));
+        EnumerableRel.Result actual = new EnumerableRel.Result(
+                Blocks.toBlock(Expressions.constant(1)), 
PhysTypeImpl.of((JavaTypeFactory) cluster.getTypeFactory(), rowType, 
JavaRowFormat.ARRAY), JavaRowFormat.ARRAY);
+        when(implementor.result(any(PhysType.class), 
any(BlockStatement.class))).thenReturn(actual);
+        EnumerableScan scan = new EnumerableScan(cluster, cluster.traitSet(), 
relOptTable, LogicalTableScan.create(cluster, relOptTable, 
Collections.emptyList()), "MySQL");
+        assertNotNull(scan.implement(implementor, EnumerableRel.Prefer.ARRAY));
+    }
+    
+    @Test
+    void assertImplementWithDynamicParameters() {
+        EnumerableRelImplementor implementor = 
mock(EnumerableRelImplementor.class);
+        when(implementor.getTypeFactory()).thenReturn((JavaTypeFactory) 
cluster.getTypeFactory());
+        
when(implementor.getRootExpression()).thenReturn(Expressions.parameter(DataContext.class,
 "root"));
+        ArgumentCaptor<BlockStatement> blockCaptor = 
ArgumentCaptor.forClass(BlockStatement.class);
+        EnumerableRel.Result actual = new EnumerableRel.Result(
+                Blocks.toBlock(Expressions.constant(1)), 
PhysTypeImpl.of((JavaTypeFactory) cluster.getTypeFactory(), rowType, 
JavaRowFormat.ARRAY), JavaRowFormat.ARRAY);
+        when(implementor.result(any(PhysType.class), 
blockCaptor.capture())).thenReturn(actual);
+        SqlString sqlString = new 
SqlString(SQLDialectFactory.getSQLDialect("MySQL"), "SELECT 1", 
ImmutableList.of(1, 3));
+        assertNotNull(new EnumerableScan(cluster, cluster.traitSet(), 
relOptTable, sqlString, rowType).implement(implementor, 
EnumerableRel.Prefer.ARRAY));
+        assertThat(blockCaptor.getValue().toString(), containsString("1"));
+        assertThat(blockCaptor.getValue().toString(), containsString("3"));
+    }
+}

Reply via email to