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

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


The following commit(s) were added to refs/heads/jdbc_over_thin_sql by this 
push:
     new 94bd4c7cd42 IGNITE-26369 Jdbc. Add accessor methods to thin 
client-backed ResultSet (numeric types) (#6555)
94bd4c7cd42 is described below

commit 94bd4c7cd42be4de01cc6b8307685a4d52863b5e
Author: Max Zhuravkov <[email protected]>
AuthorDate: Fri Sep 19 16:35:54 2025 +0300

    IGNITE-26369 Jdbc. Add accessor methods to thin client-backed ResultSet 
(numeric types) (#6555)
---
 .../ignite/jdbc/ItJdbcResultSetSelfTest.java       |    6 -
 .../apache/ignite/internal/jdbc/JdbcResultSet.java |   67 +-
 .../ignite/internal/jdbc2/JdbcResultSet.java       |  421 ++++-
 .../internal/jdbc/JdbcResultSetBaseSelfTest.java   | 1652 +++++++++++++++++++-
 .../internal/jdbc/JdbcResultSetSelfTest.java       |   42 +
 .../internal/jdbc2/JdbcResultSet2SelfTest.java     |   17 +-
 6 files changed, 2072 insertions(+), 133 deletions(-)

diff --git 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcResultSetSelfTest.java
 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcResultSetSelfTest.java
index 318452a6381..8b0087eca33 100644
--- 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcResultSetSelfTest.java
+++ 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcResultSetSelfTest.java
@@ -375,7 +375,6 @@ public class ItJdbcResultSetSelfTest extends 
AbstractJdbcSelfTest {
             if (cnt == 0) {
                 assertEquals(1.0, rs.getFloat("floatVal"));
 
-                assertTrue(rs.getBoolean(7));
                 assertEquals(1, rs.getByte(7));
                 assertEquals(1, rs.getShort(7));
                 assertEquals(1, rs.getInt(7));
@@ -385,7 +384,6 @@ public class ItJdbcResultSetSelfTest extends 
AbstractJdbcSelfTest {
                 assertEquals(new BigDecimal(1), rs.getBigDecimal(7));
                 assertEquals(rs.getString(7), "1.0");
 
-                assertTrue(rs.getObject(7, Boolean.class));
                 assertEquals((byte) 1, rs.getObject(7, Byte.class));
                 assertEquals((short) 1, rs.getObject(7, Short.class));
                 assertEquals(1, rs.getObject(7, Integer.class));
@@ -413,7 +411,6 @@ public class ItJdbcResultSetSelfTest extends 
AbstractJdbcSelfTest {
             if (cnt == 0) {
                 assertEquals(1.0, rs.getDouble("doubleVal"));
 
-                assertTrue(rs.getBoolean(8));
                 assertEquals(1, rs.getByte(8));
                 assertEquals(1, rs.getShort(8));
                 assertEquals(1, rs.getInt(8));
@@ -423,7 +420,6 @@ public class ItJdbcResultSetSelfTest extends 
AbstractJdbcSelfTest {
                 assertEquals(new BigDecimal(1), rs.getBigDecimal(8));
                 assertEquals(rs.getString(8), "1.0");
 
-                assertTrue(rs.getObject(8, Boolean.class));
                 assertEquals((byte) 1, rs.getObject(8, Byte.class));
                 assertEquals((short) 1, rs.getObject(8, Short.class));
                 assertEquals(1, rs.getObject(8, Integer.class));
@@ -451,7 +447,6 @@ public class ItJdbcResultSetSelfTest extends 
AbstractJdbcSelfTest {
             if (cnt == 0) {
                 assertEquals(1, rs.getBigDecimal("bigVal").intValue());
 
-                assertTrue(rs.getBoolean(9));
                 assertEquals(1, rs.getByte(9));
                 assertEquals(1, rs.getShort(9));
                 assertEquals(1, rs.getInt(9));
@@ -461,7 +456,6 @@ public class ItJdbcResultSetSelfTest extends 
AbstractJdbcSelfTest {
                 assertEquals(new BigDecimal("1.000"), rs.getBigDecimal(9));
                 assertEquals(rs.getString(9), "1.000");
 
-                assertTrue(rs.getObject(9, Boolean.class));
                 assertEquals((byte) 1, rs.getObject(9, Byte.class));
                 assertEquals((short) 1, rs.getObject(9, Short.class));
                 assertEquals(1, rs.getObject(9, Integer.class));
diff --git 
a/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcResultSet.java 
b/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcResultSet.java
index 9444e056efe..3f05102064f 100644
--- 
a/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcResultSet.java
+++ 
b/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcResultSet.java
@@ -41,9 +41,6 @@ import java.sql.SQLXML;
 import java.sql.Statement;
 import java.sql.Time;
 import java.sql.Timestamp;
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.text.ParseException;
 import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
@@ -84,24 +81,6 @@ import org.jetbrains.annotations.TestOnly;
  * Jdbc result set implementation.
  */
 public class JdbcResultSet implements ResultSet {
-    /** Decimal format to convert string to decimal. */
-    private static final ThreadLocal<DecimalFormat> decimalFormat = new 
ThreadLocal<>() {
-        /** {@inheritDoc} */
-        @Override
-        protected DecimalFormat initialValue() {
-            DecimalFormatSymbols symbols = new DecimalFormatSymbols();
-
-            symbols.setGroupingSeparator(',');
-            symbols.setDecimalSeparator('.');
-
-            DecimalFormat decimalFormat = new DecimalFormat("", symbols);
-
-            decimalFormat.setParseBigDecimal(true);
-
-            return decimalFormat;
-        }
-    };
-
     private final JdbcStatement stmt;
     private final @Nullable Long cursorId;
     private final boolean hasResultSet;
@@ -455,21 +434,19 @@ public class JdbcResultSet implements ResultSet {
             return false;
         }
 
-        Class<?> cls = val.getClass();
-
-        if (cls == Boolean.class) {
+        if ("0".equals(val)) {
+            return false;
+        } else if ("1".equals(val)) {
+            return true;
+        } else if (val instanceof Boolean) {
             return ((Boolean) val);
-        } else if (val instanceof Number) {
-            return ((Number) val).intValue() != 0;
-        } else if (cls == String.class || cls == Character.class) {
-            try {
-                return Integer.parseInt(val.toString()) != 0;
-            } catch (NumberFormatException e) {
-                throw new SQLException("Cannot convert to boolean: " + val, 
SqlStateCode.CONVERSION_FAILED, e);
-            }
-        } else {
-            throw new SQLException("Cannot convert to boolean: " + val, 
SqlStateCode.CONVERSION_FAILED);
+        } else if (val instanceof Byte || val instanceof Short || val 
instanceof Integer || val instanceof Long) {
+            long num = ((Number) val).longValue();
+            // 0 - false, anything else is true.
+            return num != 0;
         }
+
+        throw new SQLException("Cannot convert to boolean: " + val, 
SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
@@ -629,8 +606,6 @@ public class JdbcResultSet implements ResultSet {
 
         if (val instanceof Number) {
             return ((Number) val).floatValue();
-        } else if (cls == Boolean.class) {
-            return ((Boolean) val ? 1 : 0);
         } else if (cls == String.class || cls == Character.class) {
             try {
                 return Float.parseFloat(val.toString());
@@ -663,8 +638,6 @@ public class JdbcResultSet implements ResultSet {
 
         if (val instanceof Number) {
             return ((Number) val).doubleValue();
-        } else if (cls == Boolean.class) {
-            return ((Boolean) val ? 1d : 0d);
         } else if (cls == String.class || cls == Character.class) {
             try {
                 return Double.parseDouble(val.toString());
@@ -701,18 +674,18 @@ public class JdbcResultSet implements ResultSet {
             return null;
         }
 
-        Class<?> cls = val.getClass();
-
-        if (cls == BigDecimal.class) {
+        if (val instanceof BigDecimal) {
             return (BigDecimal) val;
-        } else if (val instanceof Number) {
+        } else if (val instanceof Float || val instanceof Double) {
+            // Perform conversion from double for floating point numbers
             return new BigDecimal(((Number) val).doubleValue());
-        } else if (cls == Boolean.class) {
-            return new BigDecimal((Boolean) val ? 1 : 0);
-        } else if (cls == String.class || cls == Character.class) {
+        } else if (val instanceof Number) {
+            // Perform exact conversion from integer types
+            return new BigDecimal(((Number) val).longValue());
+        } else if (val instanceof String) {
             try {
-                return (BigDecimal) decimalFormat.get().parse(val.toString());
-            } catch (ParseException e) {
+                return new BigDecimal(val.toString());
+            } catch (Exception e) {
                 throw new SQLException("Cannot convert to BigDecimal: " + val, 
SqlStateCode.CONVERSION_FAILED, e);
             }
         } else {
diff --git 
a/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
 
b/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
index 32f64f76441..31f00ee846b 100644
--- 
a/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
+++ 
b/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
@@ -17,9 +17,12 @@
 
 package org.apache.ignite.internal.jdbc2;
 
+import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
+
 import java.io.InputStream;
 import java.io.Reader;
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.net.URL;
 import java.sql.Array;
 import java.sql.Blob;
@@ -37,12 +40,16 @@ import java.sql.SQLXML;
 import java.sql.Statement;
 import java.sql.Time;
 import java.sql.Timestamp;
+import java.time.temporal.Temporal;
 import java.util.Calendar;
 import java.util.List;
 import java.util.Map;
+import java.util.UUID;
 import org.apache.ignite.internal.jdbc.proto.SqlStateCode;
 import org.apache.ignite.internal.lang.IgniteExceptionMapperUtil;
 import org.apache.ignite.internal.sql.ResultSetMetadataImpl;
+import org.apache.ignite.sql.ColumnMetadata;
+import org.apache.ignite.sql.ColumnType;
 import org.apache.ignite.sql.ResultSetMetadata;
 import org.apache.ignite.sql.SqlRow;
 import org.jetbrains.annotations.Nullable;
@@ -60,6 +67,10 @@ public class JdbcResultSet implements ResultSet {
 
     private static final ResultSetMetadata EMPTY_METADATA = new 
ResultSetMetadataImpl(List.of());
 
+    private static final BigDecimal MIN_DOUBLE = 
BigDecimal.valueOf(-Double.MAX_VALUE);
+
+    private static final BigDecimal MAX_DOUBLE = 
BigDecimal.valueOf(Double.MAX_VALUE);
+
     private final org.apache.ignite.sql.ResultSet<SqlRow> rs;
 
     private final ResultSetMetadata rsMetadata;
@@ -143,178 +154,412 @@ public class JdbcResultSet implements ResultSet {
         ensureNotClosed();
         ensureHasCurrentRow();
 
-        throw new UnsupportedOperationException();
+        Object value = getValue(colIdx);
+        if (value == null) {
+            return null;
+        }
+
+        if (value instanceof Temporal || value instanceof byte[] || value 
instanceof UUID) {
+            throw new UnsupportedOperationException();
+        } else {
+            return String.valueOf(value);
+        }
     }
 
     /** {@inheritDoc} */
     @Override
     public String getString(String colLb) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        int colIdx = findColumn(colLb);
 
-        throw new UnsupportedOperationException();
+        return getString(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override
     public boolean getBoolean(int colIdx) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        Object val = getValue(colIdx);
 
-        throw new UnsupportedOperationException();
+        if (val == null) {
+            return false;
+        }
+
+        ColumnMetadata column = rsMetadata.columns().get(colIdx - 1);
+        switch (column.type()) {
+            case BOOLEAN:
+                return ((Boolean) val);
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+                long num = ((Number) val).longValue();
+                return num != 0;
+            case STRING:
+                String str = (String) val;
+                if ("0".equals(str)) {
+                    return false;
+                } else if ("1".equals(str)) {
+                    return true;
+                }
+                break;
+            default:
+                // Fallthrough
+        }
+
+        throw new SQLException("Cannot convert to boolean: " + val, 
SqlStateCode.CONVERSION_FAILED);
     }
 
     /** {@inheritDoc} */
     @Override
     public boolean getBoolean(String colLb) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        int colIdx = findColumn(colLb);
 
-        throw new UnsupportedOperationException();
+        return getBoolean(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override
     public byte getByte(int colIdx) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        Object val = getValue(colIdx);
 
-        throw new UnsupportedOperationException();
+        if (val == null) {
+            return 0;
+        }
+
+        ColumnType columnType = getColumnType(colIdx);
+        switch (columnType) {
+            case BOOLEAN:
+                return (Boolean) val ? (byte) 1 : (byte) 0;
+            case INT8:
+                return (byte) val;
+            case INT16:
+            case INT32:
+            case INT64:
+                //noinspection NumericCastThatLosesPrecision
+                return (byte) getLongValue(((Number) val).longValue(), 
Byte.TYPE.getTypeName(), Byte.MIN_VALUE, Byte.MAX_VALUE);
+            case FLOAT:
+                //noinspection NumericCastThatLosesPrecision
+                return (byte) getFloatValueAsLong((float) val, 
Byte.TYPE.getTypeName(), Byte.MIN_VALUE, Byte.MAX_VALUE);
+            case DOUBLE:
+                //noinspection NumericCastThatLosesPrecision
+                return (byte) getDoubleValueAsLong((double) val, 
Byte.TYPE.getTypeName(), Byte.MIN_VALUE, Byte.MAX_VALUE);
+            case DECIMAL:
+                //noinspection NumericCastThatLosesPrecision
+                return (byte) getDecimalValueAsLong((BigDecimal) val, 
Byte.TYPE.getTypeName(), Byte.MIN_VALUE, Byte.MAX_VALUE);
+            case STRING:
+                try {
+                    return Byte.parseByte(val.toString());
+                } catch (NumberFormatException e) {
+                    throw conversionError(Byte.TYPE.getTypeName(), val, e);
+                }
+            default:
+                throw conversionError(Byte.TYPE.getTypeName(), val);
+        }
     }
 
     /** {@inheritDoc} */
     @Override
     public byte getByte(String colLb) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        int colIdx = findColumn(colLb);
 
-        throw new UnsupportedOperationException();
+        return getByte(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override
     public short getShort(int colIdx) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        Object val = getValue(colIdx);
 
-        throw new UnsupportedOperationException();
+        if (val == null) {
+            return 0;
+        }
+
+        ColumnType columnType = getColumnType(colIdx);
+        switch (columnType) {
+            case BOOLEAN:
+                return (Boolean) val ? (short) 1 : (short) 0;
+            case INT8:
+                return (byte) val;
+            case INT16:
+                return (short) val;
+            case INT32:
+            case INT64:
+                //noinspection NumericCastThatLosesPrecision
+                return (short) getLongValue(((Number) val).longValue(), 
Short.TYPE.getTypeName(), Short.MIN_VALUE, Short.MAX_VALUE);
+            case FLOAT:
+                //noinspection NumericCastThatLosesPrecision
+                return (short) getFloatValueAsLong((float) val, 
Short.TYPE.getTypeName(), Short.MIN_VALUE, Short.MAX_VALUE);
+            case DOUBLE:
+                //noinspection NumericCastThatLosesPrecision
+                return (short) getDoubleValueAsLong((double) val, 
Short.TYPE.getTypeName(), Short.MIN_VALUE, Short.MAX_VALUE);
+            case DECIMAL:
+                //noinspection NumericCastThatLosesPrecision
+                return (short) getDecimalValueAsLong((BigDecimal) val, 
Short.TYPE.getTypeName(), Short.MIN_VALUE, Short.MAX_VALUE);
+            case STRING:
+                try {
+                    return Short.parseShort(val.toString());
+                } catch (NumberFormatException e) {
+                    throw conversionError(Short.TYPE.getTypeName(), val, e);
+                }
+            default:
+                throw conversionError(Short.TYPE.getTypeName(), val);
+        }
     }
 
     /** {@inheritDoc} */
     @Override
     public short getShort(String colLb) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        int colIdx = findColumn(colLb);
 
-        throw new UnsupportedOperationException();
+        return getShort(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override
     public int getInt(int colIdx) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        Object val = getValue(colIdx);
 
-        throw new UnsupportedOperationException();
+        if (val == null) {
+            return 0;
+        }
+
+        ColumnType columnType = getColumnType(colIdx);
+        switch (columnType) {
+            case BOOLEAN:
+                return (Boolean) val ? 1 : 0;
+            case INT8:
+                return (byte) val;
+            case INT16:
+                return (short) val;
+            case INT32:
+                return (int) val;
+            case INT64:
+                //noinspection NumericCastThatLosesPrecision
+                return (int) getLongValue(((Number) val).longValue(), 
Integer.TYPE.getTypeName(), Integer.MIN_VALUE, Integer.MAX_VALUE);
+            case FLOAT:
+                //noinspection NumericCastThatLosesPrecision
+                return (int) getFloatValueAsLong((float) val, 
Integer.TYPE.getTypeName(), Integer.MIN_VALUE, Integer.MAX_VALUE);
+            case DOUBLE:
+                //noinspection NumericCastThatLosesPrecision
+                return (int) getDoubleValueAsLong((double) val, 
Integer.TYPE.getTypeName(), Integer.MIN_VALUE, Integer.MAX_VALUE);
+            case DECIMAL:
+                //noinspection NumericCastThatLosesPrecision
+                return (int) getDecimalValueAsLong((BigDecimal) val, 
Integer.TYPE.getTypeName(), Integer.MIN_VALUE, Integer.MAX_VALUE);
+            case STRING:
+                try {
+                    return Integer.parseInt(val.toString());
+                } catch (NumberFormatException e) {
+                    throw conversionError(Integer.TYPE.getTypeName(), val, e);
+                }
+            default:
+                throw conversionError(Integer.TYPE.getTypeName(), val);
+        }
     }
 
     /** {@inheritDoc} */
     @Override
     public int getInt(String colLb) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        int colIdx = findColumn(colLb);
 
-        throw new UnsupportedOperationException();
+        return getInt(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override
     public long getLong(int colIdx) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        Object val = getValue(colIdx);
 
-        throw new UnsupportedOperationException();
+        if (val == null) {
+            return 0;
+        }
+
+        ColumnType columnType = getColumnType(colIdx);
+        switch (columnType) {
+            case BOOLEAN:
+                return (Boolean) val ? 1 : 0;
+            case INT8:
+                return (byte) val;
+            case INT16:
+                return (short) val;
+            case INT32:
+                return (int) val;
+            case INT64:
+                return (long) val;
+            case FLOAT:
+                return getFloatValueAsLong((float) val, 
Long.TYPE.getTypeName(), Long.MIN_VALUE, Long.MAX_VALUE);
+            case DOUBLE:
+                return getDoubleValueAsLong((double) val, 
Long.TYPE.getTypeName(), Long.MIN_VALUE, Long.MAX_VALUE);
+            case DECIMAL:
+                return getDecimalValueAsLong((BigDecimal) val, 
Long.TYPE.getTypeName(), Long.MIN_VALUE, Long.MAX_VALUE);
+            case STRING:
+                try {
+                    return Long.parseLong(val.toString());
+                } catch (NumberFormatException e) {
+                    throw conversionError(Long.TYPE.getTypeName(), val, e);
+                }
+            default:
+                throw conversionError(Long.TYPE.getTypeName(), val);
+        }
     }
 
     /** {@inheritDoc} */
     @Override
     public long getLong(String colLb) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        int colIdx = findColumn(colLb);
 
-        throw new UnsupportedOperationException();
+        return getLong(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override
     public float getFloat(int colIdx) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        Object val = getValue(colIdx);
 
-        throw new UnsupportedOperationException();
+        if (val == null) {
+            return 0;
+        }
+
+        ColumnType columnType = getColumnType(colIdx);
+        switch (columnType) {
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case FLOAT:
+                return ((Number) val).floatValue();
+            case DOUBLE:
+                double num = (double) val;
+                if (num < -Float.MAX_VALUE || num > Float.MAX_VALUE) {
+                    throw conversionError(Float.TYPE.getTypeName(), val);
+                }
+                //noinspection NumericCastThatLosesPrecision
+                return (float) num;
+            case DECIMAL:
+                BigDecimal bd = (BigDecimal) val;
+                if (bd.doubleValue() < -Float.MAX_VALUE || bd.doubleValue() > 
Float.MAX_VALUE) {
+                    throw conversionError(Float.TYPE.getTypeName(), val);
+                }
+                return bd.floatValue();
+            case STRING:
+                try {
+                    return Float.parseFloat(val.toString());
+                } catch (NumberFormatException e) {
+                    throw conversionError(Float.TYPE.getTypeName(), val, e);
+                }
+            default:
+                throw conversionError(Float.TYPE.getTypeName(), val);
+        }
     }
 
     /** {@inheritDoc} */
     @Override
     public float getFloat(String colLb) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        int colIdx = findColumn(colLb);
 
-        throw new UnsupportedOperationException();
+        return getFloat(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override
     public double getDouble(int colIdx) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        Object val = getValue(colIdx);
 
-        throw new UnsupportedOperationException();
+        if (val == null) {
+            return 0.0d;
+        }
+
+        ColumnType columnType = getColumnType(colIdx);
+        switch (columnType) {
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case FLOAT:
+                return ((Number) val).doubleValue();
+            case DOUBLE:
+                return (double) val;
+            case DECIMAL:
+                BigDecimal bd = (BigDecimal) val;
+                if (bd.compareTo(MIN_DOUBLE) < 0 || bd.compareTo(MAX_DOUBLE) > 
0) {
+                    throw conversionError(Double.TYPE.getTypeName(), val);
+                }
+                return bd.doubleValue();
+            case STRING:
+                try {
+                    return Double.parseDouble(val.toString());
+                } catch (NumberFormatException e) {
+                    throw conversionError(Double.TYPE.getTypeName(), val, e);
+                }
+            default:
+                throw conversionError(Double.TYPE.getTypeName(), val);
+        }
     }
 
     /** {@inheritDoc} */
     @Override
     public double getDouble(String colLb) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        int colIdx = findColumn(colLb);
 
-        throw new UnsupportedOperationException();
+        return getDouble(colIdx);
     }
 
     /** {@inheritDoc} */
     @Override
+    @Nullable
     public BigDecimal getBigDecimal(int colIdx, int scale) throws SQLException 
{
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        BigDecimal val = getBigDecimal(colIdx);
 
-        throw new UnsupportedOperationException();
+        return val == null ? null : val.setScale(scale, RoundingMode.HALF_UP);
     }
 
     /** {@inheritDoc} */
     @Override
+    @Nullable
     public BigDecimal getBigDecimal(int colIdx) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        Object val = getValue(colIdx);
 
-        throw new UnsupportedOperationException();
+        if (val == null) {
+            return null;
+        }
+
+        ColumnType columnType = getColumnType(colIdx);
+        switch (columnType) {
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+                return new BigDecimal(((Number) val).longValue());
+            case FLOAT:
+            case DOUBLE:
+                return new BigDecimal(((Number) val).doubleValue());
+            case DECIMAL:
+                return (BigDecimal) val;
+            case STRING:
+                try {
+                    return new BigDecimal(val.toString());
+                } catch (Exception e) {
+                    throw new SQLException("Cannot convert to BigDecimal: " + 
val, SqlStateCode.CONVERSION_FAILED, e);
+                }
+            default:
+                throw new SQLException("Cannot convert to BigDecimal: " + val, 
SqlStateCode.CONVERSION_FAILED);
+        }
     }
 
     /** {@inheritDoc} */
     @Override
+    @Nullable
     public BigDecimal getBigDecimal(String colLb, int scale) throws 
SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        int colIdx = findColumn(colLb);
 
-        throw new UnsupportedOperationException();
+        return getBigDecimal(colIdx, scale);
     }
 
     /** {@inheritDoc} */
     @Override
+    @Nullable
     public BigDecimal getBigDecimal(String colLb) throws SQLException {
-        ensureNotClosed();
-        ensureHasCurrentRow();
+        int colIdx = findColumn(colLb);
 
-        throw new UnsupportedOperationException();
+        return getBigDecimal(colIdx);
     }
 
     /** {@inheritDoc} */
@@ -1787,7 +2032,7 @@ public class JdbcResultSet implements ResultSet {
             if (targetCls.isAssignableFrom(cls)) {
                 return val;
             } else {
-                throw new SQLException("Cannot convert to " + 
targetCls.getName() + ": " + val, SqlStateCode.CONVERSION_FAILED);
+                throw conversionError(targetCls.getTypeName(), val);
             }
         }
     }
@@ -1798,4 +2043,62 @@ public class JdbcResultSet implements ResultSet {
         }
         return jdbcMeta;
     }
+
+    private ColumnType getColumnType(int colIdx) {
+        ColumnMetadata column = rsMetadata.columns().get(colIdx - 1);
+        return column.type();
+    }
+
+    private static long getLongValue(long val, String typeName, long min, long 
max) throws SQLException {
+        if (val < min || val > max) {
+            throw conversionError(typeName, val);
+        }
+        return val;
+    }
+
+    private static long getFloatValueAsLong(float val, String typeName, long 
min, long max) throws SQLException {
+        if (val < min || val > max || Float.isInfinite(val) || 
Float.isNaN(val)) {
+            throw conversionError(typeName, val);
+        }
+        //noinspection NumericCastThatLosesPrecision
+        return (long) val;
+    }
+
+    private static long getDoubleValueAsLong(double val, String typeName, long 
min, long max) throws SQLException {
+        if (val < min || val > max || Double.isInfinite(val) || 
Double.isNaN(val)) {
+            throw conversionError(typeName, val);
+        }
+        //noinspection NumericCastThatLosesPrecision
+        return (long) val;
+    }
+
+    private static long getDecimalValueAsLong(BigDecimal num, String typeName, 
long min, long max) throws SQLException {
+        long val;
+        boolean failed;
+
+        // We can safely remove a fractional part, conversion from one int 
type to another involves rounding but 
+        // longValueExact fails if a fractional part present.
+        BigDecimal intNum = num.setScale(0, RoundingMode.DOWN);
+        try {
+            val = intNum.longValueExact();
+            failed = false;
+        } catch (ArithmeticException e) {
+            failed = true;
+            val = 0;
+        }
+
+        if (failed || val < min || val > max) {
+            throw conversionError(typeName, num);
+        }
+
+        return val;
+    }
+
+    private static SQLException conversionError(String typeName, Object val) {
+        return conversionError(typeName, val, null);
+    }
+
+    private static SQLException conversionError(String typeName, Object val, 
@Nullable Throwable cause) {
+        return new SQLException(format("Cannot convert to {}: {}", typeName, 
val), SqlStateCode.CONVERSION_FAILED, cause);
+    }
 }
diff --git 
a/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc/JdbcResultSetBaseSelfTest.java
 
b/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc/JdbcResultSetBaseSelfTest.java
index c9ba5c1a0cc..48efc7cf7ed 100644
--- 
a/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc/JdbcResultSetBaseSelfTest.java
+++ 
b/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc/JdbcResultSetBaseSelfTest.java
@@ -29,6 +29,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import java.io.InputStream;
 import java.io.Reader;
 import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
 import java.sql.Blob;
 import java.sql.Clob;
 import java.sql.Date;
@@ -53,12 +55,19 @@ import java.util.Map;
 import java.util.UUID;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
+import java.util.stream.Stream;
+import org.apache.ignite.internal.jdbc.proto.SqlStateCode;
 import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
 import org.apache.ignite.sql.ColumnType;
 import org.jetbrains.annotations.Nullable;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.function.Executable;
 import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.CsvSource;
 import org.junit.jupiter.params.provider.EnumSource;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.junit.jupiter.params.provider.ValueSource;
 
 /**
  * Compatibility tests to ensure that both JDBC result set adapters behave 
identically for core java.sql.ResultSet methods (excluding
@@ -92,6 +101,1623 @@ public abstract class JdbcResultSetBaseSelfTest extends 
BaseIgniteAbstractTest {
         return createMultiRow(null, columns, values);
     }
 
+    private static ColumnType columnTypefromObject(Object value) {
+        if (value == null) {
+            return ColumnType.NULL;
+        }
+        for (ColumnType columnType : ColumnType.values()) {
+            if (columnType.javaClass().equals(value.getClass())) {
+                return columnType;
+            }
+        }
+        throw new IllegalArgumentException("No column type for " + value);
+    }
+
+    @ParameterizedTest
+    @ValueSource(booleans = {true, false})
+    public void getBoolean(boolean boolValue) throws SQLException {
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.BOOLEAN, 0, 0, false), boolValue)) {
+            assertTrue(rs.next());
+
+            String strVal = boolValue ? "true" : "false";
+            int value = boolValue ? 1 : 0;
+
+            assertEquals(boolValue, rs.getBoolean(1));
+            assertEquals(boolValue, rs.getBoolean("C"));
+
+            assertEquals(value, rs.getByte(1));
+            assertEquals(value, rs.getByte("C"));
+
+            assertEquals(value, rs.getShort(1));
+            assertEquals(value, rs.getShort("C"));
+
+            assertEquals(value, rs.getInt(1));
+            assertEquals(value, rs.getInt("C"));
+
+            assertEquals(value, rs.getLong(1));
+            assertEquals(value, rs.getLong("C"));
+
+            expectSqlConversionError(() -> rs.getFloat(1), "float");
+            expectSqlConversionError(() -> rs.getFloat("C"), "float");
+
+            expectSqlConversionError(() -> rs.getDouble(1), "double");
+            expectSqlConversionError(() -> rs.getDouble("C"), "double");
+
+            expectSqlConversionError(() -> rs.getBigDecimal(1), "BigDecimal");
+            expectSqlConversionError(() -> rs.getBigDecimal("C"), 
"BigDecimal");
+
+            //noinspection deprecation
+            expectSqlConversionError(() -> rs.getBigDecimal(1, 2), 
"BigDecimal");
+            //noinspection deprecation
+            expectSqlConversionError(() -> rs.getBigDecimal("C", 2), 
"BigDecimal");
+
+            assertEquals(strVal, rs.getString(1));
+            assertEquals(strVal, rs.getString("C"));
+
+            assertEquals(strVal, rs.getNString(1));
+            assertEquals(strVal, rs.getNString("C"));
+
+            // getObject
+
+            assertEquals(boolValue, rs.getObject(1));
+            assertEquals(boolValue, rs.getObject("C"));
+
+            assertEquals(Byte.valueOf((byte) value), rs.getObject(1, 
Byte.class));
+            assertEquals(Byte.valueOf((byte) value), rs.getObject("C", 
Byte.class));
+
+            assertEquals(Short.valueOf((short) value), rs.getObject(1, 
Short.class));
+            assertEquals(Short.valueOf((short) value), rs.getObject("C", 
Short.class));
+
+            assertEquals(Integer.valueOf(value), rs.getObject(1, 
Integer.class));
+            assertEquals(Integer.valueOf(value), rs.getObject("C", 
Integer.class));
+
+            assertEquals(Long.valueOf(value), rs.getObject(1, Long.class));
+            assertEquals(Long.valueOf(value), rs.getObject("C", Long.class));
+
+            expectSqlConversionError(() -> rs.getObject(1, Float.class), 
"float");
+            expectSqlConversionError(() -> rs.getObject("C", Float.class), 
"float");
+
+            expectSqlConversionError(() -> rs.getObject(1, Double.class), 
"double");
+            expectSqlConversionError(() -> rs.getObject("C", Double.class), 
"double");
+
+            expectSqlConversionError(() -> rs.getObject(1, BigDecimal.class), 
"BigDecimal");
+            expectSqlConversionError(() -> rs.getObject("C", 
BigDecimal.class), "BigDecimal");
+
+            assertEquals(strVal, rs.getObject(1, String.class));
+            assertEquals(strVal, rs.getObject("C", String.class));
+
+            expectSqlConversionError(() -> rs.getObject(1, UUID.class), 
"java.util.UUID");
+            expectSqlConversionError(() -> rs.getObject("C", UUID.class), 
"java.util.UUID");
+        }
+    }
+
+    @ParameterizedTest
+    @CsvSource({
+            "true, 1, true",
+            "true, 0, false",
+            "false, -1, ",
+            "true, 0, ",
+            "false, -129, ",
+            "false, 128, ",
+            "false, xyz, ",
+            "false,, "
+    })
+    public void getBooleanFromString(boolean valid, String value, String 
result) throws SQLException {
+        if (value == null) {
+            value = "";
+        }
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.STRING, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (!valid) {
+                String error = "Cannot convert to boolean: " + value;
+
+                expectSqlException(() -> rs.getBoolean(1), error);
+                expectSqlException(() -> rs.getBoolean("C"), error);
+
+                expectSqlException(() -> rs.getObject(1, Boolean.class), 
error);
+                expectSqlException(() -> rs.getObject("C", Boolean.class), 
error);
+
+            } else {
+                boolean expected = Boolean.parseBoolean(result);
+
+                assertEquals(expected, rs.getBoolean(1));
+                assertEquals(expected, rs.getBoolean("C"));
+
+                assertEquals(expected, rs.getObject(1, Boolean.class));
+                assertEquals(expected, rs.getObject("C", Boolean.class));
+            }
+        }
+    }
+
+    @ParameterizedTest
+    @ValueSource(bytes = {-42, -1, 0, 1, 42})
+    public void getByte(byte value) throws SQLException {
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.INT8, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            BigDecimal decimalVal = BigDecimal.valueOf(value);
+            BigDecimal decimalScaledVal = 
BigDecimal.valueOf(value).setScale(2, RoundingMode.HALF_UP);
+            String strVal = String.valueOf(value);
+
+            if (value == 0) {
+                assertFalse(rs.getBoolean(1));
+                assertFalse(rs.getBoolean("C"));
+            } else {
+                assertTrue(rs.getBoolean(1));
+                assertTrue(rs.getBoolean("C"));
+            }
+
+            assertEquals(value, rs.getByte(1));
+            assertEquals(value, rs.getByte("C"));
+
+            assertEquals(value, rs.getShort(1));
+            assertEquals(value, rs.getShort("C"));
+
+            assertEquals(value, rs.getInt(1));
+            assertEquals(value, rs.getInt("C"));
+
+            assertEquals(value, rs.getLong(1));
+            assertEquals(value, rs.getLong("C"));
+
+            assertEquals(value, rs.getFloat(1));
+            assertEquals(value, rs.getFloat("C"));
+
+            assertEquals(value, rs.getDouble(1));
+            assertEquals(value, rs.getDouble("C"));
+
+            assertEquals(decimalVal, rs.getBigDecimal(1));
+            assertEquals(decimalVal, rs.getBigDecimal("C"));
+
+            //noinspection deprecation
+            assertEquals(decimalScaledVal, rs.getBigDecimal(1, 2));
+            //noinspection deprecation
+            assertEquals(decimalScaledVal, rs.getBigDecimal("C", 2));
+
+            assertEquals(strVal, rs.getString(1));
+            assertEquals(strVal, rs.getString("C"));
+
+            assertEquals(strVal, rs.getNString(1));
+            assertEquals(strVal, rs.getNString("C"));
+
+            // getObject
+
+            assertEquals(value, rs.getObject(1));
+            assertEquals(value, rs.getObject("C"));
+
+            assertEquals(Byte.valueOf(value), rs.getObject(1, Byte.class));
+            assertEquals(Byte.valueOf(value), rs.getObject("C", Byte.class));
+
+            assertEquals(Short.valueOf(value), rs.getObject(1, Short.class));
+            assertEquals(Short.valueOf(value), rs.getObject("C", Short.class));
+
+            assertEquals(Integer.valueOf(value), rs.getObject(1, 
Integer.class));
+            assertEquals(Integer.valueOf(value), rs.getObject("C", 
Integer.class));
+
+            assertEquals(Long.valueOf(value), rs.getObject(1, Long.class));
+            assertEquals(Long.valueOf(value), rs.getObject("C", Long.class));
+
+            assertEquals(Float.valueOf(value), rs.getObject(1, Float.class));
+            assertEquals(Float.valueOf(value), rs.getObject("C", Float.class));
+
+            assertEquals(Double.valueOf(value), rs.getObject(1, Double.class));
+            assertEquals(Double.valueOf(value), rs.getObject("C", 
Double.class));
+
+            assertEquals(decimalVal, rs.getObject(1, BigDecimal.class));
+            assertEquals(decimalVal, rs.getObject("C", BigDecimal.class));
+
+            assertEquals(strVal, rs.getObject(1, String.class));
+            assertEquals(strVal, rs.getObject("C", String.class));
+
+            expectSqlConversionError(() -> rs.getObject(1, UUID.class), 
"java.util.UUID");
+            expectSqlConversionError(() -> rs.getObject("C", UUID.class), 
"java.util.UUID");
+        }
+    }
+
+    @ParameterizedTest
+    @CsvSource({
+            "true, -128, -128",
+            "true, 127, 127",
+            "true, -42, -42",
+            "true, 42, 42",
+            "false, -129, ",
+            "false, 128, ",
+            "false, xyz, ",
+            "false,, "
+    })
+    public void getByteFromString(boolean valid, String value, String result) 
throws SQLException {
+        if (value == null) {
+            value = "";
+        }
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.STRING, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (!valid) {
+                String error = "Cannot convert to byte: " + value;
+
+                expectSqlException(() -> rs.getByte(1), error);
+                expectSqlException(() -> rs.getByte("C"), error);
+
+                expectSqlException(() -> rs.getObject(1, Byte.class), error);
+                expectSqlException(() -> rs.getObject("C", Byte.class), error);
+            } else {
+                byte expected = Byte.parseByte(result);
+                assertEquals(expected, rs.getByte(1));
+                assertEquals(expected, rs.getByte("C"));
+
+                assertEquals(expected, rs.getObject(1, Byte.class));
+                assertEquals(expected, rs.getObject("C", Byte.class));
+            }
+        }
+    }
+
+    @ParameterizedTest
+    @ValueSource(booleans = {true, false})
+    public void getByteFromBoolean(boolean value) throws SQLException {
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.BOOLEAN, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (value) {
+                assertEquals(1, rs.getByte(1));
+                assertEquals(1, rs.getByte("C"));
+            } else {
+                assertEquals(0, rs.getByte(1));
+                assertEquals(0, rs.getByte("C"));
+            }
+        }
+    }
+
+    @ParameterizedTest
+    @MethodSource("getByteNumbers")
+    public void getByteFromNumber(boolean valid, Number value) throws 
SQLException {
+        ColumnType columnType = columnTypefromObject(value);
+
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
columnType, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (valid) {
+                assertEquals(value.byteValue(), rs.getByte(1));
+                assertEquals(value.byteValue(), rs.getByte("C"));
+
+                assertEquals(value.byteValue(), rs.getObject(1, Byte.class));
+                assertEquals(value.byteValue(), rs.getObject("C", Byte.class));
+            } else {
+                expectSqlConversionError(() -> rs.getByte(1), "byte");
+                expectSqlConversionError(() -> rs.getByte("C"), "byte");
+
+                expectSqlConversionError(() -> rs.getObject(1, Byte.class), 
"byte");
+                expectSqlConversionError(() -> rs.getObject("C", Byte.class), 
"byte");
+            }
+        }
+    }
+
+    private static Stream<Arguments> getByteNumbers() {
+        return Stream.of(
+                Arguments.of(true, Byte.MAX_VALUE),
+                Arguments.of(true, Byte.MIN_VALUE),
+
+                Arguments.of(true, (short) 42),
+                Arguments.of(false, (short) (Byte.MAX_VALUE + 1)),
+                Arguments.of(false, (short) (Byte.MIN_VALUE - 1)),
+
+                Arguments.of(true, 42),
+                Arguments.of(true, 42L),
+
+                Arguments.of(true, 42.0f),
+                Arguments.of(false, (float) (Byte.MAX_VALUE + 1L)),
+                Arguments.of(false, (float) (Byte.MIN_VALUE - 1L)),
+                Arguments.of(false, Float.NaN),
+                Arguments.of(false, Float.NEGATIVE_INFINITY),
+                Arguments.of(false, Float.POSITIVE_INFINITY),
+
+                Arguments.of(true, 42.0d),
+                Arguments.of(false, (double) (Byte.MAX_VALUE + 1L)),
+                Arguments.of(false, (double) (Byte.MIN_VALUE - 1L)),
+                Arguments.of(false, Double.NaN),
+                Arguments.of(false, Double.NEGATIVE_INFINITY),
+                Arguments.of(false, Double.POSITIVE_INFINITY),
+
+                Arguments.of(true, BigDecimal.valueOf(42.1)),
+                Arguments.of(true, BigDecimal.valueOf(42.9)),
+                Arguments.of(true, BigDecimal.valueOf(Byte.MAX_VALUE)),
+                Arguments.of(true, BigDecimal.valueOf(Byte.MIN_VALUE)),
+                Arguments.of(false, BigDecimal.valueOf((short) (Byte.MAX_VALUE 
+ 1))),
+                Arguments.of(false, BigDecimal.valueOf((short) (Byte.MIN_VALUE 
- 1)))
+        );
+    }
+
+    @ParameterizedTest
+    @ValueSource(shorts = {-42, -1, 0, 1, 42})
+    public void getShort(short value) throws SQLException {
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.INT16, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            BigDecimal decimalVal = BigDecimal.valueOf(value);
+            BigDecimal decimalScaledVal = 
BigDecimal.valueOf(value).setScale(2, RoundingMode.HALF_UP);
+            String strVal = String.valueOf(value);
+
+            if (value == 0) {
+                assertFalse(rs.getBoolean(1));
+                assertFalse(rs.getBoolean("C"));
+            } else {
+                assertTrue(rs.getBoolean(1));
+                assertTrue(rs.getBoolean("C"));
+            }
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((byte) value, rs.getByte(1));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((byte) value, rs.getByte("C"));
+
+            assertEquals(value, rs.getShort(1));
+            assertEquals(value, rs.getShort("C"));
+
+            assertEquals(value, rs.getInt(1));
+            assertEquals(value, rs.getInt("C"));
+
+            assertEquals(value, rs.getLong(1));
+            assertEquals(value, rs.getLong("C"));
+
+            assertEquals(value, rs.getFloat(1));
+            assertEquals(value, rs.getFloat("C"));
+
+            assertEquals(value, rs.getDouble(1));
+            assertEquals(value, rs.getDouble("C"));
+
+            assertEquals(decimalVal, rs.getBigDecimal(1));
+            assertEquals(decimalVal, rs.getBigDecimal("C"));
+
+            //noinspection deprecation
+            assertEquals(decimalScaledVal, rs.getBigDecimal(1, 2));
+            //noinspection deprecation
+            assertEquals(decimalScaledVal, rs.getBigDecimal("C", 2));
+
+            assertEquals(strVal, rs.getString(1));
+            assertEquals(strVal, rs.getString("C"));
+
+            assertEquals(strVal, rs.getNString(1));
+            assertEquals(strVal, rs.getNString("C"));
+
+            // getObject
+
+            assertEquals(value, rs.getObject(1));
+            assertEquals(value, rs.getObject("C"));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Byte.valueOf((byte) value), rs.getObject(1, 
Byte.class));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Byte.valueOf((byte) value), rs.getObject("C", 
Byte.class));
+
+            assertEquals(Short.valueOf(value), rs.getObject(1, Short.class));
+            assertEquals(Short.valueOf(value), rs.getObject("C", Short.class));
+
+            assertEquals(Integer.valueOf(value), rs.getObject(1, 
Integer.class));
+            assertEquals(Integer.valueOf(value), rs.getObject("C", 
Integer.class));
+
+            assertEquals(Long.valueOf(value), rs.getObject(1, Long.class));
+            assertEquals(Long.valueOf(value), rs.getObject("C", Long.class));
+
+            assertEquals(Float.valueOf(value), rs.getObject(1, Float.class));
+            assertEquals(Float.valueOf(value), rs.getObject("C", Float.class));
+
+            assertEquals(Double.valueOf(value), rs.getObject(1, Double.class));
+            assertEquals(Double.valueOf(value), rs.getObject("C", 
Double.class));
+
+            assertEquals(decimalVal, rs.getObject(1, BigDecimal.class));
+            assertEquals(decimalVal, rs.getObject("C", BigDecimal.class));
+
+            assertEquals(strVal, rs.getObject(1, String.class));
+            assertEquals(strVal, rs.getObject("C", String.class));
+
+            expectSqlConversionError(() -> rs.getObject(1, UUID.class), 
"java.util.UUID");
+            expectSqlConversionError(() -> rs.getObject("C", UUID.class), 
"java.util.UUID");
+        }
+    }
+
+    @ParameterizedTest
+    @CsvSource({
+            "true, -32768, -32768",
+            "true, 32767, 32767",
+            "true, -42, -42",
+            "true, 42, 42",
+            "false, -32769, ",
+            "false, 32768, ",
+            "false, xyz, ",
+            "false,, "
+    })
+    public void getShortFromString(boolean valid, String value, String result) 
throws SQLException {
+        if (value == null) {
+            value = "";
+        }
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.STRING, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (!valid) {
+                String error = "Cannot convert to short: " + value;
+
+                expectSqlException(() -> rs.getShort(1), error);
+                expectSqlException(() -> rs.getShort("C"), error);
+
+                expectSqlException(() -> rs.getObject(1, Short.class), error);
+                expectSqlException(() -> rs.getObject("C", Short.class), 
error);
+            } else {
+                short expected = Short.parseShort(result);
+
+                assertEquals(expected, rs.getShort(1));
+                assertEquals(expected, rs.getShort("C"));
+
+                assertEquals(expected, rs.getObject(1, Short.class));
+                assertEquals(expected, rs.getObject("C", Short.class));
+            }
+        }
+    }
+
+    @ParameterizedTest
+    @ValueSource(booleans = {true, false})
+    public void getShortFromBoolean(boolean value) throws SQLException {
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.BOOLEAN, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (value) {
+                assertEquals(1, rs.getShort(1));
+                assertEquals(1, rs.getShort("C"));
+            } else {
+                assertEquals(0, rs.getShort(1));
+                assertEquals(0, rs.getShort("C"));
+            }
+        }
+    }
+
+    @ParameterizedTest
+    @MethodSource("getShortNumbers")
+    public void getShortFromNumber(boolean valid, Number value) throws 
SQLException {
+        ColumnType columnType = columnTypefromObject(value);
+
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
columnType, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (valid) {
+                assertEquals(value.shortValue(), rs.getShort(1));
+                assertEquals(value.shortValue(), rs.getShort("C"));
+
+                assertEquals(value.shortValue(), rs.getObject(1, Short.class));
+                assertEquals(value.shortValue(), rs.getObject("C", 
Short.class));
+            } else {
+                expectSqlConversionError(() -> rs.getShort(1), "short");
+                expectSqlConversionError(() -> rs.getShort("C"), "short");
+
+                expectSqlConversionError(() -> rs.getObject(1, Short.class), 
"short");
+                expectSqlConversionError(() -> rs.getObject("C", Short.class), 
"short");
+            }
+        }
+    }
+
+    private static Stream<Arguments> getShortNumbers() {
+        return Stream.of(
+                Arguments.of(true, (byte) 42),
+
+                Arguments.of(true, Short.MAX_VALUE),
+                Arguments.of(true, Short.MIN_VALUE),
+
+                Arguments.of(false, Short.MAX_VALUE + 1),
+                Arguments.of(false, Short.MIN_VALUE - 1),
+
+                Arguments.of(true, 42),
+                Arguments.of(true, 42L),
+
+                Arguments.of(true, 42.0f),
+                Arguments.of(false, (float) (Short.MAX_VALUE + 1L)),
+                Arguments.of(false, (float) (Short.MIN_VALUE - 1L)),
+                Arguments.of(false, Float.NaN),
+                Arguments.of(false, Float.NEGATIVE_INFINITY),
+                Arguments.of(false, Float.POSITIVE_INFINITY),
+
+                Arguments.of(true, 42.0d),
+                Arguments.of(false, (double) (Short.MAX_VALUE + 1L)),
+                Arguments.of(false, (double) (Short.MIN_VALUE - 1L)),
+                Arguments.of(false, Double.NaN),
+                Arguments.of(false, Double.NEGATIVE_INFINITY),
+                Arguments.of(false, Double.POSITIVE_INFINITY),
+
+                Arguments.of(true, BigDecimal.valueOf(42.1)),
+                Arguments.of(true, BigDecimal.valueOf(42.9)),
+                Arguments.of(true, BigDecimal.valueOf(Short.MAX_VALUE)),
+                Arguments.of(true, BigDecimal.valueOf(Short.MIN_VALUE)),
+                Arguments.of(false, BigDecimal.valueOf(Short.MAX_VALUE + 1)),
+                Arguments.of(false, BigDecimal.valueOf(Short.MIN_VALUE - 1))
+        );
+    }
+
+    @ParameterizedTest
+    @ValueSource(ints = {-42, -1, 0, 1, 42})
+    public void getInt(int value) throws SQLException {
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.INT32, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            BigDecimal decimalVal = BigDecimal.valueOf(value);
+            BigDecimal decimalScaledVal = 
BigDecimal.valueOf(value).setScale(2, RoundingMode.HALF_UP);
+            String strVal = String.valueOf(value);
+
+            if (value == 0) {
+                assertFalse(rs.getBoolean(1));
+                assertFalse(rs.getBoolean("C"));
+            } else {
+                assertTrue(rs.getBoolean(1));
+                assertTrue(rs.getBoolean("C"));
+            }
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((byte) value, rs.getByte(1));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((byte) value, rs.getByte("C"));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((short) value, rs.getShort(1));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((short) value, rs.getShort("C"));
+
+            assertEquals(value, rs.getInt(1));
+            assertEquals(value, rs.getInt("C"));
+
+            assertEquals(value, rs.getLong(1));
+            assertEquals(value, rs.getLong("C"));
+
+            assertEquals(value, rs.getFloat(1));
+            assertEquals(value, rs.getFloat("C"));
+
+            assertEquals(value, rs.getDouble(1));
+            assertEquals(value, rs.getDouble("C"));
+
+            assertEquals(decimalVal, rs.getBigDecimal(1));
+            assertEquals(decimalVal, rs.getBigDecimal("C"));
+
+            //noinspection deprecation
+            assertEquals(decimalScaledVal, rs.getBigDecimal(1, 2));
+            //noinspection deprecation
+            assertEquals(decimalScaledVal, rs.getBigDecimal("C", 2));
+
+            assertEquals(strVal, rs.getString(1));
+            assertEquals(strVal, rs.getString("C"));
+
+            assertEquals(strVal, rs.getNString(1));
+            assertEquals(strVal, rs.getNString("C"));
+
+            // getObject
+
+            assertEquals(value, rs.getObject(1));
+            assertEquals(value, rs.getObject("C"));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Byte.valueOf((byte) value), rs.getObject(1, 
Byte.class));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Byte.valueOf((byte) value), rs.getObject("C", 
Byte.class));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Short.valueOf((short) value), rs.getObject(1, 
Short.class));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Short.valueOf((short) value), rs.getObject("C", 
Short.class));
+
+            assertEquals(Integer.valueOf(value), rs.getObject(1, 
Integer.class));
+            assertEquals(Integer.valueOf(value), rs.getObject("C", 
Integer.class));
+
+            assertEquals(Long.valueOf(value), rs.getObject(1, Long.class));
+            assertEquals(Long.valueOf(value), rs.getObject("C", Long.class));
+
+            assertEquals(Float.valueOf(value), rs.getObject(1, Float.class));
+            assertEquals(Float.valueOf(value), rs.getObject("C", Float.class));
+
+            assertEquals(Double.valueOf(value), rs.getObject(1, Double.class));
+            assertEquals(Double.valueOf(value), rs.getObject("C", 
Double.class));
+
+            assertEquals(decimalVal, rs.getObject(1, BigDecimal.class));
+            assertEquals(decimalVal, rs.getObject("C", BigDecimal.class));
+
+            assertEquals(strVal, rs.getObject(1, String.class));
+            assertEquals(strVal, rs.getObject("C", String.class));
+
+            expectSqlConversionError(() -> rs.getObject(1, UUID.class), 
"java.util.UUID");
+            expectSqlConversionError(() -> rs.getObject("C", UUID.class), 
"java.util.UUID");
+        }
+    }
+
+    @ParameterizedTest
+    @CsvSource({
+            "true, -2147483648, -2147483648",
+            "true, 2147483647, 2147483647",
+            "true, -42, -42",
+            "true, 42, 42",
+            "false, -2147483649, ",
+            "false, 2147483648, ",
+            "false, xyz, ",
+            "false,, "
+    })
+    public void getIntFromString(boolean valid, String value, String result) 
throws SQLException {
+        if (value == null) {
+            value = "";
+        }
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.STRING, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (!valid) {
+                String error = "Cannot convert to int: " + value;
+
+                expectSqlException(() -> rs.getInt(1), error);
+                expectSqlException(() -> rs.getInt("C"), error);
+
+                expectSqlException(() -> rs.getObject(1, Integer.class), 
error);
+                expectSqlException(() -> rs.getObject("C", Integer.class), 
error);
+            } else {
+                int expected = Integer.parseInt(result);
+
+                assertEquals(expected, rs.getInt(1));
+                assertEquals(expected, rs.getInt("C"));
+
+                assertEquals(expected, rs.getObject(1, Integer.class));
+                assertEquals(expected, rs.getObject("C", Integer.class));
+            }
+        }
+    }
+
+    @ParameterizedTest
+    @ValueSource(booleans = {true, false})
+    public void getIntFromBoolean(boolean value) throws SQLException {
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.BOOLEAN, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (value) {
+                assertEquals(1, rs.getInt(1));
+                assertEquals(1, rs.getInt("C"));
+            } else {
+                assertEquals(0, rs.getInt(1));
+                assertEquals(0, rs.getInt("C"));
+            }
+        }
+    }
+
+    @ParameterizedTest
+    @MethodSource("getIntNumbers")
+    public void getIntFromNumber(boolean valid, Number value) throws 
SQLException {
+        ColumnType columnType = columnTypefromObject(value);
+
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
columnType, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (valid) {
+                assertEquals(value.intValue(), rs.getInt(1));
+                assertEquals(value.intValue(), rs.getInt("C"));
+
+                assertEquals(value.intValue(), rs.getObject(1, Integer.class));
+                assertEquals(value.intValue(), rs.getObject("C", 
Integer.class));
+            } else {
+                expectSqlConversionError(() -> rs.getInt(1), "int");
+                expectSqlConversionError(() -> rs.getInt("C"), "int");
+
+                expectSqlConversionError(() -> rs.getObject(1, Integer.class), 
"int");
+                expectSqlConversionError(() -> rs.getObject("C", 
Integer.class), "int");
+            }
+        }
+    }
+
+    private static Stream<Arguments> getIntNumbers() {
+        return Stream.of(
+                Arguments.of(true, (byte) 42),
+                Arguments.of(true, (short) 42),
+
+                Arguments.of(true, Integer.MAX_VALUE),
+                Arguments.of(true, Integer.MIN_VALUE),
+
+                Arguments.of(true, 42L),
+                Arguments.of(false, Integer.MAX_VALUE + 1L),
+                Arguments.of(false, Integer.MIN_VALUE - 1L),
+
+                Arguments.of(true, 42.0f),
+                Arguments.of(false, Float.NaN),
+                Arguments.of(false, Float.NEGATIVE_INFINITY),
+                Arguments.of(false, Float.POSITIVE_INFINITY),
+
+                Arguments.of(true, 42.0d),
+                Arguments.of(false, (double) (Integer.MAX_VALUE + 1L)),
+                Arguments.of(false, (double) (Integer.MIN_VALUE - 1L)),
+                Arguments.of(false, Double.NaN),
+                Arguments.of(false, Double.NEGATIVE_INFINITY),
+                Arguments.of(false, Double.POSITIVE_INFINITY),
+
+                Arguments.of(true, BigDecimal.valueOf(42)),
+                Arguments.of(true, BigDecimal.valueOf(42.1)),
+                Arguments.of(true, BigDecimal.valueOf(42.9)),
+                Arguments.of(true, BigDecimal.valueOf(Integer.MAX_VALUE)),
+                Arguments.of(true, BigDecimal.valueOf(Integer.MIN_VALUE)),
+                Arguments.of(false, BigDecimal.valueOf(Integer.MAX_VALUE + 
1L)),
+                Arguments.of(false, BigDecimal.valueOf(Integer.MIN_VALUE - 1L))
+        );
+    }
+
+    @ParameterizedTest
+    @ValueSource(longs = {-42, -1, 0, 1, 42})
+    public void getLong(long value) throws SQLException {
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.INT64, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            BigDecimal decimalVal = BigDecimal.valueOf(value);
+            BigDecimal decimalScaledVal = 
BigDecimal.valueOf(value).setScale(2, RoundingMode.HALF_UP);
+            String strVal = String.valueOf(value);
+
+            if (value == 0) {
+                assertFalse(rs.getBoolean(1));
+                assertFalse(rs.getBoolean("C"));
+            } else {
+                assertTrue(rs.getBoolean(1));
+                assertTrue(rs.getBoolean("C"));
+            }
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((byte) value, rs.getByte(1));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((byte) value, rs.getByte("C"));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((short) value, rs.getShort(1));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((short) value, rs.getShort("C"));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((int) value, rs.getInt(1));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((int) value, rs.getInt("C"));
+
+            assertEquals(value, rs.getLong(1));
+            assertEquals(value, rs.getLong("C"));
+
+            assertEquals(value, rs.getFloat(1));
+            assertEquals(value, rs.getFloat("C"));
+
+            assertEquals(value, rs.getDouble(1));
+            assertEquals(value, rs.getDouble("C"));
+
+            assertEquals(decimalVal, rs.getBigDecimal(1));
+            assertEquals(decimalVal, rs.getBigDecimal("C"));
+
+            //noinspection deprecation
+            assertEquals(decimalScaledVal, rs.getBigDecimal(1, 2));
+            //noinspection deprecation
+            assertEquals(decimalScaledVal, rs.getBigDecimal("C", 2));
+
+            assertEquals(strVal, rs.getString(1));
+            assertEquals(strVal, rs.getString("C"));
+
+            assertEquals(strVal, rs.getNString(1));
+            assertEquals(strVal, rs.getNString("C"));
+
+            // getObject
+
+            assertEquals(value, rs.getObject(1));
+            assertEquals(value, rs.getObject("C"));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Byte.valueOf((byte) value), rs.getObject(1, 
Byte.class));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Byte.valueOf((byte) value), rs.getObject("C", 
Byte.class));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Short.valueOf((short) value), rs.getObject(1, 
Short.class));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Short.valueOf((short) value), rs.getObject("C", 
Short.class));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Integer.valueOf((int) value), rs.getObject(1, 
Integer.class));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Integer.valueOf((int) value), rs.getObject("C", 
Integer.class));
+
+            assertEquals(Long.valueOf(value), rs.getObject(1, Long.class));
+            assertEquals(Long.valueOf(value), rs.getObject("C", Long.class));
+
+            assertEquals(Float.valueOf(value), rs.getObject(1, Float.class));
+            assertEquals(Float.valueOf(value), rs.getObject("C", Float.class));
+
+            assertEquals(Double.valueOf(value), rs.getObject(1, Double.class));
+            assertEquals(Double.valueOf(value), rs.getObject("C", 
Double.class));
+
+            assertEquals(decimalVal, rs.getObject(1, BigDecimal.class));
+            assertEquals(decimalVal, rs.getObject("C", BigDecimal.class));
+
+            assertEquals(strVal, rs.getObject(1, String.class));
+            assertEquals(strVal, rs.getObject("C", String.class));
+
+            expectSqlConversionError(() -> rs.getObject(1, UUID.class), 
"java.util.UUID");
+            expectSqlConversionError(() -> rs.getObject("C", UUID.class), 
"java.util.UUID");
+        }
+    }
+
+    @ParameterizedTest
+    @CsvSource({
+            "true, -9223372036854775808, -9223372036854775808",
+            "true, 9223372036854775807, 9223372036854775807",
+            "true, -42, -42",
+            "true, 42, 42",
+            "false, -9223372036854775809, ",
+            "false, 9223372036854775808, ",
+            "false, xyz, ",
+            "false,, "
+    })
+    public void getLongFromString(boolean valid, String value, String result) 
throws SQLException {
+        if (value == null) {
+            value = "";
+        }
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.STRING, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (!valid) {
+                String error = "Cannot convert to long: " + value;
+
+                expectSqlException(() -> rs.getLong(1), error);
+                expectSqlException(() -> rs.getLong("C"), error);
+
+                expectSqlException(() -> rs.getObject(1, Long.class), error);
+                expectSqlException(() -> rs.getObject("C", Long.class), error);
+            } else {
+                long expected = Long.parseLong(result);
+
+                assertEquals(expected, rs.getLong(1));
+                assertEquals(expected, rs.getLong("C"));
+
+                assertEquals(expected, rs.getObject(1, Long.class));
+                assertEquals(expected, rs.getObject("C", Long.class));
+            }
+        }
+    }
+
+    @ParameterizedTest
+    @ValueSource(booleans = {true, false})
+    public void getLongFromBoolean(boolean value) throws SQLException {
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.BOOLEAN, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (value) {
+                assertEquals(1, rs.getLong(1));
+                assertEquals(1, rs.getLong("C"));
+            } else {
+                assertEquals(0, rs.getLong(1));
+                assertEquals(0, rs.getLong("C"));
+            }
+        }
+    }
+
+    @ParameterizedTest
+    @MethodSource("getLongNumbers")
+    public void getLongFromNumber(boolean valid, Number value) throws 
SQLException {
+        ColumnType columnType = columnTypefromObject(value);
+
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
columnType, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (valid) {
+                assertEquals(value.longValue(), rs.getLong(1));
+                assertEquals(value.longValue(), rs.getLong("C"));
+
+                assertEquals(value.longValue(), rs.getObject(1, Long.class));
+                assertEquals(value.longValue(), rs.getObject("C", Long.class));
+            } else {
+                expectSqlConversionError(() -> rs.getLong(1), "long");
+                expectSqlConversionError(() -> rs.getLong("C"), "long");
+
+                expectSqlConversionError(() -> rs.getObject(1, Long.class), 
"long");
+                expectSqlConversionError(() -> rs.getObject("C", Long.class), 
"long");
+            }
+        }
+    }
+
+    private static Stream<Arguments> getLongNumbers() {
+        return Stream.of(
+                Arguments.of(true, (byte) 42),
+                Arguments.of(true, (short) 42),
+
+                Arguments.of(true, 42),
+                Arguments.of(true, Long.MAX_VALUE),
+                Arguments.of(true, Long.MIN_VALUE),
+
+                Arguments.of(true, 42.0f),
+                Arguments.of(true, (float) (Long.MAX_VALUE)),
+                Arguments.of(true, (float) (Long.MIN_VALUE)),
+                Arguments.of(false, Float.NaN),
+                Arguments.of(false, Float.NEGATIVE_INFINITY),
+                Arguments.of(false, Float.POSITIVE_INFINITY),
+
+                Arguments.of(true, 42.0d),
+                Arguments.of(true, (double) (Long.MAX_VALUE)),
+                Arguments.of(true, (double) (Long.MIN_VALUE)),
+                Arguments.of(false, Double.NaN),
+                Arguments.of(false, Double.NEGATIVE_INFINITY),
+                Arguments.of(false, Double.POSITIVE_INFINITY),
+
+                Arguments.of(true, BigDecimal.valueOf(42)),
+                Arguments.of(true, BigDecimal.valueOf(42.1)),
+                Arguments.of(true, BigDecimal.valueOf(42.9)),
+                Arguments.of(true, BigDecimal.valueOf(Long.MAX_VALUE)),
+                Arguments.of(true, BigDecimal.valueOf(Long.MIN_VALUE)),
+                Arguments.of(false, 
BigDecimal.valueOf(Long.MAX_VALUE).add(BigDecimal.ONE)),
+                Arguments.of(false, 
BigDecimal.valueOf(Long.MIN_VALUE).add(BigDecimal.ONE.negate()))
+        );
+    }
+
+    @ParameterizedTest
+    @ValueSource(floats = {-42.3f, 42.9f})
+    public void getFloat(float value) throws SQLException {
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.FLOAT, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            BigDecimal decimalVal = new BigDecimal(value);
+            BigDecimal decimalScaledVal = new BigDecimal(value).setScale(2, 
RoundingMode.HALF_UP);
+            String strVal = String.valueOf(value);
+
+            expectSqlConversionError(() -> rs.getBoolean(1), "boolean");
+            expectSqlConversionError(() -> rs.getBoolean("C"), "boolean");
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((byte) value, rs.getByte(1));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((byte) value, rs.getByte("C"));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((short) value, rs.getShort(1));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((short) value, rs.getShort("C"));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((int) value, rs.getInt(1));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((int) value, rs.getInt("C"));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((long) value, rs.getLong(1));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((long) value, rs.getLong("C"));
+
+            assertEquals(value, rs.getFloat(1));
+            assertEquals(value, rs.getFloat("C"));
+
+            assertEquals(value, rs.getDouble(1));
+            assertEquals(value, rs.getDouble("C"));
+
+            assertEquals(decimalVal, rs.getBigDecimal(1));
+            assertEquals(decimalVal, rs.getBigDecimal("C"));
+
+            assertEquals(decimalScaledVal, rs.getBigDecimal(1, 2));
+            assertEquals(decimalScaledVal, rs.getBigDecimal("C", 2));
+
+            assertEquals(strVal, rs.getString(1));
+            assertEquals(strVal, rs.getString("C"));
+
+            assertEquals(strVal, rs.getNString(1));
+            assertEquals(strVal, rs.getNString("C"));
+
+            // getObject
+
+            assertEquals(value, rs.getObject(1));
+            assertEquals(value, rs.getObject("C"));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Byte.valueOf((byte) value), rs.getObject(1, 
Byte.class));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Byte.valueOf((byte) value), rs.getObject("C", 
Byte.class));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Short.valueOf((short) value), rs.getObject(1, 
Short.class));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Short.valueOf((short) value), rs.getObject("C", 
Short.class));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Integer.valueOf((int) value), rs.getObject(1, 
Integer.class));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Integer.valueOf((int) value), rs.getObject("C", 
Integer.class));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Long.valueOf((long) value), rs.getObject(1, 
Long.class));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Long.valueOf((long) value), rs.getObject("C", 
Long.class));
+
+            assertEquals(Float.valueOf(value), rs.getObject(1, Float.class));
+            assertEquals(Float.valueOf(value), rs.getObject("C", Float.class));
+
+            assertEquals(Double.valueOf(value), rs.getObject(1, Double.class));
+            assertEquals(Double.valueOf(value), rs.getObject("C", 
Double.class));
+
+            assertEquals(decimalVal, rs.getObject(1, BigDecimal.class));
+            assertEquals(decimalVal, rs.getObject("C", BigDecimal.class));
+
+            assertEquals(strVal, rs.getObject(1, String.class));
+            assertEquals(strVal, rs.getObject("C", String.class));
+
+            expectSqlConversionError(() -> rs.getObject(1, UUID.class), 
"java.util.UUID");
+            expectSqlConversionError(() -> rs.getObject("C", UUID.class), 
"java.util.UUID");
+        }
+    }
+
+    @ParameterizedTest
+    @CsvSource({
+            "true, -9223372036854775808, -9223372036854775808",
+            "true, 9223372036854775807, 9223372036854775807",
+            "true, -42.43, -42.43",
+            "true, 42.43, 42.43",
+            "false, xyz, ",
+            "false,, "
+    })
+    public void getFloatFromString(boolean valid, String value, String result) 
throws SQLException {
+        if (value == null) {
+            value = "";
+        }
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.STRING, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (!valid) {
+                String error = "Cannot convert to float: " + value;
+
+                expectSqlException(() -> rs.getFloat(1), error);
+                expectSqlException(() -> rs.getFloat("C"), error);
+
+                expectSqlException(() -> rs.getObject(1, Float.class), error);
+                expectSqlException(() -> rs.getObject("C", Float.class), 
error);
+            } else {
+                float expected = Float.parseFloat(result);
+
+                assertEquals(expected, rs.getFloat(1));
+                assertEquals(expected, rs.getFloat("C"));
+
+                assertEquals(expected, rs.getObject(1, Float.class));
+                assertEquals(expected, rs.getObject("C", Float.class));
+            }
+        }
+    }
+
+    @ParameterizedTest
+    @MethodSource("getFloatNumbers")
+    public void getFloatFromNumber(boolean valid, Number value) throws 
SQLException {
+        ColumnType columnType = columnTypefromObject(value);
+
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
columnType, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (valid) {
+                assertEquals(value.floatValue(), rs.getFloat(1));
+                assertEquals(value.floatValue(), rs.getFloat("C"));
+
+                assertEquals(value.floatValue(), rs.getObject(1, Float.class));
+                assertEquals(value.floatValue(), rs.getObject("C", 
Float.class));
+            } else {
+                expectSqlConversionError(() -> rs.getFloat(1), "float");
+                expectSqlConversionError(() -> rs.getFloat("C"), "float");
+
+                expectSqlConversionError(() -> rs.getObject(1, Float.class), 
"float");
+                expectSqlConversionError(() -> rs.getObject("C", Float.class), 
"float");
+            }
+        }
+    }
+
+    private static Stream<Arguments> getFloatNumbers() {
+        return Stream.of(
+                Arguments.of(true, (byte) 42),
+                Arguments.of(true, (short) 42),
+
+                Arguments.of(true, 42),
+                Arguments.of(true, Long.MAX_VALUE),
+                Arguments.of(true, Long.MIN_VALUE),
+
+                Arguments.of(true, 42.0f),
+                Arguments.of(true, (float) (Long.MAX_VALUE)),
+                Arguments.of(true, (float) (Long.MIN_VALUE)),
+                Arguments.of(true, Float.NaN),
+                Arguments.of(true, Float.NEGATIVE_INFINITY),
+                Arguments.of(true, Float.POSITIVE_INFINITY),
+
+                Arguments.of(true, 42.0d),
+                Arguments.of(true, (double) (Long.MAX_VALUE)),
+                Arguments.of(true, (double) (Long.MIN_VALUE)),
+                Arguments.of(true, Double.NaN),
+                Arguments.of(false, Double.NEGATIVE_INFINITY),
+                Arguments.of(false, Double.POSITIVE_INFINITY),
+
+                Arguments.of(true, BigDecimal.valueOf(42)),
+                Arguments.of(true, BigDecimal.valueOf(Float.MAX_VALUE)),
+                Arguments.of(true, BigDecimal.valueOf(-Float.MAX_VALUE)),
+                Arguments.of(false, BigDecimal.valueOf(Double.MAX_VALUE)),
+                Arguments.of(false, BigDecimal.valueOf(-Double.MAX_VALUE))
+        );
+    }
+
+    @ParameterizedTest
+    @ValueSource(doubles = {-42.3d, 0, 42.9d})
+    public void getDouble(double value) throws SQLException {
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.DOUBLE, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            BigDecimal decimalVal = new BigDecimal(value);
+            BigDecimal decimalScaledVal = new BigDecimal(value).setScale(2, 
RoundingMode.HALF_UP);
+            String strVal = String.valueOf(value);
+
+            expectSqlConversionError(() -> rs.getBoolean(1), "boolean");
+            expectSqlConversionError(() -> rs.getBoolean("C"), "boolean");
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((byte) value, rs.getByte(1));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((byte) value, rs.getByte("C"));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((short) value, rs.getShort(1));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((short) value, rs.getShort("C"));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((int) value, rs.getInt(1));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((int) value, rs.getInt("C"));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((long) value, rs.getLong(1));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals((long) value, rs.getLong("C"));
+
+            assertEquals((float) value, rs.getFloat(1));
+            assertEquals((float) value, rs.getFloat("C"));
+
+            assertEquals(value, rs.getDouble(1));
+            assertEquals(value, rs.getDouble("C"));
+
+            assertEquals(decimalVal, rs.getBigDecimal(1));
+            assertEquals(decimalVal, rs.getBigDecimal("C"));
+
+            //noinspection deprecation
+            assertEquals(decimalScaledVal, rs.getBigDecimal(1, 2));
+            //noinspection deprecation
+            assertEquals(decimalScaledVal, rs.getBigDecimal("C", 2));
+
+            assertEquals(strVal, rs.getString(1));
+            assertEquals(strVal, rs.getString("C"));
+
+            assertEquals(strVal, rs.getNString(1));
+            assertEquals(strVal, rs.getNString("C"));
+
+            // getObject
+
+            assertEquals(value, rs.getObject(1));
+            assertEquals(value, rs.getObject("C"));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Byte.valueOf((byte) value), rs.getObject(1, 
Byte.class));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Byte.valueOf((byte) value), rs.getObject("C", 
Byte.class));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Short.valueOf((short) value), rs.getObject(1, 
Short.class));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Short.valueOf((short) value), rs.getObject("C", 
Short.class));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Integer.valueOf((int) value), rs.getObject(1, 
Integer.class));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Integer.valueOf((int) value), rs.getObject("C", 
Integer.class));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Long.valueOf((long) value), rs.getObject(1, 
Long.class));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Long.valueOf((long) value), rs.getObject("C", 
Long.class));
+
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Float.valueOf((float) value), rs.getObject(1, 
Float.class));
+            //noinspection NumericCastThatLosesPrecision
+            assertEquals(Float.valueOf((float) value), rs.getObject("C", 
Float.class));
+
+            assertEquals(Double.valueOf(value), rs.getObject(1, Double.class));
+            assertEquals(Double.valueOf(value), rs.getObject("C", 
Double.class));
+
+            assertEquals(decimalVal, rs.getObject(1, BigDecimal.class));
+            assertEquals(decimalVal, rs.getObject("C", BigDecimal.class));
+
+            assertEquals(strVal, rs.getObject(1, String.class));
+            assertEquals(strVal, rs.getObject("C", String.class));
+
+            expectSqlConversionError(() -> rs.getObject(1, UUID.class), 
"java.util.UUID");
+            expectSqlConversionError(() -> rs.getObject("C", UUID.class), 
"java.util.UUID");
+        }
+    }
+
+    @ParameterizedTest
+    @CsvSource({
+            "true, -9223372036854775808, -9223372036854775808",
+            "true, 9223372036854775807, 9223372036854775807",
+            "true, -42.43, -42.43",
+            "true, 42.43, 42.43",
+            "false, xyz, ",
+            "false,, "
+    })
+    public void getDoubleFromString(boolean valid, String value, String 
result) throws SQLException {
+        if (value == null) {
+            value = "";
+        }
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.STRING, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (!valid) {
+                String error = "Cannot convert to double: " + value;
+
+                expectSqlException(() -> rs.getDouble(1), error);
+                expectSqlException(() -> rs.getDouble("C"), error);
+
+                expectSqlException(() -> rs.getObject(1, Double.class), error);
+                expectSqlException(() -> rs.getObject("C", Double.class), 
error);
+            } else {
+                double expected = Double.parseDouble(result);
+
+                assertEquals(expected, rs.getDouble(1));
+                assertEquals(expected, rs.getDouble("C"));
+
+                assertEquals(expected, rs.getObject(1, Double.class));
+                assertEquals(expected, rs.getObject("C", Double.class));
+            }
+        }
+    }
+
+    @ParameterizedTest
+    @MethodSource("getDoubleNumbers")
+    public void getDoubleFromNumber(boolean valid, Number value) throws 
SQLException {
+        ColumnType columnType = columnTypefromObject(value);
+
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
columnType, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (valid) {
+                assertEquals(value.doubleValue(), rs.getDouble(1));
+                assertEquals(value.doubleValue(), rs.getDouble("C"));
+
+                assertEquals(value.doubleValue(), rs.getObject(1, 
Double.class));
+                assertEquals(value.doubleValue(), rs.getObject("C", 
Double.class));
+            } else {
+                expectSqlConversionError(() -> rs.getDouble(1), "double");
+                expectSqlConversionError(() -> rs.getDouble("C"), "double");
+
+                expectSqlConversionError(() -> rs.getObject(1, Double.class), 
"double");
+                expectSqlConversionError(() -> rs.getObject("C", 
Double.class), "double");
+            }
+        }
+    }
+
+    private static Stream<Arguments> getDoubleNumbers() {
+        return Stream.of(
+                Arguments.of(true, (byte) 42),
+                Arguments.of(true, (short) 42),
+
+                Arguments.of(true, 42),
+                Arguments.of(true, Long.MAX_VALUE),
+                Arguments.of(true, Long.MIN_VALUE),
+
+                Arguments.of(true, 42.0f),
+                Arguments.of(true, (float) (Long.MAX_VALUE)),
+                Arguments.of(true, (float) (Long.MIN_VALUE)),
+                Arguments.of(true, Float.NaN),
+                Arguments.of(true, Float.NEGATIVE_INFINITY),
+                Arguments.of(true, Float.POSITIVE_INFINITY),
+
+                Arguments.of(true, 42.0d),
+                Arguments.of(true, (double) (Long.MAX_VALUE)),
+                Arguments.of(true, (double) (Long.MIN_VALUE)),
+                Arguments.of(true, Double.NaN),
+                Arguments.of(true, Double.NEGATIVE_INFINITY),
+                Arguments.of(true, Double.POSITIVE_INFINITY),
+
+                Arguments.of(true, BigDecimal.valueOf(42.0d)),
+                Arguments.of(true, BigDecimal.valueOf(Double.MAX_VALUE)),
+                Arguments.of(true, BigDecimal.valueOf(-Double.MAX_VALUE)),
+                Arguments.of(false, BigDecimal.TEN.pow(512, 
MathContext.DECIMAL128)),
+                Arguments.of(false, BigDecimal.TEN.pow(512, 
MathContext.DECIMAL128).negate())
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("getBigDecimalValues")
+    public void getBigDecimal(BigDecimal value) throws SQLException {
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.DECIMAL, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            BigDecimal decimalScaledVal = value.setScale(2, 
RoundingMode.HALF_UP);
+            String strVal = String.valueOf(value);
+
+            expectSqlConversionError(() -> rs.getBoolean(1), "boolean");
+            expectSqlConversionError(() -> rs.getBoolean("C"), "boolean");
+
+            assertEquals(value.byteValue(), rs.getByte(1));
+            assertEquals(value.byteValue(), rs.getByte("C"));
+
+            assertEquals(value.shortValue(), rs.getShort(1));
+            assertEquals(value.shortValue(), rs.getShort("C"));
+
+            assertEquals(value.intValue(), rs.getInt(1));
+            assertEquals(value.intValue(), rs.getInt("C"));
+
+            assertEquals(value.longValue(), rs.getLong(1));
+            assertEquals(value.longValue(), rs.getLong("C"));
+
+            assertEquals(value.floatValue(), rs.getFloat(1));
+            assertEquals(value.floatValue(), rs.getFloat("C"));
+
+            assertEquals(value.doubleValue(), rs.getDouble(1));
+            assertEquals(value.doubleValue(), rs.getDouble("C"));
+
+            assertEquals(value, rs.getBigDecimal(1));
+            assertEquals(value, rs.getBigDecimal("C"));
+
+            //noinspection deprecation
+            assertEquals(decimalScaledVal, rs.getBigDecimal(1, 2));
+            //noinspection deprecation
+            assertEquals(decimalScaledVal, rs.getBigDecimal("C", 2));
+
+            assertEquals(strVal, rs.getString(1));
+            assertEquals(strVal, rs.getString("C"));
+
+            assertEquals(strVal, rs.getNString(1));
+            assertEquals(strVal, rs.getNString("C"));
+
+            // getObject
+
+            assertEquals(value, rs.getObject(1));
+            assertEquals(value, rs.getObject("C"));
+
+            assertEquals(Byte.valueOf(value.byteValue()), rs.getObject(1, 
Byte.class));
+            assertEquals(Byte.valueOf(value.byteValue()), rs.getObject("C", 
Byte.class));
+
+            assertEquals(Short.valueOf(value.shortValue()), rs.getObject(1, 
Short.class));
+            assertEquals(Short.valueOf(value.shortValue()), rs.getObject("C", 
Short.class));
+
+            assertEquals(Integer.valueOf(value.intValue()), rs.getObject(1, 
Integer.class));
+            assertEquals(Integer.valueOf(value.intValue()), rs.getObject("C", 
Integer.class));
+
+            assertEquals(Long.valueOf(value.longValue()), rs.getObject(1, 
Long.class));
+            assertEquals(Long.valueOf(value.longValue()), rs.getObject("C", 
Long.class));
+
+            assertEquals(Float.valueOf(value.floatValue()), rs.getObject(1, 
Float.class));
+            assertEquals(Float.valueOf(value.floatValue()), rs.getObject("C", 
Float.class));
+
+            assertEquals(Double.valueOf(value.doubleValue()), rs.getObject(1, 
Double.class));
+            assertEquals(Double.valueOf(value.doubleValue()), 
rs.getObject("C", Double.class));
+
+            assertEquals(value, rs.getObject(1, BigDecimal.class));
+            assertEquals(value, rs.getObject("C", BigDecimal.class));
+
+            assertEquals(strVal, rs.getObject(1, String.class));
+            assertEquals(strVal, rs.getObject("C", String.class));
+
+            expectSqlConversionError(() -> rs.getObject(1, UUID.class), 
"java.util.UUID");
+            expectSqlConversionError(() -> rs.getObject("C", UUID.class), 
"java.util.UUID");
+        }
+    }
+
+    private static Stream<BigDecimal> getBigDecimalValues() {
+        return Stream.of(
+                new BigDecimal("121.234").negate(),
+                BigDecimal.ONE.negate(),
+                BigDecimal.ZERO,
+                BigDecimal.ONE,
+                new BigDecimal("121.234")
+        );
+    }
+
+    @ParameterizedTest
+    @CsvSource({
+            "true, -9223372036854775808, -9223372036854775808",
+            "true, 9223372036854775807, 9223372036854775807",
+            "true, -42, -42",
+            "true, 42, 42",
+            "true, -9223372036854775809, -9223372036854775809",
+            "true, 9223372036854775808, 9223372036854775808",
+            "true, 10223372036854775808.34954375423432, 
10223372036854775808.34954375423432",
+            "true, -10223372036854775808.34954375423432, 
-10223372036854775808.34954375423432",
+            "false, xyz, ",
+            "false,, "
+    })
+    public void getBigDecimalFromString(boolean valid, String value, String 
result) throws SQLException {
+        if (value == null) {
+            value = "";
+        }
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.STRING, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (!valid) {
+                String error = "Cannot convert to BigDecimal: " + value;
+
+                expectSqlException(() -> rs.getBigDecimal(1), error);
+                expectSqlException(() -> rs.getBigDecimal("C"), error);
+            } else {
+                BigDecimal expected = new BigDecimal(result);
+
+                assertEquals(expected, rs.getBigDecimal(1));
+                assertEquals(expected, rs.getBigDecimal("C"));
+
+                assertEquals(expected, rs.getObject(1, BigDecimal.class));
+                assertEquals(expected, rs.getObject("C", BigDecimal.class));
+            }
+        }
+    }
+
+    @ParameterizedTest
+    @MethodSource("getBigDecimalNumbers")
+    public void getBigDecimalFromNumber(boolean valid, Number value) throws 
SQLException {
+        ColumnType columnType = columnTypefromObject(value);
+
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
columnType, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (valid) {
+                BigDecimal expected;
+                if (value instanceof BigDecimal) {
+                    expected = (BigDecimal) value;
+                } else if (value instanceof Float || value instanceof Double) {
+                    expected = new BigDecimal(value.doubleValue());
+                } else {
+                    expected = new BigDecimal(value.longValue());
+                }
+
+                assertEquals(expected, rs.getBigDecimal(1));
+                assertEquals(expected, rs.getBigDecimal("C"));
+
+                assertEquals(expected, rs.getObject(1, BigDecimal.class));
+                assertEquals(expected, rs.getObject("C", BigDecimal.class));
+            } else {
+                expectSqlConversionError(() -> rs.getBigDecimal(1), "double");
+                expectSqlConversionError(() -> rs.getBigDecimal("C"), 
"double");
+
+                expectSqlConversionError(() -> rs.getObject(1, 
BigDecimal.class), "double");
+                expectSqlConversionError(() -> rs.getObject("C", 
BigDecimal.class), "double");
+            }
+        }
+    }
+
+    private static Stream<Arguments> getBigDecimalNumbers() {
+        return Stream.of(
+                Arguments.of(true, (byte) 42),
+                Arguments.of(true, (short) 42),
+
+                Arguments.of(true, 42),
+                Arguments.of(true, Long.MAX_VALUE),
+                Arguments.of(true, Long.MIN_VALUE),
+
+                Arguments.of(true, 42.0f),
+                Arguments.of(true, Float.MAX_VALUE),
+                Arguments.of(true, -Float.MAX_VALUE),
+
+                Arguments.of(true, 42.0d),
+                Arguments.of(true, Double.MAX_VALUE),
+                Arguments.of(true, -Double.MAX_VALUE),
+
+                Arguments.of(true, BigDecimal.valueOf(42.0d)),
+                Arguments.of(true, BigDecimal.valueOf(42.123d)),
+                Arguments.of(true, BigDecimal.valueOf(45.9d)),
+                Arguments.of(true, BigDecimal.valueOf(Double.MAX_VALUE)),
+                Arguments.of(true, BigDecimal.valueOf(-Double.MAX_VALUE)),
+                Arguments.of(true, 
BigDecimal.valueOf(Double.MAX_VALUE).add(BigDecimal.TEN)),
+                Arguments.of(true, 
BigDecimal.valueOf(-Double.MAX_VALUE).add(BigDecimal.TEN.negate()))
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("getBigDecimalScaledValues")
+    public void getBigDecimalScaled(BigDecimal value, int scale) throws 
SQLException {
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.DECIMAL, value.precision(), scale, false), value)) {
+            assertTrue(rs.next());
+
+            BigDecimal decimalScaledVal = value.setScale(scale, 
RoundingMode.HALF_UP);
+            String strVal = String.valueOf(value);
+
+            expectSqlConversionError(() -> rs.getBoolean(1), "boolean");
+            expectSqlConversionError(() -> rs.getBoolean("C"), "boolean");
+
+            assertEquals(value.byteValue(), rs.getByte(1));
+            assertEquals(value.byteValue(), rs.getByte("C"));
+
+            assertEquals(value.shortValue(), rs.getShort(1));
+            assertEquals(value.shortValue(), rs.getShort("C"));
+
+            assertEquals(value.intValue(), rs.getInt(1));
+            assertEquals(value.intValue(), rs.getInt("C"));
+
+            assertEquals(value.longValue(), rs.getLong(1));
+            assertEquals(value.longValue(), rs.getLong("C"));
+
+            assertEquals(value.floatValue(), rs.getFloat(1));
+            assertEquals(value.floatValue(), rs.getFloat("C"));
+
+            assertEquals(value.doubleValue(), rs.getDouble(1));
+            assertEquals(value.doubleValue(), rs.getDouble("C"));
+
+            assertEquals(value, rs.getBigDecimal(1));
+            assertEquals(value, rs.getBigDecimal("C"));
+
+            //noinspection deprecation
+            assertEquals(decimalScaledVal, rs.getBigDecimal(1, scale));
+            //noinspection deprecation
+            assertEquals(decimalScaledVal, rs.getBigDecimal("C", scale));
+
+            assertEquals(strVal, rs.getString(1));
+            assertEquals(strVal, rs.getString("C"));
+
+            assertEquals(strVal, rs.getNString(1));
+            assertEquals(strVal, rs.getNString("C"));
+
+            // getObject
+
+            assertEquals(value, rs.getObject(1));
+            assertEquals(value, rs.getObject("C"));
+
+            assertEquals(Byte.valueOf(value.byteValue()), rs.getObject(1, 
Byte.class));
+            assertEquals(Byte.valueOf(value.byteValue()), rs.getObject("C", 
Byte.class));
+
+            assertEquals(Short.valueOf(value.shortValue()), rs.getObject(1, 
Short.class));
+            assertEquals(Short.valueOf(value.shortValue()), rs.getObject("C", 
Short.class));
+
+            assertEquals(Integer.valueOf(value.intValue()), rs.getObject(1, 
Integer.class));
+            assertEquals(Integer.valueOf(value.intValue()), rs.getObject("C", 
Integer.class));
+
+            assertEquals(Long.valueOf(value.longValue()), rs.getObject(1, 
Long.class));
+            assertEquals(Long.valueOf(value.longValue()), rs.getObject("C", 
Long.class));
+
+            assertEquals(Float.valueOf(value.floatValue()), rs.getObject(1, 
Float.class));
+            assertEquals(Float.valueOf(value.floatValue()), rs.getObject("C", 
Float.class));
+
+            assertEquals(Double.valueOf(value.doubleValue()), rs.getObject(1, 
Double.class));
+            assertEquals(Double.valueOf(value.doubleValue()), 
rs.getObject("C", Double.class));
+
+            assertEquals(value, rs.getObject(1, BigDecimal.class));
+            assertEquals(value, rs.getObject("C", BigDecimal.class));
+
+            assertEquals(strVal, rs.getObject(1, String.class));
+            assertEquals(strVal, rs.getObject("C", String.class));
+
+            expectSqlConversionError(() -> rs.getObject(1, UUID.class), 
"java.util.UUID");
+            expectSqlConversionError(() -> rs.getObject("C", UUID.class), 
"java.util.UUID");
+        }
+    }
+
+    private static Stream<Arguments> getBigDecimalScaledValues() {
+        return Stream.of(
+                Arguments.of(new BigDecimal("67.098912301287").negate(), 13),
+                Arguments.of(new BigDecimal("121.234").negate(), 3),
+                Arguments.of(BigDecimal.ZERO, 0),
+                Arguments.of(new BigDecimal("121.234"), 3),
+                Arguments.of(new BigDecimal("67.098912301287"), 13)
+        );
+    }
+
+    @ParameterizedTest
+    @CsvSource({
+            "true, 0, -9223372036854775808, -9223372036854775808",
+            "true, 0, 9223372036854775807, 9223372036854775807",
+            "true, 0, -42, -42",
+            "true, 0, 42, 42",
+            "true, 0, -9223372036854775809, -9223372036854775809",
+            "true, 0, 9223372036854775808, 9223372036854775808",
+            "true, 14, 10223372036854775808.34954375423432, 
10223372036854775808.34954375423432",
+            "true, 14, -10223372036854775808.34954375423432, 
-10223372036854775808.34954375423432",
+            "false, 2, xyz, ",
+            "false, 2, , "
+    })
+    public void getBigDecimalScaledFromString(boolean valid, int scale, String 
value, String result) throws SQLException {
+        if (value == null) {
+            value = "";
+        }
+        try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.STRING, 0, 0, false), value)) {
+            assertTrue(rs.next());
+
+            if (!valid) {
+                //noinspection deprecation
+                expectSqlException(() -> rs.getBigDecimal(1, scale), "Cannot 
convert to BigDecimal: " + value);
+                //noinspection deprecation
+                expectSqlException(() -> rs.getBigDecimal("C", scale), "Cannot 
convert to BigDecimal: " + value);
+            } else {
+                //noinspection deprecation
+                assertEquals(new BigDecimal(result), rs.getBigDecimal(1, 
scale));
+                //noinspection deprecation
+                assertEquals(new BigDecimal(result), rs.getBigDecimal("C", 
scale));
+            }
+        }
+    }
+
     @Test
     public void getNotSupportedTypes() throws SQLException {
         try (ResultSet rs = createSingleRow(new ColumnDefinition("C", 
ColumnType.STRING, 3, 0, false), "ABC")) {
@@ -1117,12 +2743,18 @@ public abstract class JdbcResultSetBaseSelfTest extends 
BaseIgniteAbstractTest {
         }
     }
 
-    private static void expectNotSupported(ResultSetMethod m) {
-        assertThrows(SQLFeatureNotSupportedException.class, m::call);
+    private static void expectSqlConversionError(Executable call, String 
typeName) {
+        SQLException err = assertThrows(SQLException.class, call);
+        assertThat(err.getMessage(), containsString("Cannot convert to " + 
typeName));
+        assertEquals(SqlStateCode.CONVERSION_FAILED, err.getSQLState());
+    }
+
+    private static void expectNotSupported(Executable call) {
+        assertThrows(SQLFeatureNotSupportedException.class, call);
     }
 
-    protected static void expectSqlException(ResultSetMethod m, String 
message) {
-        SQLException err = assertThrows(SQLException.class, m::call);
+    private static void expectSqlException(Executable m, String message) {
+        SQLException err = assertThrows(SQLException.class, m);
         assertThat(err.getMessage(), containsString(message));
     }
 
@@ -1136,21 +2768,15 @@ public abstract class JdbcResultSetBaseSelfTest extends 
BaseIgniteAbstractTest {
         assertThat(err.getMessage(), containsString("Column not found: " + 
column));
     }
 
-    private static void expectPositioned(ResultSetMethod m) {
-        SQLException err = assertThrows(SQLException.class, m::call);
+    private static void expectPositioned(Executable call) {
+        SQLException err = assertThrows(SQLException.class, call);
         assertThat(err.getMessage(), containsString("Result set is not 
positioned on a row."));
     }
 
-    private static void expectClosed(ResultSetMethod method) {
+    private static void expectClosed(Executable method) {
         expectSqlException(method, "Result set is closed.");
     }
 
-    /** Result set function. */
-    @FunctionalInterface
-    protected interface ResultSetMethod {
-        void call() throws SQLException;
-    }
-
     /** Result set function. */
     @FunctionalInterface
     protected interface ResultSetPositionalMethod {
diff --git 
a/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc/JdbcResultSetSelfTest.java
 
b/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc/JdbcResultSetSelfTest.java
index fbacdef6b02..7157462549b 100644
--- 
a/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc/JdbcResultSetSelfTest.java
+++ 
b/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc/JdbcResultSetSelfTest.java
@@ -76,4 +76,46 @@ public class JdbcResultSetSelfTest extends 
JdbcResultSetBaseSelfTest {
     public void navigationMethods() throws SQLException {
         super.navigationMethods();
     }
+
+    // getByte does not have range checks in the current JDBC driver it is not 
worth fixing them
+    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26140";)
+    @Override
+    public void getByteFromNumber(boolean valid, Number value) throws 
SQLException {
+        super.getByteFromNumber(valid, value);
+    }
+
+    // getShort does not have range checks  in the current JDBC driver it is 
not worth fixing them
+    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26140";)
+    @Override
+    public void getShortFromNumber(boolean valid, Number value) throws 
SQLException {
+        super.getShortFromNumber(valid, value);
+    }
+
+    // getInt does not have range checks  in the current JDBC driver it is not 
worth fixing them
+    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26140";)
+    @Override
+    public void getIntFromNumber(boolean valid, Number value) throws 
SQLException {
+        super.getLongFromNumber(valid, value);
+    }
+
+    // getLong does not have range checks  in the current JDBC driver it is 
not worth fixing them
+    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26140";)
+    @Override
+    public void getLongFromNumber(boolean valid, Number value) throws 
SQLException {
+        super.getLongFromNumber(valid, value);
+    }
+
+    // getFloat does not have range checks  in the current JDBC driver it is 
not worth fixing them
+    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26140";)
+    @Override
+    public void getFloatFromNumber(boolean valid, Number value) throws 
SQLException {
+        super.getFloatFromNumber(valid, value);
+    }
+
+    // getDouble does not have range checks  in the current JDBC driver it is 
not worth fixing them
+    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26140";)
+    @Override
+    public void getDoubleFromNumber(boolean valid, Number value) throws 
SQLException {
+        super.getDoubleFromNumber(valid, value);
+    }
 }
diff --git 
a/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSet2SelfTest.java
 
b/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSet2SelfTest.java
index c74a57f6dc8..45014c3b8ba 100644
--- 
a/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSet2SelfTest.java
+++ 
b/modules/jdbc/src/test/java/org/apache/ignite/internal/jdbc2/JdbcResultSet2SelfTest.java
@@ -74,8 +74,6 @@ import org.mockito.internal.stubbing.answers.ThrowsException;
  */
 public class JdbcResultSet2SelfTest extends JdbcResultSetBaseSelfTest {
 
-    // getXXX are not implemented yet
-    // TODO https://issues.apache.org/jira/browse/IGNITE-26369: numerics
     // TODO https://issues.apache.org/jira/browse/IGNITE-26379: datetime
     @Disabled("https://issues.apache.org/jira/browse/IGNITE-26140";)
     @Override
@@ -85,8 +83,6 @@ public class JdbcResultSet2SelfTest extends 
JdbcResultSetBaseSelfTest {
         super.wasNullPositional(columnType);
     }
 
-    // getXXX are not implemented yet
-    // TODO https://issues.apache.org/jira/browse/IGNITE-26369: numerics
     // TODO https://issues.apache.org/jira/browse/IGNITE-26379: datetime
     @Disabled("https://issues.apache.org/jira/browse/IGNITE-26140";)
     @Override
@@ -97,7 +93,6 @@ public class JdbcResultSet2SelfTest extends 
JdbcResultSetBaseSelfTest {
     }
 
     // getXXX are not implemented yet
-    // TODO https://issues.apache.org/jira/browse/IGNITE-26369: numerics
     // TODO https://issues.apache.org/jira/browse/IGNITE-26379: datetime
     @Disabled("https://issues.apache.org/jira/browse/IGNITE-26140";)
     @Test
@@ -135,13 +130,19 @@ public class JdbcResultSet2SelfTest extends 
JdbcResultSetBaseSelfTest {
     @Test
     @Override
     public void getMetadata() throws SQLException {
-        try (ResultSet rs = createResultSet(null, 
-                List.of(new ColumnDefinition("C", ColumnType.BOOLEAN, 0, 0, 
false)), 
+        try (ResultSet rs = createResultSet(null,
+                List.of(new ColumnDefinition("C", ColumnType.BOOLEAN, 0, 0, 
false)),
                 List.of(List.of(true)))
         ) {
             ResultSetMetaData metaData = rs.getMetaData();
             assertEquals(1, metaData.getColumnCount());
         }
+
+        // Empty metadata
+        try (ResultSet rs = createResultSet(null, List.of(), List.of())) {
+            ResultSetMetaData metaData = rs.getMetaData();
+            assertEquals(0, metaData.getColumnCount());
+        }
     }
 
     @Test
@@ -286,7 +287,7 @@ public class JdbcResultSet2SelfTest extends 
JdbcResultSetBaseSelfTest {
     private static class ResultSetStub implements 
org.apache.ignite.sql.ResultSet<SqlRow> {
         private final ResultSetMetadata meta;
         private final Iterator<List<Object>> it;
-        private List<Object> current;
+        private @Nullable List<Object> current;
 
         ResultSetStub(ResultSetMetadata meta, List<List<Object>> rows) {
             this.meta = Objects.requireNonNull(meta, "meta");

Reply via email to