Protocols

The following protocols are available globally.

Cursor

  • 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: contains, 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.

    See more

    Declaration

    Swift

    public protocol Cursor : AnyObject
  • The protocol for custom SQLite aggregates.

    For example:

    struct 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
    }
    
    See more

    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, and DatabaseSnapshot.

    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 than DatabasePool.

    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 more

    Declaration

    Swift

    public protocol DatabaseReader : AnyObject, Sendable

DatabaseRegionConvertible

  • DatabaseRegionConvertible is the protocol for values that can be turned into a DatabaseRegion.

    Such values specify the region obserbed by DatabaseRegionObservation.

    See more

    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 more

    Declaration

    Swift

    public protocol DatabaseValueConvertible : SQLExpressible, StatementBinding

FetchRequest

  • The protocol for all requests that fetch database rows, and tell how those rows should be interpreted.

    struct 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
    
    See more

    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 and DatabasePool.

    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 than DatabasePool.

    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 more

    Declaration

    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:

    To use a row adapter, provide it to any method that fetches:

    let 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)
    
    See more

    Declaration

    Swift

    public protocol RowAdapter : _RowAdapter

Cursors

StatementBinding

  • Undocumented

    See more

    Declaration

    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 and DatabaseValueConvertible. GRDB will then automatically apply the optimization whenever direct access to SQLite is possible:

    let 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
        }
    }
    
    See more

    Declaration

    Swift

    public protocol StatementColumnConvertible

SQLSelectable

SQLOrderingTerm

SQLExpressible

TransactionObserver

  • A transaction observer is notified of all changes and transactions committed or rollbacked on a database.

    Adopting types must be a class.

    See more

    Declaration

    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:

    class 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)
        }
    }
    
    See more

TableRequest

  • The protocol for all requests that feed from a database table

    See more

    Declaration

    Swift

    public protocol TableRequest
  • Types that adopt TableRecord declare a particular relationship with a database table.

    Types that adopt both TableRecord and FetchableRecord are granted with built-in methods that allow to fetch instances identified by key:

    try Player.fetchOne(db, key: 123)  // Player?
    try Citizenship.fetchOne(db, key: ["citizenId": 12, "countryId": 45]) // Citizenship?
    
    See more

    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 more

    Declaration

    Swift

    public protocol ColumnExpression : SQLSpecificExpressible
  • The base protocol for all associations that define a connection between two record types.

    See more

    Declaration

    Swift

    public protocol Association : DerivableRequest, _Association

AssociationToOne

AssociationToMany

TypedRequest

SelectionRequest

FilteredRequest

AggregatingRequest

OrderedRequest

JoinableRequest

DerivableRequest

SQLSubqueryable

  • The protocol for types that can be embedded as a subquery.

    See more

    Declaration

    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 more

    Declaration

    Swift

    public protocol VirtualTableModule
  • Types that adopt EncodableRecord can be encoded into the database.

    See more

    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:

    try 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?
    
    See more

    Declaration

    Swift

    public protocol FetchableRecord
  • Types that adopt MutablePersistableRecord can be inserted, updated, and deleted.

    See more

    Declaration

    Swift

    public protocol MutablePersistableRecord : EncodableRecord, TableRecord

PersistableRecord