Database
public final class Database
A Database connection.
You don’t create a database directly. Instead, you use a DatabaseQueue, or a DatabasePool:
let dbQueue = DatabaseQueue(...)
// The Database is the `db` in the closure:
try dbQueue.inDatabase { db in
try db.execute(...)
}
-
See BusyMode and https://www.sqlite.org/c3ref/busy_handler.html
Declaration
Swift
public typealias BusyCallback = (_ numberOfTries: Int) -> Bool
-
When there are several connections to a database, a connection may try to access the database while it is locked by another connection.
The BusyMode enum describes the behavior of GRDB when such a situation occurs:
.immediateError: The SQLITE_BUSY error is immediately returned to the connection that tries to access the locked database.
.timeout: The SQLITE_BUSY error will be returned only if the database remains locked for more than the specified duration.
.callback: Perform your custom lock handling.
To set the busy mode of a database, use Configuration:
let configuration = Configuration(busyMode: .timeout(1)) let dbQueue = DatabaseQueue(path: "...", configuration: configuration)
Relevant SQLite documentation:
- https://www.sqlite.org/c3ref/busy_timeout.html
- https://www.sqlite.org/c3ref/busy_handler.html
- https://www.sqlite.org/lang_transaction.html
- https://www.sqlite.org/wal.html
Declaration
Swift
public enum BusyMode
-
The available checkpoint modes.
See moreDeclaration
Swift
public enum CheckpointMode: Int32
-
Declaration
Swift
public struct CollationName : RawRepresentable, Hashable
-
Declaration
Swift
public enum ConflictResolution : String
-
An SQL column type.
try db.create(table: "persons") { t in t.column("id", .integer).primaryKey() t.column("title", .text) }
See https://www.sqlite.org/datatype3.html
See moreDeclaration
Swift
public struct ColumnType : RawRepresentable, Hashable
-
Declaration
Swift
public enum ForeignKeyAction : String
-
An SQLite transaction kind. See https://www.sqlite.org/lang_transaction.html
See moreDeclaration
Swift
public enum TransactionKind
-
The end of a transaction: Commit, or Rollback
See moreDeclaration
Swift
public enum TransactionCompletion
-
The database configuration
Declaration
Swift
public let configuration: Configuration
-
The raw SQLite connection, suitable for the SQLite C API.
Declaration
Swift
public let sqliteConnection: SQLiteConnection
-
The rowID of the most recently inserted row.
If no row has ever been inserted using this database connection, returns zero.
For more detailed information, see https://www.sqlite.org/c3ref/last_insert_rowid.html
Declaration
Swift
public var lastInsertedRowID: Int64
-
The number of rows modified, inserted or deleted by the most recent successful INSERT, UPDATE or DELETE statement.
For more detailed information, see https://www.sqlite.org/c3ref/changes.html
Declaration
Swift
public var changesCount: Int
-
The total number of rows modified, inserted or deleted by all successful INSERT, UPDATE or DELETE statements since the database connection was opened.
For more detailed information, see https://www.sqlite.org/c3ref/total_changes.html
Declaration
Swift
public var totalChangesCount: Int
-
True if the database connection is currently in a transaction.
Declaration
Swift
public var isInsideTransaction: Bool
-
Returns a new prepared statement that can be reused.
let statement = try db.makeSelectStatement("SELECT COUNT(*) FROM persons WHERE age > ?") let moreThanTwentyCount = try Int.fetchOne(statement, arguments: [20])! let moreThanThirtyCount = try Int.fetchOne(statement, arguments: [30])!
Throws
A DatabaseError whenever SQLite could not parse the sql query.Declaration
Swift
public func makeSelectStatement(_ sql: String) throws -> SelectStatement
Parameters
sql
An SQL query.
Return Value
A SelectStatement.
-
Returns a prepared statement that can be reused.
let statement = try db.cachedSelectStatement("SELECT COUNT(*) FROM persons WHERE age > ?") let moreThanTwentyCount = try Int.fetchOne(statement, arguments: [20])! let moreThanThirtyCount = try Int.fetchOne(statement, arguments: [30])!
The returned statement may have already been used: it may or may not contain values for its eventual arguments.
Throws
A DatabaseError whenever SQLite could not parse the sql query.Declaration
Swift
public func cachedSelectStatement(_ sql: String) throws -> SelectStatement
Parameters
sql
An SQL query.
Return Value
An UpdateStatement.
-
Returns a new prepared statement that can be reused.
let statement = try db.makeUpdateStatement("INSERT INTO persons (name) VALUES (?)") try statement.execute(arguments: ["Arthur"]) try statement.execute(arguments: ["Barbara"])
Throws
A DatabaseError whenever SQLite could not parse the sql query.Declaration
Swift
public func makeUpdateStatement(_ sql: String) throws -> UpdateStatement
Parameters
sql
An SQL query.
Return Value
An UpdateStatement.
-
Returns a prepared statement that can be reused.
let statement = try db.cachedUpdateStatement("INSERT INTO persons (name) VALUES (?)") try statement.execute(arguments: ["Arthur"]) try statement.execute(arguments: ["Barbara"])
The returned statement may have already been used: it may or may not contain values for its eventual arguments.
Throws
A DatabaseError whenever SQLite could not parse the sql query.Declaration
Swift
public func cachedUpdateStatement(_ sql: String) throws -> UpdateStatement
Parameters
sql
An SQL query.
Return Value
An UpdateStatement.
-
Executes one or several SQL statements, separated by semi-colons.
try db.execute( "INSERT INTO persons (name) VALUES (:name)", arguments: ["name": "Arthur"]) try db.execute( "INSERT INTO persons (name) VALUES (?);" + "INSERT INTO persons (name) VALUES (?);" + "INSERT INTO persons (name) VALUES (?);", arguments; ['Arthur', 'Barbara', 'Craig'])
This method may throw a DatabaseError.
Throws
A DatabaseError whenever an SQLite error occurs.Declaration
Swift
public func execute(_ sql: String, arguments: StatementArguments? = nil) throws
Parameters
sql
An SQL query.
arguments
Optional statement arguments.
-
Add or redefine an SQL function.
let fn = DatabaseFunction("succ", argumentCount: 1) { databaseValues in let dbv = databaseValues.first! guard let int = dbv.value() as Int? else { return nil } return int + 1 } db.add(function: fn) try Int.fetchOne(db, "SELECT succ(1)")! // 2
Declaration
Swift
public func add(function: DatabaseFunction)
-
Remove an SQL function.
Declaration
Swift
public func remove(function: DatabaseFunction)
-
Add or redefine a collation.
let collation = DatabaseCollation("localized_standard") { (string1, string2) in return (string1 as NSString).localizedStandardCompare(string2) } db.add(collation: collation) try db.execute("CREATE TABLE files (name TEXT COLLATE localized_standard")
Declaration
Swift
public func add(collation: DatabaseCollation)
-
Remove a collation.
Declaration
Swift
public func remove(collation: DatabaseCollation)
-
Clears the database schema cache.
You may need to clear the cache manually if the database schema is modified by another connection.
Declaration
Swift
public func clearSchemaCache()
-
Returns whether a table exists.
Declaration
Swift
public func tableExists(_ tableName: String) throws -> Bool
-
The primary key for table named
tableName
; nil if table has no primary key.Throws
A DatabaseError if table does not exist.Declaration
Swift
public func primaryKey(_ tableName: String) throws -> PrimaryKeyInfo?
-
The number of columns in the table named
tableName
.Throws
A DatabaseError if table does not exist.Declaration
Swift
public func columnCount(in tableName: String) throws -> Int
-
The indexes on table named
tableName
; returns the empty array if the table does not exist.Note: SQLite does not define any index for INTEGER PRIMARY KEY columns: this method does not return any index that represents this primary key.
If you want to know if a set of columns uniquely identify a row, prefer table(_:hasUniqueKey:) instead.
Declaration
Swift
public func indexes(on tableName: String) throws -> [IndexInfo]
-
True if a sequence of columns uniquely identifies a row, that is to say if the columns are the primary key, or if there is a unique index on them.
Declaration
Swift
public func table<T: Sequence>(_ tableName: String, hasUniqueKey columns: T) throws -> Bool where T.Iterator.Element == String
-
Executes a block inside a database transaction.
try dbQueue.inDatabase do { try db.inTransaction { try db.execute("INSERT ...") return .commit } }
If the block throws an error, the transaction is rollbacked and the error is rethrown.
This method is not reentrant: you can’t nest transactions.
Throws
The error thrown by the block.Declaration
Swift
public func inTransaction(_ kind: TransactionKind? = nil, _ block: () throws -> TransactionCompletion) throws
Parameters
kind
The transaction type (default nil). If nil, the transaction type is configuration.defaultTransactionKind, which itself defaults to .immediate. See https://www.sqlite.org/lang_transaction.html for more information.
block
A block that executes SQL statements and return either .commit or .rollback.
-
Executes a block inside a savepoint.
try dbQueue.inDatabase do { try db.inSavepoint { try db.execute("INSERT ...") return .commit } }
If the block throws an error, the savepoint is rollbacked and the error is rethrown.
This method is reentrant: you can nest savepoints.
Throws
The error thrown by the block.Declaration
Swift
public func inSavepoint(_ block: () throws -> TransactionCompletion) throws
Parameters
block
A block that executes SQL statements and return either .commit or .rollback.
-
Add a transaction observer, so that it gets notified of database changes.
The transaction observer is weakly referenced: it is not retained, and stops getting notifications after it is deallocated.
Declaration
Swift
public func add(transactionObserver: TransactionObserver)
Parameters
transactionObserver
A transaction observer.
-
Remove a transaction observer.
Declaration
Swift
public func remove(transactionObserver: TransactionObserver)
-
Undocumented
Declaration
Swift
public final class Database
-
Creates a database table.
try db.create(table: "pointOfInterests") { t in t.column("id", .integer).primaryKey() t.column("title", .text) t.column("favorite", .boolean).notNull().default(false) t.column("longitude", .double).notNull() t.column("latitude", .double).notNull() }
See https://www.sqlite.org/lang_createtable.html and https://www.sqlite.org/withoutrowid.html
Throws
A DatabaseError whenever an SQLite error occurs.Declaration
Swift
public func create(table name: String, temporary: Bool = false, ifNotExists: Bool = false, withoutRowID: Bool, body: (TableDefinition) -> Void) throws
Parameters
name
The table name.
temporary
If true, creates a temporary table.
ifNotExists
If false, no error is thrown if table already exists.
withoutRowID
If true, uses WITHOUT ROWID optimization.
body
A closure that defines table columns and constraints.
-
Creates a database table.
try db.create(table: "pointOfInterests") { t in t.column("id", .integer).primaryKey() t.column("title", .text) t.column("favorite", .boolean).notNull().default(false) t.column("longitude", .double).notNull() t.column("latitude", .double).notNull() }
See https://www.sqlite.org/lang_createtable.html
Throws
A DatabaseError whenever an SQLite error occurs.Declaration
Swift
public func create(table name: String, temporary: Bool = false, ifNotExists: Bool = false, body: (TableDefinition) -> Void) throws
Parameters
name
The table name.
temporary
If true, creates a temporary table.
ifNotExists
If false, no error is thrown if table already exists.
body
A closure that defines table columns and constraints.
-
Renames a database table.
See https://www.sqlite.org/lang_altertable.html
Throws
A DatabaseError whenever an SQLite error occurs.Declaration
Swift
public func rename(table name: String, to newName: String) throws
-
Modifies a database table.
try db.alter(table: "persons") { t in t.add(column: "url", .text) }
See https://www.sqlite.org/lang_altertable.html
Throws
A DatabaseError whenever an SQLite error occurs.Declaration
Swift
public func alter(table name: String, body: (TableAlteration) -> Void) throws
Parameters
name
The table name.
body
A closure that defines table alterations.
-
Deletes a database table.
See https://www.sqlite.org/lang_droptable.html
Throws
A DatabaseError whenever an SQLite error occurs.Declaration
Swift
public func drop(table name: String) throws
-
Undocumented
Declaration
Swift
public final class Database
-
Creates an index.
try db.create(index: "personByEmail", on: "person", columns: ["email"])
SQLite can also index expressions (https://www.sqlite.org/expridx.html) and use specific collations. To create such an index, use a raw SQL query.
try db.execute("CREATE INDEX ...")
Declaration
Swift
public func create(index name: String, on table: String, columns: [String], unique: Bool = false, ifNotExists: Bool = false) throws
Parameters
name
The index name.
table
The name of the indexed table.
columns
The indexed columns.
unique
If true, creates a unique index.
ifNotExists
If false, no error is thrown if index already exists.
-
Creates a partial index.
try db.create(index: "personByEmail", on: "person", columns: ["email"], condition: Column("email") != nil)
See https://www.sqlite.org/lang_createindex.html, and https://www.sqlite.org/partialindex.html
Declaration
Swift
public func create(index name: String, on table: String, columns: [String], unique: Bool = false, ifNotExists: Bool = false, condition: SQLExpressible) throws
Parameters
name
The index name.
table
The name of the indexed table.
columns
The indexed columns.
unique
If true, creates a unique index.
ifNotExists
If false, no error is thrown if index already exists.
condition
The condition that indexed rows must verify.
-
Deletes a database index.
See https://www.sqlite.org/lang_dropindex.html
Throws
A DatabaseError whenever an SQLite error occurs.Declaration
Swift
public func drop(index name: String) throws
-
Creates a virtual database table.
try db.create(virtualTable: "vocabulary", using: "spellfix1")
See https://www.sqlite.org/lang_createtable.html
Throws
A DatabaseError whenever an SQLite error occurs.Declaration
Swift
public func create(virtualTable name: String, ifNotExists: Bool = false, using module: String) throws
Parameters
name
The table name.
ifNotExists
If false, no error is thrown if table already exists.
module
The name of an SQLite virtual table module.
-
Creates a virtual database table.
let module = ... try db.create(virtualTable: "pointOfInterests", using: module) { t in ... }
The type of the closure argument
t
depends on the type of the module argument: refer to this module’s documentation.Use this method to create full-text tables using the FTS3, FTS4, or FTS5 modules:
try db.create(virtualTable: "books", using: FTS4()) { t in t.column("title") t.column("author") t.column("body") }
See https://www.sqlite.org/lang_createtable.html
Throws
A DatabaseError whenever an SQLite error occurs.Declaration
Swift
public func create<Module: VirtualTableModule>(virtualTable tableName: String, ifNotExists: Bool = false, using module: Module, _ body: ((Module.TableDefinition) -> Void)? = nil) throws
Parameters
name
The table name.
ifNotExists
If false, no error is thrown if table already exists.
module
a VirtualTableModule
body
An optional closure that defines the virtual table.