diff --git a/Package.resolved b/Package.resolved index 279fb07e..e9704f0e 100644 --- a/Package.resolved +++ b/Package.resolved @@ -91,6 +91,15 @@ "version" : "601.0.1" } }, + { + "identity" : "swift-tagged", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-tagged", + "state" : { + "revision" : "3907a9438f5b57d317001dc99f3f11b46882272b", + "version" : "0.10.0" + } + }, { "identity" : "xctest-dynamic-overlay", "kind" : "remoteSourceControl", diff --git a/Sources/StructuredQueriesSQLiteCore/FTS5.swift b/Sources/StructuredQueriesSQLiteCore/FTS5.swift index 1c4c5e1b..def9574f 100644 --- a/Sources/StructuredQueriesSQLiteCore/FTS5.swift +++ b/Sources/StructuredQueriesSQLiteCore/FTS5.swift @@ -15,7 +15,7 @@ extension TableDefinition where QueryValue: FTS5 { public func bm25( _ rankings: KeyValuePairs, Double> = [:] ) -> some QueryExpression { - var queryFragments: [QueryFragment] = ["\(QueryValue.self)"] + var queryFragments: [QueryFragment] = ["\(quote: QueryValue.tableName)"] if !rankings.isEmpty { var columnNameToRanking: QueryFragment = """ CASE "name" @@ -89,7 +89,12 @@ extension TableDefinition where QueryValue: FTS5 { } } -extension TableColumnExpression where Root: FTS5 { +extension TableColumnExpression +where + Root: FTS5, + Value.QueryOutput: _OptionalPromotable, + Value.QueryOutput._Optionalized.Wrapped: StringProtocol +{ /// A string expression highlighting matches in this column using the given delimiters. /// /// - Parameters: @@ -99,11 +104,11 @@ extension TableColumnExpression where Root: FTS5 { public func highlight( _ open: some StringProtocol, _ close: some StringProtocol - ) -> some QueryExpression { + ) -> some QueryExpression { SQLQueryExpression( """ highlight(\ - \(Root.self), \ + \(quote: Root.tableName), \ (\(cid)), \(quote: "\(open)", delimiter: .text), \ \(quote: "\(close)", delimiter: .text)\ @@ -139,11 +144,11 @@ extension TableColumnExpression where Root: FTS5 { _ close: some StringProtocol, _ ellipsis: some StringProtocol, _ tokens: Int - ) -> some QueryExpression { + ) -> some QueryExpression { SQLQueryExpression( """ snippet(\ - \(Root.self), \ + \(quote: Root.tableName), \ (\(cid)), \(quote: "\(open)", delimiter: .text), \ \(quote: "\(close)", delimiter: .text), \ @@ -165,3 +170,7 @@ extension TableColumnExpression { ) } } + +extension Optional: FTS5 where Wrapped: FTS5 {} + +extension TableAlias: FTS5 where Base: FTS5 {} diff --git a/Tests/StructuredQueriesTests/FTSTests.swift b/Tests/StructuredQueriesTests/FTSTests.swift index 5980c12e..834b74d8 100644 --- a/Tests/StructuredQueriesTests/FTSTests.swift +++ b/Tests/StructuredQueriesTests/FTSTests.swift @@ -140,5 +140,70 @@ extension SnapshotTests { """ } } + + @Test func outerJoin() { + assertQuery( + Reminder + .leftJoin(ReminderText.all) { $0.rowid.eq($1.rowid) } + .select { $1.tags.highlight("**", "**") } + .order { $1.bm25() } + ) { + """ + SELECT highlight("reminderTexts", (SELECT "cid" FROM pragma_table_info('reminderTexts') WHERE "name" = 'tags'), + '**', '**') + FROM "reminders" + LEFT JOIN "reminderTexts" ON ("reminders"."rowid" = "reminderTexts"."rowid") + ORDER BY bm25("reminderTexts") + """ + } results: { + """ + ┌────────────────────┐ + │ "someday optional" │ + │ "someday optional" │ + │ "" │ + │ "car kids" │ + │ "" │ + │ "" │ + │ "" │ + │ "" │ + │ "" │ + │ "" │ + └────────────────────┘ + """ + } + } + + @Test func alias() { + enum RT: AliasName {} + assertQuery( + Reminder + .leftJoin(ReminderText.as(RT.self).all) { $0.rowid.eq($1.rowid) } + .select { $1.tags.highlight("**", "**") } + .order { $1.bm25() } + ) { + """ + SELECT highlight("reminderTexts", (SELECT "cid" FROM pragma_table_info('reminderTexts') WHERE "name" = 'tags'), + '**', '**') + FROM "reminders" + LEFT JOIN "reminderTexts" AS "rTs" ON ("reminders"."rowid" = "rTs"."rowid") + ORDER BY bm25("reminderTexts") + """ + } results: { + """ + ┌────────────────────┐ + │ "someday optional" │ + │ "someday optional" │ + │ "" │ + │ "car kids" │ + │ "" │ + │ "" │ + │ "" │ + │ "" │ + │ "" │ + │ "" │ + └────────────────────┘ + """ + } + } } }