diff --git a/Sources/StructuredQueriesCore/SQLite/FTS5.swift b/Sources/StructuredQueriesCore/SQLite/FTS5.swift index b8998f5f..90d8618b 100644 --- a/Sources/StructuredQueriesCore/SQLite/FTS5.swift +++ b/Sources/StructuredQueriesCore/SQLite/FTS5.swift @@ -2,7 +2,9 @@ import IssueReporting /// A virtual table using the FTS5 extension. /// -/// Apply this protocol to a `@Table` declaration to introduce FTS5 helpers. +/// Apply this protocol to a `@Table` declaration to introduce [FTS5] helpers. +/// +/// [FTS5]: https://www.sqlite.org/fts5.html public protocol FTS5: Table {} extension TableDefinition where QueryValue: FTS5 { @@ -13,6 +15,16 @@ extension TableDefinition where QueryValue: FTS5 { /// // SELECT … FROM "reminderTexts" WHERE ("reminderTexts" MATCH 'get') /// ``` /// + /// > Important: Avoid passing a string entered by the user directly to this operator. FTS5 + /// > queries have a distinct [syntax] that can specify particular columns and refine a search in + /// > various ways. If FTS5 is given a query with invalid syntax, it can even throw SQL errors at + /// > runtime. + /// > + /// > Instead, consider transforming the user's input into a query by quoting, prefixing, and/or + /// > combining inputs from your UI into a valid query before handing it off to SQLite. + /// + /// [syntax]: https://www.sqlite.org/fts5.html#full_text_query_syntax + /// /// - Parameter pattern: A string expression describing the `MATCH` pattern. /// - Returns: A predicate expression. public func match(_ pattern: some StringProtocol) -> some QueryExpression { @@ -60,7 +72,7 @@ extension TableColumnExpression where Root: FTS5 { /// /// ```swift /// ReminderText.where { $0.title.match("get") } - /// // SELECT … FROM "reminderTexts" WHERE ("reminderTexts"."title" MATCH 'get') + /// // SELECT … FROM "reminderTexts" WHERE ("reminderTexts" MATCH 'title:\"get\"') /// ``` /// /// - Parameter pattern: A string expression describing the `MATCH` pattern.