MutablePersistableRecord
public protocol MutablePersistableRecord : TableRecord
Types that adopt MutablePersistableRecord can be inserted, updated, and deleted.
-
persistenceConflictPolicy
Default implementationThe policy that handles SQLite conflicts when records are inserted or updated.
This property is optional: its default value uses the ABORT policy for both insertions and updates, and has GRDB generate regular INSERT and UPDATE queries.
If insertions are resolved with .ignore policy, the
didInsert(with:for:)
method is not called upon successful insertion, even if a row was actually inserted without any conflict.Default Implementation
Describes the conflict policy for insertions and updates.
The default value specifies ABORT policy for both insertions and updates, which has GRDB generate regular INSERT and UPDATE queries.
Declaration
Swift
static var persistenceConflictPolicy: PersistenceConflictPolicy { get }
-
encode(to:)
Default implementationDefines the values persisted in the database.
Store in the container argument all values that should be stored in the columns of the database table (see databaseTableName()).
Primary key columns, if any, must be included.
struct Player : MutablePersistableRecord { var id: Int64? var name: String? func encode(to container: inout PersistenceContainer) { container["id"] = id container["name"] = name } }
It is undefined behavior to set different values for the same column. Column names are case insensitive, so defining both
name
andNAME
is considered undefined behavior.Default Implementation
Declaration
Swift
func encode(to container: inout PersistenceContainer)
-
didInsert(with:for:)
Default implementationNotifies the record that it was succesfully inserted.
Do not call this method directly: it is called for you, in a protected dispatch queue, with the inserted RowID and the eventual INTEGER PRIMARY KEY column name.
This method is optional: the default implementation does nothing.
struct Player : MutablePersistableRecord { var id: Int64? var name: String? mutating func didInsert(with rowID: Int64, for column: String?) { self.id = rowID } }
Default Implementation
Notifies the record that it was succesfully inserted.
The default implementation does nothing.
Declaration
Swift
mutating func didInsert(with rowID: Int64, for column: String?)
Parameters
rowID
The inserted rowID.
column
The name of the eventual INTEGER PRIMARY KEY column.
-
insert(_:)
Default implementationExecutes an INSERT statement.
This method is guaranteed to have inserted a row in the database if it returns without error.
Upon successful insertion, the didInsert(with:for:) method is called with the inserted RowID and the eventual INTEGER PRIMARY KEY column name.
This method has a default implementation, so your adopting types don’t have to implement it. Yet your types can provide their own implementation of insert(). In their implementation, it is recommended that they invoke the performInsert() method.
Throws
A DatabaseError whenever an SQLite error occurs.Default Implementation
Executes an INSERT statement.
The default implementation for insert() invokes performInsert().
Declaration
Swift
mutating func insert(_ db: Database) throws
Parameters
db
A database connection.
-
update(_:columns:)
Default implementationExecutes an UPDATE statement.
This method is guaranteed to have updated a row in the database if it returns without error.
This method has a default implementation, so your adopting types don’t have to implement it. Yet your types can provide their own implementation of update(). In their implementation, it is recommended that they invoke the performUpdate() method.
Throws
A DatabaseError is thrown whenever an SQLite error occurs. PersistenceError.recordNotFound is thrown if the primary key does not match any row in the database.Default Implementation
Executes an UPDATE statement.
Throws
A DatabaseError is thrown whenever an SQLite error occurs. PersistenceError.recordNotFound is thrown if the primary key does not match any row in the database.Executes an UPDATE statement.
Throws
A DatabaseError is thrown whenever an SQLite error occurs. PersistenceError.recordNotFound is thrown if the primary key does not match any row in the database.Executes an UPDATE statement.
Throws
A DatabaseError is thrown whenever an SQLite error occurs. PersistenceError.recordNotFound is thrown if the primary key does not match any row in the database.Declaration
Swift
func update(_ db: Database, columns: Set<String>) throws
Parameters
db
A database connection.
columns
The columns to update.
-
save(_:)
Default implementationExecutes an INSERT or an UPDATE statement so that
self
is saved in the database.If the receiver has a non-nil primary key and a matching row in the database, this method performs an update.
Otherwise, performs an insert.
This method is guaranteed to have inserted or updated a row in the database if it returns without error.
This method has a default implementation, so your adopting types don’t have to implement it. Yet your types can provide their own implementation of save(). In their implementation, it is recommended that they invoke the performSave() method.
Throws
A DatabaseError whenever an SQLite error occurs, or errors thrown by update().Default Implementation
Executes an INSERT or an UPDATE statement so that
self
is saved in the database.The default implementation for save() invokes performSave().
Declaration
Swift
mutating func save(_ db: Database) throws
Parameters
db
A database connection.
-
delete(_:)
Default implementationExecutes a DELETE statement.
This method has a default implementation, so your adopting types don’t have to implement it. Yet your types can provide their own implementation of delete(). In their implementation, it is recommended that they invoke the performDelete() method.
Throws
A DatabaseError is thrown whenever an SQLite error occurs.Default Implementation
Executes a DELETE statement.
The default implementation for delete() invokes performDelete().
Declaration
Swift
@discardableResult func delete(_ db: Database) throws -> Bool
Parameters
db
A database connection.
Return Value
Whether a database row was deleted.
-
exists(_:)
Default implementationReturns true if and only if the primary key matches a row in the database.
This method has a default implementation, so your adopting types don’t have to implement it. Yet your types can provide their own implementation of exists(). In their implementation, it is recommended that they invoke the performExists() method.
Throws
A DatabaseError is thrown whenever an SQLite error occurs.Default Implementation
Returns true if and only if the primary key matches a row in the database.
The default implementation for exists() invokes performExists().
Declaration
Swift
func exists(_ db: Database) throws -> Bool
Parameters
db
A database connection.
Return Value
Whether the primary key matches a row in the database.
-
databaseEncodingUserInfo
Default implementationWhen the PersistableRecord type also adopts the standard Encodable protocol, you can use this dictionary to customize the encoding process into database rows.
For example:
// A key that holds a encoder's name let encoderName = CodingUserInfoKey(rawValue: "encoderName")! // A PersistableRecord + Encodable record struct Player: PersistableRecord, Encodable { // Customize the encoder name when encoding a database row static let databaseEncodingUserInfo: [CodingUserInfoKey: Any] = [encoderName: "Database"] func encode(to encoder: Encoder) throws { // Print the encoder name print(encoder.userInfo[encoderName]) ... } } let player = Player(...) // prints "Database" try player.insert(db) // prints "JSON" let encoder = JSONEncoder() encoder.userInfo = [encoderName: "JSON"] let data = try encoder.encode(player)
Default Implementation
Declaration
Swift
static var databaseEncodingUserInfo: [CodingUserInfoKey : Any] { get }
-
databaseJSONEncoder(for:)
Default implementationWhen the PersistableRecord type also adopts the standard Encodable protocol, this method controls the encoding process of nested properties into JSON database columns.
The default implementation returns a JSONEncoder with the following properties:
- dataEncodingStrategy: .base64
- dateEncodingStrategy: .millisecondsSince1970
- nonConformingFloatEncodingStrategy: .throw
- outputFormatting: .sortedKeys (iOS 11.0+, macOS 10.13+, watchOS 4.0+)
You can override those defaults:
struct Achievement: Encodable { var name: String var date: Date } struct Player: Encodable, PersistableRecord { // stored in a JSON column var achievements: [Achievement] static func databaseJSONEncoder(for column: String) -> JSONEncoder { let encoder = JSONEncoder() encoder.dateEncodingStrategy = .iso8601 return encoder } }
Default Implementation
Declaration
Swift
static func databaseJSONEncoder(for column: String) -> JSONEncoder
-
databaseDateEncodingStrategy
Default implementationWhen the PersistableRecord type also adopts the standard Encodable protocol, this property controls the encoding of date properties.
Default value is .deferredToDate
For example:
struct Player: PersistableRecord, Encodable { static let databaseDateEncodingStrategy: DatabaseDateEncodingStrategy = .timeIntervalSince1970 var name: String var registrationDate: Date // encoded as an epoch timestamp }
Default Implementation
Declaration
Swift
static var databaseDateEncodingStrategy: DatabaseDateEncodingStrategy { get }
-
databaseUUIDEncodingStrategy
Default implementationWhen the PersistableRecord type also adopts the standard Encodable protocol, this property controls the encoding of UUID properties.
Default value is .deferredToUUID
For example:
struct Player: PersistableProtocol, Encodable { static let databaseUUIDEncodingStrategy: DatabaseUUIDEncodingStrategy = .string // encoded in a string like "E621E1F8-C36C-495A-93FC-0C247A3E6E5F" var uuid: UUID }
Default Implementation
Declaration
Swift
static var databaseUUIDEncodingStrategy: DatabaseUUIDEncodingStrategy { get }
-
request(for:)
Extension methodCreates a request that fetches the associated record(s).
For example:
struct Team: { static let players = hasMany(Player.self) var players: QueryInterfaceRequest<Player> { return request(for: Team.players) } } let team: Team = ... let players = try team.players.fetchAll(db) // [Player]
Declaration
Swift
public func request<A>(for association: A) -> QueryInterfaceRequest<A.RowDecoder> where Self == A.OriginRowDecoder, A : Association
-
databaseDictionary
Extension methodA dictionary whose keys are the columns encoded in the
encode(to:)
method.Declaration
Swift
public var databaseDictionary: [String : DatabaseValue] { get }
-
update(_:)
Extension methodExecutes an UPDATE statement that updates all table columns.
Throws
A DatabaseError is thrown whenever an SQLite error occurs. PersistenceError.recordNotFound is thrown if the primary key does not match any row in the database.Declaration
Swift
public func update(_ db: Database) throws
Parameters
db
A database connection.
-
updateChanges(_:from:)
Extension methodIf the record has any difference from the other record, executes an UPDATE statement so that those differences and only those difference are saved in the database.
This method is guaranteed to have saved the eventual differences in the database if it returns without error.
For example:
if let oldPlayer = try Player.fetchOne(db, key: 42) { var newPlayer = oldPlayer newPlayer.score += 10 newPlayer.hasAward = true try newPlayer.updateChanges(db, from: oldRecord) }
Throws
A DatabaseError is thrown whenever an SQLite error occurs. PersistenceError.recordNotFound is thrown if the primary key does not match any row in the database and record could not be updated.See also
updateChanges(_:with:)Declaration
Swift
@discardableResult public func updateChanges(_ db: Database, from record: MutablePersistableRecord) throws -> Bool
Parameters
db
A database connection.
record
The comparison record.
Return Value
Whether the record had changes.
-
updateChanges(_:with:)
Extension methodMutates the record according to the provided closure, and then, if the record has any difference from its previous version, executes an UPDATE statement so that those differences and only those difference are saved in the database.
This method is guaranteed to have saved the eventual differences in the database if it returns without error.
For example:
if var player = try Player.fetchOne(db, key: 42) { try player.updateChanges(db) { $0.score += 10 $0.hasAward = true } }
Throws
A DatabaseError is thrown whenever an SQLite error occurs. PersistenceError.recordNotFound is thrown if the primary key does not match any row in the database and record could not be updated.Declaration
Swift
@discardableResult public mutating func updateChanges(_ db: Database, with change: (inout Self) throws -> Void) throws -> Bool
Parameters
db
A database connection.
change
A closure that modifies the record.
Return Value
Whether the record had changes.
-
databaseEquals(_:)
Extension methodReturns a boolean indicating whether this record and the other record have the same database representation.
Declaration
Swift
public func databaseEquals(_ record: Self) -> Bool
-
databaseChanges(from:)
Extension methodA dictionary of values changed from the other record.
Its keys are column names. Its values come from the other record.
Note that this method is not symmetrical, not only in terms of values, but also in terms of columns. When the two records don’t define the same set of columns in their
encode(to:)
method, only the columns defined by the receiver record are considered.Declaration
Swift
public func databaseChanges(from record: MutablePersistableRecord) -> [String : DatabaseValue]
-
performInsert(_:)
Extension methodDon’t invoke this method directly: it is an internal method for types that adopt MutablePersistableRecord.
performInsert() provides the default implementation for insert(). Types that adopt MutablePersistableRecord can invoke performInsert() in their implementation of insert(). They should not provide their own implementation of performInsert().
Declaration
Swift
public mutating func performInsert(_ db: Database) throws
-
performUpdate(_:columns:)
Extension methodDon’t invoke this method directly: it is an internal method for types that adopt MutablePersistableRecord.
performUpdate() provides the default implementation for update(). Types that adopt MutablePersistableRecord can invoke performUpdate() in their implementation of update(). They should not provide their own implementation of performUpdate().
Throws
A DatabaseError is thrown whenever an SQLite error occurs. PersistenceError.recordNotFound is thrown if the primary key does not match any row in the database.Declaration
Swift
public func performUpdate(_ db: Database, columns: Set<String>) throws
Parameters
db
A database connection.
columns
The columns to update.
-
performSave(_:)
Extension methodDon’t invoke this method directly: it is an internal method for types that adopt MutablePersistableRecord.
performSave() provides the default implementation for save(). Types that adopt MutablePersistableRecord can invoke performSave() in their implementation of save(). They should not provide their own implementation of performSave().
This default implementation forwards the job to
update
orinsert
.Declaration
Swift
public mutating func performSave(_ db: Database) throws
-
performDelete(_:)
Extension methodDon’t invoke this method directly: it is an internal method for types that adopt MutablePersistableRecord.
performDelete() provides the default implementation for deelte(). Types that adopt MutablePersistableRecord can invoke performDelete() in their implementation of delete(). They should not provide their own implementation of performDelete().
Declaration
Swift
public func performDelete(_ db: Database) throws -> Bool
-
performExists(_:)
Extension methodDon’t invoke this method directly: it is an internal method for types that adopt MutablePersistableRecord.
performExists() provides the default implementation for exists(). Types that adopt MutablePersistableRecord can invoke performExists() in their implementation of exists(). They should not provide their own implementation of performExists().
Declaration
Swift
public func performExists(_ db: Database) throws -> Bool
-
updateChanges(_:with:)
Extension methodMutates the record according to the provided closure, and then, if the record has any difference from its previous version, executes an UPDATE statement so that those differences and only those difference are saved in the database.
This method is guaranteed to have saved the eventual differences in the database if it returns without error.
For example:
if let player = try Player.fetchOne(db, key: 42) { try player.updateChanges(db) { $0.score += 10 $0.hasAward = true } }
Throws
A DatabaseError is thrown whenever an SQLite error occurs. PersistenceError.recordNotFound is thrown if the primary key does not match any row in the database and record could not be updated.Declaration
Swift
@discardableResult public func updateChanges(_ db: Database, with change: (Self) throws -> Void) throws -> Bool
Parameters
db
A database connection.
change
A closure that modifies the record.
Return Value
Whether the record had changes.
-
deleteAll(_:)
Extension methodDeletes all records; returns the number of deleted rows.
Throws
A DatabaseError is thrown whenever an SQLite error occurs.Declaration
Swift
@discardableResult public static func deleteAll(_ db: Database) throws -> Int
Parameters
db
A database connection.
Return Value
The number of deleted rows
-
deleteAll(_:keys:)
Extension methodDelete records identified by their primary keys; returns the number of deleted rows.
// DELETE FROM player WHERE id IN (1, 2, 3) try Player.deleteAll(db, keys: [1, 2, 3]) // DELETE FROM country WHERE code IN ('FR', 'US', 'DE') try Country.deleteAll(db, keys: ["FR", "US", "DE"])
When the table has no explicit primary key, GRDB uses the hidden
rowid
column:// DELETE FROM document WHERE rowid IN (1, 2, 3) try Document.deleteAll(db, keys: [1, 2, 3])
Declaration
Swift
@discardableResult public static func deleteAll<Sequence>(_ db: Database, keys: Sequence) throws -> Int where Sequence : Sequence, Sequence.Element : DatabaseValueConvertible
Parameters
db
A database connection.
keys
A sequence of primary keys.
Return Value
The number of deleted rows
-
deleteOne(_:key:)
Extension methodDelete a record, identified by its primary key; returns whether a database row was deleted.
// DELETE FROM player WHERE id = 123 try Player.deleteOne(db, key: 123) // DELETE FROM country WHERE code = 'FR' try Country.deleteOne(db, key: "FR")
When the table has no explicit primary key, GRDB uses the hidden
rowid
column:// DELETE FROM document WHERE rowid = 1 try Document.deleteOne(db, key: 1)
Declaration
Swift
@discardableResult public static func deleteOne<PrimaryKeyType>(_ db: Database, key: PrimaryKeyType?) throws -> Bool where PrimaryKeyType : DatabaseValueConvertible
Parameters
db
A database connection.
key
A primary key value.
Return Value
Whether a database row was deleted.
-
deleteAll(_:keys:)
Extension methodDelete records identified by the provided unique keys (primary key or any key with a unique index on it); returns the number of deleted rows.
try Player.deleteAll(db, keys: [["email": "a@example.com"], ["email": "b@example.com"]])
Declaration
Swift
@discardableResult public static func deleteAll(_ db: Database, keys: [[String : DatabaseValueConvertible?]]) throws -> Int
Parameters
db
A database connection.
keys
An array of key dictionaries.
Return Value
The number of deleted rows
-
deleteOne(_:key:)
Extension methodDelete a record, identified by a unique key (the primary key or any key with a unique index on it); returns whether a database row was deleted.
Player.deleteOne(db, key: ["name": Arthur"])
Declaration
Swift
@discardableResult public static func deleteOne(_ db: Database, key: [String : DatabaseValueConvertible?]) throws -> Bool
Parameters
db
A database connection.
key
A dictionary of values.
Return Value
Whether a database row was deleted.