diff --git a/src/main/java/org/duckdb/DuckDBResultSetMetaData.java b/src/main/java/org/duckdb/DuckDBResultSetMetaData.java index 8b9c6dc3d..9bc233be5 100644 --- a/src/main/java/org/duckdb/DuckDBResultSetMetaData.java +++ b/src/main/java/org/duckdb/DuckDBResultSetMetaData.java @@ -310,17 +310,58 @@ public int getColumnDisplaySize(int column) throws SQLException { } public int getPrecision(int column) throws SQLException { - DuckDBColumnTypeMetaData typeMetaData = typeMetadataForColumn(column); + checkColumn(column); + DuckDBColumnTypeMetaData typeMetaData = column_types_meta[column - 1]; - if (typeMetaData == null) { - return 0; + if (typeMetaData != null) { + return typeMetaData.width; } - return typeMetaData.width; + DuckDBColumnType colType = column_types[column - 1]; + switch (colType) { + case BOOLEAN: + return 5; + case TINYINT: + case UTINYINT: + return 3; + case SMALLINT: + case USMALLINT: + return 5; + case INTEGER: + case UINTEGER: + return 10; + case BIGINT: + case UBIGINT: + return 19; + case HUGEINT: + case UHUGEINT: + return 38; + case FLOAT: + return 8; + case DOUBLE: + return 17; + case TIME: + return 15; + case DATE: + return 13; + case TIMESTAMP: + case TIMESTAMP_MS: + case TIMESTAMP_NS: + case TIMESTAMP_S: + return 29; + case TIMESTAMP_WITH_TIME_ZONE: + return 35; + case VARCHAR: + case BLOB: + return Integer.MAX_VALUE; + default: + return 0; + } } public int getScale(int column) throws SQLException { - DuckDBColumnTypeMetaData typeMetaData = typeMetadataForColumn(column); + checkColumn(column); + DuckDBColumnTypeMetaData typeMetaData = column_types_meta[column - 1]; if (typeMetaData == null) { return 0; @@ -347,10 +388,9 @@ public boolean isWrapperFor(Class iface) { return iface.isInstance(this); } - private DuckDBColumnTypeMetaData typeMetadataForColumn(int columnIndex) throws SQLException { + private void checkColumn(int columnIndex) throws SQLException { if (columnIndex > column_count) { throw new SQLException("Column index out of bounds"); } - return column_types_meta[columnIndex - 1]; } } diff --git a/src/test/java/org/duckdb/TestResults.java b/src/test/java/org/duckdb/TestResults.java index 93e7a2868..a0798fe32 100644 --- a/src/test/java/org/duckdb/TestResults.java +++ b/src/test/java/org/duckdb/TestResults.java @@ -8,6 +8,7 @@ import java.math.BigInteger; import java.sql.*; import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.Properties; import java.util.UUID; @@ -297,4 +298,69 @@ public static void test_results_strings_cast() throws Exception { } } } + + public static void test_results_precision() throws Exception { + try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement()) { + try (ResultSet rs = stmt.executeQuery("SELECT TRUE::BOOLEAN")) { + assertEquals(rs.getMetaData().getPrecision(1), 5); + } + try (ResultSet rs = stmt.executeQuery("SELECT 42::TINYINT")) { + assertEquals(rs.getMetaData().getPrecision(1), 3); + } + try (ResultSet rs = stmt.executeQuery("SELECT 42::UTINYINT")) { + assertEquals(rs.getMetaData().getPrecision(1), 3); + } + try (ResultSet rs = stmt.executeQuery("SELECT 42::SMALLINT")) { + assertEquals(rs.getMetaData().getPrecision(1), 5); + } + try (ResultSet rs = stmt.executeQuery("SELECT 42::USMALLINT")) { + assertEquals(rs.getMetaData().getPrecision(1), 5); + } + try (ResultSet rs = stmt.executeQuery("SELECT 42::INTEGER")) { + assertEquals(rs.getMetaData().getPrecision(1), 10); + } + try (ResultSet rs = stmt.executeQuery("SELECT 42::UINTEGER")) { + assertEquals(rs.getMetaData().getPrecision(1), 10); + } + try (ResultSet rs = stmt.executeQuery("SELECT 42::BIGINT")) { + assertEquals(rs.getMetaData().getPrecision(1), 19); + } + try (ResultSet rs = stmt.executeQuery("SELECT 42::UBIGINT")) { + assertEquals(rs.getMetaData().getPrecision(1), 19); + } + try (ResultSet rs = stmt.executeQuery("SELECT 42::HUGEINT")) { + assertEquals(rs.getMetaData().getPrecision(1), 38); + } + try (ResultSet rs = stmt.executeQuery("SELECT 42::UHUGEINT")) { + assertEquals(rs.getMetaData().getPrecision(1), 38); + } + try (ResultSet rs = stmt.executeQuery("SELECT 42::FLOAT")) { + assertEquals(rs.getMetaData().getPrecision(1), 8); + } + try (ResultSet rs = stmt.executeQuery("SELECT 42::DOUBLE")) { + assertEquals(rs.getMetaData().getPrecision(1), 17); + } + try (ResultSet rs = stmt.executeQuery("SELECT 42::DECIMAL(15,3)")) { + assertEquals(rs.getMetaData().getPrecision(1), 15); + } + try (ResultSet rs = stmt.executeQuery("SELECT NULL::TIME")) { + assertEquals(rs.getMetaData().getPrecision(1), 15); + } + try (ResultSet rs = stmt.executeQuery("SELECT NULL::DATE")) { + assertEquals(rs.getMetaData().getPrecision(1), 13); + } + try (ResultSet rs = stmt.executeQuery("SELECT NULL::TIMESTAMP")) { + assertEquals(rs.getMetaData().getPrecision(1), 29); + } + try (ResultSet rs = stmt.executeQuery("SELECT NULL::TIMESTAMP WITH TIME ZONE")) { + assertEquals(rs.getMetaData().getPrecision(1), 35); + } + try (ResultSet rs = stmt.executeQuery("SELECT NULL::VARCHAR")) { + assertEquals(rs.getMetaData().getPrecision(1), Integer.MAX_VALUE); + } + try (ResultSet rs = stmt.executeQuery("SELECT NULL::BLOB")) { + assertEquals(rs.getMetaData().getPrecision(1), Integer.MAX_VALUE); + } + } + } }