From da908657099a20f2796e49e6ed42c102a9aa7a80 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Sat, 14 Sep 2024 22:26:11 -0400 Subject: [PATCH] Use sqlite3_close_v2 to close databases. Close databases in a deferred manner if there are unclosed prepared statements. Previously closing a database while statements were open resulted in a `BusyException`. See https://www.sqlite.org/c3ref/close.html for more context. --- CHANGELOG.md | 7 +++++++ ext/sqlite3/database.c | 4 ++-- test/test_database.rb | 4 +--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38a7e650..7d30b22a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # sqlite3-ruby Changelog +## next / unreleased + +### Improved + +- Use `sqlite3_close_v2` to close databases in a deferred manner if there are unclosed prepared statements. Previously closing a database while statements were open resulted in a `BusyException`. See https://www.sqlite.org/c3ref/close.html for more context. @flavorjones + + ## 2.0.4 / 2024-08-13 ### Dependencies diff --git a/ext/sqlite3/database.c b/ext/sqlite3/database.c index 9c730e30..2ad07de5 100644 --- a/ext/sqlite3/database.c +++ b/ext/sqlite3/database.c @@ -25,7 +25,7 @@ deallocate(void *ctx) sqlite3RubyPtr c = (sqlite3RubyPtr)ctx; sqlite3 *db = c->db; - if (db) { sqlite3_close(db); } + if (db) { sqlite3_close_v2(db); } xfree(c); } @@ -131,7 +131,7 @@ sqlite3_rb_close(VALUE self) TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx); db = ctx->db; - CHECK(db, sqlite3_close(ctx->db)); + CHECK(db, sqlite3_close_v2(ctx->db)); ctx->db = NULL; diff --git a/test/test_database.rb b/test/test_database.rb index 6662eab9..16a80906 100644 --- a/test/test_database.rb +++ b/test/test_database.rb @@ -611,9 +611,7 @@ def call action, a, b, c, d def test_close_with_open_statements s = @db.prepare("select 'foo'") - assert_raises(SQLite3::BusyException) do - @db.close - end + @db.close # refute_raises(SQLite3::BusyException) ensure s&.close end