From a82c459ed0d163208c2c3685f132e4e57b5b463a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=84=A0=EC=9A=B0?= Date: Tue, 28 Jan 2025 09:20:07 +0900 Subject: [PATCH] Implement close on LimboStatement and JDBC4Statement independently --- .../tursodatabase/core/LimboResultSet.java | 1 - .../tursodatabase/core/LimboStatement.java | 18 ++++++++++- .../tursodatabase/jdbc4/JDBC4Statement.java | 32 +++++++++++-------- .../core/LimboStatementTest.java | 31 ++++++++++++++++++ .../jdbc4/JDBC4StatementTest.java | 19 +++++++++++ 5 files changed, 85 insertions(+), 16 deletions(-) create mode 100644 bindings/java/src/test/java/org/github/tursodatabase/core/LimboStatementTest.java diff --git a/bindings/java/src/main/java/org/github/tursodatabase/core/LimboResultSet.java b/bindings/java/src/main/java/org/github/tursodatabase/core/LimboResultSet.java index ec6e63a26..b226c53d0 100644 --- a/bindings/java/src/main/java/org/github/tursodatabase/core/LimboResultSet.java +++ b/bindings/java/src/main/java/org/github/tursodatabase/core/LimboResultSet.java @@ -114,7 +114,6 @@ public class LimboResultSet { } public void close() throws SQLException { - this.statement.close(); this.open = false; } diff --git a/bindings/java/src/main/java/org/github/tursodatabase/core/LimboStatement.java b/bindings/java/src/main/java/org/github/tursodatabase/core/LimboStatement.java index df82b71e3..8566c403e 100644 --- a/bindings/java/src/main/java/org/github/tursodatabase/core/LimboStatement.java +++ b/bindings/java/src/main/java/org/github/tursodatabase/core/LimboStatement.java @@ -21,6 +21,8 @@ public class LimboStatement { private final long statementPointer; private final LimboResultSet resultSet; + private boolean closed; + // TODO: what if the statement we ran was DDL, update queries and etc. Should we still create a // resultSet? public LimboStatement(String sql, long statementPointer) { @@ -71,12 +73,26 @@ public class LimboStatement { * Closes the current statement and releases any resources associated with it. This method calls * the native `_close` method to perform the actual closing operation. */ - public void close() { + public void close() throws SQLException { + if (closed) { + return; + } + this.resultSet.close(); _close(statementPointer); + closed = true; } private native void _close(long statementPointer); + /** + * Checks if the statement is closed. + * + * @return true if the statement is closed, false otherwise. + */ + public boolean isClosed() { + return closed; + } + @Override public String toString() { return "LimboStatement{" diff --git a/bindings/java/src/main/java/org/github/tursodatabase/jdbc4/JDBC4Statement.java b/bindings/java/src/main/java/org/github/tursodatabase/jdbc4/JDBC4Statement.java index 1005d2e27..7cbf6f69d 100644 --- a/bindings/java/src/main/java/org/github/tursodatabase/jdbc4/JDBC4Statement.java +++ b/bindings/java/src/main/java/org/github/tursodatabase/jdbc4/JDBC4Statement.java @@ -19,6 +19,8 @@ public class JDBC4Statement implements Statement { private final LimboConnection connection; @Nullable private LimboStatement statement = null; + // Because JDBC4Statement has different life cycle in compared to LimboStatement, let's use this + // field to manage JDBC4Statement lifecycle private boolean closed; private boolean closeOnCompletion; @@ -73,8 +75,14 @@ public class JDBC4Statement implements Statement { @Override public void close() throws SQLException { - clearGeneratedKeys(); - internalClose(); + if (closed) { + return; + } + + if (this.statement != null) { + this.statement.close(); + } + closed = true; } @@ -148,8 +156,7 @@ public class JDBC4Statement implements Statement { */ @Override public boolean execute(String sql) throws SQLException { - internalClose(); - + ensureOpen(); return this.withConnectionTimeout( () -> { try { @@ -296,8 +303,7 @@ public class JDBC4Statement implements Statement { @Override public boolean isClosed() throws SQLException { - // TODO - return false; + return this.closed; } @Override @@ -344,14 +350,6 @@ public class JDBC4Statement implements Statement { return false; } - protected void internalClose() throws SQLException { - // TODO - } - - protected void clearGeneratedKeys() throws SQLException { - // TODO - } - protected void updateGeneratedKeys() throws SQLException { // TODO } @@ -376,4 +374,10 @@ public class JDBC4Statement implements Statement { protected interface SQLCallable { T call() throws SQLException; } + + private void ensureOpen() throws SQLException { + if (closed) { + throw new SQLException("Statement is closed"); + } + } } diff --git a/bindings/java/src/test/java/org/github/tursodatabase/core/LimboStatementTest.java b/bindings/java/src/test/java/org/github/tursodatabase/core/LimboStatementTest.java new file mode 100644 index 000000000..ea0620a8d --- /dev/null +++ b/bindings/java/src/test/java/org/github/tursodatabase/core/LimboStatementTest.java @@ -0,0 +1,31 @@ +package org.github.tursodatabase.core; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Properties; +import org.github.tursodatabase.TestUtils; +import org.github.tursodatabase.jdbc4.JDBC4Connection; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class LimboStatementTest { + + private JDBC4Connection connection; + + @BeforeEach + void setUp() throws Exception { + String filePath = TestUtils.createTempFile(); + String url = "jdbc:sqlite:" + filePath; + connection = new JDBC4Connection(url, filePath, new Properties()); + } + + @Test + void closing_statement_closes_related_resources() throws Exception { + LimboStatement stmt = connection.prepare("SELECT 1"); + stmt.execute(); + + stmt.close(); + assertTrue(stmt.isClosed()); + assertFalse(stmt.getResultSet().isOpen()); + } +} diff --git a/bindings/java/src/test/java/org/github/tursodatabase/jdbc4/JDBC4StatementTest.java b/bindings/java/src/test/java/org/github/tursodatabase/jdbc4/JDBC4StatementTest.java index 2a837629d..c9894d2a2 100644 --- a/bindings/java/src/test/java/org/github/tursodatabase/jdbc4/JDBC4StatementTest.java +++ b/bindings/java/src/test/java/org/github/tursodatabase/jdbc4/JDBC4StatementTest.java @@ -3,6 +3,7 @@ package org.github.tursodatabase.jdbc4; import static org.junit.jupiter.api.Assertions.*; import java.sql.ResultSet; +import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import org.github.tursodatabase.TestUtils; @@ -51,4 +52,22 @@ class JDBC4StatementTest { stmt.execute("INSERT INTO users VALUES (1, 'limbo');"); assertTrue(stmt.execute("SELECT * FROM users;")); } + + @Test + void close_statement_test() throws Exception { + stmt.close(); + assertTrue(stmt.isClosed()); + } + + @Test + void double_close_is_no_op() throws SQLException { + stmt.close(); + assertDoesNotThrow(() -> stmt.close()); + } + + @Test + void operations_on_closed_statement_should_throw_exception() throws Exception { + stmt.close(); + assertThrows(SQLException.class, () -> stmt.execute("SELECT 1")); + } }