This is an automated email from the ASF dual-hosted git repository. mbudiu pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/calcite.git
commit 68f9ee0cc053130b2b3793aafc896c128e706aa5 Author: Mihai Budiu <[email protected]> AuthorDate: Wed Aug 7 11:36:17 2024 -0700 Handle the case where maximum scale is less than 6 Signed-off-by: Mihai Budiu <[email protected]> --- .../apache/calcite/rel/type/RelDataTypeSystem.java | 25 +++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/apache/calcite/rel/type/RelDataTypeSystem.java b/core/src/main/java/org/apache/calcite/rel/type/RelDataTypeSystem.java index 0028cbbfd1..ccc9537d6f 100644 --- a/core/src/main/java/org/apache/calcite/rel/type/RelDataTypeSystem.java +++ b/core/src/main/java/org/apache/calcite/rel/type/RelDataTypeSystem.java @@ -294,22 +294,41 @@ public interface RelDataTypeSystem { int s1 = type1.getScale(); int s2 = type2.getScale(); + int six = Math.min(6, getMaxNumericScale()); int d = p1 - s1 + s2; - int scale = Math.max(6, s1 + p2 + 1); + int scale = Math.max(six, s1 + p2 + 1); int precision = d + scale; // Rules from // https://learn.microsoft.com/en-us/sql/t-sql/data-types/precision-scale-and-length-transact-sql - int bound = getMaxNumericPrecision() - 6; // 32 in the MS documentation + // Rules reproduced here in case the web page goes away. + // Note that in SQL server getMaxNumericPrecision() == 38 and + // getMaxNumericScale() > 6. + // In multiplication and division operations, we need precision - scale places to store + // the integral part of the result. The scale might be reduced using the following rules: + // + // - The resulting scale is reduced to min(scale, 38 - (precision-scale)) + // if the integral part is less than 32, because it can't be greater than + // 38 - (precision-scale). The result might be rounded in this case. + // - The scale isn't changed if it's less than 6 and if the integral part + // is greater than 32. In this case, an overflow error might be raised if + // it can't fit into decimal(38, scale). + // - The scale is set to 6 if it's greater than 6 and if the integral part + // is greater than 32. In this case, both the integral part and scale would be + // reduced and resulting type is decimal(38, 6). The result might be rounded to + // 7 decimal places, or the overflow error is thrown if the integral part + // can't fit into 32 digits. + int bound = getMaxNumericPrecision() - six; // This was '32' in the MS documentation if (precision <= bound) { scale = Math.min(scale, getMaxNumericScale() - (precision - scale)); } else { // precision > bound - scale = Math.min(6, scale); + scale = Math.min(six, scale); } precision = Math.min(precision, getMaxNumericPrecision()); assert precision > 0; + assert scale <= getMaxNumericScale(); RelDataType ret; ret = typeFactory.
