Implement close on LimboStatement and JDBC4Statement independently

This commit is contained in:
김선우 2025-01-28 09:20:07 +09:00
parent eeed305b07
commit a82c459ed0
5 changed files with 85 additions and 16 deletions

View file

@ -114,7 +114,6 @@ public class LimboResultSet {
}
public void close() throws SQLException {
this.statement.close();
this.open = false;
}

View file

@ -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{"

View file

@ -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> {
T call() throws SQLException;
}
private void ensureOpen() throws SQLException {
if (closed) {
throw new SQLException("Statement is closed");
}
}
}

View file

@ -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());
}
}

View file

@ -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"));
}
}