Skip to content

Commit

Permalink
IGNITE-22160: Sql. Usability of error message in case of numeric over…
Browse files Browse the repository at this point in the history
…flow (#4296)
  • Loading branch information
lowka authored Aug 29, 2024
1 parent 35fbde0 commit 3c43871
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,39 @@ SELECT CAST('1e2' AS DECIMAL);
100

# overflow
statement error

statement error: Numeric field overflow. A field with precision 5, scale 0 must round to an absolute value less than 10^5.
SELECT CAST(1e20 AS DECIMAL(5));

# overflow
statement error
statement error: Numeric field overflow. A field with precision 5, scale 0 must round to an absolute value less than 10^5.
SELECT CAST(-1e20 AS DECIMAL(5));

statement error: Numeric field overflow. A field with precision 3, scale 5 must round to an absolute value less than 10^-2.
SELECT 0.3::DECIMAL(3, 5);

statement error: Numeric field overflow. A field with precision 3, scale 3 must round to an absolute value less than 1.
SELECT -1::DECIMAL(3, 3);

# the first cast produces must report an error
statement error: Numeric field overflow. A field with precision 3, scale 0 must round to an absolute value less than 10^3.
SELECT 9999999::DECIMAL(3)::DECIMAL(4, 2);

for val in ['10000', 10000::SMALLINT, 10000::INT, 10000::BIGINT, 10000::REAL, 10000::FLOAT, 10000::DOUBLE, 10000::DECIMAL, 10000::DECIMAL(10)]

statement error: Numeric field overflow. A field with precision 4, scale 2 must round to an absolute value less than 10^2.
SELECT ${val}::DECIMAL(4, 2);

statement error: Numeric field overflow. A field with precision 2, scale 4 must round to an absolute value less than 10^-2.
SELECT ${val}::DECIMAL(2, 4);

statement error: Numeric field overflow. A field with precision 2, scale 2 must round to an absolute value less than 1.
SELECT ${val}::DECIMAL(2, 2);

statement error: Numeric field overflow. A field with precision 3, scale 0 must round to an absolute value less than 10^3.
SELECT ${val}::DECIMAL(3);

endfor

for val in [100::TINYINT, 100::SMALLINT, 100::INT, 100::BIGINT, 100::DECIMAL, 100::DECIMAL(3)]

query T
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.apache.ignite.internal.sql.engine.exec.exp;

import static org.apache.calcite.runtime.SqlFunctions.charLength;
import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
import static org.apache.ignite.internal.sql.engine.prepare.IgniteSqlValidator.NUMERIC_FIELD_OVERFLOW_ERROR;
import static org.apache.ignite.lang.ErrorGroups.Sql.RUNTIME_ERR;

Expand Down Expand Up @@ -368,13 +369,13 @@ private static BigDecimal processValueWithIntegralPart(Number value, int precisi
BigDecimal dec = convertToBigDecimal(value);

if (scale > precision) {
throw new SqlException(RUNTIME_ERR, NUMERIC_FIELD_OVERFLOW_ERROR);
throw numericOverflowError(precision, scale);
} else {
int currentSignificantDigits = dec.precision() - dec.scale();
int expectedSignificantDigits = precision - scale;

if (currentSignificantDigits > expectedSignificantDigits) {
throw new SqlException(RUNTIME_ERR, NUMERIC_FIELD_OVERFLOW_ERROR);
throw numericOverflowError(precision, scale);
}
}

Expand All @@ -394,7 +395,7 @@ private static BigDecimal processFractionData(Number value, int precision, int s
int numPrecision = Math.min(num0.precision(), scale);

if (numPrecision > precision) {
throw new SqlException(RUNTIME_ERR, NUMERIC_FIELD_OVERFLOW_ERROR);
throw numericOverflowError(precision, scale);
}

return num.setScale(scale, roundingMode);
Expand All @@ -417,6 +418,22 @@ private static BigDecimal convertToBigDecimal(Number value) {
return dec;
}

private static SqlException numericOverflowError(int precision, int scale) {
String maxVal;

if (precision == scale) {
maxVal = "1";
} else {
maxVal = format("10^{}", precision - scale);
}

String detail = format("A field with precision {}, scale {} must round to an absolute value less than {}.",
precision, scale, maxVal
);

throw new SqlException(RUNTIME_ERR, NUMERIC_FIELD_OVERFLOW_ERROR + ". " + detail);
}

/** CAST(VARCHAR AS VARBINARY). */
public static ByteString toByteString(String s) {
return s == null ? null : new ByteString(s.getBytes(Commons.typeFactory().getDefaultCharset()));
Expand Down

0 comments on commit 3c43871

Please sign in to comment.