Skip to content

Commit bbf3935

Browse files
committed
Merge branch 'development'
2 parents 3ecb5c5 + 442b8b0 commit bbf3935

Some content is hidden

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

47 files changed

+1347
-254
lines changed

.github/workflows/CI.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
name: "iOS"
5151
- xcode: "Xcode_16.1.app"
5252
runsOn: macOS-14
53-
destination: "OS=18.0,name=Apple TV"
53+
destination: "OS=18.1,name=Apple TV"
5454
name: "tvOS"
5555
steps:
5656
- uses: actions/checkout@v4

CHANGELOG.md

+14-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception:
77

88
#### 7.x Releases
99

10-
- `7.0.0` Betas - [7.0.0-beta](#700-beta) - [7.0.0-beta.2](#700-beta2) - [7.0.0-beta.3](#700-beta3) - [7.0.0-beta.4](#700-beta4) - [7.0.0-beta.5](#700-beta5) - [7.0.0-beta.6](#700-beta6)
10+
- `7.0.0` Betas - [7.0.0-beta](#700-beta) - [7.0.0-beta.2](#700-beta2) - [7.0.0-beta.3](#700-beta3) - [7.0.0-beta.4](#700-beta4) - [7.0.0-beta.5](#700-beta5) - [7.0.0-beta.6](#700-beta6) - [7.0.0-beta.7](#700-beta7)
1111

1212
#### 6.x Releases
1313

@@ -131,6 +131,18 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception:
131131

132132
---
133133

134+
## 7.0.0-beta.7
135+
136+
Released January 19, 2025
137+
138+
- **New**: Select all columns from a table, but a few ones by [@groue](https://github.com/groue) in [#1700](https://github.com/groue/GRDB.swift/pull/1700)
139+
- **Fixed**: Fix typo in Readme.md by [@kevinlg](https://github.com/kevinlg) in [#1697](https://github.com/groue/GRDB.swift/pull/1697)
140+
- **New**: Bump custom SQLite to 3.47.2 by [@groue](https://github.com/groue) in [#1696](https://github.com/groue/GRDB.swift/pull/1696)
141+
- **Fixed**: Update LICENSE, fix copyright license year by [@JasonnnW3000](https://github.com/JasonnnW3000) in [#1695](https://github.com/groue/GRDB.swift/pull/1695)
142+
- **Fixed**: Core: import `ucrt` on Windows for `strcmp` by [@compnerd](https://github.com/compnerd) in [#1662](https://github.com/groue/GRDB.swift/pull/1662)
143+
- **Fixed**: Foundation: elide extensions on Windows to match Linux by [@compnerd](https://github.com/compnerd) in [#1661](https://github.com/groue/GRDB.swift/pull/1661)
144+
- **Fixed**: Docs: fixes typos "FST"->"FTS" by [@nylki](https://github.com/nylki) in [#1660](https://github.com/groue/GRDB.swift/pull/1660)
145+
134146
## 7.0.0-beta.6
135147

136148
Released October 13, 2024
@@ -172,7 +184,7 @@ Released September 29, 2024
172184

173185
[Migrating From GRDB 6 to GRDB 7](Documentation/GRDB7MigrationGuide.md) describes in detail how to bump the GRDB version in your application.
174186

175-
The new [Swift Concurrency and GRDB](https://swiftpackageindex.com/groue/grdb.swift/v7.0.0-beta.6/documentation/grdb/swiftconcurrency) guide explains how to best integrate GRDB and Swift Concurrency.
187+
The new [Swift Concurrency and GRDB](https://swiftpackageindex.com/groue/grdb.swift/v7.0.0-beta.7/documentation/grdb/swiftconcurrency) guide explains how to best integrate GRDB and Swift Concurrency.
176188

177189
The [demo app](Documentation/DemoApps/) was rewritten from scratch in a brand new Xcode 16 project.
178190

Documentation/CustomSQLiteBuilds.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Custom SQLite Builds
33

44
By default, GRDB uses the version of SQLite that ships with the target operating system.
55

6-
**You can build GRDB with a custom build of [SQLite 3.46.1](https://www.sqlite.org/changes.html).**
6+
**You can build GRDB with a custom build of [SQLite 3.47.2](https://www.sqlite.org/changes.html).**
77

88
A custom SQLite build can activate extra SQLite features, and extra GRDB features as well, such as support for the [FTS5 full-text search engine](../../../#full-text-search), and [SQLite Pre-Update Hooks](https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/transactionobserver).
99

Documentation/FTS5Tokenizers.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ FTS5 Tokenizers
33

44
**[FTS5](https://www.sqlite.org/fts5.html) is an extensible full-text search engine.**
55

6-
GRDB lets you define your own custom FST5 tokenizers, and extend SQLite built-in tokenizers. Possible use cases are:
6+
GRDB lets you define your own custom FTS5 tokenizers, and extend SQLite built-in tokenizers. Possible use cases are:
77

88
- Have "fi" match the ligature "fi" (U+FB01)
99
- Have "first" match "1st"
@@ -95,7 +95,7 @@ let documents = try Document.matching(pattern).fetchAll(db)
9595

9696
## FTS5Tokenizer
9797

98-
**FST5Tokenizer** is the protocol for all FTS5 tokenizers.
98+
**FTS5Tokenizer** is the protocol for all FTS5 tokenizers.
9999

100100
It only requires a tokenization method that matches the low-level `xTokenize` C function documented at https://www.sqlite.org/fts5.html#custom_tokenizers. We'll discuss it more when describing custom tokenizers.
101101

Documentation/FullTextSearch.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Generally speaking, FTS5 is better than FTS4 which improves on FTS3. But this do
8282

8383
- **The location of the indexed text in your database schema.** Only FTS4 and FTS5 support "contentless" and "external content" tables.
8484

85-
- See [FST3 vs. FTS4](https://www.sqlite.org/fts3.html#differences_between_fts3_and_fts4) and [FTS5 vs. FTS3/4](https://www.sqlite.org/fts5.html#appendix_a) for more differences.
85+
- See [FTS3 vs. FTS4](https://www.sqlite.org/fts3.html#differences_between_fts3_and_fts4) and [FTS5 vs. FTS3/4](https://www.sqlite.org/fts5.html#appendix_a) for more differences.
8686

8787
> **Note**: In case you were still wondering, it is recommended to read the SQLite documentation: [FTS3 & FTS4](https://www.sqlite.org/fts3.html) and [FTS5](https://www.sqlite.org/fts5.html).
8888

Documentation/GRDB7MigrationGuide.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ Do not miss [Swift Concurrency and GRDB], for more recommendations regarding non
228228
- The async sequence returned by [`ValueObservation.values`](https://swiftpackageindex.com/groue/grdb.swiftdocumentation/grdb/valueobservation/values(in:scheduling:bufferingpolicy:)) now iterates on the cooperative thread pool by default. Use .mainActor as the scheduler if you need the previous behavior.
229229

230230
[Migrating to Swift 6]: https://www.swift.org/migration/documentation/migrationguide
231-
[Sharing a Database]: https://swiftpackageindex.com/groue/grdb.swift/v7.0.0-beta.6/documentation/grdb/databasesharing
232-
[Transaction Kinds]: https://swiftpackageindex.com/groue/grdb.swift/v7.0.0-beta.6/documentation/grdb/transactions#Transaction-Kinds
233-
[Swift Concurrency and GRDB]: https://swiftpackageindex.com/groue/grdb.swift/v7.0.0-beta.6/documentation/grdb/swiftconcurrency
234-
[Record]: https://swiftpackageindex.com/groue/grdb.swift/v7.0.0-beta.6/documentation/grdb/record
231+
[Sharing a Database]: https://swiftpackageindex.com/groue/grdb.swift/v7.0.0-beta.7/documentation/grdb/databasesharing
232+
[Transaction Kinds]: https://swiftpackageindex.com/groue/grdb.swift/v7.0.0-beta.7/documentation/grdb/transactions#Transaction-Kinds
233+
[Swift Concurrency and GRDB]: https://swiftpackageindex.com/groue/grdb.swift/v7.0.0-beta.7/documentation/grdb/swiftconcurrency
234+
[Record]: https://swiftpackageindex.com/groue/grdb.swift/v7.0.0-beta.7/documentation/grdb/record

Documentation/QueryInterfaceOrganization.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -497,15 +497,15 @@ protocol SQLSelectable {
497497
SQLSelectable feeds the `select()` method of the query interface:
498498

499499
```swift
500-
Player.select(AllColumns())
500+
Player.select(.allColumns)
501501
Player.select(Column("name"), Column("score"))
502502
```
503503

504504
All [SQLSpecificExpressible] values are selectable. Other selectable values are:
505505

506506
```swift
507507
// SELECT * FROM player
508-
Player.select(AllColumns())
508+
Player.select(.allColumns)
509509

510510
// SELECT MAX(score) AS maxScore FROM player
511511
Player.select(max(Column("score")).forKey("maxScore"))

GRDB.swift.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'GRDB.swift'
3-
s.version = '7.0.0-beta.6'
3+
s.version = '7.0.0-beta.7'
44

55
s.license = { :type => 'MIT', :file => 'LICENSE' }
66
s.summary = 'A toolkit for SQLite databases, with a focus on application development.'

GRDB/Core/StatementAuthorizer.swift

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import string_h
1313
import Glibc
1414
#elseif os(macOS) || os(iOS) || os(watchOS) || os(tvOS) || os(visionOS)
1515
import Darwin
16+
#elseif os(Windows)
17+
import ucrt
1618
#endif
1719

1820
/// `StatementAuthorizer` provides information about compiled database

GRDB/Core/Support/Foundation/NSNumber.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#if !os(Linux)
1+
#if !os(Linux) && !os(Windows)
22
import Foundation
33

44
private let integerRoundingBehavior = NSDecimalNumberHandler(

GRDB/Core/Support/Foundation/URL.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Foundation
22

3-
#if !os(Linux)
3+
#if !os(Linux) && !os(Windows)
44
/// NSURL stores its absoluteString in the database.
55
extension NSURL: DatabaseValueConvertible {
66

GRDB/Core/Support/Foundation/UUID.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import SQLite3
99

1010
import Foundation
1111

12-
#if !os(Linux)
12+
#if !os(Linux) && !os(Windows)
1313
/// NSUUID adopts DatabaseValueConvertible
1414
extension NSUUID: DatabaseValueConvertible {
1515
/// Returns a BLOB database value containing the uuid bytes.

GRDB/Documentation.docc/DatabaseSchemaRecommendations.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ extension Player: FetchableRecord, MutablePersistableRecord {
151151
// Required because the primary key
152152
// is the hidden rowid column.
153153
static var databaseSelection: [any SQLSelectable] {
154-
[AllColumns(), Column.rowID]
154+
[.allColumns, .rowID]
155155
}
156156

157157
// Update id upon successful insertion

GRDB/Documentation.docc/SwiftConcurrency.md

+63-92
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,73 @@ All safety guarantees of Swift 6 are enforced during database accesses. They are
3939

4040
The following sections describe, with more details, how GRDB interacts with Swift Concurrency.
4141

42-
- <doc:SwiftConcurrency#Non-Sendable-Record-Types>
4342
- <doc:SwiftConcurrency#Shorthand-Closure-Notation>
4443
- <doc:SwiftConcurrency#Non-Sendable-Configuration-of-Record-Types>
44+
- <doc:SwiftConcurrency#Non-Sendable-Record-Types>
4545
- <doc:SwiftConcurrency#Choosing-between-Synchronous-and-Asynchronous-Database-Accesses>
4646

47+
### Shorthand Closure Notation
48+
49+
In the Swift 5 language mode, the compiler emits a warning when a database access is written with the shorthand closure notation:
50+
51+
```swift
52+
// Standard closure:
53+
let count = try await writer.read { db in
54+
try Player.fetchCount(db)
55+
}
56+
57+
// Shorthand notation:
58+
// ⚠️ Converting non-sendable function value to '@Sendable (Database)
59+
// throws -> Int' may introduce data races.
60+
let count = try await writer.read(Player.fetchCount)
61+
```
62+
63+
**You can remove this warning** by enabling [SE-0418: Inferring `Sendable` for methods and key path literals](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0418-inferring-sendable-for-methods.md), as below:
64+
65+
- **Using Xcode**
66+
67+
Set `SWIFT_UPCOMING_FEATURE_INFER_SENDABLE_FROM_CAPTURES` to `YES` in the build settings of your target.
68+
69+
- **In a SwiftPM package manifest**
70+
71+
Enable the `InferSendableFromCaptures` upcoming feature:
72+
73+
```swift
74+
.target(
75+
name: "MyTarget",
76+
swiftSettings: [
77+
.enableUpcomingFeature("InferSendableFromCaptures")
78+
]
79+
)
80+
```
81+
82+
This language feature is not enabled by default, because it can potentially [affect source compatibility](https://www.swift.org/migration/documentation/swift-6-concurrency-migration-guide/sourcecompatibility#Inferring-Sendable-for-methods-and-key-path-literals).
83+
84+
### Non-Sendable Configuration of Record Types
85+
86+
In the Swift 6 language mode, and in the Swift 5 language mode with strict concurrency checkings, the compiler emits an error or a warning when a record type specifies which columns it fetches from the database, with the ``TableRecord/databaseSelection-7iphs`` static property:
87+
88+
```swift
89+
extension Player: FetchableRecord, PersistableRecord {
90+
// ❌ Static property 'databaseSelection' is not concurrency-safe
91+
// because non-'Sendable' type '[any SQLSelectable]'
92+
// may have shared mutable state
93+
static let databaseSelection: [any SQLSelectable] = [
94+
Column("id"), Column("name"), Column("score")
95+
]
96+
}
97+
```
98+
99+
**To fix this error**, replace the stored property with a computed property:
100+
101+
```swift
102+
extension Player: FetchableRecord, PersistableRecord {
103+
static var databaseSelection: [any SQLSelectable] {
104+
[Column("id"), Column("name"), Column("score")]
105+
}
106+
}
107+
```
108+
47109
### Non-Sendable Record Types
48110

49111
In the Swift 6 language mode, and in the Swift 5 language mode with strict concurrency checkings, the compiler emits an error or a warning when the application reads, writes, or observes a non-[`Sendable`](https://developer.apple.com/documentation/swift/sendable) type.
@@ -128,97 +190,6 @@ You do not need to perform this refactoring right away: you can compile your app
128190

129191
Yes. Classes that can not be modified, made of constant `let` properties, are Sendable. Those immutable classes will not make it easy to modify the database, though.
130192

131-
#### FAQ: Why this Sendable requirement?
132-
133-
**GRDB needs new features in the Swift language and the SDKs in order to deal with non-Sendable types.**
134-
135-
[SE-0430: `sending` parameter and result values](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0430-transferring-parameters-and-results.md) looks like the language feature we need, but:
136-
137-
- `DispatchQueue.async` does not accept a `sending` closure. GRDB needs this in order to accept non-Sendable records to be sent to the database, as below:
138-
139-
```swift
140-
let nonSendableRecord: Player
141-
try await writer.write { db in
142-
try nonSendableRecord.insert(db)
143-
}
144-
```
145-
146-
Please [file a feedback](http://feedbackassistant.apple.com) for requesting this DispatchQueue improvement. The more the merrier. I personally filed FB15270949.
147-
148-
- Database access methods taint the values they fetch. In the code below, the rules of [SE-0414: Region based Isolation](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0414-region-based-isolation.md) have the compiler refuse that the fetched player is sent back to the caller:
149-
150-
```swift
151-
let player = try await writer.read { db in
152-
try Player.fetchOne(db, id: 42)
153-
}
154-
```
155-
156-
Strictly speaking, the compiler diagnostic is correct: one could copy the non-Sendable `db` argument into the fetched `Player` instance, making it unsuitable for later use. In practice, nobody does that. Copying `db` is a programmer error, and GRDB promptly raises a fatal error whenever a `db` copy would be improperly used. But there is no way to tell the compiler about this practice.
157-
158-
For all those reasons, GRDB has to require values that are asynchronously written and read from the database to be `Sendable`.
159-
160-
### Shorthand Closure Notation
161-
162-
In the Swift 5 language mode, the compiler emits a warning when a database access is written with the shorthand closure notation:
163-
164-
```swift
165-
// Standard closure:
166-
let count = try await writer.read { db in
167-
try Player.fetchCount(db)
168-
}
169-
170-
// Shorthand notation:
171-
// ⚠️ Converting non-sendable function value to '@Sendable (Database)
172-
// throws -> Int' may introduce data races.
173-
let count = try await writer.read(Player.fetchCount)
174-
```
175-
176-
**You can remove this warning** by enabling [SE-0418: Inferring `Sendable` for methods and key path literals](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0418-inferring-sendable-for-methods.md), as below:
177-
178-
- **Using Xcode**
179-
180-
Set `SWIFT_UPCOMING_FEATURE_INFER_SENDABLE_FROM_CAPTURES` to `YES` in the build settings of your target.
181-
182-
- **In a SwiftPM package manifest**
183-
184-
Enable the `InferSendableFromCaptures` upcoming feature:
185-
186-
```swift
187-
.target(
188-
name: "MyTarget",
189-
swiftSettings: [
190-
.enableUpcomingFeature("InferSendableFromCaptures")
191-
]
192-
)
193-
```
194-
195-
This language feature is not enabled by default, because it can potentially [affect source compatibility](https://www.swift.org/migration/documentation/swift-6-concurrency-migration-guide/sourcecompatibility#Inferring-Sendable-for-methods-and-key-path-literals).
196-
197-
### Non-Sendable Configuration of Record Types
198-
199-
In the Swift 6 language mode, and in the Swift 5 language mode with strict concurrency checkings, the compiler emits an error or a warning when a record type specifies which columns it fetches from the database, with the ``TableRecord/databaseSelection-7iphs`` static property:
200-
201-
```swift
202-
extension Player: FetchableRecord, MutablePersistableRecord {
203-
// ❌ Static property 'databaseSelection' is not concurrency-safe
204-
// because non-'Sendable' type '[any SQLSelectable]'
205-
// may have shared mutable state
206-
static let databaseSelection: [any SQLSelectable] = [
207-
Column("id"), Column("name"), Column("score")
208-
]
209-
}
210-
```
211-
212-
**To fix this error**, replace the stored property with a computed property:
213-
214-
```swift
215-
extension Player: FetchableRecord, MutablePersistableRecord {
216-
static var databaseSelection: [any SQLSelectable] {
217-
[Column("id"), Column("name"), Column("score")]
218-
}
219-
}
220-
```
221-
222193
### Choosing between Synchronous and Asynchronous Database Accesses
223194

224195
GRDB connections provide two versions of `read` and `write`, one that is synchronous, and one that is asynchronous. It might not be clear how to choose one or the other.

GRDB/QueryInterface/SQL/Column.swift

+7
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ extension ColumnExpression {
6161

6262
extension ColumnExpression where Self == Column {
6363
/// The hidden rowID column.
64+
///
65+
/// For example:
66+
///
67+
/// ```swift
68+
/// // SELECT rowid FROM player
69+
/// let rowids = try Player.select(.rowID).fetchSet(db)
70+
/// ```
6471
public static var rowID: Self { Column.rowID }
6572
}
6673

GRDB/QueryInterface/SQL/SQLExpression.swift

+8-1
Original file line numberDiff line numberDiff line change
@@ -2136,7 +2136,14 @@ public protocol SQLExpressible {
21362136
}
21372137

21382138
extension SQLExpressible where Self == Column {
2139-
/// The hidden rowID column
2139+
/// The hidden rowID column.
2140+
///
2141+
/// For example:
2142+
///
2143+
/// ```swift
2144+
/// // SELECT rowid FROM player
2145+
/// let rowids = try Player.select(.rowID).fetchSet(db)
2146+
/// ```
21402147
public static var rowID: Self { Column.rowID }
21412148
}
21422149

GRDB/QueryInterface/SQL/SQLRelation.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ extension SQLRelation {
636636
}
637637

638638
// <https://github.com/groue/GRDB.swift/issues/1357>
639-
guard selection.allSatisfy(\.isTriviallyCountable) else {
639+
if selection.contains(where: \.requiresTrivialCount) {
640640
return try fetchTrivialCount(db)
641641
}
642642

0 commit comments

Comments
 (0)