diff --git a/libsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/LibsqlStatement.java b/libsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/LibsqlStatement.java
index 1fc946b..535e2cd 100644
--- a/libsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/LibsqlStatement.java
+++ b/libsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/LibsqlStatement.java
@@ -31,6 +31,9 @@
* {@link Statement#KEEP_CURRENT_RESULT} and {@link Statement#CLOSE_ALL_RESULTS} throw
* {@link SQLFeatureNotSupportedException} naming both constants, and any other value throws
* {@code SQLException("Invalid argument")}. The method always returns {@code false}.
+ *
Closing a result set closes the statement when {@link #closeOnCompletion()} was called,
+ * per {@code java.sql}. sqlite-jdbc 3.53.4.0 does the same, including for prepared
+ * statements.
* {@link #closeOnCompletion()} and {@link #isCloseOnCompletion()} throw {@code
* SQLException("Statement is closed")} after the statement is closed.
* {@link #close()} closes the current result set and generated-key results.
diff --git a/libsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlStatementLifecycleTest.java b/libsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlStatementLifecycleTest.java
index 94747c2..02aea64 100644
--- a/libsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlStatementLifecycleTest.java
+++ b/libsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlStatementLifecycleTest.java
@@ -125,6 +125,73 @@ void closeOnCompletionAndIsCloseOnCompletionThrowAfterClose() throws SQLExceptio
.hasMessage("statement is closed");
}
+ @Test
+ void closingQueryResultSetClosesCloseOnCompletionStatement() throws SQLException {
+ RecordingConnection connection = new RecordingConnection(ROWS);
+ Statement statement = connection.createStatement();
+ statement.closeOnCompletion();
+
+ ResultSet resultSet = statement.executeQuery("select value from t");
+ resultSet.close();
+
+ assertThat(resultSet.isClosed()).isTrue();
+ assertThat(statement.isClosed()).isTrue();
+ }
+
+ @Test
+ void closingExecuteResultSetClosesCloseOnCompletionStatement() throws SQLException {
+ RecordingConnection connection = new RecordingConnection(ROWS);
+ Statement statement = connection.createStatement();
+ statement.closeOnCompletion();
+
+ assertThat(statement.execute("select value from t")).isTrue();
+ ResultSet resultSet = statement.getResultSet();
+ resultSet.close();
+
+ assertThat(resultSet.isClosed()).isTrue();
+ assertThat(statement.isClosed()).isTrue();
+ }
+
+ @Test
+ void closingPreparedResultSetClosesCloseOnCompletionStatement() throws SQLException {
+ RecordingConnection connection = new RecordingConnection(ROWS);
+ LibsqlPreparedStatement statement =
+ new LibsqlPreparedStatement(connection, "select value from t");
+ statement.closeOnCompletion();
+
+ ResultSet resultSet = statement.executeQuery();
+ resultSet.close();
+
+ assertThat(resultSet.isClosed()).isTrue();
+ assertThat(statement.isClosed()).isTrue();
+ }
+
+ @Test
+ void closingResultSetLeavesStatementWithoutCloseOnCompletionOpen() throws SQLException {
+ RecordingConnection connection = new RecordingConnection(ROWS);
+ Statement statement = connection.createStatement();
+
+ ResultSet resultSet = statement.executeQuery("select value from t");
+ resultSet.close();
+
+ assertThat(resultSet.isClosed()).isTrue();
+ assertThat(statement.isClosed()).isFalse();
+ }
+
+ @Test
+ void metadataStatementClosesWithoutCloseOnCompletion() throws SQLException {
+ RecordingConnection connection = new RecordingConnection(ROWS);
+
+ ResultSet resultSet = connection.getMetaData().getTableTypes();
+ LibsqlStatement statement = (LibsqlStatement) resultSet.getStatement();
+ assertThat(statement.isCloseOnCompletion()).isFalse();
+
+ resultSet.close();
+
+ assertThat(resultSet.isClosed()).isTrue();
+ assertThat(statement.isClosed()).isTrue();
+ }
+
@Test
void executeAndGetConnectionStillWorkAfterClose() throws SQLException {
RecordingConnection connection = new RecordingConnection(ROWS);