This is an automated email from the ASF dual-hosted git repository.

zstan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new ea59431e01 IGNITE-22578 Sql. Extend test coverage for numeric to/from 
decimal cast with overflow (#3985)
ea59431e01 is described below

commit ea59431e01ac1b74757d904dcc54ddf3a9ca3603
Author: Evgeniy Stanilovskiy <[email protected]>
AuthorDate: Mon Jul 1 09:28:37 2024 +0300

    IGNITE-22578 Sql. Extend test coverage for numeric to/from decimal cast 
with overflow (#3985)
---
 .../ignite/jdbc/ItJdbcComplexQuerySelfTest.java    |   4 +-
 .../internal/sql/engine/ItDataTypesTest.java       | 139 +++++++++++++------
 .../internal/sql/engine/ItFunctionsTest.java       |   3 +-
 .../integrationTest/sql/cast/test_cast_bigint.test |   2 +-
 .../integrationTest/sql/cast/test_cast_int.test    |   4 +-
 .../sql/cast/test_cast_smallint.test               |   4 +-
 .../sql/cast/test_cast_tinyint.test                |   4 +-
 .../sql/engine/exec/exp/ConverterUtils.java        |  49 ++++---
 .../sql/engine/exec/exp/IgniteExpressions.java     |  51 ++-----
 .../sql/engine/prepare/IgniteSqlValidator.java     |  78 -----------
 .../internal/sql/engine/rex/IgniteRexBuilder.java  |  13 ++
 .../internal/sql/engine/util/IgniteMath.java       | 148 ++++++++++++++++++---
 12 files changed, 285 insertions(+), 214 deletions(-)

diff --git 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcComplexQuerySelfTest.java
 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcComplexQuerySelfTest.java
index f6f3614c68..15c767f503 100644
--- 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcComplexQuerySelfTest.java
+++ 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcComplexQuerySelfTest.java
@@ -209,7 +209,7 @@ public class ItJdbcComplexQuerySelfTest extends 
AbstractJdbcSelfTest {
 
         // Check non-indexed field.
         JdbcTestUtils.assertThrowsSqlException(
-                "For input string: \"B\"",
+                "Invalid input syntax for type INTEGER: \"B\"",
                 () -> stmt.executeQuery("select * from PUBLIC.Org where name = 
2"));
 
         // Check indexed field.
@@ -218,7 +218,7 @@ public class ItJdbcComplexQuerySelfTest extends 
AbstractJdbcSelfTest {
         }
 
         JdbcTestUtils.assertThrowsSqlException(
-                "For input string: \"Mike Green\"",
+                "Invalid input syntax for type INTEGER: \"Mike Green\"",
                 () -> stmt.executeQuery("select * from PUBLIC.Person where 
name = 2"));
     }
 }
diff --git 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java
 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java
index 186c84c521..e068db34c4 100644
--- 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java
+++ 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java
@@ -150,8 +150,17 @@ public class ItDataTypesTest extends 
BaseSqlIntegrationTest {
                 + Integer.MAX_VALUE + ", " + Long.MAX_VALUE + ')');
 
         assertQuery("SELECT tiny FROM tbl").returns(Byte.MAX_VALUE).check();
+        assertQuery(format("SELECT tiny FROM tbl WHERE tiny < {}", 2 * 
Byte.MAX_VALUE)).returns(Byte.MAX_VALUE).check();
+        assertQuery(format("SELECT tiny FROM tbl WHERE tiny < '{}'::INTEGER", 
2 * Byte.MAX_VALUE)).returns(Byte.MAX_VALUE).check();
+
         assertQuery("SELECT small FROM tbl").returns(Short.MAX_VALUE).check();
+        assertQuery(format("SELECT small FROM tbl WHERE small < {}", 2 * 
Short.MAX_VALUE)).returns(Short.MAX_VALUE).check();
+        assertQuery(format("SELECT small FROM tbl WHERE small < 
'{}'::INTEGER", 2 * Short.MAX_VALUE)).returns(Short.MAX_VALUE).check();
+
         assertQuery("SELECT i FROM tbl").returns(Integer.MAX_VALUE).check();
+        assertQuery(format("SELECT i FROM tbl WHERE i < {}", 2L * 
Integer.MAX_VALUE)).returns(Integer.MAX_VALUE).check();
+        assertQuery(format("SELECT i FROM tbl WHERE i < '{}'::BIGINT", 2L * 
Integer.MAX_VALUE)).returns(Integer.MAX_VALUE).check();
+
         assertQuery("SELECT big FROM tbl").returns(Long.MAX_VALUE).check();
 
         sql("DELETE from tbl");
@@ -160,8 +169,17 @@ public class ItDataTypesTest extends 
BaseSqlIntegrationTest {
                 + Integer.MIN_VALUE + ", " + Long.MIN_VALUE + ')');
 
         assertQuery("SELECT tiny FROM tbl").returns(Byte.MIN_VALUE).check();
+        assertQuery(format("SELECT tiny FROM tbl WHERE tiny > {}", 2 * 
Byte.MIN_VALUE)).returns(Byte.MIN_VALUE).check();
+        assertQuery(format("SELECT tiny FROM tbl WHERE tiny > '{}'::INTEGER", 
2 * Byte.MIN_VALUE)).returns(Byte.MIN_VALUE).check();
+
         assertQuery("SELECT small FROM tbl").returns(Short.MIN_VALUE).check();
+        assertQuery(format("SELECT small FROM tbl WHERE small > {}", 2 * 
Short.MIN_VALUE)).returns(Short.MIN_VALUE).check();
+        assertQuery(format("SELECT small FROM tbl WHERE small > 
'{}'::INTEGER", 2 * Short.MIN_VALUE)).returns(Short.MIN_VALUE).check();
+
         assertQuery("SELECT i FROM tbl").returns(Integer.MIN_VALUE).check();
+        assertQuery(format("SELECT i FROM tbl WHERE i > {}", 2L * 
Integer.MIN_VALUE)).returns(Integer.MIN_VALUE).check();
+        assertQuery(format("SELECT i FROM tbl WHERE i > '{}'::BIGINT", 2L * 
Integer.MIN_VALUE)).returns(Integer.MIN_VALUE).check();
+
         assertQuery("SELECT big FROM tbl").returns(Long.MIN_VALUE).check();
     }
 
@@ -453,6 +471,7 @@ public class ItDataTypesTest extends BaseSqlIntegrationTest 
{
         return Stream.of(
                 // BIGINT
                 arguments(SqlTypeName.BIGINT, "SELECT 9223372036854775807 + 
1", EMPTY_PARAM),
+                arguments(SqlTypeName.BIGINT, "SELECT 
CAST(9223372036854775807.5 AS BIGINT)", EMPTY_PARAM),
                 arguments(SqlTypeName.BIGINT, "SELECT 9223372036854775807 * 
2", EMPTY_PARAM),
                 arguments(SqlTypeName.BIGINT, "SELECT -9223372036854775808 - 
1", EMPTY_PARAM),
                 arguments(SqlTypeName.BIGINT, "SELECT -(-9223372036854775807 - 
1)", EMPTY_PARAM),
@@ -462,15 +481,23 @@ public class ItDataTypesTest extends 
BaseSqlIntegrationTest {
 
                 // INTEGER
                 arguments(SqlTypeName.INTEGER, "SELECT 2147483647 + 1", 
EMPTY_PARAM),
+                arguments(SqlTypeName.INTEGER, "SELECT CAST(CAST(2147483648 AS 
BIGINT) AS INTEGER)", EMPTY_PARAM),
                 arguments(SqlTypeName.INTEGER, "SELECT 2147483647 * 2", 
EMPTY_PARAM),
                 arguments(SqlTypeName.INTEGER, "SELECT -2147483648 - 1", 
EMPTY_PARAM),
                 arguments(SqlTypeName.INTEGER, "SELECT -(-2147483647 - 1)", 
EMPTY_PARAM),
                 arguments(SqlTypeName.INTEGER, "SELECT -CAST(-2147483648 AS 
INTEGER)", EMPTY_PARAM),
                 arguments(SqlTypeName.INTEGER, "SELECT -(?)", -2147483648),
                 arguments(SqlTypeName.INTEGER, "SELECT -2147483648/-1", 
EMPTY_PARAM),
+                arguments(SqlTypeName.INTEGER, "select 
CAST(9223372036854775807.5 + 9223372036854775807.5 AS INTEGER)",
+                        EMPTY_PARAM),
 
                 // SMALLINT
                 arguments(SqlTypeName.SMALLINT, "SELECT 32000::SMALLINT + 
1000::SMALLINT", EMPTY_PARAM),
+                arguments(SqlTypeName.SMALLINT, "select 
CAST(9223372036854775807.5 + 9223372036854775807.5 AS SMALLINT)",
+                        EMPTY_PARAM),
+                arguments(SqlTypeName.SMALLINT, "SELECT CAST(CAST(33000 AS 
BIGINT) AS SMALLINT)", EMPTY_PARAM),
+                arguments(SqlTypeName.SMALLINT, "SELECT CAST(CAST(33000 AS 
FLOAT) AS SMALLINT)", EMPTY_PARAM),
+                arguments(SqlTypeName.SMALLINT, "SELECT CAST(CAST(33000 + 1 AS 
FLOAT) AS SMALLINT)", EMPTY_PARAM),
                 arguments(SqlTypeName.SMALLINT, "SELECT 17000::SMALLINT * 
2::SMALLINT", EMPTY_PARAM),
                 arguments(SqlTypeName.SMALLINT, "SELECT -32000::SMALLINT - 
1000::SMALLINT", EMPTY_PARAM),
                 arguments(SqlTypeName.SMALLINT, "SELECT -(-32767::SMALLINT - 
1::SMALLINT)", EMPTY_PARAM),
@@ -480,25 +507,91 @@ public class ItDataTypesTest extends 
BaseSqlIntegrationTest {
 
                 // TINYINT
                 arguments(SqlTypeName.TINYINT, "SELECT 2::TINYINT + 
127::TINYINT", EMPTY_PARAM),
+                arguments(SqlTypeName.TINYINT, "select 
CAST(9223372036854775807.5 + 9223372036854775807.5 AS TINYINT)",
+                        EMPTY_PARAM),
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(CAST(200 AS 
BIGINT) AS TINYINT)", EMPTY_PARAM),
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(CAST(200 AS FLOAT) 
AS TINYINT)", EMPTY_PARAM),
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(CAST(200 + 1 AS 
FLOAT) AS TINYINT)", EMPTY_PARAM),
                 arguments(SqlTypeName.TINYINT, "SELECT 2::TINYINT * 
127::TINYINT", EMPTY_PARAM),
                 arguments(SqlTypeName.TINYINT, "SELECT -2::TINYINT - 
127::TINYINT", EMPTY_PARAM),
                 arguments(SqlTypeName.TINYINT, "SELECT -(-127::TINYINT - 
1::TINYINT)", EMPTY_PARAM),
                 arguments(SqlTypeName.TINYINT, "SELECT -CAST(-128 AS 
TINYINT)", EMPTY_PARAM),
                 arguments(SqlTypeName.TINYINT, "SELECT -CAST(? AS TINYINT)", 
-128),
-                arguments(SqlTypeName.TINYINT, "SELECT CAST(-128 AS 
TINYINT)/-1::TINYINT", EMPTY_PARAM)
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(-128 AS 
TINYINT)/-1::TINYINT", EMPTY_PARAM),
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(CAST(200 + 1 AS 
FLOAT) AS TINYINT)", EMPTY_PARAM)
         );
     }
 
     @ParameterizedTest(name = "{1}")
     @MethodSource("decimalOverflowsValidation")
-    public void testCalcOpOverflowValidationCheck(SqlTypeName type, String 
expr, Boolean withException) {
+    public void testCastDecimalOverflows(SqlTypeName type, String expr, 
Boolean withException) {
         if (withException) {
-            assertThrowsSqlException(Sql.STMT_PARSE_ERR, "out of range", () -> 
sql(expr));
+            assertThrowsSqlException(Sql.RUNTIME_ERR, type + " out of range", 
() -> sql(expr));
         } else {
             sql(expr);
         }
     }
 
+    private static Stream<Arguments> decimalOverflowsValidation() {
+        return Stream.of(
+                // BIGINT
+                arguments(SqlTypeName.BIGINT, "SELECT 
CAST(9223372036854775807.1 AS BIGINT)", false),
+                arguments(SqlTypeName.BIGINT, "SELECT 
CAST(9223372036854775807.5 - 1 AS BIGINT)", false),
+                arguments(SqlTypeName.BIGINT, "SELECT 
CAST(-9223372036854775808.1 AS BIGINT)", false),
+                arguments(SqlTypeName.BIGINT, "SELECT 
CAST(9223372036854775807.5 AS BIGINT)", true),
+                arguments(SqlTypeName.BIGINT, "SELECT 
CAST(9223372036854775808.1 AS BIGINT)", true),
+                arguments(SqlTypeName.BIGINT, "SELECT CAST(9223372036854775808 
AS BIGINT)", true),
+                arguments(SqlTypeName.BIGINT, "SELECT 
CAST('9223372036854775808' AS BIGINT)", true),
+                arguments(SqlTypeName.BIGINT, "SELECT 
CAST(-9223372036854775809 AS BIGINT)", true),
+                arguments(SqlTypeName.BIGINT, "SELECT CAST(' 
-9223372036854775809' AS BIGINT)", true),
+
+
+                // INTEGER
+                arguments(SqlTypeName.INTEGER, "SELECT CAST(2147483647.1 AS 
INTEGER)", false),
+                arguments(SqlTypeName.INTEGER, "SELECT CAST(2147483647.5 AS 
INTEGER)", false),
+                arguments(SqlTypeName.INTEGER, "SELECT CAST(2147483647.5 - 1 
AS INTEGER)", false),
+                arguments(SqlTypeName.INTEGER, "SELECT CAST(-2147483648.1 AS 
INTEGER)", false),
+                arguments(SqlTypeName.INTEGER, "SELECT CAST(2147483647 + 1 AS 
INTEGER)", true),
+                arguments(SqlTypeName.INTEGER, "SELECT CAST(2147483648.1 AS 
INTEGER)", true),
+                arguments(SqlTypeName.INTEGER, "SELECT CAST(CAST(2147483648.1 
AS DOUBLE) AS INTEGER)", true),
+                arguments(SqlTypeName.INTEGER, "SELECT CAST(CAST(2147483648.1 
AS FLOAT) AS INTEGER)", true),
+                arguments(SqlTypeName.INTEGER, "SELECT CAST(2147483648 AS 
INTEGER)", true),
+                arguments(SqlTypeName.INTEGER, "SELECT CAST('2147483648' AS 
INTEGER)", true),
+                arguments(SqlTypeName.INTEGER, "SELECT CAST(-2147483649 AS 
INTEGER)", true),
+                arguments(SqlTypeName.INTEGER, "SELECT CAST(' -2147483649' AS 
INTEGER)", true),
+
+
+                // SMALLINT
+                arguments(SqlTypeName.SMALLINT, "SELECT CAST(32767.1 AS 
SMALLINT)", false),
+                arguments(SqlTypeName.SMALLINT, "SELECT CAST(32767.5 AS 
SMALLINT)", false),
+                arguments(SqlTypeName.SMALLINT, "SELECT CAST(32767.5 - 1 AS 
SMALLINT)", false),
+                arguments(SqlTypeName.SMALLINT, "SELECT CAST(-32768.1 AS 
SMALLINT)", false),
+                arguments(SqlTypeName.SMALLINT, "SELECT CAST(32767 + 1 AS 
SMALLINT)", true),
+                arguments(SqlTypeName.SMALLINT, "SELECT CAST(32768.1 AS 
SMALLINT)", true),
+                arguments(SqlTypeName.SMALLINT, "SELECT CAST(CAST(32768 AS 
DOUBLE) AS SMALLINT)", true),
+                arguments(SqlTypeName.SMALLINT, "SELECT CAST(CAST(32768 AS 
FLOAT) AS SMALLINT)", true),
+                arguments(SqlTypeName.SMALLINT, "SELECT CAST(32768 AS 
SMALLINT)", true),
+                arguments(SqlTypeName.SMALLINT, "SELECT CAST('32768' AS 
SMALLINT)", true),
+                arguments(SqlTypeName.SMALLINT, "SELECT CAST(-32769 AS 
SMALLINT)", true),
+                arguments(SqlTypeName.SMALLINT, "SELECT CAST(' -32769' AS 
SMALLINT)", true),
+
+
+                // TINYINT
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(127.1 AS 
TINYINT)", false),
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(127.5 AS 
TINYINT)", false),
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(127.5 - 1 AS 
TINYINT)", false),
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(-128.1 AS 
TINYINT)", false),
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(127 + 1 AS 
TINYINT)", true),
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(128.1 AS 
TINYINT)", true),
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(CAST(128 AS 
DOUBLE) AS TINYINT)", true),
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(CAST(128 AS FLOAT) 
AS TINYINT)", true),
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(128 AS TINYINT)", 
true),
+                arguments(SqlTypeName.TINYINT, "SELECT CAST('128' AS 
TINYINT)", true),
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(-129 AS TINYINT)", 
true),
+                arguments(SqlTypeName.TINYINT, "SELECT CAST(' -129' AS 
TINYINT)", true)
+        );
+    }
+
     @Test
     @SuppressWarnings("ThrowableNotThrown")
     public void testCharTypesWithTrailingSpacesAreTrimmed() {
@@ -653,46 +746,6 @@ public class ItDataTypesTest extends 
BaseSqlIntegrationTest {
         );
     }
 
-    private static Stream<Arguments> decimalOverflowsValidation() {
-        return Stream.of(
-                // BIGINT
-                arguments(SqlTypeName.BIGINT, "SELECT 
CAST(9223372036854775807.1 AS BIGINT)", false),
-                arguments(SqlTypeName.BIGINT, "SELECT 
CAST(9223372036854775807.5 AS BIGINT)", true),
-                arguments(SqlTypeName.BIGINT, "SELECT 
CAST(9223372036854775807.5 - 1 AS BIGINT)", false),
-                arguments(SqlTypeName.BIGINT, "SELECT 
CAST(9223372036854775808.1 AS BIGINT)", true),
-                arguments(SqlTypeName.BIGINT, "SELECT CAST(9223372036854775808 
AS BIGINT)", true),
-                arguments(SqlTypeName.BIGINT, "SELECT 
CAST(-9223372036854775809 AS BIGINT)", true),
-                arguments(SqlTypeName.BIGINT, "SELECT 
CAST(-9223372036854775808.1 AS BIGINT)", false),
-
-                // INTEGER
-                arguments(SqlTypeName.INTEGER, "SELECT CAST(2147483647.1 AS 
INTEGER)", false),
-                arguments(SqlTypeName.INTEGER, "SELECT CAST(2147483647.5 AS 
INTEGER)", true),
-                arguments(SqlTypeName.INTEGER, "SELECT CAST(2147483647.5 - 1 
AS INTEGER)", false),
-                arguments(SqlTypeName.INTEGER, "SELECT CAST(2147483648.1 AS 
INTEGER)", true),
-                arguments(SqlTypeName.INTEGER, "SELECT CAST(2147483648 AS 
INTEGER)", true),
-                arguments(SqlTypeName.INTEGER, "SELECT CAST(-2147483649 AS 
INTEGER)", true),
-                arguments(SqlTypeName.INTEGER, "SELECT CAST(-2147483648.1 AS 
INTEGER)", false),
-
-                // SMALLINT
-                arguments(SqlTypeName.SMALLINT, "SELECT CAST(32767.1 AS 
SMALLINT)", false),
-                arguments(SqlTypeName.SMALLINT, "SELECT CAST(32767.5 AS 
SMALLINT)", true),
-                arguments(SqlTypeName.SMALLINT, "SELECT CAST(32767.5 - 1 AS 
SMALLINT)", false),
-                arguments(SqlTypeName.SMALLINT, "SELECT CAST(32768.1 AS 
SMALLINT)", true),
-                arguments(SqlTypeName.SMALLINT, "SELECT CAST(32768 AS 
SMALLINT)", true),
-                arguments(SqlTypeName.SMALLINT, "SELECT CAST(-32769 AS 
SMALLINT)", true),
-                arguments(SqlTypeName.SMALLINT, "SELECT CAST(-32768.1 AS 
SMALLINT)", false),
-
-                // TINYINT
-                arguments(SqlTypeName.TINYINT, "SELECT CAST(127.1 AS 
TINYINT)", false),
-                arguments(SqlTypeName.TINYINT, "SELECT CAST(127.5 AS 
TINYINT)", true),
-                arguments(SqlTypeName.TINYINT, "SELECT CAST(127.5 - 1 AS 
TINYINT)", false),
-                arguments(SqlTypeName.TINYINT, "SELECT CAST(128.1 AS 
TINYINT)", true),
-                arguments(SqlTypeName.TINYINT, "SELECT CAST(128 AS TINYINT)", 
true),
-                arguments(SqlTypeName.TINYINT, "SELECT CAST(-129 AS TINYINT)", 
true),
-                arguments(SqlTypeName.TINYINT, "SELECT CAST(-128.1 AS 
TINYINT)", false)
-        );
-    }
-
     static String asLiteral(Object value, RelDataType type) {
         if (SqlTypeUtil.isCharacter(type)) {
             String str = (String) value;
diff --git 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItFunctionsTest.java
 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItFunctionsTest.java
index c4486d51ce..cd81db432b 100644
--- 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItFunctionsTest.java
+++ 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItFunctionsTest.java
@@ -356,7 +356,8 @@ public class ItFunctionsTest extends BaseSqlIntegrationTest 
{
         assertQuery("SELECT TYPEOF('abcd' || COALESCE('efg', 
?))").withParams("2").returns("VARCHAR").check();
 
         // An expression that produces an error
-        assertThrowsSqlException(Sql.STMT_PARSE_ERR, "", () -> sql("SELECT 
typeof(CAST('NONE' as INTEGER))"));
+        assertThrowsSqlException(Sql.RUNTIME_ERR, "Invalid input syntax for 
type INTEGER: \"NONE\"",
+                () -> sql("SELECT typeof(CAST('NONE' as INTEGER))"));
 
         assertThrowsWithCause(() -> sql("SELECT TYPEOF()"), 
SqlValidatorException.class, "Invalid number of arguments");
 
diff --git 
a/modules/sql-engine/src/integrationTest/sql/cast/test_cast_bigint.test 
b/modules/sql-engine/src/integrationTest/sql/cast/test_cast_bigint.test
index 0b723c1d17..cb747047e4 100644
--- a/modules/sql-engine/src/integrationTest/sql/cast/test_cast_bigint.test
+++ b/modules/sql-engine/src/integrationTest/sql/cast/test_cast_bigint.test
@@ -74,7 +74,7 @@ SELECT CAST(100.1::DOUBLE AS BIGINT);
 ----
 100
 
-statement error: Character x is neither a decimal digit number, decimal point, 
nor "e" notation exponential mark.
+statement error: Invalid input syntax for type BIGINT: "100x"
 SELECT CAST('100x' AS BIGINT);
 
 statement error: Cast function cannot convert value of type BINARY(1) to type 
BIGINT
diff --git a/modules/sql-engine/src/integrationTest/sql/cast/test_cast_int.test 
b/modules/sql-engine/src/integrationTest/sql/cast/test_cast_int.test
index c58cd4bf9f..8788a1dfa4 100644
--- a/modules/sql-engine/src/integrationTest/sql/cast/test_cast_int.test
+++ b/modules/sql-engine/src/integrationTest/sql/cast/test_cast_int.test
@@ -14,7 +14,7 @@ SELECT CAST(1e1 AS INT);
 ----
 10
 
-statement error: For input string: "1e2"
+statement error: Invalid input syntax for type INTEGER: "1e2"
 SELECT CAST('1e2' AS INT);
 
 # overflow
@@ -70,7 +70,7 @@ SELECT CAST(100.1::DOUBLE AS INT);
 ----
 100
 
-statement error: Character x is neither a decimal digit number, decimal point, 
nor "e" notation exponential mark.
+statement error: Invalid input syntax for type INTEGER: "100x"
 SELECT CAST('100x' AS INT);
 
 statement error: Cast function cannot convert value of type BINARY(1) to type 
INT
diff --git 
a/modules/sql-engine/src/integrationTest/sql/cast/test_cast_smallint.test 
b/modules/sql-engine/src/integrationTest/sql/cast/test_cast_smallint.test
index 6f53d399f4..1d98d3aa4f 100644
--- a/modules/sql-engine/src/integrationTest/sql/cast/test_cast_smallint.test
+++ b/modules/sql-engine/src/integrationTest/sql/cast/test_cast_smallint.test
@@ -14,7 +14,7 @@ SELECT CAST(1e1 AS SMALLINT);
 ----
 10
 
-statement error: For input string: "1e2"
+statement error: Invalid input syntax for type SMALLINT: "1e2"
 SELECT CAST('1e2' AS SMALLINT);
 
 # overflow
@@ -70,7 +70,7 @@ SELECT CAST(100.1::DOUBLE AS SMALLINT);
 ----
 100
 
-statement error: Character x is neither a decimal digit number, decimal point, 
nor "e" notation exponential mark.
+statement error: Invalid input syntax for type SMALLINT: "100x"
 SELECT CAST('100x' AS SMALLINT);
 
 statement error: Cast function cannot convert value of type BINARY(1) to type 
SMALLINT
diff --git 
a/modules/sql-engine/src/integrationTest/sql/cast/test_cast_tinyint.test 
b/modules/sql-engine/src/integrationTest/sql/cast/test_cast_tinyint.test
index 76e65345ec..048b4f55a4 100644
--- a/modules/sql-engine/src/integrationTest/sql/cast/test_cast_tinyint.test
+++ b/modules/sql-engine/src/integrationTest/sql/cast/test_cast_tinyint.test
@@ -14,7 +14,7 @@ SELECT CAST(1e1 AS TINYINT);
 ----
 10
 
-statement error: For input string: "1e2"
+statement error: Invalid input syntax for type TINYINT: "1e2"
 SELECT CAST('1e2' AS TINYINT);
 
 # overflow
@@ -70,7 +70,7 @@ SELECT CAST(100.1::DOUBLE AS TINYINT);
 ----
 100
 
-statement error: Character x is neither a decimal digit number, decimal point, 
nor "e" notation exponential mark.
+statement error: Invalid input syntax for type TINYINT: "100x"
 SELECT CAST('100x' AS TINYINT);
 
 statement error: Cast function cannot convert value of type BINARY(1) to type 
TINYINT
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/ConverterUtils.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/ConverterUtils.java
index 601176a96e..a9a28218b5 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/ConverterUtils.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/ConverterUtils.java
@@ -30,9 +30,11 @@ import org.apache.calcite.linq4j.tree.Primitive;
 import org.apache.calcite.linq4j.tree.Types;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.runtime.SqlFunctions;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.BuiltInMethod;
 import org.apache.calcite.util.Util;
+import org.apache.ignite.internal.sql.engine.util.IgniteMath;
 
 /**
  * ConverterUtils.
@@ -222,31 +224,32 @@ public class ConverterUtils {
         Primitive toPrimitive = Primitive.of(toType);
         Primitive fromPrimitive = Primitive.of(fromType);
 
-        // check overflow for 'integer' subtypes
-        if (fromPrimitive == Primitive.LONG && toPrimitive == Primitive.INT) {
-            return IgniteExpressions.convertToIntExact(operand);
-        }
-
-        if ((fromPrimitive == Primitive.LONG || fromPrimitive == 
Primitive.INT) && toPrimitive == Primitive.SHORT) {
-            return IgniteExpressions.convertToShortExact(operand);
-        }
+        boolean fromNumber = fromType instanceof Class
+                && Number.class.isAssignableFrom((Class<?>) fromType);
+        Primitive fromBox = Primitive.ofBox(fromType);
 
-        if ((fromPrimitive == Primitive.LONG || fromPrimitive == Primitive.INT 
|| fromPrimitive == Primitive.SHORT)
-                && toPrimitive == Primitive.BYTE) {
-            return IgniteExpressions.convertToByteExact(operand);
-        }
-
-        if (!Primitive.isBox(fromType)) {
-            if ((fromType == BigDecimal.class || fromType == String.class) && 
toPrimitive == Primitive.LONG) {
-                return IgniteExpressions.convertToLongExact(operand);
+        if (toPrimitive != null) {
+            if ((toPrimitive == Primitive.LONG || toPrimitive == Primitive.INT 
|| toPrimitive == Primitive.SHORT
+                    || toPrimitive == Primitive.BYTE) && fromType == 
String.class) {
+                return Expressions.call(IgniteMath.class, "convertTo"
+                        + SqlFunctions.initcap(toPrimitive.primitiveName) + 
"Exact", operand);
             }
 
-            if (fromType == BigDecimal.class && toPrimitive == Primitive.BYTE) 
{
-                return IgniteExpressions.convertToByteExact(operand);
+            if (fromPrimitive != null) {
+                // E.g. from "float" to "double"
+                return IgniteExpressions.convertChecked(operand, 
fromPrimitive, toPrimitive);
             }
 
-            if (fromType == BigDecimal.class && toPrimitive == 
Primitive.SHORT) {
-                return IgniteExpressions.convertToShortExact(operand);
+            if (fromNumber) {
+                // Generate "x.shortValue()".
+                return IgniteExpressions.unboxChecked(operand, fromBox, 
toPrimitive);
+            } else {
+                // E.g. from "Object" to "short".
+                // Generate "SqlFunctions.toShort(x)"
+                return Expressions.call(
+                        SqlFunctions.class,
+                        "to" + SqlFunctions.initcap(toPrimitive.primitiveName),
+                        operand);
             }
         }
 
@@ -274,12 +277,6 @@ public class ConverterUtils {
                 || Primitive.ofBox(fromType) == primitive;
     }
 
-    private static boolean representAsInternalType(Type type) {
-        return type == java.sql.Date.class
-                || type == java.sql.Time.class
-                || type == java.sql.Timestamp.class;
-    }
-
     /**
      * In {@link org.apache.calcite.sql.type.SqlTypeAssignmentRule}, some 
rules decide whether one type can be
      * assignable to another type.
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/IgniteExpressions.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/IgniteExpressions.java
index 09081d6da0..99d81c1e36 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/IgniteExpressions.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/IgniteExpressions.java
@@ -18,11 +18,13 @@
 package org.apache.ignite.internal.sql.engine.exec.exp;
 
 import java.lang.reflect.Type;
-import java.math.BigDecimal;
 import org.apache.calcite.linq4j.tree.Expression;
 import org.apache.calcite.linq4j.tree.ExpressionType;
 import org.apache.calcite.linq4j.tree.Expressions;
+import org.apache.calcite.linq4j.tree.Primitive;
+import org.apache.calcite.runtime.SqlFunctions;
 import org.apache.ignite.internal.sql.engine.util.IgniteMath;
+import org.jetbrains.annotations.Nullable;
 
 /** Calcite liq4j expressions customized for Ignite. */
 public class IgniteExpressions {
@@ -97,49 +99,22 @@ public class IgniteExpressions {
         return Expressions.makeBinary(ExpressionType.Divide, left, right);
     }
 
-    /** Generate expression for method IgniteMath.convertToIntExact(). */
-    public static Expression convertToIntExact(Expression exp) {
-        Type type = exp.getType();
-
-        if (type == Long.TYPE || type == Long.class) {
-            return Expressions.call(IgniteMath.class, "convertToIntExact", 
exp);
-        }
-
-        return exp;
-    }
-
-    /** Generate expression for method IgniteMath.convertToIntExact(). */
-    public static Expression convertToLongExact(Expression exp) {
-        Type type = exp.getType();
-
-        if (type == BigDecimal.class || type == String.class) {
-            return Expressions.call(IgniteMath.class, "convertToLongExact", 
exp);
+    static Expression convertChecked(Expression exp, Primitive fromPrimitive, 
Primitive toPrimitive) {
+        if (fromPrimitive.ordinal() <= toPrimitive.ordinal() || 
!toPrimitive.isFixedNumeric()) {
+            return Expressions.convert_(exp, toPrimitive.primitiveClass);
         }
 
-        return exp;
+        return Expressions.call(IgniteMath.class, "convertTo"
+                + SqlFunctions.initcap(toPrimitive.primitiveName) + "Exact", 
exp);
     }
 
-    /** Generate expression for method IgniteMath.convertToShortExact(). */
-    public static Expression convertToShortExact(Expression exp) {
-        Type type = exp.getType();
-
-        if (type == Long.TYPE || type == Long.class || type == Integer.TYPE || 
type == Integer.class || type == BigDecimal.class) {
-            return Expressions.call(IgniteMath.class, "convertToShortExact", 
exp);
-        }
-
-        return exp;
-    }
-
-    /** Generate expression for method IgniteMath.convertToByteExact(). */
-    public static Expression convertToByteExact(Expression exp) {
-        Type type = exp.getType();
-
-        if (type == Long.TYPE || type == Long.class || type == Integer.TYPE || 
type == Integer.class
-                || type == Short.TYPE || type == Short.class || type == 
BigDecimal.class) {
-            return Expressions.call(IgniteMath.class, "convertToByteExact", 
exp);
+    static Expression unboxChecked(Expression exp, @Nullable Primitive 
fromBox, Primitive toPrimitive) {
+        if ((fromBox != null && fromBox.ordinal() <= toPrimitive.ordinal()) || 
!toPrimitive.isFixedNumeric()) {
+            return Expressions.unbox(exp, toPrimitive);
         }
 
-        return exp;
+        return Expressions.call(IgniteMath.class, "convertTo"
+                + SqlFunctions.initcap(toPrimitive.primitiveName) + "Exact", 
exp);
     }
 
     /** Generate expression for method IgniteMath.negateExact() for integer 
subtypes. */
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java
index c2b66f287d..832af32cf2 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java
@@ -19,18 +19,15 @@ package org.apache.ignite.internal.sql.engine.prepare;
 
 import static java.util.Objects.requireNonNull;
 import static org.apache.calcite.sql.type.SqlTypeName.INTEGER;
-import static org.apache.calcite.sql.type.SqlTypeName.INT_TYPES;
 import static org.apache.calcite.sql.type.SqlTypeUtil.isNull;
 import static org.apache.calcite.util.Static.RESOURCE;
 import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
-import static org.apache.ignite.lang.ErrorGroups.Sql.STMT_PARSE_ERR;
 
 import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
 import it.unimi.dsi.fastutil.ints.IntArraySet;
 import it.unimi.dsi.fastutil.ints.IntSet;
 import java.math.BigDecimal;
-import java.math.RoundingMode;
 import java.util.AbstractList;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -41,7 +38,6 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
-import java.util.regex.Pattern;
 import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.prepare.CalciteCatalogReader;
 import org.apache.calcite.prepare.Prepare;
@@ -73,9 +69,7 @@ import org.apache.calcite.sql.dialect.CalciteSqlDialect;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.calcite.sql.type.SqlTypeName;
-import org.apache.calcite.sql.type.SqlTypeName.Limit;
 import org.apache.calcite.sql.type.SqlTypeUtil;
-import org.apache.calcite.sql.util.SqlBasicVisitor;
 import org.apache.calcite.sql.util.SqlShuttle;
 import org.apache.calcite.sql.validate.SelectScope;
 import org.apache.calcite.sql.validate.SqlValidator;
@@ -84,7 +78,6 @@ import org.apache.calcite.sql.validate.SqlValidatorNamespace;
 import org.apache.calcite.sql.validate.SqlValidatorScope;
 import org.apache.calcite.sql.validate.SqlValidatorTable;
 import org.apache.calcite.sql.validate.SqlValidatorUtil;
-import org.apache.calcite.util.Util;
 import org.apache.ignite.internal.sql.engine.schema.IgniteDataSource;
 import org.apache.ignite.internal.sql.engine.schema.IgniteSystemView;
 import org.apache.ignite.internal.sql.engine.schema.IgniteTable;
@@ -95,7 +88,6 @@ import org.apache.ignite.internal.sql.engine.type.UuidType;
 import org.apache.ignite.internal.sql.engine.util.Commons;
 import org.apache.ignite.internal.sql.engine.util.IgniteResource;
 import org.apache.ignite.internal.sql.engine.util.TypeUtils;
-import org.apache.ignite.sql.SqlException;
 import org.jetbrains.annotations.Nullable;
 
 /** Validator. */
@@ -109,9 +101,6 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
 
     public static final String NUMERIC_FIELD_OVERFLOW_ERROR = "Numeric field 
overflow";
 
-    // Approximate and exact numeric types.
-    private static final Pattern NUMERIC = 
Pattern.compile("^\\s*\\d+(\\.{1}\\d*)\\s*$");
-
     static {
         EnumSet<SqlKind> kinds = EnumSet.noneOf(SqlKind.class);
 
@@ -138,9 +127,6 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
      */
     private final IdentityHashMap<SqlDynamicParam, SqlDynamicParam> 
dynamicParamNodes = new IdentityHashMap<>();
 
-    /** Literal processing. */
-    private final LiteralExtractor litExtractor = new LiteralExtractor();
-
     /**
      * Creates a validator.
      *
@@ -676,71 +662,7 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
                     String typeName = 
returnType.getSqlTypeName().getSpaceName();
                     throw newValidationError(expr, 
IgniteResource.INSTANCE.invalidStringLength(typeName));
                 }
-
-                literalCanFitType(expr, returnType);
-            }
-        }
-    }
-
-    /** Check literal can fit to declared exact numeric type, work only for 
single literal. */
-    private void literalCanFitType(SqlNode expr, RelDataType toType) {
-        if (INT_TYPES.contains(toType.getSqlTypeName())) {
-            SqlLiteral literal = litExtractor.getLiteral(expr);
-
-            if (literal == null || literal.toValue() == null) {
-                return;
             }
-
-            int precision = toType.getSqlTypeName().allowsPrec() ? 
toType.getPrecision() : -1;
-            int scale = toType.getSqlTypeName().allowsScale() ? 
toType.getScale() : -1;
-
-            BigDecimal max = (BigDecimal) 
toType.getSqlTypeName().getLimit(true, Limit.OVERFLOW, false, precision, scale);
-            BigDecimal min = (BigDecimal) 
toType.getSqlTypeName().getLimit(false, Limit.OVERFLOW, false, precision, 
scale);
-
-            String litValue = requireNonNull(literal.toValue());
-
-            BigDecimal litValueToDecimal = null;
-
-            try {
-                litValueToDecimal = new BigDecimal(litValue).setScale(0, 
RoundingMode.HALF_UP);
-            } catch (NumberFormatException e) {
-                if (!NUMERIC.matcher(litValue).matches()) {
-                    throw new SqlException(STMT_PARSE_ERR, e);
-                }
-            }
-
-            if (max.compareTo(litValueToDecimal) < 0 || 
min.compareTo(litValueToDecimal) > 0) {
-                throw new SqlException(STMT_PARSE_ERR, "Value '" + litValue + 
"'"
-                        + " out of range for type " + toType.getSqlTypeName());
-            }
-        }
-    }
-
-    private static class LiteralExtractor extends SqlBasicVisitor<SqlNode> {
-        private @Nullable SqlLiteral extracted;
-
-        private @Nullable SqlLiteral getLiteral(SqlNode expr) {
-            extracted = null;
-            try {
-                expr.accept(this);
-            } catch (Util.FoundOne e) {
-                Util.swallow(e, null);
-            }
-            return extracted;
-        }
-
-        /** {@inheritDoc} */
-        @Override
-        public SqlNode visit(SqlLiteral literal) {
-            extracted = extracted != null ? null : literal;
-            return literal;
-        }
-
-        /** {@inheritDoc} */
-        @Override
-        public SqlNode visit(SqlDynamicParam param) {
-            extracted = null;
-            throw Util.FoundOne.NULL;
         }
     }
 
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rex/IgniteRexBuilder.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rex/IgniteRexBuilder.java
index c9914c787d..ccb6de6b66 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rex/IgniteRexBuilder.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rex/IgniteRexBuilder.java
@@ -17,6 +17,9 @@
 
 package org.apache.ignite.internal.sql.engine.rex;
 
+import static org.apache.calcite.sql.type.SqlTypeName.BIGINT;
+
+import java.math.BigInteger;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.rex.RexBuilder;
@@ -43,6 +46,16 @@ public class IgniteRexBuilder extends RexBuilder {
     /** {@inheritDoc} **/
     @Override
     public RexNode makeLiteral(@Nullable Object value, RelDataType type, 
boolean allowCast, boolean trim) {
+        if (value != null && type.getSqlTypeName() == BIGINT && value 
instanceof BigInteger) {
+            BigInteger bd = (BigInteger) value;
+
+            try {
+                bd.longValueExact();
+            } catch (ArithmeticException e) {
+                throw new ArithmeticException(BIGINT.getName() + " out of 
range");
+            }
+        }
+
         // We need to override this method because otherwise
         // default implementation will call RexBuilder::guessType(@Nullable 
Object value)
         // for a custom data type which will then raise the following 
assertion:
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/IgniteMath.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/IgniteMath.java
index de069eb7c0..88e612389a 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/IgniteMath.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/IgniteMath.java
@@ -24,7 +24,9 @@ import static org.apache.calcite.sql.type.SqlTypeName.TINYINT;
 import static org.apache.ignite.lang.ErrorGroups.Sql.RUNTIME_ERR;
 
 import java.math.BigDecimal;
+import java.math.BigInteger;
 import java.math.RoundingMode;
+import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.ignite.sql.SqlException;
 
 /** Math operations with overflow checking. */
@@ -32,6 +34,13 @@ public class IgniteMath {
     private static final BigDecimal UPPER_LONG = 
BigDecimal.valueOf(Long.MAX_VALUE);
     private static final BigDecimal LOWER_LONG = 
BigDecimal.valueOf(Long.MIN_VALUE);
 
+    private static final BigDecimal UPPER_LONG_BIG_DECIMAL = 
BigDecimal.valueOf(Long.MAX_VALUE).add(BigDecimal.ONE);
+    private static final BigDecimal LOWER_LONG_BIG_DECIMAL = 
BigDecimal.valueOf(Long.MIN_VALUE).subtract(BigDecimal.ONE);
+    private static final Double UPPER_LONG_DOUBLE = (double) Long.MAX_VALUE;
+    private static final Double LOWER_LONG_DOUBLE = (double) Long.MIN_VALUE;
+    private static final Float UPPER_LONG_FLOAT = (float) Long.MAX_VALUE;
+    private static final Float LOWER_LONG_FLOAT = (float) Long.MIN_VALUE;
+
     /** Returns the sum of its arguments, throwing an exception if the result 
overflows an {@code long}. */
     public static long addExact(long x, long y) {
         long r = x + y;
@@ -262,6 +271,37 @@ public class IgniteMath {
         throw new SqlException(RUNTIME_ERR, "Division by zero");
     }
 
+    /** Cast value to {@code long}, throwing an exception if the result 
overflows an {@code long}. */
+    public static long convertToLongExact(BigDecimal x) {
+        if (x.compareTo(UPPER_LONG) > 0 || x.compareTo(LOWER_LONG) < 0) {
+            throw new SqlException(RUNTIME_ERR, BIGINT.getName() + " out of 
range");
+        }
+        return x.longValue();
+    }
+
+    /** Cast value to {@code long}, throwing an exception if the result 
overflows an {@code long}. */
+    public static long convertToLongExact(double x) {
+        if (x > Long.MAX_VALUE || x < Long.MIN_VALUE) {
+            throw new ArithmeticException(BIGINT.getName() + " out of range");
+        }
+
+        return (long) x;
+    }
+
+    /** Cast value to {@code long}, throwing an exception if the result 
overflows an {@code long}. */
+    public static long convertToLongExact(String x) {
+        try {
+            BigDecimal decimal = new BigDecimal(x.strip());
+            if (UPPER_LONG.compareTo(decimal.setScale(0, 
RoundingMode.HALF_UP)) < 0
+                    || LOWER_LONG.compareTo(decimal.setScale(0, 
RoundingMode.HALF_UP)) > 0) {
+                throw new SqlException(RUNTIME_ERR, BIGINT.getName() + " out 
of range");
+            }
+            return decimal.longValue();
+        } catch (NumberFormatException ex1) {
+            throw new SqlException(RUNTIME_ERR, "Invalid input syntax for type 
" + BIGINT.getName() + ": \"" + x + "\"", ex1);
+        }
+    }
+
     /** Cast value to {@code int}, throwing an exception if the result 
overflows an {@code int}. */
     public static int convertToIntExact(long x) {
         if ((int) x != x) {
@@ -271,23 +311,31 @@ public class IgniteMath {
         return (int) x;
     }
 
-    /** Cast value to {@code long}, throwing an exception if the result 
overflows an {@code long}. */
-    public static long convertToLongExact(BigDecimal x) {
-        if (x.compareTo(UPPER_LONG) > 0 || x.compareTo(LOWER_LONG) < 0) {
-            throw new SqlException(RUNTIME_ERR, BIGINT.getName() + " out of 
range");
+    /** Cast value to {@code int}, throwing an exception if the result 
overflows an {@code int}. */
+    public static int convertToIntExact(double x) {
+        if (x > Integer.MAX_VALUE || x < Integer.MIN_VALUE) {
+            throw new ArithmeticException(INTEGER.getName() + " out of range");
         }
-        return x.longValue();
+
+        return (int) x;
     }
 
-    /** Cast value to {@code long}, throwing an exception if the result 
overflows an {@code long}. */
-    public static long convertToLongExact(String x) {
-        BigDecimal decimal = new BigDecimal(x);
-        if (UPPER_LONG.compareTo(decimal.setScale(0, RoundingMode.HALF_UP)) < 0
-                || LOWER_LONG.compareTo(decimal.setScale(0, 
RoundingMode.HALF_UP)) > 0) {
-            throw new SqlException(RUNTIME_ERR, BIGINT.getName() + " out of 
range");
-        }
+    /** Cast value to {@code int}, throwing an exception if the result 
overflows an {@code int}. */
+    public static int convertToIntExact(Number x) {
+        checkNumberLongBounds(INTEGER, x);
+        return convertToIntExact(x.longValue());
+    }
 
-        return decimal.longValue();
+    /** Cast value to {@code int}, throwing an exception if the result 
overflows an {@code int}. */
+    public static int convertToIntExact(String x) {
+        try {
+            BigInteger bi = new BigInteger(x.strip());
+            return bi.intValueExact();
+        } catch (ArithmeticException ex) {
+            throw new SqlException(RUNTIME_ERR, INTEGER.getName() + " out of 
range", ex);
+        } catch (NumberFormatException ex1) {
+            throw new SqlException(RUNTIME_ERR, "Invalid input syntax for type 
" + INTEGER.getName() + ": \"" + x + "\"", ex1);
+        }
     }
 
     /** Cast value to {@code short}, throwing an exception if the result 
overflows an {@code short}. */
@@ -299,10 +347,46 @@ public class IgniteMath {
         return (short) x;
     }
 
+    /** Cast value to {@code short}, throwing an exception if the result 
overflows an {@code short}. */
+    public static short convertToShortExact(Number x) {
+        checkNumberLongBounds(SMALLINT, x);
+        return convertToShortExact(x.longValue());
+    }
+
+    /** Cast value to {@code short}, throwing an exception if the result 
overflows an {@code short}. */
+    public static short convertToShortExact(double x) {
+        if (x > Short.MAX_VALUE || x < Short.MIN_VALUE) {
+            throw new ArithmeticException(SMALLINT.getName() + " out of 
range");
+        }
+
+        return (short) x;
+    }
+
+    /** Cast value to {@code short}, throwing an exception if the result 
overflows an {@code short}. */
+    public static short convertToShortExact(String x) {
+        try {
+            BigInteger bi = new BigInteger(x.strip());
+            return bi.shortValueExact();
+        } catch (ArithmeticException ex) {
+            throw new SqlException(RUNTIME_ERR, SMALLINT.getName() + " out of 
range", ex);
+        } catch (NumberFormatException ex1) {
+            throw new SqlException(RUNTIME_ERR, "Invalid input syntax for type 
" + SMALLINT.getName() + ": \"" + x + "\"", ex1);
+        }
+    }
+
+    /** Cast value to {@code byte}, throwing an exception if the result 
overflows an {@code byte}. */
+    public static byte convertToByteExact(double x) {
+        if (x > Byte.MAX_VALUE || x < Byte.MIN_VALUE) {
+            throw new ArithmeticException(TINYINT.getName() + " out of range");
+        }
+
+        return (byte) x;
+    }
+
     /** Cast value to {@code byte}, throwing an exception if the result 
overflows an {@code byte}. */
-    public static short convertToShortExact(BigDecimal x) {
-        long num = x.longValue();
-        return convertToShortExact(num);
+    public static byte convertToByteExact(Number x) {
+        checkNumberLongBounds(TINYINT, x);
+        return convertToByteExact(x.longValue());
     }
 
     /** Cast value to {@code byte}, throwing an exception if the result 
overflows an {@code byte}. */
@@ -315,8 +399,34 @@ public class IgniteMath {
     }
 
     /** Cast value to {@code byte}, throwing an exception if the result 
overflows an {@code byte}. */
-    public static byte convertToByteExact(BigDecimal x) {
-        long num = x.longValue();
-        return convertToByteExact(num);
+    public static byte convertToByteExact(String x) {
+        try {
+            BigInteger bi = new BigInteger(x.strip());
+            return bi.byteValueExact();
+        } catch (ArithmeticException ex) {
+            throw new SqlException(RUNTIME_ERR, TINYINT.getName() + " out of 
range", ex);
+        } catch (NumberFormatException ex1) {
+            throw new SqlException(RUNTIME_ERR, "Invalid input syntax for type 
" + TINYINT.getName() + ": \"" + x + "\"", ex1);
+        }
+    }
+
+    private static void checkNumberLongBounds(SqlTypeName type, Number x) {
+        if (x instanceof BigDecimal) {
+            if ((((BigDecimal) x).compareTo(UPPER_LONG_BIG_DECIMAL) < 0 && 
((BigDecimal) x).compareTo(LOWER_LONG_BIG_DECIMAL) > 0)) {
+                return;
+            }
+        } else if (x instanceof Double) {
+            if ((((Double) x).compareTo(UPPER_LONG_DOUBLE) <= 0 && ((Double) 
x).compareTo(LOWER_LONG_DOUBLE) >= 0)) {
+                return;
+            }
+        } else if (x instanceof Float) {
+            if ((((Float) x).compareTo(UPPER_LONG_FLOAT) <= 0 && ((Float) 
x).compareTo(LOWER_LONG_FLOAT) >= 0)) {
+                return;
+            }
+        } else {
+            return;
+        }
+
+        throw new ArithmeticException(type.getName() + " out of range");
     }
 }


Reply via email to