[tracker/wip/carlosg/fts5-syntax-under-the-rug] libtracker-data: Do not expose FTS5 syntax through fts:match




commit e2e56d2f2d32e86083524b27fd47ce8bb15df4ef
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu Sep 3 12:44:31 2020 +0200

    libtracker-data: Do not expose FTS5 syntax through fts:match
    
    We used to simply forward all FTS match string interpretation to SQLite's
    FTS implementation, and used to allow and announce its features, e.g.
    use of AND/OR keywords for more complex matches.
    
    When FTS5 came through, the FTS query syntax got a major revamp, also
    in the complexity of the allowed syntax, including non natural language
    (e.g. symbols like ^ or *).
    
    This makes all the gory details of this parser available to users, but
    also its pitfalls, e.g. execution-time errors are raised when the search
    string contains special symbols non-interpretable by the FTS5 parser.
    
    Since fts:match is often plugged directly to search entries in UIs around,
    it seems a bad approach to maybe fail the query or not depending on the
    last character entered. Arguably applications might cater for this
    additional level of syntax, but it's sadly not trivial and kind of a moving
    target (fts5 still does add features from time to time), seems bad to leave
    this up to applications.
    
    So, hide all FTS5 syntax from the upper layers. The fts:match string forcibly
    becomes '"%s"*' so it is ensured that all the input string is interpreted as
    "search terms". It is also ensured that the given search string cannot break
    out of that. The '*' character makes the last term in the search string be
    interpreted as a prefix search.
    
    We lose some neat things there, like AND/OR mentioned above, or the
    possibility to match a single property instead of a whole row. AND is already
    the default, OR can be obtained through additional fts:match, and the last
    one is a rather obscure feature. Might be neat to bring back in another form
    someday. (e.g. make fts:match a FILTER function).
    
    Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/3114

 src/libtracker-data/tracker-sparql.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index e55795a2b..7219ce09a 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -1482,10 +1482,11 @@ tracker_sparql_add_fts_subquery (TrackerSparql         *sparql,
                if (tracker_sparql_find_graph (sparql, tracker_token_get_idstring (graph))) {
                        _append_string_printf (sparql,
                                               "%s FROM \"%s\".\"fts5\" "
-                                              "WHERE fts5 = ",
+                                              "WHERE fts5 = '\"' || REPLACE (",
                                               select_items->str,
                                               tracker_token_get_idstring (graph));
                        _append_literal_sql (sparql, binding);
+                       _append_string (sparql, ", '\"', ' ') || '\"*'");
                } else {
                        _append_empty_select (sparql, n_properties);
                }
@@ -1497,9 +1498,10 @@ tracker_sparql_add_fts_subquery (TrackerSparql         *sparql,
                if (!sparql->policy.filter_unnamed_graph) {
                        _append_string_printf (sparql,
                                               "%s, 0 FROM \"main\".\"fts5\" "
-                                              "WHERE fts5 = ",
+                                              "WHERE fts5 = '\"' || REPLACE (",
                                               select_items->str);
                        _append_literal_sql (sparql, binding);
+                       _append_string (sparql, ", '\"', ' ') || '\"*'");
                } else {
                        _append_empty_select (sparql, n_properties);
                }
@@ -1511,11 +1513,12 @@ tracker_sparql_add_fts_subquery (TrackerSparql         *sparql,
                        _append_string_printf (sparql,
                                               "UNION ALL %s, %d AS graph "
                                               "FROM \"%s\".\"fts5\" "
-                                              "WHERE fts5 = ",
+                                              "WHERE fts5 = '\"' || REPLACE (",
                                               select_items->str,
                                               GPOINTER_TO_INT (graph_id),
                                               (gchar *) graph_name);
                        _append_literal_sql (sparql, binding);
+                       _append_string (sparql, ", '\"', ' ') || '\"*'");
                }
        }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]