Protocols
The following protocols are available globally.
-
A type that supplies the values of some external resource, one at a time.
Overview
The most common way to iterate over the elements of a cursor is to use a
while
loop:let cursor = ... while let element = try cursor.next() { ... }
Relationship with standard Sequence and IteratorProtocol
Cursors share traits with lazy sequences and iterators from the Swift standard library. Differences are:
- Cursor types are classes, and have a lifetime.
- Cursor iteration may throw errors.
- A cursor can not be repeated.
The protocol comes with default implementations for many operations similar to those defined by Swift’s Sequence protocol:
See morecontains
,dropFirst
,dropLast
,drop(while:)
,enumerated
,filter
,first
,flatMap
,forEach
,joined
,joined(separator:)
,max
,max(by:)
,min
,min(by:)
,map
,prefix
,prefix(while:)
,reduce
,reduce(into:)
,suffix
.Declaration
Swift
public protocol Cursor : AnyObject
-
The protocol for custom SQLite aggregates.
For example:
See morestruct MySum : DatabaseAggregate { var sum: Int = 0 mutating func step(_ dbValues: [DatabaseValue]) { if let int = Int.fromDatabaseValue(dbValues[0]) { sum += int } } func finalize() -> DatabaseValueConvertible? { return sum } } let dbQueue = DatabaseQueue() let fn = DatabaseFunction("mysum", argumentCount: 1, aggregate: MySum.self) try dbQueue.write { db in db.add(function: fn) try db.execute(sql: "CREATE TABLE test(i)") try db.execute(sql: "INSERT INTO test(i) VALUES (1)") try db.execute(sql: "INSERT INTO test(i) VALUES (2)") try Int.fetchOne(db, sql: "SELECT mysum(i) FROM test")! // 3 }
Declaration
Swift
public protocol DatabaseAggregate
-
DatabaseReader
is the protocol for all types that can fetch values from an SQLite database.It is adopted by
DatabaseQueue
,DatabasePool
, andDatabaseSnapshot
.The protocol comes with isolation guarantees that describe the behavior of adopting types in a multithreaded application.
Types that adopt the protocol can provide in practice stronger guarantees. For example,
DatabaseQueue
provides a stronger isolation level thanDatabasePool
.Warning: Isolation guarantees stand as long as there is no external connection to the database. Should you have to cope with external connections, protect yourself with transactions, and be ready to setup a busy handler.
See moreDeclaration
Swift
public protocol DatabaseReader : AnyObject, Sendable
-
DatabaseRegionConvertible
is the protocol for values that can be turned into aDatabaseRegion
.Such values specify the region obserbed by
See moreDatabaseRegionObservation
.Declaration
Swift
public protocol DatabaseRegionConvertible
-
Types that adopt DatabaseValueConvertible can be initialized from database values.
The protocol comes with built-in methods that allow to fetch cursors, arrays, or single values:
try String.fetchCursor(db, sql: "SELECT name FROM ...", arguments:...) // Cursor of String try String.fetchAll(db, sql: "SELECT name FROM ...", arguments:...) // [String] try String.fetchOne(db, sql: "SELECT name FROM ...", arguments:...) // String? let statement = try db.makeStatement(sql: "SELECT name FROM ...") try String.fetchCursor(statement, arguments:...) // Cursor of String try String.fetchAll(statement, arguments:...) // [String] try String.fetchOne(statement, arguments:...) // String?
DatabaseValueConvertible is adopted by Bool, Int, String, etc.
See moreDeclaration
Swift
public protocol DatabaseValueConvertible : SQLExpressible, StatementBinding
-
The protocol for all requests that fetch database rows, and tell how those rows should be interpreted.
See morestruct Player: FetchableRecord { ... } let request: ... // Some FetchRequest that fetches Player try request.fetchCursor(db) // Cursor of Player try request.fetchAll(db) // [Player] try request.fetchSet(db) // Set<Player> try request.fetchOne(db) // Player? try request.fetchCount(db) // Int
Declaration
Swift
public protocol FetchRequest : DatabaseRegionConvertible, SQLSubqueryable
-
DatabaseWriter
is the protocol for all types that can write into an SQLite database.It is adopted by
DatabaseQueue
andDatabasePool
.The protocol comes with isolation guarantees that describe the behavior of adopting types in a multithreaded application.
Types that adopt the protocol can in practice provide stronger guarantees. For example,
DatabaseQueue
provides a stronger isolation level thanDatabasePool
.Warning: Isolation guarantees stand as long as there is no external connection to the database. Should you have to cope with external connections, protect yourself with transactions, and be ready to setup a busy handler.
See moreDeclaration
Swift
public protocol DatabaseWriter : DatabaseReader
-
RowAdapter
is a protocol that helps two incompatible row interfaces working together.GRDB ships with four concrete types that adopt the RowAdapter protocol:
ColumnMapping
: renames row columnsEmptyRowAdapter
: hides all columnsRangeRowAdapter
: exposes a range of columnsRenameColumnAdapter
: transforms column names with a functionScopeAdapter
: defines row scopesSuffixRowAdapter
: hides the first columns of a row
To use a row adapter, provide it to any method that fetches:
See morelet adapter = SuffixRowAdapter(fromIndex: 2) let sql = "SELECT 1 AS foo, 2 AS bar, 3 AS baz" // [baz:3] try Row.fetchOne(db, sql: sql, adapter: adapter)
Declaration
Swift
public protocol RowAdapter : _RowAdapter
-
A protocol for cursors that iterate a database statement.
See moreDeclaration
Swift
public protocol DatabaseCursor : _DatabaseCursor
-
Undocumented
See moreDeclaration
Swift
public protocol StatementBinding
-
The
StatementColumnConvertible
protocol grants access to the low-level C interface that extracts values from query results: https://www.sqlite.org/c3ref/column_blob.html. It can bring performance improvements.To use it, have a value type adopt both
StatementColumnConvertible
andDatabaseValueConvertible
. GRDB will then automatically apply the optimization whenever direct access to SQLite is possible:
See morelet rows = Row.fetchCursor(db, sql: "SELECT ...") while let row = try rows.next() { let int: Int = row[0] // there } let ints = Int.fetchAll(db, sql: "SELECT ...") // there struct Player { init(row: Row) { name = row["name"] // there score = row["score"] // there } }
Declaration
Swift
public protocol StatementColumnConvertible
-
SQLSelectable is the protocol for types that can be selected, as described at https://www.sqlite.org/syntax/result-column.html
See moreDeclaration
Swift
public protocol SQLSelectable
-
The protocol for all types that can be used as an SQL ordering term, as described at https://www.sqlite.org/syntax/ordering-term.html
See moreDeclaration
Swift
public protocol SQLOrderingTerm
-
SQLExpressible
is the protocol for all types that can be used as an SQL expression.It is adopted by protocols like
DatabaseValueConvertible
, and types likeColumn
.See https://github.com/groue/GRDB.swift/#the-query-interface
See moreDeclaration
Swift
public protocol SQLExpressible
-
SQLSpecificExpressible
is a protocol for all database-specific types that can be turned into an SQL expression. Types whose existence is not purely dedicated to the database should adopt theSQLExpressible
protocol instead.For example,
Column
is a type that only exists to help you build requests, and it adoptsSQLSpecificExpressible
.On the other side,
See moreInt
adoptsSQLExpressible
.Declaration
Swift
public protocol SQLSpecificExpressible : SQLExpressible, SQLOrderingTerm, SQLSelectable
-
A transaction observer is notified of all changes and transactions committed or rollbacked on a database.
Adopting types must be a class.
See moreDeclaration
Swift
public protocol TransactionObserver : AnyObject
-
The protocol for custom FTS5 tokenizers.
See more -
The protocol for FTS5 tokenizers
See more -
The protocol for custom FTS5 tokenizers that wrap another tokenizer.
Types that adopt FTS5WrapperTokenizer don’t have to implement the low-level FTS5Tokenizer.tokenize(context:flags:pText:nText:tokenCallback:).
Instead, they process regular Swift strings.
Here is the implementation for a trivial tokenizer that wraps the built-in ascii tokenizer without any custom processing:
See moreclass TrivialAsciiTokenizer : FTS5WrapperTokenizer { static let name = "trivial" let wrappedTokenizer: FTS5Tokenizer init(db: Database, arguments: [String]) throws { wrappedTokenizer = try db.makeTokenizer(.ascii()) } func accept( token: String, flags: FTS5TokenFlags, for tokenization: FTS5Tokenization, tokenCallback: FTS5WrapperTokenCallback) throws { try tokenCallback(token, flags) } }
-
The protocol for all requests that feed from a database table
See moreDeclaration
Swift
public protocol TableRequest
-
Types that adopt
TableRecord
declare a particular relationship with a database table.Types that adopt both
TableRecord
andFetchableRecord
are granted with built-in methods that allow to fetch instances identified by key:
See moretry Player.fetchOne(db, key: 123) // Player? try Citizenship.fetchOne(db, key: ["citizenId": 12, "countryId": 45]) // Citizenship?
Declaration
Swift
public protocol TableRecord
-
Adopt the ColumnExpression protocol when you define a column type.
You can, for example, define a String-based column enum:
enum Columns: String, ColumnExpression { case id, name, score } let arthur = try Player.filter(Columns.name == "Arthur").fetchOne(db)
You can also define a genuine column type:
struct MyColumn: ColumnExpression { var name: String var sqlType: String } let nameColumn = MyColumn(name: "name", sqlType: "VARCHAR") let arthur = try Player.filter(nameColumn == "Arthur").fetchOne(db)
See https://github.com/groue/GRDB.swift#the-query-interface
See moreDeclaration
Swift
public protocol ColumnExpression : SQLSpecificExpressible
-
The base protocol for all associations that define a connection between two record types.
See moreDeclaration
Swift
public protocol Association : DerivableRequest, _Association
-
The base protocol for all associations that define a one-to-one connection.
See moreDeclaration
Swift
public protocol AssociationToOne : Association
-
The base protocol for all associations that define a one-to-many connection.
See moreDeclaration
Swift
public protocol AssociationToMany : Association
-
The protocol for all requests that know how database rows should be interpreted.
See moreDeclaration
Swift
public protocol TypedRequest
-
The protocol for all requests that can refine their selection.
See moreDeclaration
Swift
public protocol SelectionRequest
-
The protocol for all requests that can be filtered.
See moreDeclaration
Swift
public protocol FilteredRequest
-
The protocol for all requests that can aggregate.
See moreDeclaration
Swift
public protocol AggregatingRequest
-
The protocol for all requests that can be ordered.
See moreDeclaration
Swift
public protocol OrderedRequest
-
The protocol for all requests that can be associated.
See moreDeclaration
Swift
public protocol JoinableRequest : TypedRequest, _JoinableRequest
-
The base protocol for all requests that can be refined.
See moreDeclaration
Swift
public protocol DerivableRequest: AggregatingRequest, FilteredRequest, JoinableRequest, OrderedRequest, SelectionRequest, TableRequest
-
The protocol for types that can be embedded as a subquery.
See moreDeclaration
Swift
public protocol SQLSubqueryable : SQLSpecificExpressible
-
The protocol for SQLite virtual table modules. It lets you define a DSL for the
Database.create(virtualTable:using:)
method:let module = ... try db.create(virtualTable: "item", using: module) { t in ... }
GRDB ships with three concrete classes that implement this protocol: FTS3, FTS4 and FTS5.
See moreDeclaration
Swift
public protocol VirtualTableModule
-
Types that adopt
See moreEncodableRecord
can be encoded into the database.Declaration
Swift
public protocol EncodableRecord
-
Types that adopt
FetchableRecord
can be initialized from a database Row.let row = try Row.fetchOne(db, sql: "SELECT ...")! let player = Player(row)
The protocol comes with built-in methods that allow to fetch cursors, arrays, or single records:
See moretry Player.fetchCursor(db, sql: "SELECT ...", arguments:...) // Cursor of Player try Player.fetchAll(db, sql: "SELECT ...", arguments:...) // [Player] try Player.fetchOne(db, sql: "SELECT ...", arguments:...) // Player? let statement = try db.makeStatement(sql: "SELECT ...") try Player.fetchCursor(statement, arguments:...) // Cursor of Player try Player.fetchAll(statement, arguments:...) // [Player] try Player.fetchOne(statement, arguments:...) // Player?
Declaration
Swift
public protocol FetchableRecord
-
Types that adopt
See moreMutablePersistableRecord
can be inserted, updated, and deleted.Declaration
Swift
public protocol MutablePersistableRecord : EncodableRecord, TableRecord
-
Types that adopt
PersistableRecord
can be inserted, updated, and deleted.Unlike
See moreMutablePersistableRecord
, theinsert(_:)
andsave(_:)
methods are not mutating methods.Declaration
Swift
public protocol PersistableRecord : MutablePersistableRecord
-
A protocol indicating that an activity or action supports cancellation.
See moreDeclaration
Swift
public protocol DatabaseCancellable
-
The
ValueReducer
protocol supportsValueObservation
.Declaration
Swift
public protocol ValueReducer : _ValueReducer