?_searchmode=raw option (#686)

This commit is contained in:
Simon Willison 2020-02-24 21:56:03 -08:00 committed by GitHub
commit 6cb65555f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 4 deletions

View file

@ -356,13 +356,18 @@ class TableView(RowTableShared):
pair for pair in special_args.items() if pair[0].startswith("_search") pair for pair in special_args.items() if pair[0].startswith("_search")
) )
search = "" search = ""
search_mode_raw = special_args.get("_searchmode") == "raw"
if fts_table and search_args: if fts_table and search_args:
if "_search" in search_args: if "_search" in search_args:
# Simple ?_search=xxx # Simple ?_search=xxx
search = search_args["_search"] search = search_args["_search"]
where_clauses.append( where_clauses.append(
"{fts_pk} in (select rowid from {fts_table} where {fts_table} match escape_fts(:search))".format( "{fts_pk} in (select rowid from {fts_table} where {fts_table} match {match_clause})".format(
fts_table=escape_sqlite(fts_table), fts_pk=escape_sqlite(fts_pk) fts_table=escape_sqlite(fts_table),
fts_pk=escape_sqlite(fts_pk),
match_clause=":search"
if search_mode_raw
else "escape_fts(:search)",
) )
) )
extra_human_descriptions.append('search matches "{}"'.format(search)) extra_human_descriptions.append('search matches "{}"'.format(search))
@ -375,10 +380,12 @@ class TableView(RowTableShared):
raise DatasetteError("Cannot search by that column", status=400) raise DatasetteError("Cannot search by that column", status=400)
where_clauses.append( where_clauses.append(
"rowid in (select rowid from {fts_table} where {search_col} match escape_fts(:search_{i}))".format( "rowid in (select rowid from {fts_table} where {search_col} match {match_clause})".format(
fts_table=escape_sqlite(fts_table), fts_table=escape_sqlite(fts_table),
search_col=escape_sqlite(search_col), search_col=escape_sqlite(search_col),
i=i, match_clause=":search_{}".format(i)
if search_mode_raw
else "escape_fts(:search_{})".format(i),
) )
) )
extra_human_descriptions.append( extra_human_descriptions.append(

View file

@ -281,6 +281,12 @@ Special table arguments
Like ``_search=`` but allows you to specify the column to be searched, as Like ``_search=`` but allows you to specify the column to be searched, as
opposed to searching all columns that have been indexed by FTS. opposed to searching all columns that have been indexed by FTS.
``?_searchmode=raw``
With this option, queries passed to ``?_search=`` or ``?_search_COLUMN=`` will
not have special characters escaped. This means you can make use of the full
set of `advanced SQLite FTS syntax <https://www.sqlite.org/fts5.html#full_text_query_syntax>`__,
though this could potentially result in errors if the wrong syntax is used.
``?_where=SQL-fragment`` ``?_where=SQL-fragment``
If the :ref:`config_allow_sql` config option is enabled, this parameter If the :ref:`config_allow_sql` config option is enabled, this parameter
can be used to pass one or more additional SQL fragments to be used in the can be used to pass one or more additional SQL fragments to be used in the

View file

@ -952,6 +952,19 @@ def test_sortable_columns_metadata(app_client):
"/fixtures/searchable.json?_search=AND", "/fixtures/searchable.json?_search=AND",
[], [],
), ),
(
# Without _searchmode=raw this should return no results
"/fixtures/searchable.json?_search=te*+AND+do*",
[],
),
(
# _searchmode=raw
"/fixtures/searchable.json?_search=te*+AND+do*&_searchmode=raw",
[
[1, "barry cat", "terry dog", "panther"],
[2, "terry dog", "sara weasel", "puma"],
],
),
( (
"/fixtures/searchable.json?_search=weasel", "/fixtures/searchable.json?_search=weasel",
[[2, "terry dog", "sara weasel", "puma"]], [[2, "terry dog", "sara weasel", "puma"]],