diff --git a/core/src/main/java/org/apache/calcite/sql/type/BasicSqlType.java b/core/src/main/java/org/apache/calcite/sql/type/BasicSqlType.java index e8e9332d6197..635c07c662d3 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/BasicSqlType.java +++ b/core/src/main/java/org/apache/calcite/sql/type/BasicSqlType.java @@ -205,6 +205,13 @@ BasicSqlType createWithCharsetAndCollation(Charset charset, sb.append(getScale()); } sb.append(')'); + } else if (printScale && typeName == SqlTypeName.DECIMAL) { + // Include scale in the digest when precision is not specified (CALCITE-5212). + sb.append('('); + sb.append(PRECISION_NOT_SPECIFIED); + sb.append(", "); + sb.append(scale); + sb.append(')'); } if (!withDetail) { return; diff --git a/core/src/test/java/org/apache/calcite/sql/type/SqlTypeFactoryTest.java b/core/src/test/java/org/apache/calcite/sql/type/SqlTypeFactoryTest.java index 8f5e5e4018db..cab5de8f68f8 100644 --- a/core/src/test/java/org/apache/calcite/sql/type/SqlTypeFactoryTest.java +++ b/core/src/test/java/org/apache/calcite/sql/type/SqlTypeFactoryTest.java @@ -19,6 +19,7 @@ import org.apache.calcite.rel.type.RelDataTypeFactory; import org.apache.calcite.rel.type.RelDataTypeField; import org.apache.calcite.rel.type.RelDataTypeFieldImpl; +import org.apache.calcite.rel.type.RelDataTypeSystem; import org.apache.calcite.rel.type.RelRecordType; import org.apache.calcite.rel.type.StructKind; @@ -35,7 +36,9 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasToString; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; @@ -239,6 +242,27 @@ private void checkPrecision(int p0, int p1, int expectedMax, assertThat(SqlTypeUtil.comparePrecision(p1, p1), is(0)); } + /** Test case for + * [CALCITE-5212] + * Decimal with scale but unspecified precision collides in type cache. */ + @Test void testCreateSqlTypeDecimalUnspecifiedPrecisionWithScale() { + SqlTypeFixture f = new SqlTypeFixture(); + RelDataTypeFactory tf = f.typeFactory; + final int pUn = RelDataType.PRECISION_NOT_SPECIFIED; + RelDataType d5 = tf.createSqlType(SqlTypeName.DECIMAL, pUn, 5); + RelDataType d3 = tf.createSqlType(SqlTypeName.DECIMAL, pUn, 3); + assertEquals(5, d5.getScale()); + assertEquals(3, d3.getScale()); + assertNotEquals(d5, d3); + assertNotEquals(d5.getFullTypeString(), d3.getFullTypeString()); + // Order independence: first created shape must not be returned for another scale. + SqlTypeFactoryImpl tf2 = new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + RelDataType d3b = tf2.createSqlType(SqlTypeName.DECIMAL, pUn, 3); + RelDataType d5b = tf2.createSqlType(SqlTypeName.DECIMAL, pUn, 5); + assertEquals(3, d3b.getScale()); + assertEquals(5, d5b.getScale()); + } + /** Test case for * [CALCITE-2464] * Allow to set nullability for columns of structured types. */