Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
groue committed Apr 1, 2023
2 parents a1b76f9 + 12e3923 commit 3184334
Show file tree
Hide file tree
Showing 17 changed files with 154 additions and 70 deletions.
44 changes: 32 additions & 12 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,26 @@ jobs:
fail-fast: false
matrix:
include:
- xcode: "Xcode_14.1.app"
- xcode: "Xcode_14.2.app"
runsOn: macOS-12
destination: "platform=macOS"
name: "macOS"
- xcode: "Xcode_14.1.app"
- xcode: "Xcode_14.2.app"
runsOn: macOS-12
destination: "OS=16.1,name=iPhone 14"
destination: "OS=16.2,name=iPhone 14"
name: "iOS"
- xcode: "Xcode_14.1.app"
- xcode: "Xcode_14.2.app"
runsOn: macOS-12
destination: "OS=16.1,name=Apple TV"
name: "tvOS"
- xcode: "Xcode_14.1.app"
runsOn: macOS-12
destination: "platform=macOS"
name: "macOS"
- xcode: "Xcode_14.1.app"
runsOn: macOS-12
destination: "OS=16.1,name=iPhone 14"
name: "iOS"
- xcode: "Xcode_14.0.1.app"
runsOn: macOS-12
destination: "platform=macOS"
Expand All @@ -72,6 +80,9 @@ jobs:
fail-fast: false
matrix:
include:
- xcode: "Xcode_14.2.app"
runsOn: macOS-12
name: "Xcode 14.2"
- xcode: "Xcode_14.1.app"
runsOn: macOS-12
name: "Xcode 14.1"
Expand All @@ -92,9 +103,9 @@ jobs:
fail-fast: false
matrix:
include:
- xcode: "Xcode_14.1.app"
- xcode: "Xcode_14.2.app"
runsOn: macOS-12
name: "Xcode 14.1"
name: "Xcode 14.2"
steps:
- uses: actions/checkout@v3
- name: ${{ matrix.name }}
Expand All @@ -109,9 +120,12 @@ jobs:
fail-fast: false
matrix:
include:
- xcode: "Xcode_14.1.app"
- xcode: "Xcode_14.2.app"
runsOn: macOS-12
name: "Xcode 14.1"
name: "Xcode 14.2"
- xcode: "Xcode_14.0.1.app"
runsOn: macOS-12
name: "Xcode 14.0.1"
steps:
- uses: actions/checkout@v3
- name: ${{ matrix.name }}
Expand All @@ -126,9 +140,12 @@ jobs:
fail-fast: false
matrix:
include:
- xcode: "Xcode_14.1.app"
- xcode: "Xcode_14.2.app"
runsOn: macOS-12
name: "Xcode 14.1"
name: "Xcode 14.2"
- xcode: "Xcode_14.0.1.app"
runsOn: macOS-12
name: "Xcode 14.0.1"
steps:
- uses: actions/checkout@v3
- name: ${{ matrix.name }}
Expand All @@ -143,9 +160,12 @@ jobs:
fail-fast: false
matrix:
include:
- xcode: "Xcode_14.1.app"
- xcode: "Xcode_14.2.app"
runsOn: macOS-12
name: "Xcode 14.1"
name: "Xcode 14.2"
- xcode: "Xcode_14.0.1.app"
runsOn: macOS-12
name: "Xcode 14.0.1"
steps:
- uses: actions/checkout@v3
- name: ${{ matrix.name }}
Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception:

#### 6.x Releases

- `6.10.x` Releases - [6.10.0](#6100)
- `6.10.x` Releases - [6.10.0](#6100) - [6.10.1](#6101)
- `6.9.x` Releases - [6.9.0](#690) - [6.9.1](#691) - [6.9.2](#692)
- `6.8.x` Releases - [6.8.0](#680)
- `6.7.x` Releases - [6.7.0](#670)
Expand Down Expand Up @@ -108,6 +108,12 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception:

---

## 6.10.1

Released April 1, 2023 • [diff](https://github.com/groue/GRDB.swift/compare/v6.10.0...v6.10.1)

- **Fixed**: [#1357](https://github.com/groue/GRDB.swift/pull/1357) `QueryInterfaceRequest.fetchCount` no longer executes invalid SQL queries for some requests.

## 6.10.0

Released March 20, 2023 • [diff](https://github.com/groue/GRDB.swift/compare/v6.9.2...v6.10.0)
Expand Down
1 change: 0 additions & 1 deletion Documentation/ReleaseProcess.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ To release a new GRDB version:
- Check tag authors: `git for-each-ref --format '%(refname) %(authorname)' refs/tags`
- Push to the master & development branch
- `pod trunk push --allow-warnings GRDB.swift.podspec`
- Update https://github.com/groue/WWDCCompanion
- Update [performance comparison](https://github.com/groue/GRDB.swift/wiki/Performance):

`make test_performance | Tests/parsePerformanceTests.rb | Tests/generatePerformanceReport.rb`
2 changes: 1 addition & 1 deletion GRDB.swift.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'GRDB.swift'
s.version = '6.10.0'
s.version = '6.10.1'

s.license = { :type => 'MIT', :file => 'LICENSE' }
s.summary = 'A toolkit for SQLite databases, with a focus on application development.'
Expand Down
40 changes: 22 additions & 18 deletions GRDB/Core/DatabaseQueue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -225,21 +225,22 @@ extension DatabaseQueue: DatabaseReader {

public func asyncRead(_ value: @escaping (Result<Database, Error>) -> Void) {
writer.async { db in
defer {
// Ignore error because we can not notify it.
try? db.commit()
try? db.endReadOnly()
}

do {
// The transaction guarantees snapshot isolation against eventual
// external connection.
try db.beginTransaction(.deferred)
// Enter read-only mode before starting a transaction, so that the
// transaction commit does not trigger database observation.
// See <https://github.com/groue/GRDB.swift/pull/1213>.
try db.beginReadOnly()
try db.beginTransaction(.deferred)
value(.success(db))
} catch {
value(.failure(error))
return
}

value(.success(db))

// Ignore error because we can not notify it.
try? db.endReadOnly()
try? db.commit()
}
}

Expand Down Expand Up @@ -273,20 +274,23 @@ extension DatabaseQueue: DatabaseReader {
writer.execute { db in
// ... and that no transaction is opened.
GRDBPrecondition(!db.isInsideTransaction, "must not be called from inside a transaction.")

defer {
// Ignore error because we can not notify it.
try? db.commit()
try? db.endReadOnly()
}

do {
try db.beginTransaction(.deferred)
// Enter read-only mode before starting a transaction, so that the
// transaction commit does not trigger database observation.
// See <https://github.com/groue/GRDB.swift/pull/1213>.
try db.beginReadOnly()
try db.beginTransaction(.deferred)
value(.success(db))
} catch {
value(.failure(error))
return
}

value(.success(db))

// Ignore error because we can not notify it.
try? db.endReadOnly()
try? db.commit()
}
}

Expand Down
13 changes: 8 additions & 5 deletions GRDB/Core/DatabaseWriter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -289,14 +289,13 @@ public protocol DatabaseWriter: DatabaseReader {
/// ```
///
/// - note: Usage of this method is discouraged, because waiting on the
/// returned ``DatabaseFuture`` blocks a thread. You may prefer the
/// asynchronous version of this method: ``spawnConcurrentRead(_:)``.
/// returned ``DatabaseFuture`` blocks a thread. You may prefer
/// ``spawnConcurrentRead(_:)`` instead.
/// - parameter value: A closure which accesses the database.
func concurrentRead<T>(_ value: @escaping (Database) throws -> T) -> DatabaseFuture<T>

// Exposed for RxGRDB and GRBCombine. Naming is not stabilized.
/// Schedules read-only database operations for execution, and
/// returns immediately.
/// Schedules read-only database operations for execution.
///
/// - note: [**🔥 EXPERIMENTAL**](https://github.com/groue/GRDB.swift/blob/master/README.md#what-are-experimental-features)
///
Expand All @@ -311,7 +310,7 @@ public protocol DatabaseWriter: DatabaseReader {
/// by the database writer.
///
/// In the example below, the number of players is fetched concurrently with
/// the player insertion. Yet the future is guaranteed to return zero:
/// the player insertion. Yet it is guaranteed to return zero:
///
/// ```swift
/// try writer.writeWithoutTransaction { db in
Expand All @@ -334,6 +333,10 @@ public protocol DatabaseWriter: DatabaseReader {
/// }
/// ```
///
/// - important: The database operations are executed immediately,
/// or asynchronously, depending on the actual class
/// of `DatabaseWriter`.
///
/// - parameter value: A closure which accesses the database. Its argument
/// is a `Result` that provides the database connection, or the failure
/// that would prevent establishing the read access to the database.
Expand Down
20 changes: 13 additions & 7 deletions GRDB/Core/TransactionObserver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ class DatabaseObservationBroker {

if savepointStack.isEmpty {
// Notify now
for statementObservation in statementObservations where statementObservation.predicate.evaluate(event) {
for statementObservation in statementObservations where statementObservation.tracksEvent(event) {
statementObservation.transactionObservation.databaseWillChange(with: event)
}
} else {
Expand All @@ -479,7 +479,7 @@ class DatabaseObservationBroker {

if savepointStack.isEmpty {
// Notify now
for statementObservation in statementObservations where statementObservation.predicate.evaluate(event) {
for statementObservation in statementObservations where statementObservation.tracksEvent(event) {
statementObservation.transactionObservation.databaseDidChange(with: event)
}
} else {
Expand Down Expand Up @@ -639,7 +639,7 @@ class DatabaseObservationBroker {

for (event, statementObservations) in eventsBuffer {
assert(statementObservations.isEmpty || !database.isReadOnly, "Read-only transactions are not notified")
for statementObservation in statementObservations where statementObservation.predicate.evaluate(event) {
for statementObservation in statementObservations where statementObservation.tracksEvent(event) {
event.send(to: statementObservation.transactionObservation)
}
}
Expand Down Expand Up @@ -969,12 +969,18 @@ final class TransactionObservation {
struct StatementObservation {
var transactionObservation: TransactionObservation

/// Filters database events that should be notified.
var predicate: DatabaseEventPredicate
/// A predicate that filters database events that should be notified.
///
/// Call this predicate as a method:
///
/// ```
/// if observation.tracksEvent(event) { ... }
/// ```
var tracksEvent: DatabaseEventPredicate

init(transactionObservation: TransactionObservation, trackingEvents predicate: DatabaseEventPredicate) {
self.transactionObservation = transactionObservation
self.predicate = predicate
self.tracksEvent = predicate
}
}

Expand Down Expand Up @@ -1447,7 +1453,7 @@ enum DatabaseEventPredicate {
/// statement authorizer.
case matching(observedEventKinds: [DatabaseEventKind], authorizerEventKinds: [DatabaseEventKind])

func evaluate(_ event: some DatabaseEventProtocol) -> Bool {
func callAsFunction(_ event: some DatabaseEventProtocol) -> Bool {
switch self {
case .all:
return true
Expand Down
21 changes: 3 additions & 18 deletions GRDB/Core/WALSnapshot.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// swiftlint:disable:next line_length
#if SQLITE_ENABLE_SNAPSHOT || (!GRDBCUSTOMSQLITE && !GRDBCIPHER && (compiler(>=5.7.1) || !(os(macOS) || targetEnvironment(macCatalyst))))
/// An instance of WALSnapshot records the state of a WAL mode database for some
/// specific point in history.
///
Expand All @@ -20,13 +22,6 @@
///
/// See <https://www.sqlite.org/c3ref/snapshot.html>.
final class WALSnapshot: Sendable {
// Xcode 14 (Swift 5.7) ships with a macOS SDK that misses snapshot support.
// Xcode 14.1 (Swift 5.7.1) ships with a macOS SDK that has snapshot support.
// This is the meaning of (compiler(>=5.7.1) || !(os(macOS) || targetEnvironment(macCatalyst)))
// swiftlint:disable:next line_length
#if SQLITE_ENABLE_SNAPSHOT || (!GRDBCUSTOMSQLITE && !GRDBCIPHER && (compiler(>=5.7.1) || !(os(macOS) || targetEnvironment(macCatalyst))))
static let available = true

let sqliteSnapshot: UnsafeMutablePointer<sqlite3_snapshot>

init(_ db: Database) throws {
Expand Down Expand Up @@ -67,15 +62,5 @@ final class WALSnapshot: Sendable {
func compare(_ other: WALSnapshot) -> CInt {
sqlite3_snapshot_cmp(sqliteSnapshot, other.sqliteSnapshot)
}
#else
static let available = false

init(_ db: Database) throws {
throw DatabaseError(resultCode: .SQLITE_MISUSE, message: "snapshots are not available")
}

func compare(_ other: WALSnapshot) -> CInt {
preconditionFailure("snapshots are not available")
}
#endif
}
#endif
2 changes: 2 additions & 0 deletions GRDB/Fixits.swift
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,5 @@ extension ValueObservation {
where Reducer == ValueReducers.Fetch<Value>
{ preconditionFailure() }
}

// swiftlint:enable all
7 changes: 6 additions & 1 deletion GRDB/QueryInterface/SQL/SQLRelation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,12 @@ extension SQLRelation {
guard !isDistinct else {
return try fetchTrivialCount(db)
}


// <https://github.com/groue/GRDB.swift/issues/1357>
guard selection.allSatisfy(\.isTriviallyCountable) else {
return try fetchTrivialCount(db)
}

// SELECT expr1, expr2, ... FROM tableName ...
// ->
// SELECT COUNT(*) FROM tableName ...
Expand Down
12 changes: 12 additions & 0 deletions GRDB/QueryInterface/SQL/SQLSelection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,18 @@ extension SQLSelection {
return .literal(sqlLiteral.qualified(with: alias))
}
}

/// Supports SQLRelation.fetchCount.
///
/// See <https://github.com/groue/GRDB.swift/issues/1357>
var isTriviallyCountable: Bool {
switch impl {
case .aliasedExpression, .literal:
return false
case .allColumns, .qualifiedAllColumns, .expression:
return true
}
}
}

extension [SQLSelection] {
Expand Down
Loading

0 comments on commit 3184334

Please sign in to comment.