Skip to content

Commit 365ce8f

Browse files
committed
Merge remote-tracking branch 'origin/main' into temp-triggers
2 parents 473615e + 567f841 commit 365ce8f

File tree

7 files changed

+101
-34
lines changed

7 files changed

+101
-34
lines changed

Sources/StructuredQueriesCore/Internal/Deprecations.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,13 @@ extension Table {
8484

8585
@available(*, deprecated, renamed: "insert(or:_:select:onConflictDoUpdate:)")
8686
public static func insert<
87-
V1, each V2, C1: QueryExpression, each C2: QueryExpression, From, Joins
87+
V1, each V2, From, Joins
8888
>(
8989
or conflictResolution: ConflictResolution? = nil,
9090
_ columns: (TableColumns) -> (TableColumn<Self, V1>, repeat TableColumn<Self, each V2>),
91-
select selection: () -> Select<(C1, repeat each C2), From, Joins>,
91+
select selection: () -> Select<(V1, repeat each V2), From, Joins>,
9292
onConflict updates: ((inout Updates<Self>) -> Void)?
93-
) -> InsertOf<Self>
94-
where C1.QueryValue == V1, (repeat (each C2).QueryValue) == (repeat each V2) {
93+
) -> InsertOf<Self> {
9594
insert(or: conflictResolution, columns, select: selection, onConflictDoUpdate: updates)
9695
}
9796
}

Sources/StructuredQueriesCore/QueryFragment.swift

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,20 @@ public struct QueryFragment: Hashable, Sendable {
6464
public func prepare(
6565
_ template: (_ offset: Int) -> String
6666
) -> (sql: String, bindings: [QueryBinding]) {
67-
segments.enumerated().reduce(into: (sql: "", bindings: [QueryBinding]())) {
68-
switch $1.element {
69-
case .sql(let sql):
70-
$0.sql.append(sql)
67+
var sql = ""
68+
var bindings: [QueryBinding] = []
69+
var offset = 1
70+
for segment in segments {
71+
switch segment {
72+
case .sql(let fragment):
73+
sql.append(fragment)
7174
case .binding(let binding):
72-
$0.sql.append(template($1.offset + 1))
73-
$0.bindings.append(binding)
75+
defer { offset += 1 }
76+
sql.append(template(offset))
77+
bindings.append(binding)
7478
}
7579
}
80+
return (sql, bindings)
7681
}
7782
}
7883

Sources/StructuredQueriesCore/Statements/Insert.swift

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -301,18 +301,15 @@ extension Table {
301301
/// - Returns: An insert statement.
302302
public static func insert<
303303
V1,
304-
each V2,
305-
C1: QueryExpression,
306-
each C2: QueryExpression
304+
each V2
307305
>(
308306
or conflictResolution: ConflictResolution? = nil,
309307
_ columns: (TableColumns) -> (TableColumn<Self, V1>, repeat TableColumn<Self, each V2>),
310-
select selection: () -> some PartialSelectStatement<(C1, repeat each C2)>,
308+
select selection: () -> some PartialSelectStatement<(V1, repeat each V2)>,
311309
onConflictDoUpdate updates: ((inout Updates<Self>) -> Void)? = nil,
312310
@QueryFragmentBuilder<Bool>
313311
where updateFilter: (TableColumns) -> [QueryFragment] = { _ in [] }
314-
) -> InsertOf<Self>
315-
where C1.QueryValue == V1, (repeat (each C2).QueryValue) == (repeat each V2) {
312+
) -> InsertOf<Self> {
316313
_insert(
317314
or: conflictResolution,
318315
columns,
@@ -342,14 +339,12 @@ extension Table {
342339
public static func insert<
343340
V1,
344341
each V2,
345-
C1: QueryExpression,
346-
each C2: QueryExpression,
347342
T1,
348343
each T2
349344
>(
350345
or conflictResolution: ConflictResolution? = nil,
351346
_ columns: (TableColumns) -> (TableColumn<Self, V1>, repeat TableColumn<Self, each V2>),
352-
select selection: () -> some PartialSelectStatement<(C1, repeat each C2)>,
347+
select selection: () -> some PartialSelectStatement<(V1, repeat each V2)>,
353348
onConflict conflictTargets: (TableColumns) -> (
354349
TableColumn<Self, T1>, repeat TableColumn<Self, each T2>
355350
),
@@ -358,8 +353,7 @@ extension Table {
358353
doUpdate updates: (inout Updates<Self>) -> Void = { _ in },
359354
@QueryFragmentBuilder<Bool>
360355
where updateFilter: (TableColumns) -> [QueryFragment] = { _ in [] }
361-
) -> InsertOf<Self>
362-
where C1.QueryValue == V1, (repeat (each C2).QueryValue) == (repeat each V2) {
356+
) -> InsertOf<Self> {
363357
withoutActuallyEscaping(updates) { updates in
364358
_insert(
365359
or: conflictResolution,
@@ -375,20 +369,18 @@ extension Table {
375369

376370
private static func _insert<
377371
each Value,
378-
each ResultColumn: QueryExpression,
379372
each ConflictTarget
380373
>(
381374
or conflictResolution: ConflictResolution? = nil,
382375
_ columns: (TableColumns) -> (repeat TableColumn<Self, each Value>),
383-
select selection: () -> some PartialSelectStatement<(repeat each ResultColumn)>,
376+
select selection: () -> some PartialSelectStatement<(repeat each Value)>,
384377
onConflict conflictTargets: (TableColumns) -> (repeat TableColumn<Self, each ConflictTarget>)?,
385378
@QueryFragmentBuilder<Bool>
386379
where targetFilter: (TableColumns) -> [QueryFragment] = { _ in [] },
387380
doUpdate updates: ((inout Updates<Self>) -> Void)?,
388381
@QueryFragmentBuilder<Bool>
389382
where updateFilter: (TableColumns) -> [QueryFragment] = { _ in [] }
390-
) -> InsertOf<Self>
391-
where (repeat (each ResultColumn).QueryValue) == (repeat each Value) {
383+
) -> InsertOf<Self> {
392384
var columnNames: [String] = []
393385
for column in repeat each columns(Self.columns) {
394386
columnNames.append(column.name)

Sources/StructuredQueriesTestSupport/AssertQuery.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,22 @@ public func assertQuery<each V: QueryRepresentable, S: Statement<(repeat each V)
9797
line: line,
9898
column: column
9999
)
100+
} else if results != nil {
101+
assertInlineSnapshot(
102+
of: table,
103+
as: .lines,
104+
message: "Results expected to be empty",
105+
syntaxDescriptor: InlineSnapshotSyntaxDescriptor(
106+
trailingClosureLabel: "results",
107+
trailingClosureOffset: snapshotTrailingClosureOffset + 1
108+
),
109+
matches: results,
110+
fileID: fileID,
111+
file: filePath,
112+
function: function,
113+
line: line,
114+
column: column
115+
)
100116
}
101117
} catch {
102118
assertInlineSnapshot(

Tests/StructuredQueriesTests/InsertTests.swift

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -473,15 +473,6 @@ extension SnapshotTests {
473473
DO NOTHING
474474
RETURNING "reminderID", "tagID"
475475
"""
476-
} results: {
477-
"""
478-
┌──────────────────┐
479-
│ ReminderTag( │
480-
│ reminderID: 1, │
481-
│ tagID: 1 │
482-
│ ) │
483-
└──────────────────┘
484-
"""
485476
}
486477
}
487478

@@ -621,6 +612,30 @@ extension SnapshotTests {
621612
"""
622613
}
623614
}
615+
616+
@Test func insertSelectSQL() {
617+
assertQuery(
618+
RemindersList.insert {
619+
$0.title
620+
} select: {
621+
Values(#sql("'Groceries'"))
622+
}
623+
.returning(\.id)
624+
) {
625+
"""
626+
INSERT INTO "remindersLists"
627+
("title")
628+
SELECT 'Groceries'
629+
RETURNING "id"
630+
"""
631+
} results: {
632+
"""
633+
┌───┐
634+
│ 4 │
635+
└───┘
636+
"""
637+
}
638+
}
624639
}
625640
}
626641

Tests/StructuredQueriesTests/QueryFragmentTests.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,27 @@ extension SnapshotTests {
4646
"""
4747
}
4848
}
49+
@Test func prepare() {
50+
let query = #sql(
51+
"""
52+
SELECT \(Reminder.id) FROM \(Reminder.self)
53+
WHERE \(Reminder.id) > \(1) AND \(Reminder.title) COLLATE NOCASE LIKE \(bind: "%get%")
54+
"""
55+
)
56+
.query
57+
58+
#expect(
59+
query.prepare { "$\($0)" } == (
60+
"""
61+
SELECT "reminders"."id" FROM "reminders"
62+
WHERE "reminders"."id" > $1 AND "reminders"."title" COLLATE NOCASE LIKE $2
63+
""",
64+
[
65+
.int(1),
66+
.text("%get%"),
67+
]
68+
)
69+
)
70+
}
4971
}
5072
}

Tests/StructuredQueriesTests/WhereTests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,24 @@ extension SnapshotTests {
4242
}
4343
}
4444

45+
@Test(.snapshots(record: .never)) func emptyResults() {
46+
withKnownIssue("This assert should fail") {
47+
assertQuery(
48+
Reminder.where { $0.isCompleted && !$0.isCompleted }
49+
) {
50+
"""
51+
SELECT "reminders"."id", "reminders"."assignedUserID", "reminders"."dueDate", "reminders"."isCompleted", "reminders"."isFlagged", "reminders"."notes", "reminders"."priority", "reminders"."remindersListID", "reminders"."title"
52+
FROM "reminders"
53+
WHERE ("reminders"."isCompleted") AND ("reminders"."isFlagged")
54+
"""
55+
} results: {
56+
"""
57+
Results
58+
"""
59+
}
60+
}
61+
}
62+
4563
@Test func or() {
4664
assertQuery(
4765
Reminder.where(\.isCompleted).or(Reminder.where(\.isFlagged))

0 commit comments

Comments
 (0)