Skip to content

Commit 6bf346c

Browse files
committed
Merge branch 'development'
2 parents 23f4254 + 1036dd4 commit 6bf346c

File tree

322 files changed

+13514
-9746
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

322 files changed

+13514
-9746
lines changed

CHANGELOG.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
55

66
GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception: APIs flagged [**:fire: EXPERIMENTAL**](README.md#what-are-experimental-features). Those are unstable, and may break between any two minor releases of the library.
77

8+
#### 6.x Releases
9+
10+
- `6.0.0` Betas - [6.0.0-beta](#600-beta)
11+
812
#### 5.x Releases
913

1014
- `5.26.x` Releases - [5.26.0](#5260)
@@ -93,6 +97,61 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception:
9397

9498
---
9599

100+
## 6.0.0-beta
101+
102+
Released August 21, 2022 • [diff](https://github.com/groue/GRDB.swift/compare/v5.26.0...v6.0.0-beta)
103+
104+
### New
105+
106+
Upgrading your app can bring improvements: check [Migrating From GRDB 5 to GRDB 6](Documentation/GRDB6MigrationGuide.md) for some suggestions.
107+
108+
- :star: Support for [`UPSERT`](https://www.sqlite.org/lang_UPSERT.html): `player.upsert(db)`, etc. See [Persistence Methods](README.md#persistence-methods).
109+
110+
- :star: Support for the [`RETURNING` clause](https://www.sqlite.org/lang_returning.html): `player.insertAndFetch(db)`, `Player.deleteAndFetchAll(db)`, etc. See [Persistence Methods and the `RETURNING` clause](README.md#persistence-methods-and-the-returning-clause).
111+
112+
- :star: [Persistence Callbacks](README.md#persistence-callbacks) allow record types to customize persistence methods: `didInsert`, `willSave`, etc.
113+
114+
- :star: Better support for unexpected database values. Where GRDB 5 would crash during encoding and decoding database values, GRDB 6 has learned to throw errors instead. Record protocols throw decoding and encoding errors, and value requests throw errors on invalid inputs.
115+
116+
- Request protocols and cursors now define primary associated types, enabled by [SE-0346](https://github.com/apple/swift-evolution/blob/main/proposals/0346-light-weight-same-type-syntax.md).
117+
118+
- All persistence methods now accept an explicit conflict policy: `player.insert(db, onConflict: .replace)`, etc.
119+
120+
- You can append the contents of a cursor to a collection with `RangeReplaceableCollection.append(contentsOf:)`.
121+
122+
- `ValueObservation.map` now accepts a throwing closure argument.
123+
124+
### Documentation Updates
125+
126+
- :star: **[Migrating From GRDB 5 to GRDB 6](Documentation/GRDB6MigrationGuide.md)**: suggestions for improving your applications, and guidance for handling the breaking changes.
127+
- The [Persistence Methods](README.md#persistence-methods) chapter introduces the `upsert` method.
128+
- The [Persistence Methods and the `RETURNING` clause](README.md#persistence-methods-and-the-returning-clause) chapter introduces persistence methods that fetch inserted, updated and deleted values.
129+
- The [Persistence Callbacks](README.md#persistence-callbacks) chapter introduces the callback invoked from persistence methods, such as `didInsert`, `willSave`, etc.
130+
- The [DatabaseRegionObservation](README.md#databaseregionobservation) chapter was updated for the new `DatabaseRegionObservation.start` method.
131+
- The [Transaction Hook](README.md#transaction-hook) chapter describes the new `Database.afterNextTransaction(onCommit:onRollback:)` method.
132+
- The [Value Queries](README.md#value-queries) chapter explains how to distinguish a request that returns no value from a request that fetches a NULL value.
133+
134+
### Breaking Changes
135+
136+
- Removed deprecated methods
137+
- :star: Bumped requirements:
138+
- Swift 5.7+ and Xcode 14+ are required.
139+
- iOS 11.0+ / macOS 10.13+ / tvOS 11.0+ / watchOS 4.0+ / SQLite 3.19.3+ are required.
140+
- :star: Record protocols were refactored:
141+
- The `FetchableRecord.init(row:)` initializer can now throw errors.
142+
- The `EncodableRecord.encode(to:)` method can now throw errors.
143+
- Record types can no longer override persistence methods. You use [Persistence Callbacks](README.md#persistence-callbacks) instead.
144+
- Various breaking changes:
145+
- The in-memory `DatabaseQueue()` initializer can now throw errors.
146+
- The `selectID()` method is replaced with `selectPrimaryKey(as:)`.
147+
- `Cursor.isEmpty` is now a throwing property, instead of a method.
148+
- The `Record.copy()` method was removed, without replacement.
149+
- The `DerivableRequest.limit(_:offset_:)` method was removed, without replacement.
150+
- `DatabaseRegionObservation.start(in:onError:onChange:)` now returns a cancellable.
151+
- The `DatabaseRegionObservation.extent` property was removed.
152+
- The `statement` property of database cursors was replaced with read-only properties such as `sql` or `columnNames`.
153+
- The `Database.afterNextTransactionCommit(_:)` method was renamed `Database.afterNextTransaction(onCommit:onRollback:)`, and is now able to report rollbacks as well as commits.
154+
96155
## 5.26.0
97156

98157
Released July 9, 2022 • [diff](https://github.com/groue/GRDB.swift/compare/v5.25.0...v5.26.0)

Documentation/AssociationsBasics.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -712,9 +712,9 @@ struct Author: TableRecord {
712712
}
713713
```
714714

715-
> :point_up: **Note**: Generally speaking, all foreign keys are supported, including composite keys that span several columns.
715+
> **Note**: Generally speaking, all foreign keys are supported, including composite keys that span several columns.
716716
>
717-
> :warning: **Warning**: SQLite voids foreign key constraints when one or more of a foreign key column is NULL (see [SQLite Foreign Key Support](https://www.sqlite.org/foreignkeys.html)). GRDB does not match foreign keys that involve a NULL value either.
717+
> **Warning**: SQLite voids foreign key constraints when one or more of a foreign key column is NULL (see [SQLite Foreign Key Support](https://www.sqlite.org/foreignkeys.html)). GRDB does not match foreign keys that involve a NULL value either.
718718
719719
Sometimes the database schema does not define any foreign key. And sometimes, there are *several* foreign keys from a table to another.
720720

@@ -1210,7 +1210,7 @@ In the description of the [joining methods] above, we have seen that you need to
12101210

12111211
In this chapter, we take the reversed perspective. We list various shapes of decoded record types. When you find the type you want, you'll know the joining method you need.
12121212

1213-
> :point_up: **Note**: If you don't find the type you want, chances are that you are fighting the framework, and should reconsider your position. Your escape hatch is the low-level apis described in [Decoding a Joined Request with FetchableRecord].
1213+
> **Note**: If you don't find the type you want, chances are that you are fighting the framework, and should reconsider your position. Your escape hatch is the low-level apis described in [Decoding a Joined Request with FetchableRecord].
12141214
12151215
- [`including(required:)`]
12161216

@@ -1435,7 +1435,7 @@ struct BookInfo: FetchableRecord, Decodable {
14351435
let bookInfos: [BookInfo] = try BookInfo.fetchAll(db, request)
14361436
```
14371437

1438-
> :warning: **Warning**: you can not currently chain a required association behind an optional association:
1438+
> **Warning**: you can not currently chain a required association behind an optional association:
14391439
>
14401440
> ```swift
14411441
> // Not implemented
@@ -1751,7 +1751,7 @@ Associations support more refinements:
17511751
.fetchAll(db)
17521752
```
17531753

1754-
> :warning: **Warning**: associations refined with `limit`, `distinct`, `group`, `having`, or association aggregates can only be used with `including(all:)`. You will get a fatal error if you use them with other joining methods: `including(required:)`, etc.
1754+
> **Warning**: associations refined with `limit`, `distinct`, `group`, `having`, or association aggregates can only be used with `including(all:)`. You will get a fatal error if you use them with other joining methods: `including(required:)`, etc.
17551755

17561756

17571757
## Table Aliases
@@ -1823,7 +1823,7 @@ let request = Book.aliased(bookAlias)
18231823
.filter(sql: "b.publishDate >= a.deathDate")
18241824
```
18251825

1826-
> :point_up: **Note**: avoid reusing table aliases between several tables or requests, because you will get a fatal error:
1826+
> **Note**: avoid reusing table aliases between several tables or requests, because you will get a fatal error:
18271827
>
18281828
> ```swift
18291829
> // Fatal error: A TableAlias most not be used to refer to multiple tables
@@ -1832,7 +1832,7 @@ let request = Book.aliased(bookAlias)
18321832
> let people = Person.aliased(alias)...
18331833
> ```
18341834
>
1835-
> :point_up: **Note**: you can't use the `including(all:)` method and use table aliases to filter the associated records on other records:
1835+
> **Note**: you can't use the `including(all:)` method and use table aliases to filter the associated records on other records:
18361836
>
18371837
> ```swift
18381838
> // NOT IMPLEMENTED: loading all authors along with their posthumous books
@@ -1899,15 +1899,15 @@ For example, we can start by defining base requests as extensions to the [Deriva
18991899

19001900
```swift
19011901
// Author requests
1902-
extension DerivableRequest where RowDecoder == Author {
1902+
extension DerivableRequest<Author> {
19031903
/// Filters authors by country
19041904
func filter(country: String) -> Self {
19051905
filter(Column("country") == country)
19061906
}
19071907
}
19081908

19091909
// Book requests
1910-
extension DerivableRequest where RowDecoder == Book {
1910+
extension DerivableRequest<Book> {
19111911
/// Filters books by author country
19121912
func filter(authorCountry: String) -> Self {
19131913
joining(required: Book.author.filter(country: country))
@@ -2165,8 +2165,8 @@ struct BookInfo: FetchableRecord {
21652165
var country: Country?
21662166
var coverImage: CoverImage?
21672167

2168-
init(row: Row) {
2169-
book = Book(row: row)
2168+
init(row: Row) throws {
2169+
book = try Book(row: row)
21702170
author = row["author"]
21712171
country = row["country"]
21722172
coverImage = row["coverImage"]
@@ -2200,8 +2200,8 @@ struct AuthorInfo: FetchableRecord {
22002200
var author: Author
22012201
var books: [Book]
22022202

2203-
init(row: Row) {
2204-
author = Author(row: row)
2203+
init(row: Row) throws {
2204+
author = try Author(row: row)
22052205
books = row["books"]
22062206
}
22072207
}
@@ -2843,7 +2843,7 @@ let request = Book.all().filter(country: "ES")
28432843
Those methods are defined on extensions to the `DerivableRequest` protocol:
28442844

28452845
```swift
2846-
extension DerivableRequest where RowDecoder == Author {
2846+
extension DerivableRequest<Author> {
28472847
func filter(country: String) -> Self {
28482848
filter(Column("country") == country)
28492849
}
@@ -2853,7 +2853,7 @@ extension DerivableRequest where RowDecoder == Author {
28532853
}
28542854
}
28552855

2856-
extension DerivableRequest where RowDecoder == Book {
2856+
extension DerivableRequest<Book> {
28572857
func filter(country: String) -> Self {
28582858
joining(required: Book.author.filter(country: country))
28592859
}

Documentation/CommonTableExpressions.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ In this guide, you will learn how to:
1616
- [Fetch Values From Common Table Expressions]
1717
- Join CTEs with [Associations to Common Table Expressions]
1818

19-
> :point_up: **Note**: most code examples will be trivial, and not very "useful". This is because the goal of this guide is to stay focused on the GRDB support for CTEs. Rich setup would just be distracting. So bring your own good ideas with you!
19+
> **Note**: most code examples will be trivial, and not very "useful". This is because the goal of this guide is to stay focused on the GRDB support for CTEs. Rich setup would just be distracting. So bring your own good ideas with you!
2020
2121

2222
## Define Common Table Expressions
@@ -82,7 +82,7 @@ let counterCTE = CommonTableExpression(
8282
""")
8383
```
8484

85-
> :point_up: **Note**: many recursive CTEs use the `UNION ALL` SQL operator. The query interface does not provide any Swift support for it, so you'll generally have to write SQL in your definitions of recursive CTEs.
85+
> **Note**: many recursive CTEs use the `UNION ALL` SQL operator. The query interface does not provide any Swift support for it, so you'll generally have to write SQL in your definitions of recursive CTEs.
8686
8787

8888
## Embed Common Table Expressions in Requests
@@ -126,13 +126,13 @@ let request = Player
126126
.filter(Column("name") == playerNameCTE.all())
127127
```
128128

129-
> :point_up: **Note**: the `with(_:)` method can be called as many times as a there are common table expressions in your request.
129+
> **Note**: the `with(_:)` method can be called as many times as a there are common table expressions in your request.
130130
>
131-
> :point_up: **Note**: the `with(_:)` method can be called at any time, as all request methods: `Player.with(...).filter(...).with(...)`.
131+
> **Note**: the `with(_:)` method can be called at any time, as all request methods: `Player.with(...).filter(...).with(...)`.
132132
>
133-
> :point_up: **Note**: the `with(_:)` method replaces any previously embedded CTE that has the same table name. This allows you to embed the same CTE several times if you feel like it.
133+
> **Note**: the `with(_:)` method replaces any previously embedded CTE that has the same table name. This allows you to embed the same CTE several times if you feel like it.
134134
>
135-
> :point_up: **Note**: the `CommonTableExpression.all()` method builds a regular [query interface request] for the content of the CTE (like `SELECT * FROM <cte name>`, not to be mismatched with the request that was used to define the CTE). You can filter this request, sort it, etc, like all query interface requests:
135+
> **Note**: the `CommonTableExpression.all()` method builds a regular [query interface request] for the content of the CTE (like `SELECT * FROM <cte name>`, not to be mismatched with the request that was used to define the CTE). You can filter this request, sort it, etc, like all query interface requests:
136136
>
137137
> ```swift
138138
> cte.all().select(...).filter(...).group(...).order(...)
@@ -234,7 +234,7 @@ Parent.including(optional: childAssociation)
234234
Parent.including(required: childAssociation)
235235
```
236236

237-
> :point_up: **Note**: common table expressions currently only define "to-one" associations, so the `including(all:)` joining method is unavailable.
237+
> **Note**: common table expressions currently only define "to-one" associations, so the `including(all:)` joining method is unavailable.
238238
239239
CTE associations are generally built with the `association(to:on:)` method, which needs:
240240

Documentation/Concurrency.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ try snapshot2.read { db in
506506
}
507507
```
508508

509-
> :point_up: **Note**: snapshots currently serialize all database accesses. In the future, snapshots may allow concurrent reads.
509+
> **Note**: snapshots currently serialize all database accesses. In the future, snapshots may allow concurrent reads.
510510

511511
[^1]: This immutable view of the database is called [snapshot isolation](https://www.sqlite.org/isolation.html).
512512

0 commit comments

Comments
 (0)