diff --git a/CHANGELOG.md b/CHANGELOG.md
index bfb8382353..68f846842e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,7 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception:
#### 6.x Releases
-- `6.29.x` Releases - [6.29.0](#6290) - [6.29.1](#6291) - [6.29.2](#6292)
+- `6.29.x` Releases - [6.29.0](#6290) - [6.29.1](#6291) - [6.29.2](#6292) - [6.29.3](#6293)
- `6.28.x` Releases - [6.28.0](#6280)
- `6.27.x` Releases - [6.27.0](#6270)
- `6.26.x` Releases - [6.26.0](#6260)
@@ -127,6 +127,12 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception:
---
+## 6.29.3
+
+Released September 7, 2024
+
+- **Fixed**: [#1613](https://github.com/groue/GRDB.swift/pull/1613) by [@groue](https://github.com/groue): Avoid SQLite misuse when releasing memory on a closed database connection
+
## 6.29.2
Released August 24, 2024
diff --git a/GRDB.swift.podspec b/GRDB.swift.podspec
index 403fd74f9c..9ebb0c099d 100644
--- a/GRDB.swift.podspec
+++ b/GRDB.swift.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'GRDB.swift'
- s.version = '6.29.2'
+ s.version = '6.29.3'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.summary = 'A toolkit for SQLite databases, with a focus on application development.'
diff --git a/GRDB/Core/Database.swift b/GRDB/Core/Database.swift
index 474373db5f..9d5a13b7bd 100644
--- a/GRDB/Core/Database.swift
+++ b/GRDB/Core/Database.swift
@@ -1575,7 +1575,9 @@ public final class Database: CustomStringConvertible, CustomDebugStringConvertib
/// Frees as much memory as possible.
public func releaseMemory() {
SchedulingWatchdog.preconditionValidQueue(self)
- sqlite3_db_release_memory(sqliteConnection)
+ if let sqliteConnection {
+ sqlite3_db_release_memory(sqliteConnection)
+ }
schemaCache.clear()
internalStatementCache.clear()
publicStatementCache.clear()
diff --git a/GRDB/Core/Support/Foundation/SQLiteDateParser.swift b/GRDB/Core/Support/Foundation/SQLiteDateParser.swift
index 4f234749dc..74db8e5fdf 100644
--- a/GRDB/Core/Support/Foundation/SQLiteDateParser.swift
+++ b/GRDB/Core/Support/Foundation/SQLiteDateParser.swift
@@ -4,7 +4,6 @@ import Foundation
@usableFromInline
struct SQLiteDateParser {
- // swiftlint:disable:next unneeded_synthesized_initializer
@usableFromInline
init() { }
diff --git a/GRDB/QueryInterface/SQL/SQLRelation.swift b/GRDB/QueryInterface/SQL/SQLRelation.swift
index 9f01841c2a..4488cc96f4 100644
--- a/GRDB/QueryInterface/SQL/SQLRelation.swift
+++ b/GRDB/QueryInterface/SQL/SQLRelation.swift
@@ -171,7 +171,7 @@ struct SQLRelation {
var source: SQLSource
var selectionPromise: DatabasePromise<[SQLSelection]>
var filterPromise: DatabasePromise?
- var ordering: SQLRelation.Ordering = SQLRelation.Ordering()
+ var ordering = SQLRelation.Ordering()
var ctes: OrderedDictionary = [:] // See also `allCTEs`
var children: OrderedDictionary = [:]
diff --git a/GRDB/Record/EncodableRecord+Encodable.swift b/GRDB/Record/EncodableRecord+Encodable.swift
index 4ecbd5f803..8ead9397bc 100644
--- a/GRDB/Record/EncodableRecord+Encodable.swift
+++ b/GRDB/Record/EncodableRecord+Encodable.swift
@@ -223,7 +223,7 @@ extension RecordEncoder: SingleValueEncodingContainer {
unsupportedSingleValueEncoding()
}
- func encode(_ value: T) throws where T : Encodable {
+ func encode(_ value: T) throws where T: Encodable {
if let record = value as? EncodableRecord {
try record.encode(to: &_persistenceContainer)
} else {
diff --git a/README.md b/README.md
index a5a40d8fc0..d5171c0c0c 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@
-**Latest release**: August 24, 2024 • [version 6.29.2](https://github.com/groue/GRDB.swift/tree/v6.29.2) • [CHANGELOG](CHANGELOG.md) • [Migrating From GRDB 5 to GRDB 6](Documentation/GRDB6MigrationGuide.md)
+**Latest release**: September 7, 2024 • [version 6.29.3](https://github.com/groue/GRDB.swift/tree/v6.29.3) • [CHANGELOG](CHANGELOG.md) • [Migrating From GRDB 5 to GRDB 6](Documentation/GRDB6MigrationGuide.md)
**Requirements**: iOS 11.0+ / macOS 10.13+ / tvOS 11.0+ / watchOS 4.0+ • SQLite 3.19.3+ • Swift 5.7+ / Xcode 14+
diff --git a/Scripts/swiftlint.yml b/Scripts/swiftlint.yml
index af49e16e21..4c2448eb54 100644
--- a/Scripts/swiftlint.yml
+++ b/Scripts/swiftlint.yml
@@ -15,6 +15,7 @@ disabled_rules:
- is_disjoint
- large_tuple
- nesting
+ - non_optional_string_data_conversion
- opening_brace
- redundant_optional_initialization
- syntactic_sugar
diff --git a/Support/Info.plist b/Support/Info.plist
index 08f23569db..5c8f9953f8 100644
--- a/Support/Info.plist
+++ b/Support/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 6.29.2
+ 6.29.3
CFBundleSignature
????
CFBundleVersion
diff --git a/Tests/GRDBTests/DatabasePoolTests.swift b/Tests/GRDBTests/DatabasePoolTests.swift
index 7580b1a347..8b45af6ab7 100644
--- a/Tests/GRDBTests/DatabasePoolTests.swift
+++ b/Tests/GRDBTests/DatabasePoolTests.swift
@@ -439,4 +439,12 @@ class DatabasePoolTests: GRDBTestCase {
// In the zombie state, closing is a noop
try dbPool.close()
}
+
+ // Regression test for
+ func test_releaseMemory_after_close() throws {
+ let dbPool = try makeDatabasePool()
+ try dbPool.read { _ in } // Create a reader
+ try dbPool.close()
+ dbPool.releaseMemory()
+ }
}
diff --git a/Tests/GRDBTests/DatabaseQueueTests.swift b/Tests/GRDBTests/DatabaseQueueTests.swift
index 7bd5adf2b5..43c415a4fa 100644
--- a/Tests/GRDBTests/DatabaseQueueTests.swift
+++ b/Tests/GRDBTests/DatabaseQueueTests.swift
@@ -467,4 +467,11 @@ class DatabaseQueueTests: GRDBTestCase {
try db.execute(sql: "SELECT * FROM sqlite_master")
}
}
+
+ // Regression test for
+ func test_releaseMemory_after_close() throws {
+ let dbQueue = try makeDatabaseQueue()
+ try dbQueue.close()
+ dbQueue.releaseMemory()
+ }
}