Skip to content

Commit a346afb

Browse files
committed
Merge remote-tracking branch 'origin/main' into agg
2 parents 21d6cea + edb84b3 commit a346afb

File tree

15 files changed

+376
-260
lines changed

15 files changed

+376
-260
lines changed

Sources/StructuredQueriesCore/Documentation.docc/Articles/DefiningYourSchema.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ To define a Swift data type that represents this table, one can use the `@Table`
5151
}
5252
```
5353

54+
> Note: If your project is using [default main actor isolation] then you further need to annotate
55+
> your struct as `nonisolated`.
56+
[default main actor isolation]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0466-control-default-actor-isolation.md
57+
5458
Note that the struct's field names match the column tables of the table exactly. In order to support
5559
property names that differ from the columns names, you can use the `@Column` macro. See the section
5660
below, <doc:DefiningYourSchema#Customizing-a-table>, for more information on how to customize your

Sources/StructuredQueriesCore/Documentation.docc/Articles/QueryCookbook.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ extension Reminder {
5050
}
5151
```
5252

53+
> Note: If your project is using [default main actor isolation] then you further need to annotate
54+
> your extension as `nonisolated`, or define the helpers directly in the declaration of the struct.
55+
[default main actor isolation]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0466-control-default-actor-isolation.md
56+
5357
Then these helpers can be used when composing together a larger, more complex query. For example,
5458
we can select all non-deleted lists with the count of all non-deleted reminders in each list like
5559
so:
@@ -131,6 +135,10 @@ extension Reminder.TableColumns {
131135
}
132136
```
133137
138+
> Note: If your project is using [default main actor isolation] then you further need to annotate
139+
> your extension as `nonisolated`.
140+
[default main actor isolation]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0466-control-default-actor-isolation.md
141+
134142
Then you can use these helpers when building a query. For example, you can use
135143
``PrimaryKeyedTableDefinition/count(distinct:filter:)`` to count the number of past due, current and
136144
scheduled reminders in one single query like so:

Sources/StructuredQueriesCore/Never.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,5 @@ extension Never: Table {
2525

2626
private struct NotDecodable: Error {}
2727
}
28+
29+
extension Never: _Selection {}

Sources/StructuredQueriesCore/Optional.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ extension Optional: Table, PartialSelectStatement, Statement where Wrapped: Tabl
183183
public typealias Selection = Wrapped.Selection?
184184
}
185185

186+
extension Optional: _Selection where Wrapped: _Selection {}
187+
186188
extension Optional: PrimaryKeyedTable where Wrapped: PrimaryKeyedTable {
187189
public typealias Draft = Wrapped.Draft?
188190
}
Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/// A type that represents a full SQL query.
2-
public protocol Statement<QueryValue>: QueryExpression, Hashable {
2+
public protocol Statement<QueryValue>: QueryExpression {
33
/// A type representing the table being queried.
44
associatedtype From: Table
55

@@ -15,13 +15,3 @@ extension Statement {
1515
"(\(.newline)\(query.indented())\(.newline))"
1616
}
1717
}
18-
19-
extension Statement {
20-
public static func == (lhs: Self, rhs: Self) -> Bool {
21-
lhs.query == rhs.query
22-
}
23-
24-
public func hash(into hasher: inout Hasher) {
25-
hasher.combine(query)
26-
}
27-
}

Sources/StructuredQueriesCore/TableAlias.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ public struct TableAlias<
183183
}
184184
}
185185

186+
extension TableAlias: _Selection where Base: _Selection {}
187+
186188
extension TableAlias: PrimaryKeyedTable where Base: PrimaryKeyedTable {
187189
public typealias Draft = TableAlias<Base.Draft, Name>
188190
}

Sources/StructuredQueriesSQLiteCore/Documentation.docc/Articles/CustomFunctions.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ func exclaim(_ string: String) -> String {
1818
}
1919
```
2020

21+
> Note: If your project is using [default main actor isolation] then you further need to annotate
22+
> your function as `nonisolated`.
23+
[default main actor isolation]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0466-control-default-actor-isolation.md
24+
2125
And will be immediately callable in a query by prefixing the function with `$`:
2226

2327
```swift

Sources/StructuredQueriesSQLiteCore/Documentation.docc/Articles/Triggers.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@ refreshed with the current time immediately.
4545

4646
This pattern of updating a timestamp when a row changes is so common that the library comes with
4747
a specialized tool just for that kind of trigger,
48-
``StructuredQueriesCore/Table/createTemporaryTrigger(_:ifNotExists:afterUpdateTouch:fileID:line:column:)``:
48+
``TemporaryTrigger/Operation/update(touch:when:)``:
4949

5050
@Row {
5151
@Column {
5252
```swift
5353
Reminder.createTemporaryTrigger(
54-
afterUpdateTouch: {
54+
after: .update: {
5555
$0.updatedAt = datetime('subsec')
5656
}
5757
)
@@ -72,14 +72,14 @@ a specialized tool just for that kind of trigger,
7272

7373
And further, the pattern of specifically updating a _timestamp_ column is so common that the library
7474
comes with another specialized too just for that kind of trigger,
75-
``StructuredQueriesCore/Table/createTemporaryTrigger(_:ifNotExists:afterUpdateTouch:fileID:line:column:)``:
75+
``TemporaryTrigger/Operation/update(touch:when:)``:
7676

7777

7878
@Row {
7979
@Column {
8080
```swift
8181
Reminder.createTemporaryTrigger(
82-
afterUpdateTouch: \.updatedAt
82+
after: .update(touch: \.updatedAt)
8383
)
8484
```
8585
}
@@ -195,11 +195,11 @@ reminder is inserted into the database with the following trigger:
195195
- ``StructuredQueriesCore/Table/createTemporaryTrigger(_:ifNotExists:before:fileID:line:column:)``
196196
- ``StructuredQueriesCore/Table/createTemporaryTrigger(_:ifNotExists:insteadOf:fileID:line:column:)``
197197

198-
### Touching records
199-
200-
- ``StructuredQueriesCore/Table/createTemporaryTrigger(_:ifNotExists:afterInsertTouch:fileID:line:column:)``
201-
- ``StructuredQueriesCore/Table/createTemporaryTrigger(_:ifNotExists:afterUpdateTouch:fileID:line:column:)``
202-
203198
### Triggers
204199

205200
- ``TemporaryTrigger``
201+
202+
### Deprecations
203+
204+
- ``StructuredQueriesCore/Table/createTemporaryTrigger(_:ifNotExists:afterInsertTouch:fileID:line:column:)``
205+
- ``StructuredQueriesCore/Table/createTemporaryTrigger(_:ifNotExists:afterUpdateTouch:fileID:line:column:)``

Sources/StructuredQueriesSQLiteCore/Internal/Deprecations.swift

Lines changed: 129 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,123 @@
11
import Foundation
22
import StructuredQueriesCore
33

4+
// NB: Deprecated after 0.22.2:
5+
6+
extension Table {
7+
@available(
8+
*,
9+
deprecated,
10+
message: "Prefer 'createTemporaryTrigger(after: .update(touch:))', instead"
11+
)
12+
public static func createTemporaryTrigger(
13+
_ name: String? = nil,
14+
ifNotExists: Bool = false,
15+
afterUpdateTouch updates: (inout Updates<Self>) -> Void,
16+
fileID: StaticString = #fileID,
17+
line: UInt = #line,
18+
column: UInt = #column
19+
) -> TemporaryTrigger<Self> {
20+
Self.createTemporaryTrigger(
21+
name,
22+
ifNotExists: ifNotExists,
23+
after: .update { _, new in
24+
Self
25+
.where { $0.rowid.eq(new.rowid) }
26+
.update { updates(&$0) }
27+
},
28+
fileID: fileID,
29+
line: line,
30+
column: column
31+
)
32+
}
33+
34+
@available(
35+
*,
36+
deprecated,
37+
message: "Prefer 'createTemporaryTrigger(after: .update(touch:))', instead"
38+
)
39+
public static func createTemporaryTrigger<D: _OptionalPromotable<Date?>>(
40+
_ name: String? = nil,
41+
ifNotExists: Bool = false,
42+
afterUpdateTouch dateColumn: KeyPath<TableColumns, TableColumn<Self, D>>,
43+
date dateFunction: any QueryExpression<D> = SQLQueryExpression<D>("datetime('subsec')"),
44+
fileID: StaticString = #fileID,
45+
line: UInt = #line,
46+
column: UInt = #column
47+
) -> TemporaryTrigger<Self> {
48+
Self.createTemporaryTrigger(
49+
name,
50+
ifNotExists: ifNotExists,
51+
afterUpdateTouch: {
52+
$0[dynamicMember: dateColumn] = dateFunction
53+
},
54+
fileID: fileID,
55+
line: line,
56+
column: column
57+
)
58+
}
59+
60+
@available(
61+
*,
62+
deprecated,
63+
message: "Prefer 'createTemporaryTrigger(after: .insert(touch:))', instead"
64+
)
65+
public static func createTemporaryTrigger(
66+
_ name: String? = nil,
67+
ifNotExists: Bool = false,
68+
afterInsertTouch updates: (inout Updates<Self>) -> Void,
69+
fileID: StaticString = #fileID,
70+
line: UInt = #line,
71+
column: UInt = #column
72+
) -> TemporaryTrigger<Self> {
73+
Self.createTemporaryTrigger(
74+
name,
75+
ifNotExists: ifNotExists,
76+
after: .insert { new in
77+
Self
78+
.where { $0.rowid.eq(new.rowid) }
79+
.update { updates(&$0) }
80+
},
81+
fileID: fileID,
82+
line: line,
83+
column: column
84+
)
85+
}
86+
87+
@available(
88+
*,
89+
deprecated,
90+
message: "Prefer 'createTemporaryTrigger(after: .insert(touch:))', instead"
91+
)
92+
public static func createTemporaryTrigger<D: _OptionalPromotable<Date?>>(
93+
_ name: String? = nil,
94+
ifNotExists: Bool = false,
95+
afterInsertTouch dateColumn: KeyPath<TableColumns, TableColumn<Self, D>>,
96+
date dateFunction: any QueryExpression<D> = SQLQueryExpression<D>("datetime('subsec')"),
97+
fileID: StaticString = #fileID,
98+
line: UInt = #line,
99+
column: UInt = #column
100+
) -> TemporaryTrigger<Self> {
101+
Self.createTemporaryTrigger(
102+
name,
103+
ifNotExists: ifNotExists,
104+
afterInsertTouch: {
105+
$0[dynamicMember: dateColumn] = dateFunction
106+
},
107+
fileID: fileID,
108+
line: line,
109+
column: column
110+
)
111+
}
112+
}
113+
4114
// NB: Deprecated after 0.5.1:
5115

6116
extension Table {
7117
@available(
8-
*, deprecated, message: "Use a trailing closure, instead: 'Table.insert { row }'"
118+
*,
119+
deprecated,
120+
message: "Use a trailing closure, instead: 'Table.insert { row }'"
9121
)
10122
public static func insert(
11123
or conflictResolution: ConflictResolution,
@@ -16,7 +128,9 @@ extension Table {
16128
}
17129

18130
@available(
19-
*, deprecated, message: "Use a trailing closure, instead: 'Table.insert { rows }'"
131+
*,
132+
deprecated,
133+
message: "Use a trailing closure, instead: 'Table.insert { rows }'"
20134
)
21135
public static func insert(
22136
or conflictResolution: ConflictResolution,
@@ -49,7 +163,10 @@ extension Table {
49163

50164
@available(*, deprecated, renamed: "insert(or:_:select:onConflictDoUpdate:)")
51165
public static func insert<
52-
V1, each V2, From, Joins
166+
V1,
167+
each V2,
168+
From,
169+
Joins
53170
>(
54171
or conflictResolution: ConflictResolution,
55172
_ columns: (TableColumns) -> (TableColumn<Self, V1>, repeat TableColumn<Self, each V2>),
@@ -62,7 +179,9 @@ extension Table {
62179

63180
extension PrimaryKeyedTable {
64181
@available(
65-
*, deprecated, message: "Use a trailing closure, instead: 'Table.insert { draft }'"
182+
*,
183+
deprecated,
184+
message: "Use a trailing closure, instead: 'Table.insert { draft }'"
66185
)
67186
public static func insert(
68187
or conflictResolution: ConflictResolution,
@@ -73,7 +192,9 @@ extension PrimaryKeyedTable {
73192
}
74193

75194
@available(
76-
*, deprecated, message: "Use a trailing closure, instead: 'Table.insert { drafts }'"
195+
*,
196+
deprecated,
197+
message: "Use a trailing closure, instead: 'Table.insert { drafts }'"
77198
)
78199
public static func insert(
79200
or conflictResolution: ConflictResolution,
@@ -84,7 +205,9 @@ extension PrimaryKeyedTable {
84205
}
85206

86207
@available(
87-
*, deprecated, message: "Use a trailing closure, instead: 'Table.upsert { draft }'"
208+
*,
209+
deprecated,
210+
message: "Use a trailing closure, instead: 'Table.upsert { draft }'"
88211
)
89212
public static func upsert(
90213
or conflictResolution: ConflictResolution,

0 commit comments

Comments
 (0)