Skip to content

Commit

Permalink
LogErrorFunction is Sendable
Browse files Browse the repository at this point in the history
  • Loading branch information
groue committed Aug 25, 2024
1 parent 30eee22 commit 9ceae3f
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 15 deletions.
30 changes: 27 additions & 3 deletions GRDB/Core/Database.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,14 @@ let SQLITE_TRANSIENT = unsafeBitCast(OpaquePointer(bitPattern: -1), to: sqlite3_
/// - ``logError``
/// - ``releaseMemory()``
/// - ``trace(options:_:)``
///
/// ### Supporting Types
///
/// - ``BusyCallback``
/// - ``BusyMode``
/// - ``CheckpointMode``
/// - ``DatabaseBackupProgress``
/// - ``LogErrorFunction``
/// - ``StorageClass``
/// - ``TraceEvent``
/// - ``TracingOptions``
Expand All @@ -143,8 +149,26 @@ public final class Database: CustomStringConvertible, CustomDebugStringConvertib

/// The error logging function.
///
/// SQLite can be configured to invoke a callback function containing
/// an error code and a terse error message whenever anomalies occur.
///
/// This global error callback must be configured early in the lifetime
/// of your application:
///
/// ```swift
/// Database.logError = { (resultCode, message) in
/// NSLog("%@", "SQLite error \(resultCode): \(message)")
/// }
/// ```
///
/// - warning: Database.logError must be set before any database
/// connection is opened. This includes the connections that your
/// application opens with GRDB, but also connections opened by
/// other tools, such as third-party libraries. Setting it after a
/// connection has been opened is an SQLite misuse, and has no effect.
///
/// Related SQLite documentation: <https://www.sqlite.org/errlog.html>
public static var logError: LogErrorFunction? = nil {
nonisolated(unsafe) public static var logError: LogErrorFunction? = nil {
didSet {
if logError != nil {
_registerErrorLogCallback { (_, code, message) in
Expand Down Expand Up @@ -1830,7 +1854,7 @@ extension Database {

// MARK: - Database-Related Types

/// See BusyMode and <https://www.sqlite.org/c3ref/busy_handler.html>
/// See ``BusyMode`` and <https://www.sqlite.org/c3ref/busy_handler.html>
public typealias BusyCallback = @Sendable (_ numberOfTries: Int) -> Bool

/// When there are several connections to a database, a connection may try
Expand Down Expand Up @@ -2019,7 +2043,7 @@ extension Database {
}

/// An error log function that takes an error code and message.
public typealias LogErrorFunction = (_ resultCode: ResultCode, _ message: String) -> Void
public typealias LogErrorFunction = @Sendable (_ resultCode: ResultCode, _ message: String) -> Void

/// An SQLite storage class.
///
Expand Down
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
- [X] GRDB7: Sendable: RowAdapter (d138af26)
- [ ] GRDB7: Sendable: ValueObservationScheduler (8429eb68)
- [X] GRDB7: Sendable: DatabaseCollation (4d9d67dd)
- [ ] GRDB7: Sendable: LogErrorFunction (f362518d)
- [X] GRDB7: Sendable: LogErrorFunction (f362518d)
- [ ] GRDB7: Sendable: ReadWriteBox (57a86a0e)
- [ ] GRDB7: Sendable: Pool (f13b2d2e)
- [ ] GRDB7: Sendable: OnDemandFuture fulfill (2aabc4c1)
Expand Down
4 changes: 2 additions & 2 deletions Tests/GRDBTests/DatabasePoolTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ class DatabasePoolTests: GRDBTestCase {
XCTFail("Expected Error")
} catch DatabaseError.SQLITE_BUSY { }
}
XCTAssert(lastMessage!.contains("unfinalized statement: SELECT * FROM sqlite_master"))
XCTAssert(lastSQLiteDiagnostic!.message.contains("unfinalized statement: SELECT * FROM sqlite_master"))

// Database is not closed: no error
try dbPool.write { db in
Expand Down Expand Up @@ -427,7 +427,7 @@ class DatabasePoolTests: GRDBTestCase {
//
// The first comes from GRDB, and the second, depending on the SQLite
// version, from `sqlite3_close_v2()`. Write the test so that it always pass:
XCTAssert(lastMessage!.contains("unfinalized statement"))
XCTAssert(lastSQLiteDiagnostic!.message.contains("unfinalized statement"))

// Database is in a zombie state.
// In the zombie state, access throws SQLITE_MISUSE
Expand Down
2 changes: 1 addition & 1 deletion Tests/GRDBTests/DatabaseQueueTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ class DatabaseQueueTests: GRDBTestCase {
XCTFail("Expected Error")
} catch DatabaseError.SQLITE_BUSY { }
}
XCTAssert(lastMessage!.contains("unfinalized statement: SELECT * FROM sqlite_master"))
XCTAssert(lastSQLiteDiagnostic!.message.contains("unfinalized statement: SELECT * FROM sqlite_master"))

// Database is not closed: no error
try dbQueue.inDatabase { db in
Expand Down
2 changes: 1 addition & 1 deletion Tests/GRDBTests/DatabaseSnapshotTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ class DatabaseSnapshotTests: GRDBTestCase {
XCTFail("Expected Error")
} catch DatabaseError.SQLITE_BUSY { }
}
XCTAssert(lastMessage!.contains("unfinalized statement: SELECT * FROM sqlite_master"))
XCTAssert(lastSQLiteDiagnostic!.message.contains("unfinalized statement: SELECT * FROM sqlite_master"))

// Database is not closed: no error
try snapshot.read { db in
Expand Down
14 changes: 7 additions & 7 deletions Tests/GRDBTests/GRDBTestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ import XCTest
@testable import GRDB

// Support for Database.logError
var lastResultCode: ResultCode? = nil
var lastMessage: String? = nil
struct SQLiteDiagnostic {
var resultCode: ResultCode
var message: String
}
private let lastSQLiteDiagnosticMutex = Mutex<SQLiteDiagnostic?>(nil)
var lastSQLiteDiagnostic: SQLiteDiagnostic? { lastSQLiteDiagnosticMutex.load() }
let logErrorSetup: Void = {
let lock = NSLock()
Database.logError = { (resultCode, message) in
lock.lock()
defer { lock.unlock() }
lastResultCode = resultCode
lastMessage = message
lastSQLiteDiagnosticMutex.store(SQLiteDiagnostic(resultCode: resultCode, message: message))
}
}()

Expand Down

0 comments on commit 9ceae3f

Please sign in to comment.