Skip to content

Commit 6366ee2

Browse files
authored
Add CTE support to createTemporaryView (pointfreeco#176)
* Add CTE support to `createTemporaryView` * wip
1 parent ed9df63 commit 6366ee2

File tree

4 files changed

+50
-18
lines changed

4 files changed

+50
-18
lines changed

Package.resolved

Lines changed: 0 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/StructuredQueriesCore/Statements/CommonTableExpression.swift

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/// Creates a common table expression that can be used to factor subqueries, or create hierarchical
22
/// or recursive queries of trees and graphs.
3-
public struct With<QueryValue>: Statement, Sendable {
3+
public struct With<Base: Statement>: Statement, Sendable {
4+
public typealias QueryValue = Base.QueryValue
45
public typealias From = Never
56

67
var ctes: [CommonTableExpressionClause]
@@ -9,7 +10,7 @@ public struct With<QueryValue>: Statement, Sendable {
910
@_disfavoredOverload
1011
public init(
1112
@CommonTableExpressionBuilder _ ctes: () -> [CommonTableExpressionClause],
12-
query statement: () -> some Statement<QueryValue>
13+
query statement: () -> Base
1314
) {
1415
self.ctes = ctes()
1516
self.statement = statement().query
@@ -22,7 +23,21 @@ public struct With<QueryValue>: Statement, Sendable {
2223
where
2324
S.QueryValue == (),
2425
S.Joins == (repeat each J),
25-
QueryValue == (S.From, repeat each J)
26+
Base == Select<(S.From, repeat each J), S.From, (repeat each J)>
27+
{
28+
self.ctes = ctes()
29+
self.statement = statement().query
30+
}
31+
32+
@_disfavoredOverload
33+
public init<S: SelectStatement>(
34+
@CommonTableExpressionBuilder _ ctes: () -> [CommonTableExpressionClause],
35+
query statement: () -> S
36+
)
37+
where
38+
S.QueryValue == (),
39+
S.Joins == (),
40+
Base == Select<S.From, S.From, ()>
2641
{
2742
self.ctes = ctes()
2843
self.statement = statement().query
@@ -40,6 +55,8 @@ public struct With<QueryValue>: Statement, Sendable {
4055
}
4156
}
4257

58+
extension With: PartialSelectStatement where Base: PartialSelectStatement {}
59+
4360
extension QueryFragment {
4461
fileprivate var presence: Self? { isEmpty ? nil : self }
4562
}

Sources/StructuredQueriesSQLiteCore/Views.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ extension Table where Self: _Selection {
77
/// - ifNotExists: Adds an `IF NOT EXISTS` clause to the `CREATE VIEW` statement.
88
/// - select: A statement describing the contents of the view.
99
/// - Returns: A temporary trigger.
10-
public static func createTemporaryView<Selection: SelectStatement>(
10+
public static func createTemporaryView<Selection: PartialSelectStatement>(
1111
ifNotExists: Bool = false,
1212
as select: Selection
1313
) -> TemporaryView<Self, Selection>
@@ -21,7 +21,7 @@ extension Table where Self: _Selection {
2121
/// This type of statement is returned from ``Table/createTemporaryView(ifNotExists:as:)``.
2222
///
2323
/// To learn more, see <doc:Views>.
24-
public struct TemporaryView<View: Table & _Selection, Selection: SelectStatement>: Statement
24+
public struct TemporaryView<View: Table & _Selection, Selection: PartialSelectStatement>: Statement
2525
where Selection.QueryValue == View {
2626
public typealias QueryValue = ()
2727
public typealias From = Never

Tests/StructuredQueriesTests/ViewsTests.swift

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,34 @@ extension SnapshotTests {
6262
"""
6363
}
6464
}
65+
66+
@Test func ctes() {
67+
assertQuery(
68+
CompletedReminder.createTemporaryView(
69+
as: With {
70+
Reminder
71+
.where(\.isCompleted)
72+
.select { CompletedReminder.Columns(reminderID: $0.id, title: $0.title) }
73+
} query: {
74+
CompletedReminder.all
75+
}
76+
)
77+
) {
78+
"""
79+
CREATE TEMPORARY VIEW
80+
"completedReminders"
81+
("reminderID", "title")
82+
AS
83+
WITH "completedReminders" AS (
84+
SELECT "reminders"."id" AS "reminderID", "reminders"."title" AS "title"
85+
FROM "reminders"
86+
WHERE "reminders"."isCompleted"
87+
)
88+
SELECT "completedReminders"."reminderID", "completedReminders"."title"
89+
FROM "completedReminders"
90+
"""
91+
}
92+
}
6593
}
6694
}
6795

@@ -70,7 +98,3 @@ private struct CompletedReminder {
7098
let reminderID: Reminder.ID
7199
let title: String
72100
}
73-
74-
extension Table where Self: _Selection {
75-
static func foo() {}
76-
}

0 commit comments

Comments
 (0)