Skip to content

Commit

Permalink
Enable strict concurrency checks on Lighter
Browse files Browse the repository at this point in the history
Let's hope we didn't break anything ;-)
  • Loading branch information
helje5 committed Apr 7, 2024
1 parent 3bcc60c commit 1f517bd
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 27 deletions.
13 changes: 10 additions & 3 deletions [email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

import PackageDescription

#if swift(>=5.10)
let settings = [ SwiftSetting.enableExperimentalFeature("StrictConcurrency") ]
#else
let settings = [ SwiftSetting ]()
#endif

var package = Package(
name: "Lighter",

Expand All @@ -28,7 +34,7 @@ var package = Package(
// generated models and such.
// Note that Lighter isn't that useful w/o code generation (i.e. as a
// standalone lib).
.target(name: "Lighter"),
.target(name: "Lighter", swiftSettings: settings),


// MARK: - Plugin Support
Expand All @@ -37,14 +43,15 @@ var package = Package(
// Swift source code.
.target(name : "LighterCodeGenAST",
path : "Plugins/Libraries/LighterCodeGenAST",
exclude : [ "README.md" ]),
exclude : [ "README.md" ], swiftSettings: settings),

// This library contains all the code generation, to be used by different
// clients.
.target(name : "LighterGeneration",
dependencies : [ "LighterCodeGenAST", "SQLite3Schema" ],
path : "Plugins/Libraries/LighterGeneration",
exclude : [ "README.md", "LighterConfiguration/README.md" ]),
exclude : [ "README.md", "LighterConfiguration/README.md" ],
swiftSettings: settings),


// MARK: - Tests
Expand Down
21 changes: 15 additions & 6 deletions Sources/Lighter/Operations/SQLDatabaseAsyncChangeOperations.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Created by Helge Heß.
// Copyright © 2022 ZeeZide GmbH.
// Copyright © 2022-2024 ZeeZide GmbH.
//

// Same like `SQLDatabaseChangeOperations`, async/await variant if available.
Expand Down Expand Up @@ -41,7 +41,9 @@ public extension SQLDatabaseAsyncChangeOperations {
async throws
where T: SQLDeletableRecord, T.Schema: SQLKeyedTableSchema
{
try await runOnDatabaseQueue { try delete(from: table, id: id) }
try await runOnDatabaseQueue {
try delete(from: T.self) { _ in T.Schema.primaryKeyColumn == id }
}
}

/**
Expand All @@ -65,8 +67,9 @@ public extension SQLDatabaseAsyncChangeOperations {
async throws
where C: SQLColumn, T == C.T, T: SQLDeletableRecord
{
let ref = T.schema[keyPath: column]
try await runOnDatabaseQueue {
try delete(from: table, where: column, is: value)
try delete(from: T.self) { _ in ref == value }
}
}

Expand All @@ -87,12 +90,18 @@ public extension SQLDatabaseAsyncChangeOperations {
* - predicate: The qualifier selecting the records to delete.
*/
@inlinable
func delete<T, P>(from table : KeyPath<Self.RecordTypes, T.Type>,
where p : @escaping ( T.Schema ) -> P)
func delete<T, P>(from table : KeyPath<Self.RecordTypes, T.Type>,
where predicate : @escaping ( T.Schema ) -> P)
async throws
where T: SQLDeletableRecord, P: SQLPredicate
{
try await runOnDatabaseQueue { try delete(from: table, where: p) }
var builder = SQLBuilder<T>()
builder.generateDelete(from: T.Schema.externalName,
where: predicate(T.schema))
let cb = builder
try await runOnDatabaseQueue {
try execute(cb.sql, cb.bindings, readOnly: false)
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/Lighter/Operations/SQLDatabaseAsyncOperations.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Created by Helge Heß.
// Copyright © 2022 ZeeZide GmbH.
// Copyright © 2022-2024 ZeeZide GmbH.
//

import Dispatch
Expand All @@ -15,7 +15,7 @@ import Dispatch
* - ``SQLDatabaseFetchOperations``
* - ``SQLDatabaseAsyncChangeOperations``
*/
public protocol SQLDatabaseAsyncOperations: SQLDatabaseOperations {
public protocol SQLDatabaseAsyncOperations: SQLDatabaseOperations, Sendable {

/**
* The queue that is used to run concurrent async SQL operations.
Expand Down
55 changes: 41 additions & 14 deletions Sources/Lighter/Operations/SQLRecordAsyncFetchOperations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,10 @@ public extension SQLRecordFetchOperations
async throws -> [ T ]
where SC: SQLColumn, SC.T == T
{
try await runOnDatabaseQueue {
try fetch(limit: limit, orderBy: column, direction)
let column = T.schema[keyPath: column]
return try await runOnDatabaseQueue {
try fetch(limit: limit, orderBy: column, direction,
where: { _ in SQLTruePredicate.shared })
}
}

Expand Down Expand Up @@ -94,7 +96,8 @@ public extension SQLRecordFetchOperations
async throws -> [ T ]
where SC: SQLColumn, SC.T == T, P: SQLPredicate
{
try await runOnDatabaseQueue {
let column = T.schema[keyPath: column]
return try await runOnDatabaseQueue {
try fetch(limit: limit, orderBy: column, direction, where: predicate)
}
}
Expand Down Expand Up @@ -132,7 +135,9 @@ public extension SQLRecordFetchOperations
where SC1: SQLColumn, SC1.T == T, SC2: SQLColumn, SC2.T == T,
P: SQLPredicate
{
try await runOnDatabaseQueue {
let column1 = T.schema[keyPath: column1]
let column2 = T.schema[keyPath: column2]
return try await runOnDatabaseQueue {
try fetch(limit: limit,
orderBy: column1, direction1, column2, direction2,
where: predicate)
Expand Down Expand Up @@ -183,7 +188,15 @@ public extension SQLRecordFetchOperations
async throws -> T?
where C: SQLColumn, T == C.T
{
try await runOnDatabaseQueue { try find(by: matchColumn, value) }
let matchColumn = T.schema[keyPath: matchColumn]
var builder = SQLBuilder<T>()
builder.generateSelect(limit: 1, predicate: matchColumn == value)

let cb = builder
return try await runOnDatabaseQueue {
try fetch(verbatim: cb.sql, bindings: cb.bindings,
indices: T.Schema.selectColumnIndices).first
}
}

/**
Expand Down Expand Up @@ -278,7 +291,8 @@ public extension SQLRecordFetchOperations
FK.Value == FK.DestinationColumn.Value,
S: Sequence & Sendable, S.Element == FK.Destination
{
try await runOnDatabaseQueue {
let foreignKey = T.schema[keyPath: foreignKey]
return try await runOnDatabaseQueue {
try fetch(for: foreignKey, in: destinationRecords,
omitEmpty: omitEmpty, limit: limit)
}
Expand Down Expand Up @@ -308,9 +322,10 @@ public extension SQLRecordFetchOperations
async throws -> [ FK.DestinationColumn.Value : [ T ] ]
where FK: SQLForeignKeyColumn, FK.T == T,
FK.Value == FK.DestinationColumn.Value,
S: Sequence, S.Element == FK.DestinationColumn.Value
S: Sequence & Sendable, S.Element == FK.DestinationColumn.Value
{
try await runOnDatabaseQueue {
let foreignKey = T.schema[keyPath: foreignKey]
return try await runOnDatabaseQueue {
try fetch(for: foreignKey, in: destinationsColumns,
omitEmpty: omitEmpty, limit: limit)
}
Expand All @@ -334,7 +349,8 @@ public extension SQLRecordFetchOperations
where FK: SQLForeignKeyColumn, FK.T == T,
FK.Value == FK.DestinationColumn.Value
{
try await runOnDatabaseQueue {
let foreignKey = T.schema[keyPath: foreignKey]
return try await runOnDatabaseQueue {
try fetch(for: foreignKey, in: destinationRecord, limit: limit)
}
}
Expand All @@ -354,7 +370,8 @@ public extension SQLRecordFetchOperations
where FK: SQLForeignKeyColumn, FK.T == T,
FK.Value == FK.DestinationColumn.Value?
{
try await runOnDatabaseQueue {
let foreignKey = T.schema[keyPath: foreignKey]
return try await runOnDatabaseQueue {
try fetch(for: foreignKey, in: destinationRecord, limit: limit)
}
}
Expand All @@ -374,7 +391,8 @@ public extension SQLRecordFetchOperations
where FK: SQLForeignKeyColumn, FK.T == T,
FK.Value? == FK.DestinationColumn.Value
{
try await runOnDatabaseQueue {
let foreignKey = T.schema[keyPath: foreignKey]
return try await runOnDatabaseQueue {
try fetch(for: foreignKey, in: destinationRecord, limit: limit)
}
}
Expand All @@ -396,7 +414,10 @@ public extension SQLRecordFetchOperations
where FK: SQLForeignKeyColumn, FK.T == T,
FK.Value == FK.DestinationColumn.Value
{
try await runOnDatabaseQueue { try findTarget(for: foreignKey, in: record) }
let foreignKey = T.schema[keyPath: foreignKey]
return try await runOnDatabaseQueue {
try findTarget(for: foreignKey, in: record)
}
}

/**
Expand All @@ -413,7 +434,10 @@ public extension SQLRecordFetchOperations
where FK: SQLForeignKeyColumn, FK.T == T,
FK.Value == Optional<FK.DestinationColumn.Value>
{
try await runOnDatabaseQueue { try findTarget(for: foreignKey, in: record) }
let foreignKey = T.schema[keyPath: foreignKey]
return try await runOnDatabaseQueue {
try findTarget(for: foreignKey, in: record)
}
}

/**
Expand All @@ -430,7 +454,10 @@ public extension SQLRecordFetchOperations
where FK: SQLForeignKeyColumn, FK.T == T,
Optional<FK.Value> == FK.DestinationColumn.Value
{
try await runOnDatabaseQueue { try findTarget(for: foreignKey, in: record) }
let foreignKey = T.schema[keyPath: foreignKey]
return try await runOnDatabaseQueue {
try findTarget(for: foreignKey, in: record)
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions Sources/Lighter/Operations/SQLRecordFetchOperations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ public struct SQLRecordFetchOperations<Ops, T: SQLRecord>
public init(_ operations: Ops) { self.operations = operations }
}

#if swift(>=5.5) && canImport(_Concurrency)
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
extension SQLRecordFetchOperations: Sendable
where Ops: SQLDatabaseAsyncOperations {}
#endif

public extension SQLDatabaseFetchOperations { // this is what DB/TX conform to

Expand Down
5 changes: 3 additions & 2 deletions Sources/Lighter/Transactions/SQLTransactionAsync.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public extension SQLDatabase where Self: SQLDatabaseAsyncOperations {
@discardableResult
func transaction<R>(
mode : SQLTransactionType = .default,
execute : @escaping ( SQLChangeTransaction<Self> ) throws -> R
execute : @Sendable @escaping ( SQLChangeTransaction<Self> ) throws -> R
) async throws -> R
{
try await runOnDatabaseQueue {
Expand Down Expand Up @@ -83,7 +83,8 @@ public extension SQLDatabase where Self: SQLDatabaseAsyncOperations {
*/
@inlinable
@discardableResult
func readTransaction<R>(execute: @escaping (SQLTransaction<Self>) throws -> R)
func readTransaction<R>(execute: @Sendable @escaping
(SQLTransaction<Self>) throws -> R)
async throws -> R
{
try await runOnDatabaseQueue {
Expand Down

0 comments on commit 1f517bd

Please sign in to comment.