Skip to content

Commit 68966b4

Browse files
committed
wip
1 parent 69d655a commit 68966b4

File tree

6 files changed

+112
-9
lines changed

6 files changed

+112
-9
lines changed

Sources/StructuredQueriesCore/Operators.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ public func == <QueryValue: _OptionalProtocol>(
192192
lhs: any QueryExpression<QueryValue>,
193193
rhs: some QueryExpression<QueryValue.Wrapped>
194194
) -> some QueryExpression<Bool> {
195-
BinaryOperator(lhs: lhs, operator: isNull(lhs) ? "IS" : "=", rhs: rhs)
195+
BinaryOperator(lhs: lhs, operator: "IS", rhs: rhs)
196196
}
197197

198198
// NB: This overload is required due to an overload resolution bug of 'Updates[dynamicMember:]'.
@@ -202,7 +202,7 @@ public func != <QueryValue: _OptionalProtocol>(
202202
lhs: any QueryExpression<QueryValue>,
203203
rhs: some QueryExpression<QueryValue.Wrapped>
204204
) -> some QueryExpression<Bool> {
205-
BinaryOperator(lhs: lhs, operator: isNull(lhs) ? "IS NOT" : "<>", rhs: rhs)
205+
BinaryOperator(lhs: lhs, operator: "IS NOT", rhs: rhs)
206206
}
207207

208208
// NB: This overload is required due to an overload resolution bug of 'Updates[dynamicMember:]'.
@@ -211,7 +211,7 @@ public func == <QueryValue: _OptionalProtocol>(
211211
lhs: any QueryExpression<QueryValue>,
212212
rhs: some QueryExpression<QueryValue>
213213
) -> some QueryExpression<Bool> {
214-
BinaryOperator(lhs: lhs, operator: isNull(lhs) || isNull(rhs) ? "IS" : "=", rhs: rhs)
214+
BinaryOperator(lhs: lhs, operator: "IS", rhs: rhs)
215215
}
216216

217217
// NB: This overload is required due to an overload resolution bug of 'Updates[dynamicMember:]'.
@@ -220,7 +220,7 @@ public func != <QueryValue: _OptionalProtocol>(
220220
lhs: any QueryExpression<QueryValue>,
221221
rhs: some QueryExpression<QueryValue>
222222
) -> some QueryExpression<Bool> {
223-
BinaryOperator(lhs: lhs, operator: isNull(lhs) || isNull(rhs) ? "IS NOT" : "<>", rhs: rhs)
223+
BinaryOperator(lhs: lhs, operator: "IS NOT", rhs: rhs)
224224
}
225225

226226
// NB: This overload is required due to an overload resolution bug of 'Updates[dynamicMember:]'.

Sources/StructuredQueriesCore/PrimaryKeyed.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ public protocol TableDraft: Table {
2323
}
2424

2525
extension TableDraft {
26+
public static subscript(
27+
dynamicMember keyPath: KeyPath<PrimaryTable.Type, some Statement<PrimaryTable>>
28+
) -> some Statement<Self> {
29+
SQLQueryExpression("\(PrimaryTable.self[keyPath: keyPath])")
30+
}
31+
32+
public static subscript(
33+
dynamicMember keyPath: KeyPath<PrimaryTable.Type, some SelectStatementOf<PrimaryTable>>
34+
) -> SelectOf<Self> {
35+
unsafeBitCast(PrimaryTable.self[keyPath: keyPath].asSelect(), to: SelectOf<Self>.self)
36+
}
37+
2638
public static var all: SelectOf<Self> {
2739
unsafeBitCast(PrimaryTable.all.asSelect(), to: SelectOf<Self>.self)
2840
}
@@ -44,6 +56,14 @@ where QueryValue: PrimaryKeyedTable {
4456
var primaryKey: TableColumn<QueryValue, PrimaryKey> { get }
4557
}
4658

59+
extension TableDefinition where QueryValue: TableDraft {
60+
public subscript<Member>(
61+
dynamicMember keyPath: KeyPath<QueryValue.PrimaryTable.TableColumns, Member>
62+
) -> Member {
63+
QueryValue.PrimaryTable.columns[keyPath: keyPath]
64+
}
65+
}
66+
4767
extension PrimaryKeyedTableDefinition {
4868
/// A query expression representing the number of rows in this table.
4969
///

Sources/StructuredQueriesCore/Statements/Where.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ public struct Where<From: Table> {
8080
public subscript(dynamicMember keyPath: KeyPath<From.Type, Self>) -> Self {
8181
self + From.self[keyPath: keyPath]
8282
}
83+
84+
public subscript(
85+
dynamicMember keyPath: KeyPath<From.PrimaryTable.Type, Where<From.PrimaryTable>>
86+
) -> Self
87+
where From: TableDraft {
88+
self + unsafeBitCast(From.PrimaryTable.self[keyPath: keyPath], to: Self.self)
89+
}
8390
#endif
8491
}
8592

Sources/StructuredQueriesCore/TableDefinition.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
///
33
/// Don't conform to this protocol directly. Instead, use the `@Table` and `@Column` macros to
44
/// generate a conformance.
5+
@dynamicMemberLookup
56
public protocol TableDefinition<QueryValue>: QueryExpression where QueryValue: Table {
67
/// An array of this table's columns.
78
static var allColumns: [any TableColumnExpression] { get }

Tests/StructuredQueriesTests/OperatorsTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ extension SnapshotTests {
2424
}
2525
assertInlineSnapshot(of: Row.columns.a == Row.columns.c, as: .sql) {
2626
"""
27-
("rows"."a" = "rows"."c")
27+
("rows"."a" IS "rows"."c")
2828
"""
2929
}
3030
assertInlineSnapshot(of: Row.columns.a == Row.columns.a, as: .sql) {
3131
"""
32-
("rows"."a" = "rows"."a")
32+
("rows"."a" IS "rows"."a")
3333
"""
3434
}
3535
assertInlineSnapshot(of: Row.columns.a == nil as Int?, as: .sql) {
@@ -64,12 +64,12 @@ extension SnapshotTests {
6464
}
6565
assertInlineSnapshot(of: Row.columns.a != Row.columns.c, as: .sql) {
6666
"""
67-
("rows"."a" <> "rows"."c")
67+
("rows"."a" IS NOT "rows"."c")
6868
"""
6969
}
7070
assertInlineSnapshot(of: Row.columns.a != Row.columns.a, as: .sql) {
7171
"""
72-
("rows"."a" <> "rows"."a")
72+
("rows"."a" IS NOT "rows"."a")
7373
"""
7474
}
7575
assertInlineSnapshot(of: Row.columns.a != nil as Int?, as: .sql) {

Tests/StructuredQueriesTests/SelectTests.swift

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,7 @@ extension SnapshotTests {
11261126
SELECT "remindersLists"."id", "remindersLists"."color", "remindersLists"."title", "reminders"."id", "reminders"."assignedUserID", "reminders"."dueDate", "reminders"."isCompleted", "reminders"."isFlagged", "reminders"."notes", "reminders"."priority", "reminders"."remindersListID", "reminders"."title"
11271127
FROM "remindersLists"
11281128
LEFT JOIN "reminders" ON ("remindersLists"."id" = "reminders"."remindersListID")
1129-
WHERE ifnull(("reminders"."priority" = 3), 0)
1129+
WHERE ifnull(("reminders"."priority" IS 3), 0)
11301130
"""
11311131
} results: {
11321132
"""
@@ -1171,6 +1171,81 @@ extension SnapshotTests {
11711171
}
11721172
}
11731173

1174+
@Test func reusableStaticHelperOnDraft() {
1175+
assertQuery(
1176+
Reminder.Draft.incomplete.select(\.id)
1177+
) {
1178+
"""
1179+
SELECT "reminders"."id"
1180+
FROM "reminders"
1181+
WHERE NOT ("reminders"."isCompleted")
1182+
"""
1183+
} results: {
1184+
"""
1185+
┌───┐
1186+
│ 1 │
1187+
│ 2 │
1188+
│ 3 │
1189+
│ 5 │
1190+
│ 6 │
1191+
│ 8 │
1192+
│ 9 │
1193+
└───┘
1194+
"""
1195+
}
1196+
assertQuery(
1197+
Reminder.Draft.where { _ in true }.incomplete.select(\.id)
1198+
) {
1199+
"""
1200+
SELECT "reminders"."id"
1201+
FROM "reminders"
1202+
WHERE 1 AND NOT ("reminders"."isCompleted")
1203+
"""
1204+
} results: {
1205+
"""
1206+
┌───┐
1207+
│ 1 │
1208+
│ 2 │
1209+
│ 3 │
1210+
│ 5 │
1211+
│ 6 │
1212+
│ 8 │
1213+
│ 9 │
1214+
└───┘
1215+
"""
1216+
}
1217+
// TODO: Compile
1218+
// assertQuery(
1219+
// Reminder.Draft.select(\.id).incomplete
1220+
// )
1221+
}
1222+
1223+
@Test func reusableColumnHelperOnDraft() {
1224+
assertQuery(
1225+
Reminder.Draft.select(\.isHighPriority)
1226+
) {
1227+
"""
1228+
SELECT ("reminders"."priority" IS 3)
1229+
FROM "reminders"
1230+
"""
1231+
} results: {
1232+
"""
1233+
┌───────┐
1234+
│ false │
1235+
│ false │
1236+
│ true │
1237+
│ false │
1238+
│ false │
1239+
│ true │
1240+
│ false │
1241+
│ true │
1242+
│ false │
1243+
│ false │
1244+
└───────┘
1245+
"""
1246+
}
1247+
}
1248+
11741249
@Test func optionalMapAndFlatMap() {
11751250
do {
11761251
let query: some Statement<Bool?> = Reminder.select {

0 commit comments

Comments
 (0)