Skip to content

Commit d715ae3

Browse files
authored
FTS5: Support outer joins and aliased tables (#171)
Currently the helpers are only surfaced directly on a conformance. This commit extends the availability to optional tables and table aliases via conditional conformance.
1 parent 7628706 commit d715ae3

File tree

3 files changed

+89
-6
lines changed

3 files changed

+89
-6
lines changed

Package.resolved

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

Sources/StructuredQueriesSQLiteCore/FTS5.swift

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ extension TableDefinition where QueryValue: FTS5 {
1515
public func bm25(
1616
_ rankings: KeyValuePairs<PartialKeyPath<Self>, Double> = [:]
1717
) -> some QueryExpression<Double> {
18-
var queryFragments: [QueryFragment] = ["\(QueryValue.self)"]
18+
var queryFragments: [QueryFragment] = ["\(quote: QueryValue.tableName)"]
1919
if !rankings.isEmpty {
2020
var columnNameToRanking: QueryFragment = """
2121
CASE "name"
@@ -89,7 +89,12 @@ extension TableDefinition where QueryValue: FTS5 {
8989
}
9090
}
9191

92-
extension TableColumnExpression where Root: FTS5 {
92+
extension TableColumnExpression
93+
where
94+
Root: FTS5,
95+
Value.QueryOutput: _OptionalPromotable,
96+
Value.QueryOutput._Optionalized.Wrapped: StringProtocol
97+
{
9398
/// A string expression highlighting matches in this column using the given delimiters.
9499
///
95100
/// - Parameters:
@@ -99,11 +104,11 @@ extension TableColumnExpression where Root: FTS5 {
99104
public func highlight(
100105
_ open: some StringProtocol,
101106
_ close: some StringProtocol
102-
) -> some QueryExpression<String> {
107+
) -> some QueryExpression<Value> {
103108
SQLQueryExpression(
104109
"""
105110
highlight(\
106-
\(Root.self), \
111+
\(quote: Root.tableName), \
107112
(\(cid)),
108113
\(quote: "\(open)", delimiter: .text), \
109114
\(quote: "\(close)", delimiter: .text)\
@@ -139,11 +144,11 @@ extension TableColumnExpression where Root: FTS5 {
139144
_ close: some StringProtocol,
140145
_ ellipsis: some StringProtocol,
141146
_ tokens: Int
142-
) -> some QueryExpression<String> {
147+
) -> some QueryExpression<Value> {
143148
SQLQueryExpression(
144149
"""
145150
snippet(\
146-
\(Root.self), \
151+
\(quote: Root.tableName), \
147152
(\(cid)),
148153
\(quote: "\(open)", delimiter: .text), \
149154
\(quote: "\(close)", delimiter: .text), \
@@ -165,3 +170,7 @@ extension TableColumnExpression {
165170
)
166171
}
167172
}
173+
174+
extension Optional: FTS5 where Wrapped: FTS5 {}
175+
176+
extension TableAlias: FTS5 where Base: FTS5 {}

Tests/StructuredQueriesTests/FTSTests.swift

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,5 +140,70 @@ extension SnapshotTests {
140140
"""
141141
}
142142
}
143+
144+
@Test func outerJoin() {
145+
assertQuery(
146+
Reminder
147+
.leftJoin(ReminderText.all) { $0.rowid.eq($1.rowid) }
148+
.select { $1.tags.highlight("**", "**") }
149+
.order { $1.bm25() }
150+
) {
151+
"""
152+
SELECT highlight("reminderTexts", (SELECT "cid" FROM pragma_table_info('reminderTexts') WHERE "name" = 'tags'),
153+
'**', '**')
154+
FROM "reminders"
155+
LEFT JOIN "reminderTexts" ON ("reminders"."rowid" = "reminderTexts"."rowid")
156+
ORDER BY bm25("reminderTexts")
157+
"""
158+
} results: {
159+
"""
160+
┌────────────────────┐
161+
"someday optional"
162+
"someday optional"
163+
""
164+
"car kids"
165+
""
166+
""
167+
""
168+
""
169+
""
170+
""
171+
└────────────────────┘
172+
"""
173+
}
174+
}
175+
176+
@Test func alias() {
177+
enum RT: AliasName {}
178+
assertQuery(
179+
Reminder
180+
.leftJoin(ReminderText.as(RT.self).all) { $0.rowid.eq($1.rowid) }
181+
.select { $1.tags.highlight("**", "**") }
182+
.order { $1.bm25() }
183+
) {
184+
"""
185+
SELECT highlight("reminderTexts", (SELECT "cid" FROM pragma_table_info('reminderTexts') WHERE "name" = 'tags'),
186+
'**', '**')
187+
FROM "reminders"
188+
LEFT JOIN "reminderTexts" AS "rTs" ON ("reminders"."rowid" = "rTs"."rowid")
189+
ORDER BY bm25("reminderTexts")
190+
"""
191+
} results: {
192+
"""
193+
┌────────────────────┐
194+
"someday optional"
195+
"someday optional"
196+
""
197+
"car kids"
198+
""
199+
""
200+
""
201+
""
202+
""
203+
""
204+
└────────────────────┘
205+
"""
206+
}
207+
}
143208
}
144209
}

0 commit comments

Comments
 (0)