From 7c22a64fb60fdf50c8a5f521ecd2c320143341d5 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Thu, 5 Nov 2020 10:01:58 -0800 Subject: [PATCH] .search() now works differently for FTS4 v.s. FTS5 --- sqlite_utils/db.py | 85 +++++++++++++++++++++++----------------------- tests/test_fts.py | 2 +- 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index cd6a5a6..bfbd17c 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -1326,51 +1326,52 @@ class Table(Queryable): assert fts_table, "Full-text search is not configured for table '{}'".format( self.name ) - return textwrap.dedent( - """ - with {original} as ( - select - rowid, - {columns} - from [{dbtable}] - ) - select - {original}.*, - [{fts}].rank as {rank} - from - [{original}] - join [{fts}] on [{original}].rowid = [{fts}].rowid - where - [{fts}] match :query - order by - {order} - {limit} - """.format( - dbtable=self.name, - original=original, - columns=columns_sql, - rank=rank, - fts=fts_table, - order=order or "{} desc".format(rank), - limit="limit {}".format(limit) if limit else "", + if self.db[fts_table].virtual_table_using == "FTS5": + sql = textwrap.dedent( + """ + with {original} as ( + select + rowid, + {columns} + from [{dbtable}] ) + select + {original}.*, + [{fts}].rank as {rank} + from + [{original}] + join [{fts}] on [{original}].rowid = [{fts}].rowid + where + [{fts}] match :query + order by + {order} + {limit} + """ + ).strip() + else: + if order == rank or order is None: + order = "rowid" + sql = textwrap.dedent( + """ + select * from "{dbtable}" where rowid in ( + select rowid from [{fts}] + where [{fts}] match :query + ) + order by {order} + """ + ).strip() + return sql.format( + dbtable=self.name, + original=original, + columns=columns_sql, + rank=rank, + fts=fts_table, + order=order or "{} desc".format(rank), + limit="limit {}".format(limit) if limit else "", ).strip() - def search(self, q): - sql = ( - textwrap.dedent( - """ - select * from "{table}" where rowid in ( - select rowid from [{table}_fts] - where [{table}_fts] match :search - ) - order by rowid - """ - ) - .strip() - .format(table=self.name) - ) - return self.db.execute(sql, (q,)).fetchall() + def search(self, q, order=None): + return self.db.execute(self.search_sql(order=order), {"query": q}).fetchall() def value_or_default(self, key, value): return self._defaults[key] if value is DEFAULT else value diff --git a/tests/test_fts.py b/tests/test_fts.py index ddcf1bd..9ae692f 100644 --- a/tests/test_fts.py +++ b/tests/test_fts.py @@ -112,7 +112,7 @@ def test_fts_tokenize(fresh_db): tokenize="porter", ) assert [("racoons are biting trash pandas", "USA", "bar")] == table.search( - "bite" + "bite", order="rowid" )