From f8052a9860c4030915201dcc333b61a69a094b8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=84=A0=EC=9A=B0?= Date: Mon, 3 Mar 2025 14:33:02 +0900 Subject: [PATCH] Implement totalChanges --- bindings/java/rs_src/limbo_statement.rs | 17 ++++++++++++ .../java/tech/turso/core/LimboStatement.java | 15 +++++++++++ .../java/tech/turso/jdbc4/JDBC4Statement.java | 9 +++---- .../tech/turso/jdbc4/JDBC4StatementTest.java | 27 +++++++++++++++++++ 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/bindings/java/rs_src/limbo_statement.rs b/bindings/java/rs_src/limbo_statement.rs index 579902d32..2012386cc 100644 --- a/bindings/java/rs_src/limbo_statement.rs +++ b/bindings/java/rs_src/limbo_statement.rs @@ -270,6 +270,23 @@ pub extern "system" fn Java_tech_turso_core_LimboStatement_bindBlob<'local>( SQLITE_OK } +#[no_mangle] +pub extern "system" fn Java_tech_turso_core_LimboStatement_totalChanges<'local>( + mut env: JNIEnv<'local>, + obj: JObject<'local>, + stmt_ptr: jlong, +) -> jlong { + let stmt = match to_limbo_statement(stmt_ptr) { + Ok(stmt) => stmt, + Err(e) => { + set_err_msg_and_throw_exception(&mut env, obj, SQLITE_ERROR, e.to_string()); + return -1 + } + }; + + stmt.connection.conn.total_changes() +} + /// Converts an optional `JObject` into Java's `LimboStepResult`. /// /// This function takes an optional `JObject` and converts it into a Java object diff --git a/bindings/java/src/main/java/tech/turso/core/LimboStatement.java b/bindings/java/src/main/java/tech/turso/core/LimboStatement.java index 711fbad8e..43be14570 100644 --- a/bindings/java/src/main/java/tech/turso/core/LimboStatement.java +++ b/bindings/java/src/main/java/tech/turso/core/LimboStatement.java @@ -214,6 +214,21 @@ public final class LimboStatement { private native int bindBlob(long statementPointer, int position, byte[] value) throws SQLException; + /** + * Returns total number of changes. + * + * @throws SQLException If a database access error occurs + */ + public long totalChanges() throws SQLException { + final long result = totalChanges(statementPointer); + if (result == -1) { + throw new SQLException("Exception while retrieving total number of changes"); + } + + return result; + } + + private native long totalChanges(long statementPointer) throws SQLException; /** * Checks if the statement is closed. * diff --git a/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4Statement.java b/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4Statement.java index 41498914a..4df79e50e 100644 --- a/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4Statement.java +++ b/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4Statement.java @@ -28,8 +28,6 @@ public class JDBC4Statement implements Statement { private final int resultSetHoldability; private int queryTimeoutSeconds; - private long updateCount; - private boolean exhaustedResults = false; private ReentrantLock connectionLock = new ReentrantLock(); @@ -74,14 +72,14 @@ public class JDBC4Statement implements Statement { @Override public int executeUpdate(String sql) throws SQLException { - execute(sql); + final long previousTotalChanges = statement == null ? 0L : statement.totalChanges(); + execute(sql); requireNonNull(statement, "statement should not be null after running execute method"); final LimboResultSet resultSet = statement.getResultSet(); resultSet.consumeAll(); - // TODO: return update count; - return 0; + return (int) (statement.totalChanges() - previousTotalChanges); } @Override @@ -176,7 +174,6 @@ public class JDBC4Statement implements Statement { statement = connection.prepare(sql); final boolean result = statement.execute(); updateGeneratedKeys(); - exhaustedResults = false; return result; } finally { diff --git a/bindings/java/src/test/java/tech/turso/jdbc4/JDBC4StatementTest.java b/bindings/java/src/test/java/tech/turso/jdbc4/JDBC4StatementTest.java index 4d1f0d338..52895442e 100644 --- a/bindings/java/src/test/java/tech/turso/jdbc4/JDBC4StatementTest.java +++ b/bindings/java/src/test/java/tech/turso/jdbc4/JDBC4StatementTest.java @@ -1,5 +1,6 @@ package tech.turso.jdbc4; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; import java.sql.ResultSet; @@ -70,4 +71,30 @@ class JDBC4StatementTest { stmt.close(); assertThrows(SQLException.class, () -> stmt.execute("SELECT 1;")); } + + @Test + void execute_update_should_return_number_of_inserted_elements() throws Exception { + assertThat(stmt.executeUpdate("CREATE TABLE s1 (c1);")).isEqualTo(0); + assertThat(stmt.executeUpdate("INSERT INTO s1 VALUES (0);")).isEqualTo(1); + assertThat(stmt.executeUpdate("INSERT INTO s1 VALUES (1), (2);")).isEqualTo(2); + assertThat(stmt.executeUpdate("INSERT INTO s1 VALUES (3), (4), (5);")).isEqualTo(3); + } + + @Test + @Disabled("Limbo update not yet supported") + void execute_update_should_return_number_of_updated_elements() throws Exception { + assertThat(stmt.executeUpdate("CREATE TABLE s1 (c1);")).isEqualTo(0); + assertThat(stmt.executeUpdate("INSERT INTO s1 VALUES (1), (2), (3);")).isEqualTo(3); + + assertThat(stmt.executeUpdate("UPDATE s1 SET c1 = 0;")).isEqualTo(3); + } + + @Test + @Disabled("Limbo delete has a bug") + void execute_update_should_return_number_of_deleted_elements() throws Exception { + assertThat(stmt.executeUpdate("CREATE TABLE s1 (c1);")).isEqualTo(0); + assertThat(stmt.executeUpdate("INSERT INTO s1 VALUES (1), (2), (3);")).isEqualTo(3); + + assertThat(stmt.executeUpdate("DELETE FROM s1")).isEqualTo(3); + } }