This is an automated email from the ASF dual-hosted git repository. zabetak pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push: new a3f81bb [CALCITE-2998] RexCopier should support all rex types (Chunwei Lei, Alexander Shilov) a3f81bb is described below commit a3f81bb7b088fd8c1d0c1df3b0f2b0cf122633de Author: Chunwei Lei <chunwei....@alibaba-inc.com> AuthorDate: Sun Apr 14 18:40:21 2019 +0800 [CALCITE-2998] RexCopier should support all rex types (Chunwei Lei, Alexander Shilov) Close apache/calcite#1164 Close apache/calcite#969 --- .../java/org/apache/calcite/rex/RexCopier.java | 22 ++- .../org/apache/calcite/rex/RexBuilderTest.java | 155 +++++++++++++++++++++ 2 files changed, 165 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/org/apache/calcite/rex/RexCopier.java b/core/src/main/java/org/apache/calcite/rex/RexCopier.java index 7b66086..f207750 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexCopier.java +++ b/core/src/main/java/org/apache/calcite/rex/RexCopier.java @@ -24,9 +24,6 @@ import org.apache.calcite.rel.type.RelDataType; * <p>This is useful when copying objects from one type factory or builder to * another. * - * <p>Due to the laziness of the author, not all Rex types are supported at - * present. - * * @see RexBuilder#copy(RexNode) */ class RexCopier extends RexShuttle { @@ -52,11 +49,10 @@ class RexCopier extends RexShuttle { } public RexNode visitOver(RexOver over) { - throw new UnsupportedOperationException(); - } - - public RexWindow visitWindow(RexWindow window) { - throw new UnsupportedOperationException(); + final boolean[] update = null; + return new RexOver(copy(over.getType()), over.getAggOperator(), + visitList(over.getOperands(), update), visitWindow(over.getWindow()), + over.isDistinct(), over.ignoreNulls()); } public RexNode visitCall(final RexCall call) { @@ -67,7 +63,7 @@ class RexCopier extends RexShuttle { } public RexNode visitCorrelVariable(RexCorrelVariable variable) { - throw new UnsupportedOperationException(); + return builder.makeCorrel(copy(variable.getType()), variable.id); } public RexNode visitFieldAccess(RexFieldAccess fieldAccess) { @@ -80,7 +76,7 @@ class RexCopier extends RexShuttle { } public RexNode visitLocalRef(RexLocalRef localRef) { - throw new UnsupportedOperationException(); + return new RexLocalRef(localRef.getIndex(), copy(localRef.getType())); } public RexNode visitLiteral(RexLiteral literal) { @@ -90,11 +86,13 @@ class RexCopier extends RexShuttle { } public RexNode visitDynamicParam(RexDynamicParam dynamicParam) { - throw new UnsupportedOperationException(); + return builder.makeDynamicParam(copy(dynamicParam.getType()), + dynamicParam.getIndex()); } public RexNode visitRangeRef(RexRangeRef rangeRef) { - throw new UnsupportedOperationException(); + return builder.makeRangeReference(copy(rangeRef.getType()), + rangeRef.getOffset(), false); } } diff --git a/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java b/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java index b8b30f0..780469a 100644 --- a/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java +++ b/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java @@ -17,10 +17,15 @@ package org.apache.calcite.rex; import org.apache.calcite.avatica.util.ByteString; +import org.apache.calcite.rel.core.CorrelationId; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.rel.type.RelDataTypeFactory; import org.apache.calcite.rel.type.RelDataTypeSystem; import org.apache.calcite.sql.SqlCollation; +import org.apache.calcite.sql.SqlWindow; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.type.BasicSqlType; import org.apache.calcite.sql.type.SqlTypeFactoryImpl; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.util.DateString; @@ -30,6 +35,9 @@ import org.apache.calcite.util.TimestampString; import org.apache.calcite.util.TimestampWithTimeZoneString; import org.apache.calcite.util.Util; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + import org.junit.Test; import java.math.BigDecimal; @@ -44,6 +52,7 @@ import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** @@ -51,6 +60,30 @@ import static org.junit.Assert.fail; */ public class RexBuilderTest { + private static final int PRECISION = 256; + + /** + * MySqlTypeFactoryImpl provides a specific implementation of + * {@link SqlTypeFactoryImpl} which sets precision to 256 for VARCHAR. + */ + private static class MySqlTypeFactoryImpl extends SqlTypeFactoryImpl { + + MySqlTypeFactoryImpl(RelDataTypeSystem typeSystem) { + super(typeSystem); + } + + @Override public RelDataType createTypeWithNullability( + final RelDataType type, + final boolean nullable) { + if (type.getSqlTypeName() == SqlTypeName.VARCHAR) { + return new BasicSqlType(this.typeSystem, type.getSqlTypeName(), + PRECISION); + } + return super.createTypeWithNullability(type, nullable); + } + } + + /** * Test RexBuilder.ensureType() */ @@ -558,6 +591,128 @@ public class RexBuilderTest { checkBigDecimalLiteral(builder, "-73786976294838206464"); } + /** Tests {@link RexCopier#visitOver(RexOver)} */ + @Test public void testCopyOver() { + final RelDataTypeFactory sourceTypeFactory = + new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + RelDataType type = sourceTypeFactory.createSqlType(SqlTypeName.VARCHAR, 65536); + + final RelDataTypeFactory targetTypeFactory = + new MySqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + final RexBuilder builder = new RexBuilder(targetTypeFactory); + + final RexOver node = (RexOver) builder.makeOver(type, + SqlStdOperatorTable.COUNT, + ImmutableList.of(builder.makeInputRef(type, 0)), + ImmutableList.of(builder.makeInputRef(type, 1)), + ImmutableList.of( + new RexFieldCollation( + builder.makeInputRef(type, 2), ImmutableSet.of())), + RexWindowBound.create( + SqlWindow.createUnboundedPreceding(SqlParserPos.ZERO), null), + RexWindowBound.create( + SqlWindow.createCurrentRow(SqlParserPos.ZERO), null), + true, true, false, false, false); + final RexNode copy = builder.copy(node); + assertTrue(copy instanceof RexOver); + + RexOver result = (RexOver) copy; + assertThat(result.getType().getSqlTypeName(), is(SqlTypeName.VARCHAR)); + assertThat(result.getType().getPrecision(), is(PRECISION)); + assertThat(result.getWindow(), is(node.getWindow())); + assertThat(result.getAggOperator(), is(node.getAggOperator())); + assertThat(result.getAggOperator(), is(node.getAggOperator())); + assertEquals(node.isDistinct(), result.isDistinct()); + assertEquals(node.ignoreNulls(), result.ignoreNulls()); + for (int i = 0; i < node.getOperands().size(); i++) { + assertThat(result.getOperands().get(i).getType().getSqlTypeName(), + is(node.getOperands().get(i).getType().getSqlTypeName())); + assertThat(result.getOperands().get(i).getType().getPrecision(), + is(PRECISION)); + } + } + + /** Tests {@link RexCopier#visitCorrelVariable(RexCorrelVariable)} */ + @Test public void testCopyCorrelVariable() { + final RelDataTypeFactory sourceTypeFactory = + new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + RelDataType type = sourceTypeFactory.createSqlType(SqlTypeName.VARCHAR, 65536); + + final RelDataTypeFactory targetTypeFactory = + new MySqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + final RexBuilder builder = new RexBuilder(targetTypeFactory); + + final RexCorrelVariable node = + (RexCorrelVariable) builder.makeCorrel(type, new CorrelationId(0)); + final RexNode copy = builder.copy(node); + assertTrue(copy instanceof RexCorrelVariable); + + final RexCorrelVariable result = (RexCorrelVariable) copy; + assertThat(result.id, is(node.id)); + assertThat(result.getType().getSqlTypeName(), is(SqlTypeName.VARCHAR)); + assertThat(result.getType().getPrecision(), is(PRECISION)); + } + + /** Tests {@link RexCopier#visitLocalRef(RexLocalRef)} */ + @Test public void testCopyLocalRef() { + final RelDataTypeFactory sourceTypeFactory = + new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + RelDataType type = sourceTypeFactory.createSqlType(SqlTypeName.VARCHAR, 65536); + + final RelDataTypeFactory targetTypeFactory = + new MySqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + final RexBuilder builder = new RexBuilder(targetTypeFactory); + + final RexLocalRef node = new RexLocalRef(0, type); + final RexNode copy = builder.copy(node); + assertTrue(copy instanceof RexLocalRef); + + final RexLocalRef result = (RexLocalRef) copy; + assertThat(result.getIndex(), is(node.getIndex())); + assertThat(result.getType().getSqlTypeName(), is(SqlTypeName.VARCHAR)); + assertThat(result.getType().getPrecision(), is(PRECISION)); + } + + /** Tests {@link RexCopier#visitDynamicParam(RexDynamicParam)} */ + @Test public void testCopyDynamicParam() { + final RelDataTypeFactory sourceTypeFactory = + new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + RelDataType type = sourceTypeFactory.createSqlType(SqlTypeName.VARCHAR, 65536); + + final RelDataTypeFactory targetTypeFactory = + new MySqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + final RexBuilder builder = new RexBuilder(targetTypeFactory); + + final RexDynamicParam node = builder.makeDynamicParam(type, 0); + final RexNode copy = builder.copy(node); + assertTrue(copy instanceof RexDynamicParam); + + final RexDynamicParam result = (RexDynamicParam) copy; + assertThat(result.getIndex(), is(node.getIndex())); + assertThat(result.getType().getSqlTypeName(), is(SqlTypeName.VARCHAR)); + assertThat(result.getType().getPrecision(), is(PRECISION)); + } + + /** Tests {@link RexCopier#visitRangeRef(RexRangeRef)} */ + @Test public void testCopyRangeRef() { + final RelDataTypeFactory sourceTypeFactory = + new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + RelDataType type = sourceTypeFactory.createSqlType(SqlTypeName.VARCHAR, 65536); + + final RelDataTypeFactory targetTypeFactory = + new MySqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + final RexBuilder builder = new RexBuilder(targetTypeFactory); + + final RexRangeRef node = builder.makeRangeReference(type, 1, true); + final RexNode copy = builder.copy(node); + assertTrue(copy instanceof RexRangeRef); + + final RexRangeRef result = (RexRangeRef) copy; + assertThat(result.getOffset(), is(node.getOffset())); + assertThat(result.getType().getSqlTypeName(), is(SqlTypeName.VARCHAR)); + assertThat(result.getType().getPrecision(), is(PRECISION)); + } + private void checkBigDecimalLiteral(RexBuilder builder, String val) { final RexLiteral literal = builder.makeExactLiteral(new BigDecimal(val)); assertThat("builder.makeExactLiteral(new BigDecimal(" + val