From 53ab45301515e94379f3da35e472339e8706e90c Mon Sep 17 00:00:00 2001 From: Orange flavored banana <106858113+moonwhistle@users.noreply.github.com> Date: Thu, 30 Oct 2025 09:54:42 +0900 Subject: [PATCH 1/3] Feat(jdbc): Implement setObject(int, Object) in JDBC4PreparedStatement --- .../turso/jdbc4/JDBC4PreparedStatement.java | 49 +++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java b/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java index 6eba787b5..72c78e5e8 100644 --- a/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java +++ b/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java @@ -26,7 +26,9 @@ import java.util.Calendar; import tech.turso.annotations.SkipNullableCheck; import tech.turso.core.TursoResultSet; -/** JDBC 4 PreparedStatement implementation for Turso databases. */ +/** + * JDBC 4 PreparedStatement implementation for Turso databases. + */ public final class JDBC4PreparedStatement extends JDBC4Statement implements PreparedStatement { private final String sql; @@ -36,7 +38,7 @@ public final class JDBC4PreparedStatement extends JDBC4Statement implements Prep * Creates a new JDBC4PreparedStatement. * * @param connection the database connection - * @param sql the SQL statement to prepare + * @param sql the SQL statement to prepare * @throws SQLException if a database access error occurs */ public JDBC4PreparedStatement(JDBC4Connection connection, String sql) throws SQLException { @@ -189,7 +191,45 @@ public final class JDBC4PreparedStatement extends JDBC4Statement implements Prep @Override public void setObject(int parameterIndex, Object x) throws SQLException { - // TODO + requireNonNull(this.statement); + if (x == null) { + this.statement.bindNull(parameterIndex); + return; + } + if (x instanceof String) { + setString(parameterIndex, (String) x); + } else if (x instanceof Integer) { + setInt(parameterIndex, (Integer) x); + } else if (x instanceof Long) { + setLong(parameterIndex, (Long) x); + } else if (x instanceof Boolean) { + setBoolean(parameterIndex, (Boolean) x); + } else if (x instanceof Double) { + setDouble(parameterIndex, (Double) x); + } else if (x instanceof Float) { + setFloat(parameterIndex, (Float) x); + } else if (x instanceof Byte) { + setByte(parameterIndex, (Byte) x); + } else if (x instanceof Short) { + setShort(parameterIndex, (Short) x); + } else if (x instanceof byte[]) { + setBytes(parameterIndex, (byte[]) x); + } else if (x instanceof java.sql.Timestamp) { + setTimestamp(parameterIndex, (java.sql.Timestamp) x); + } else if (x instanceof java.sql.Date) { + setDate(parameterIndex, (java.sql.Date) x); + } else if (x instanceof java.sql.Time) { + setTime(parameterIndex, (java.sql.Time) x); + } else if (x instanceof java.math.BigDecimal) { + setBigDecimal(parameterIndex, (java.math.BigDecimal) x); + } else if (x instanceof Blob || x instanceof Clob || x instanceof InputStream || x instanceof Reader) { + throw new SQLException( + "setObject does not yet support LOB or Stream types because the corresponding set methods are unimplemented. Type found: " + + x.getClass().getName() + ); + } else { + throw new SQLException("Unsupported object type in setObject: " + x.getClass().getName()); + } } @Override @@ -211,7 +251,8 @@ public final class JDBC4PreparedStatement extends JDBC4Statement implements Prep @Override public void setCharacterStream(int parameterIndex, Reader reader, int length) - throws SQLException {} + throws SQLException { + } @Override public void setRef(int parameterIndex, Ref x) throws SQLException { From 4cd007f2eb62abf65368495471d65071dac10ef9 Mon Sep 17 00:00:00 2001 From: Orange flavored banana <106858113+moonwhistle@users.noreply.github.com> Date: Thu, 30 Oct 2025 15:35:31 +0900 Subject: [PATCH 2/3] Test(jdbc): Add coverage for setObject(int, Object) --- .../jdbc4/JDBC4PreparedStatementTest.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/bindings/java/src/test/java/tech/turso/jdbc4/JDBC4PreparedStatementTest.java b/bindings/java/src/test/java/tech/turso/jdbc4/JDBC4PreparedStatementTest.java index d11d25c13..81868b121 100644 --- a/bindings/java/src/test/java/tech/turso/jdbc4/JDBC4PreparedStatementTest.java +++ b/bindings/java/src/test/java/tech/turso/jdbc4/JDBC4PreparedStatementTest.java @@ -338,6 +338,58 @@ class JDBC4PreparedStatementTest { assertArrayEquals(new byte[] {4, 5, 6}, rs.getBytes(4)); } + @Test + void testSetObjectCoversAllSupportedTypes() throws SQLException { + connection + .prepareStatement( + "CREATE TABLE test (" + + "col1 INTEGER, " + + "col2 REAL, " + + "col3 TEXT, " + + "col4 BLOB, " + + "col5 INTEGER, " + + "col6 TEXT, " + + "col7 TEXT, " + + "col8 TEXT, " + + "col9 TEXT" + + ")" + ).execute(); + + PreparedStatement stmt = connection.prepareStatement( + "INSERT INTO test VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" + ); + + stmt.setObject(1, 42); + stmt.setObject(2, 3.141592d); + stmt.setObject(3, "string_value"); + stmt.setObject(4, new byte[]{1, 2, 3}); + stmt.setObject(5, 1L); + stmt.setObject(6, java.sql.Date.valueOf("2025-10-30")); + stmt.setObject(7, java.sql.Time.valueOf("10:45:00")); + stmt.setObject(8, java.sql.Timestamp.valueOf("2025-10-30 10:45:00")); + stmt.setObject(9, new java.math.BigDecimal("12345.6789")); + + stmt.execute(); + + PreparedStatement stmt2 = + connection.prepareStatement("SELECT * FROM test;"); + ResultSet rs = stmt2.executeQuery(); + + assertTrue(rs.next()); + assertEquals(42, rs.getInt(1)); + assertEquals(3.141592d, rs.getDouble(2), 0.000001); + assertEquals("string_value", rs.getString(3)); + assertArrayEquals(new byte[]{1, 2, 3}, rs.getBytes(4)); + assertTrue(rs.getBoolean(5)); + assertEquals(java.sql.Date.valueOf("2025-10-30"), rs.getDate(6)); + assertEquals(java.sql.Time.valueOf("10:45:00"), rs.getTime(7)); + assertEquals(java.sql.Timestamp.valueOf("2025-10-30 10:45:00"), rs.getTimestamp(8)); + String decimalText = rs.getString(9); + assertEquals(new java.math.BigDecimal("12345.6789").stripTrailingZeros(), + new java.math.BigDecimal(decimalText).stripTrailingZeros()); + } + + @Test void execute_insert_should_return_number_of_inserted_elements() throws Exception { connection.prepareStatement("CREATE TABLE test (col INTEGER)").execute(); From 5fef79d9f65231fd8147f962a2ef6301b8207c3a Mon Sep 17 00:00:00 2001 From: Orange flavored banana <106858113+moonwhistle@users.noreply.github.com> Date: Fri, 31 Oct 2025 10:38:30 +0900 Subject: [PATCH 3/3] feat(jdbc): remove unnecessary `java.sql` prefixes in setObject --- .../turso/jdbc4/JDBC4PreparedStatement.java | 33 ++++++++------- .../jdbc4/JDBC4PreparedStatementTest.java | 40 +++++++++---------- 2 files changed, 35 insertions(+), 38 deletions(-) diff --git a/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java b/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java index 72c78e5e8..015667893 100644 --- a/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java +++ b/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java @@ -26,9 +26,7 @@ import java.util.Calendar; import tech.turso.annotations.SkipNullableCheck; import tech.turso.core.TursoResultSet; -/** - * JDBC 4 PreparedStatement implementation for Turso databases. - */ +/** JDBC 4 PreparedStatement implementation for Turso databases. */ public final class JDBC4PreparedStatement extends JDBC4Statement implements PreparedStatement { private final String sql; @@ -38,7 +36,7 @@ public final class JDBC4PreparedStatement extends JDBC4Statement implements Prep * Creates a new JDBC4PreparedStatement. * * @param connection the database connection - * @param sql the SQL statement to prepare + * @param sql the SQL statement to prepare * @throws SQLException if a database access error occurs */ public JDBC4PreparedStatement(JDBC4Connection connection, String sql) throws SQLException { @@ -214,19 +212,21 @@ public final class JDBC4PreparedStatement extends JDBC4Statement implements Prep setShort(parameterIndex, (Short) x); } else if (x instanceof byte[]) { setBytes(parameterIndex, (byte[]) x); - } else if (x instanceof java.sql.Timestamp) { - setTimestamp(parameterIndex, (java.sql.Timestamp) x); - } else if (x instanceof java.sql.Date) { - setDate(parameterIndex, (java.sql.Date) x); - } else if (x instanceof java.sql.Time) { - setTime(parameterIndex, (java.sql.Time) x); - } else if (x instanceof java.math.BigDecimal) { - setBigDecimal(parameterIndex, (java.math.BigDecimal) x); - } else if (x instanceof Blob || x instanceof Clob || x instanceof InputStream || x instanceof Reader) { + } else if (x instanceof Timestamp) { + setTimestamp(parameterIndex, (Timestamp) x); + } else if (x instanceof Date) { + setDate(parameterIndex, (Date) x); + } else if (x instanceof Time) { + setTime(parameterIndex, (Time) x); + } else if (x instanceof BigDecimal) { + setBigDecimal(parameterIndex, (BigDecimal) x); + } else if (x instanceof Blob + || x instanceof Clob + || x instanceof InputStream + || x instanceof Reader) { throw new SQLException( "setObject does not yet support LOB or Stream types because the corresponding set methods are unimplemented. Type found: " - + x.getClass().getName() - ); + + x.getClass().getName()); } else { throw new SQLException("Unsupported object type in setObject: " + x.getClass().getName()); } @@ -251,8 +251,7 @@ public final class JDBC4PreparedStatement extends JDBC4Statement implements Prep @Override public void setCharacterStream(int parameterIndex, Reader reader, int length) - throws SQLException { - } + throws SQLException {} @Override public void setRef(int parameterIndex, Ref x) throws SQLException { diff --git a/bindings/java/src/test/java/tech/turso/jdbc4/JDBC4PreparedStatementTest.java b/bindings/java/src/test/java/tech/turso/jdbc4/JDBC4PreparedStatementTest.java index 81868b121..0a5c23097 100644 --- a/bindings/java/src/test/java/tech/turso/jdbc4/JDBC4PreparedStatementTest.java +++ b/bindings/java/src/test/java/tech/turso/jdbc4/JDBC4PreparedStatementTest.java @@ -342,27 +342,26 @@ class JDBC4PreparedStatementTest { void testSetObjectCoversAllSupportedTypes() throws SQLException { connection .prepareStatement( - "CREATE TABLE test (" + - "col1 INTEGER, " + - "col2 REAL, " + - "col3 TEXT, " + - "col4 BLOB, " + - "col5 INTEGER, " + - "col6 TEXT, " + - "col7 TEXT, " + - "col8 TEXT, " + - "col9 TEXT" + - ")" - ).execute(); + "CREATE TABLE test (" + + "col1 INTEGER, " + + "col2 REAL, " + + "col3 TEXT, " + + "col4 BLOB, " + + "col5 INTEGER, " + + "col6 TEXT, " + + "col7 TEXT, " + + "col8 TEXT, " + + "col9 TEXT" + + ")") + .execute(); - PreparedStatement stmt = connection.prepareStatement( - "INSERT INTO test VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" - ); + PreparedStatement stmt = + connection.prepareStatement("INSERT INTO test VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); stmt.setObject(1, 42); stmt.setObject(2, 3.141592d); stmt.setObject(3, "string_value"); - stmt.setObject(4, new byte[]{1, 2, 3}); + stmt.setObject(4, new byte[] {1, 2, 3}); stmt.setObject(5, 1L); stmt.setObject(6, java.sql.Date.valueOf("2025-10-30")); stmt.setObject(7, java.sql.Time.valueOf("10:45:00")); @@ -371,25 +370,24 @@ class JDBC4PreparedStatementTest { stmt.execute(); - PreparedStatement stmt2 = - connection.prepareStatement("SELECT * FROM test;"); + PreparedStatement stmt2 = connection.prepareStatement("SELECT * FROM test;"); ResultSet rs = stmt2.executeQuery(); assertTrue(rs.next()); assertEquals(42, rs.getInt(1)); assertEquals(3.141592d, rs.getDouble(2), 0.000001); assertEquals("string_value", rs.getString(3)); - assertArrayEquals(new byte[]{1, 2, 3}, rs.getBytes(4)); + assertArrayEquals(new byte[] {1, 2, 3}, rs.getBytes(4)); assertTrue(rs.getBoolean(5)); assertEquals(java.sql.Date.valueOf("2025-10-30"), rs.getDate(6)); assertEquals(java.sql.Time.valueOf("10:45:00"), rs.getTime(7)); assertEquals(java.sql.Timestamp.valueOf("2025-10-30 10:45:00"), rs.getTimestamp(8)); String decimalText = rs.getString(9); - assertEquals(new java.math.BigDecimal("12345.6789").stripTrailingZeros(), + assertEquals( + new java.math.BigDecimal("12345.6789").stripTrailingZeros(), new java.math.BigDecimal(decimalText).stripTrailingZeros()); } - @Test void execute_insert_should_return_number_of_inserted_elements() throws Exception { connection.prepareStatement("CREATE TABLE test (col INTEGER)").execute();