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