Skip to content

Commit 98e2812

Browse files
committed
Convenience api for updating a single column
1 parent 8f6f1aa commit 98e2812

File tree

6 files changed

+212
-96
lines changed

6 files changed

+212
-96
lines changed

GRDB/QueryInterface/Request/QueryInterfaceRequest.swift

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
///
7878
/// ### Batch Update
7979
///
80+
/// - ``updateAll(_:onConflict:assignment:)``
8081
/// - ``updateAll(_:onConflict:assignments:)``
8182
/// - ``updateAll(_:onConflict:_:)-9r4v``
8283
/// - ``updateAll(_:onConflict:_:)-49qg8``
@@ -1036,7 +1037,41 @@ extension QueryInterfaceRequest {
10361037
/// try dbQueue.write { db in
10371038
/// // UPDATE player SET score = 0
10381039
/// let request = Player.all()
1039-
/// try request.updateAll(db) { [$0.score.set(to: 0)] }
1040+
/// try request.updateAll(db) { $0.score.set(to: 0) }
1041+
/// }
1042+
/// ```
1043+
///
1044+
/// - parameter db: A database connection.
1045+
/// - parameter conflictResolution: A policy for conflict resolution.
1046+
/// - parameter assignment: A closure that returns an assignment.
1047+
/// - returns: The number of updated rows.
1048+
/// - throws: A ``DatabaseError`` whenever an SQLite error occurs.
1049+
@discardableResult
1050+
public func updateAll(
1051+
_ db: Database,
1052+
onConflict conflictResolution: Database.ConflictResolution? = nil,
1053+
assignments: (RowDecoder.ColumnsProvider) -> ColumnAssignment
1054+
) throws -> Int
1055+
where RowDecoder: TableRecord
1056+
{
1057+
try updateAll(db, onConflict: conflictResolution, [assignments(RowDecoder.columns)])
1058+
}
1059+
1060+
/// Updates matching rows, and returns the number of updated rows.
1061+
///
1062+
/// For example:
1063+
///
1064+
/// ```swift
1065+
/// struct Player: TableRecord {
1066+
/// enum Columns {
1067+
/// static let score = Column("score")
1068+
/// }
1069+
/// }
1070+
///
1071+
/// try dbQueue.write { db in
1072+
/// // UPDATE player SET score = 0
1073+
/// let request = Player.all()
1074+
/// try request.updateAll(db) { $0.score.set(to: 0) }
10401075
/// }
10411076
/// ```
10421077
///
@@ -1797,9 +1832,9 @@ extension QueryInterfaceRequest {
17971832
///
17981833
/// try dbQueue.write { db in
17991834
/// // UPDATE player SET score = 0
1800-
/// try Player.updateAll(db) { [
1835+
/// try Player.updateAll(db) {
18011836
/// $0.score.set(to: 0)
1802-
/// ] }
1837+
/// }
18031838
/// }
18041839
/// ```
18051840
public struct ColumnAssignment {

GRDB/QueryInterface/SQL/Table.swift

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
///
4949
/// ### Updating Rows
5050
///
51+
/// - ``updateAll(_:onConflict:assignment:)``
5152
/// - ``updateAll(_:onConflict:assignments:)``
5253
/// - ``updateAll(_:onConflict:_:)-4w9b``
5354
/// - ``updateAll(_:onConflict:_:)-4cvap``
@@ -1914,7 +1915,42 @@ extension Table {
19141915
///
19151916
/// try dbQueue.write { db in
19161917
/// // UPDATE player SET score = 0
1917-
/// try playerTable.updateAll(db) { [$0.score.set(to: 0)] }
1918+
/// try playerTable.updateAll(db) { $0.score.set(to: 0) }
1919+
/// }
1920+
/// ```
1921+
///
1922+
/// - parameter db: A database connection.
1923+
/// - parameter conflictResolution: A policy for conflict resolution.
1924+
/// - parameter assignment: A closure that returns an assignments.
1925+
/// - returns: The number of updated rows.
1926+
/// - throws: A ``DatabaseError`` whenever an SQLite error occurs.
1927+
@discardableResult
1928+
public func updateAll(
1929+
_ db: Database,
1930+
onConflict conflictResolution: Database.ConflictResolution? = nil,
1931+
assignment: (RowDecoder.ColumnsProvider) -> ColumnAssignment)
1932+
throws -> Int
1933+
where RowDecoder: TableRecord
1934+
{
1935+
try updateAll(db, onConflict: conflictResolution, [assignment(RowDecoder.columns)])
1936+
}
1937+
1938+
/// Updates all rows, and returns the number of updated rows.
1939+
///
1940+
/// For example:
1941+
///
1942+
/// ```swift
1943+
/// struct Player: TableRecord {
1944+
/// enum Columns {
1945+
/// static let score = Column("score")
1946+
/// }
1947+
/// }
1948+
///
1949+
/// let playerTable = Table<Player>("player")
1950+
///
1951+
/// try dbQueue.write { db in
1952+
/// // UPDATE player SET score = 0
1953+
/// try playerTable.updateAll(db) { $0.score.set(to: 0) }
19181954
/// }
19191955
/// ```
19201956
///
@@ -1934,7 +1970,7 @@ extension Table {
19341970
{
19351971
try updateAll(db, onConflict: conflictResolution, assignments(RowDecoder.columns))
19361972
}
1937-
1973+
19381974
/// Updates all rows, and returns the number of updated rows.
19391975
///
19401976
/// For example:

GRDB/Record/TableRecord.swift

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ import Foundation
4949
///
5050
/// ### Updating Records
5151
///
52+
/// - ``updateAll(_:onConflict:assignment:)``
53+
/// - ``updateAll(_:onConflict:assignments:)``
5254
/// - ``updateAll(_:onConflict:_:)-7vv9x``
5355
/// - ``updateAll(_:onConflict:_:)-7atfw``
5456
///
@@ -758,7 +760,7 @@ extension TableRecord {
758760
///
759761
/// try dbQueue.write { db in
760762
/// // UPDATE player SET score = 0
761-
/// try Player.updateAll(db) { [$0.score.set(to: 0)] }
763+
/// try Player.updateAll(db) { $0.score.set(to: 0) }
762764
/// }
763765
/// ```
764766
///
@@ -779,6 +781,39 @@ extension TableRecord {
779781
try updateAll(db, onConflict: conflictResolution, assignments(columns))
780782
}
781783

784+
/// Updates all records, and returns the number of updated records.
785+
///
786+
/// For example:
787+
///
788+
/// ```swift
789+
/// struct Player: TableRecord {
790+
/// enum Columns {
791+
/// static let score = Column("score")
792+
/// }
793+
/// }
794+
///
795+
/// try dbQueue.write { db in
796+
/// // UPDATE player SET score = 0
797+
/// try Player.updateAll(db) { $0.score.set(to: 0) }
798+
/// }
799+
/// ```
800+
///
801+
/// - parameter db: A database connection.
802+
/// - parameter conflictResolution: A policy for conflict resolution,
803+
/// defaulting to the record's persistenceConflictPolicy.
804+
/// - parameter assignments: A closure that returns an assignment.
805+
/// - returns: The number of updated records.
806+
/// - throws: A ``DatabaseError`` whenever an SQLite error occurs.
807+
@discardableResult
808+
public static func updateAll(
809+
_ db: Database,
810+
onConflict conflictResolution: Database.ConflictResolution? = nil,
811+
assignment: (ColumnsProvider) -> ColumnAssignment)
812+
throws -> Int
813+
{
814+
try updateAll(db, onConflict: conflictResolution, [assignment(columns)])
815+
}
816+
782817
/// Updates all records, and returns the number of updated records.
783818
///
784819
/// For example:

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,7 +1767,7 @@ See the [query interface](#the-query-interface) for batch updates:
17671767
```swift
17681768
try Player
17691769
.filter { $0.team == "red" }
1770-
.updateAll(db) { [$0.score += 1] }
1770+
.updateAll(db) { $0.score += 1 }
17711771
```
17721772

17731773
:point_right: update methods are available for types that adopt the [PersistableRecord] protocol. Batch updates are available on the [TableRecord] protocol.
@@ -3237,7 +3237,7 @@ try dbQueue.write { db in
32373237
// Batch update
32383238
try Player
32393239
.filter { $0.team == "Reds" }
3240-
.updateAll(db) { [$0.score += 100] }
3240+
.updateAll(db) { $0.score += 100 }
32413241

32423242
// Batch delete
32433243
try Player
@@ -4448,34 +4448,34 @@ try Player.updateAll(db) { [
44484448
// UPDATE player SET score = 0 WHERE team = 'Reds'
44494449
try Player
44504450
.filter { $0.team == "Reds" }
4451-
.updateAll(db) { [$0.score.set(to: 0)] }
4451+
.updateAll(db) { $0.score.set(to: 0) }
44524452

44534453
// UPDATE player SET isGreat = 1 ORDER BY score DESC LIMIT 10
44544454
try Player
44554455
.order(\.score.desc)
44564456
.limit(10)
4457-
.updateAll(db) { [$0.isGreat.set(to: true)] }
4457+
.updateAll(db) { $0.isGreat.set(to: true) }
44584458

44594459
// UPDATE country SET population = 67848156 WHERE id = 'FR'
44604460
try Country
44614461
.filter(id: "FR")
4462-
.updateAll(db) { [$0.population.set(to: 67_848_156)] }
4462+
.updateAll(db) { $0.population.set(to: 67_848_156) }
44634463
```
44644464

44654465
Column assignments accept any expression:
44664466

44674467
```swift
44684468
// UPDATE player SET score = score + (bonus * 2)
4469-
try Player.updateAll(db) { [
4469+
try Player.updateAll(db) {
44704470
$0.score.set(to: $0.score + $0.bonus * 2)
4471-
] }
4471+
}
44724472
```
44734473

44744474
As a convenience, you can also use the `+=`, `-=`, `*=`, or `/=` operators:
44754475

44764476
```swift
44774477
// UPDATE player SET score = score + (bonus * 2)
4478-
try Player.updateAll(db) { [$0.score += $0.bonus * 2] }
4478+
try Player.updateAll(db) { $0.score += $0.bonus * 2 }
44794479
```
44804480

44814481
Default [Conflict Resolution] rules apply, and you may also provide a specific one:

0 commit comments

Comments
 (0)