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. */