Skip to content

Commit 98ca653

Browse files
committed
Merge branch 'development'
2 parents bd42dc6 + e5a8e13 commit 98ca653

Some content is hidden

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

48 files changed

+937
-368
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception:
77

88
#### 5.x Releases
99

10+
- `5.20.x` Releases - [5.20.0](#5200)
1011
- `5.19.x` Releases - [5.19.0](#5190)
1112
- `5.18.x` Releases - [5.18.0](#5180)
1213
- `5.17.x` Releases - [5.17.0](#5170)
@@ -86,6 +87,17 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception:
8687

8788
---
8889

90+
## 5.20.0
91+
92+
Released February 1, 2022 • [diff](https://github.com/groue/GRDB.swift/compare/v5.19.0...v5.20.0)
93+
94+
- **Fixed**: Fixed a bug of `including(all:)` for composite foreign keys and limited requests.
95+
- **Fixed**: [#1162](https://github.com/groue/GRDB.swift/pull/1162) by [@groue](https://github.com/groue): Fix truncate optimization handling.
96+
- **New**: [#1160](https://github.com/groue/GRDB.swift/pull/1160) by [@groue](https://github.com/groue): Hide statement arguments by default.
97+
- **New**: [#1161](https://github.com/groue/GRDB.swift/pull/1160) by [@groue](https://github.com/groue): Target DispatchQueue for non-read-only database connections.
98+
- **Documentation Update**: The [Database Configuration](README.md#database-configuration) chapter explains how to opt in for public statement arguments in DEBUG builds.
99+
100+
89101
## 5.19.0
90102

91103
Released January 19, 2022 • [diff](https://github.com/groue/GRDB.swift/compare/v5.18.0...v5.19.0)

Documentation/Concurrency.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ In the illustration below, the striped band shows the delay needed for the readi
469469
let snapshot = try dbPool.makeSnapshot()
470470
```
471471

472-
You can create as many snapshots as you need, regardless of the [maximum number of readers](../README.md#databasepool-configuration) in the pool. A snapshot database connection is closed when the snapshot is deinitialized.
472+
You can create as many snapshots as you need, regardless of the [maximum number of readers](../README.md#database-configuration) in the pool. A snapshot database connection is closed when the snapshot is deinitialized.
473473

474474
**A snapshot can be used from any thread.** It has the same [synchronous and asynchronous reading methods](#synchronous-and-asynchronous-database-accesses) as database queues and pools:
475475

Documentation/FullTextSearch.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ let pattern = FTS3Pattern(matchingAnyTokenIn: "") // nil
304304
let pattern = FTS3Pattern(matchingAnyTokenIn: "*") // nil
305305
```
306306

307-
FTS3Pattern are regular [values](../README.md#values). You can use them as query [arguments](http://groue.github.io/GRDB.swift/docs/5.19/Structs/StatementArguments.html):
307+
FTS3Pattern are regular [values](../README.md#values). You can use them as query [arguments](http://groue.github.io/GRDB.swift/docs/5.20/Structs/StatementArguments.html):
308308

309309
```swift
310310
let documents = try Document.fetchAll(db,
@@ -587,7 +587,7 @@ let pattern = FTS5Pattern(matchingAnyTokenIn: "") // nil
587587
let pattern = FTS5Pattern(matchingAnyTokenIn: "*") // nil
588588
```
589589

590-
FTS5Pattern are regular [values](../README.md#values). You can use them as query [arguments](http://groue.github.io/GRDB.swift/docs/5.19/Structs/StatementArguments.html):
590+
FTS5Pattern are regular [values](../README.md#values). You can use them as query [arguments](http://groue.github.io/GRDB.swift/docs/5.20/Structs/StatementArguments.html):
591591

592592
```swift
593593
let documents = try Document.fetchAll(db,

Documentation/Migrations.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ try dbQueue.read { db in
7777
}
7878
```
7979

80-
See the [DatabaseMigrator reference](http://groue.github.io/GRDB.swift/docs/5.19/Structs/DatabaseMigrator.html) for more migrator methods.
80+
See the [DatabaseMigrator reference](http://groue.github.io/GRDB.swift/docs/5.20/Structs/DatabaseMigrator.html) for more migrator methods.
8181

8282

8383
## The `eraseDatabaseOnSchemaChange` Option

GRDB.swift.podspec

Lines changed: 1 addition & 1 deletion
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 = '5.19.0'
3+
s.version = '5.20.0'
44

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

GRDB/Core/Configuration.swift

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import Foundation
21
import Dispatch
2+
import Foundation
33

44
/// Configuration for a DatabaseQueue or DatabasePool.
55
public struct Configuration {
@@ -102,6 +102,52 @@ public struct Configuration {
102102
/// [**Experimental**](http://github.com/groue/GRDB.swift#what-are-experimental-features)
103103
public var observesSuspensionNotifications = false
104104

105+
/// If false (the default), statement arguments are not visible in the
106+
/// description of database errors and trace events, preventing sensitive
107+
/// information from leaking in unexpected places.
108+
///
109+
/// For example:
110+
///
111+
/// // Error: sensitive information is not printed when an error occurs:
112+
/// do {
113+
/// let email = "..." // sensitive information
114+
/// let player = try Player.filter(Column("email") == email).fetchOne(db)
115+
/// } catch {
116+
/// print(error)
117+
/// }
118+
///
119+
/// // Trace: sensitive information is not printed when a statement is traced:
120+
/// db.trace { event in
121+
/// print(event)
122+
/// }
123+
/// let email = "..." // sensitive information
124+
/// let player = try Player.filter(Column("email") == email).fetchOne(db)
125+
///
126+
/// For debugging purpose, you can set this flag to true, and get more
127+
/// precise database reports. It is your responsibility to prevent sensitive
128+
/// information from leaking in unexpected locations, so you should not set
129+
/// this flag in release builds (think about GDPR and other
130+
/// privacy-related rules):
131+
///
132+
/// var config = Configuration()
133+
/// #if DEBUG
134+
/// // Protect sensitive information by enabling verbose debugging in DEBUG builds only
135+
/// config.publicStatementArguments = true
136+
/// #endif
137+
///
138+
/// // The descriptions of trace events and errors now contain the
139+
/// // sensitive information:
140+
/// db.trace { event in
141+
/// print(event)
142+
/// }
143+
/// do {
144+
/// let email = "..."
145+
/// let player = try Player.filter(Column("email") == email).fetchOne(db)
146+
/// } catch {
147+
/// print(error)
148+
/// }
149+
public var publicStatementArguments = false
150+
105151
// MARK: - Managing SQLite Connections
106152

107153
private var setups: [(Database) throws -> Void] = []
@@ -202,19 +248,29 @@ public struct Configuration {
202248
/// Default: .default
203249
public var qos: DispatchQoS = .default
204250

205-
/// The target queue for all database accesses.
251+
/// A target queue for database accesses.
252+
///
253+
/// Database connections which are not read-only will prefer
254+
/// `writeTargetQueue` instead, if it is not nil.
206255
///
207-
/// When you use a database pool, make sure the queue is concurrent. If
208-
/// it is serial, no concurrent database access can happen, and you may
209-
/// experience deadlocks.
256+
/// When you use a database pool, make sure this queue is concurrent. This
257+
/// is because in a serial dispatch queue, no concurrent database access can
258+
/// happen, and you may experience deadlocks.
210259
///
211260
/// If the queue is nil, all database accesses happen in unspecified
212-
/// dispatch queues whose quality of service and label are determined by the
213-
/// `qos` and `label` Configuration properties.
261+
/// dispatch queues whose quality of service is determined by the
262+
/// `qos` property.
214263
///
215264
/// Default: nil
216265
public var targetQueue: DispatchQueue? = nil
217266

267+
/// The target queue for database connections which are not read-only.
268+
///
269+
/// If this queue is nil, writer connections are controlled by `targetQueue`.
270+
///
271+
/// Default: nil
272+
public var writeTargetQueue: DispatchQueue? = nil
273+
218274
// MARK: - Factory Configuration
219275

220276
/// Creates a factory configuration
@@ -241,7 +297,15 @@ public struct Configuration {
241297
(self.label ?? defaultLabel) + (purpose.map { "." + $0 } ?? "")
242298
}
243299

244-
func makeDispatchQueue(label: String) -> DispatchQueue {
300+
func makeWriterDispatchQueue(label: String) -> DispatchQueue {
301+
if let targetQueue = writeTargetQueue ?? targetQueue {
302+
return DispatchQueue(label: label, target: targetQueue)
303+
} else {
304+
return DispatchQueue(label: label, qos: qos)
305+
}
306+
}
307+
308+
func makeReaderDispatchQueue(label: String) -> DispatchQueue {
245309
if let targetQueue = targetQueue {
246310
return DispatchQueue(label: label, target: targetQueue)
247311
} else {

GRDB/Core/Database+Statements.swift

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -542,21 +542,21 @@ public class SQLStatementCursor: Cursor {
542542
}
543543

544544
extension Database {
545-
/// Returns the authorizer that should be used during statement execution
546-
/// (this allows preventing the truncate optimization when there exists a
547-
/// transaction observer for row deletion).
545+
/// Makes sure statement can be executed, and prepares database observation.
548546
@usableFromInline
549-
func statementWillExecute(_ statement: Statement) throws -> StatementAuthorizer? {
547+
func statementWillExecute(_ statement: Statement) throws {
550548
// Two things must prevent the statement from executing: aborted
551549
// transactions, and database suspension.
552550
try checkForAbortedTransaction(sql: statement.sql, arguments: statement.arguments)
553551
try checkForSuspensionViolation(from: statement)
554552

555-
if _isRecordingSelectedRegion {
556-
_selectedRegion.formUnion(statement.databaseRegion)
553+
// Database observation: record what the statement is looking at.
554+
if isRecordingSelectedRegion {
555+
selectedRegion.formUnion(statement.databaseRegion)
557556
}
558557

559-
return observationBroker.statementWillExecute(statement)
558+
// Database observation: prepare transaction observers.
559+
observationBroker.statementWillExecute(statement)
560560
}
561561

562562
/// May throw a cancelled commit error, if a transaction observer cancels
@@ -589,7 +589,8 @@ extension Database {
589589
resultCode: resultCode,
590590
message: lastErrorMessage,
591591
sql: statement.sql,
592-
arguments: statement.arguments)
592+
arguments: statement.arguments,
593+
publicStatementArguments: configuration.publicStatementArguments)
593594
}
594595
}
595596

@@ -639,4 +640,8 @@ struct StatementCache {
639640
mutating func remove(_ statement: Statement) {
640641
statements.removeFirst { $0.value === statement }
641642
}
643+
644+
mutating func removeAll(where shouldBeRemoved: (Statement) -> Bool) {
645+
statements = statements.filter { (_, statement) in !shouldBeRemoved(statement) }
646+
}
642647
}

0 commit comments

Comments
 (0)