DatabaseQueue
A database connection that serializes accesses to an SQLite database.
final class DatabaseQueue
Usage
Open a DatabaseQueue
with the path to a database file:
import GRDB
let dbQueue = try DatabaseQueue(path: "/path/to/database.sqlite")
SQLite creates the database file if it does not already exist. The connection is closed when the database queue gets deallocated.
A DatabaseQueue
can be used from any thread. The write(_:)
and read(_:)
methods are synchronous, and block the current thread until your database statements are executed in a protected dispatch queue:
// Modify the database:
try dbQueue.write { db in
try Player(name: "Arthur").insert(db)
}
// Read values:
try dbQueue.read { db in
let players = try Player.fetchAll(db)
let playerCount = try Player.fetchCount(db)
}
Database access methods can return values:
let playerCount = try dbQueue.read { db in
try Place.fetchCount(db)
}
let newPlayerCount = try dbQueue.write { db -> Int in
try Player(name: "Arthur").insert(db)
return try Player.fetchCount(db)
}
The write(_:)
method wraps your database statements in a transaction that commits if and only if no error occurs. On the first unhandled error, all changes are reverted, the whole transaction is rollbacked, and the error is rethrown.
When you don’t need to modify the database, prefer the read(_:)
method: it prevents any modification to the database.
When precise transaction handling is required, see Transactions and Savepoints.
Asynchronous database accesses are described in Concurrency.
DatabaseQueue
can be configured with Configuration
.
In-Memory Databases
DatabaseQueue
can open a connection to an in-memory SQLite database.
Such connections are quite handy for tests and SwiftUI previews, since you do not have to perform any cleanup of the file system.
let dbQueue = try DatabaseQueue()
In order to create several connections to the same in-memory database, give this database a name:
// A shared in-memory database
let dbQueue1 = try DatabaseQueue(named: "myDatabase")
// Another connection to the same database
let dbQueue2 = try DatabaseQueue(named: "myDatabase")
See init(named:configuration:)
.
Concurrency
A DatabaseQueue
creates one single SQLite connection. All database accesses are executed in a serial writer dispatch queue, which means that there is never more than one thread that uses the database. The SQLite connection is closed when the DatabaseQueue
is deallocated.
DatabaseQueue
inherits most of its database access methods from the DatabaseReader
and DatabaseWriter
protocols. It defines a few specific database access methods as well, listed below.
A DatabaseQueue
needs your application to follow rules in order to deliver its safety guarantees. See Concurrency for more information.
Creating a DatabaseQueue
init(named: String?, configuration: Configuration
) throws Opens an in-memory SQLite database.
init(path: String, configuration: Configuration
) throws Opens or creates an SQLite database.
static func inMemoryCopy(fromPath: String, configuration: Configuration
) throws -> DatabaseQueue Returns a connection to an in-memory copy of the database at
path
.static func temporaryCopy(fromPath: String, configuration: Configuration
) throws -> DatabaseQueue Returns a connection to a private, temporary, on-disk copy of the database at
path
.
Accessing the Database
See DatabaseReader
and DatabaseWriter
for more database access methods.
func inDatabase<T>((Database) throws -> T
) rethrows -> T Executes database operations, and returns their result after they have finished executing.
func inTransaction(Database.TransactionKind?, (Database) throws -> Database.TransactionCompletion
) throws Wraps database operations inside a database transaction.
Managing the SQLite Connection
func releaseMemory(
) Free as much memory as possible.