sqlite-utils search --quote option, closes #296

This commit is contained in:
Simon Willison 2021-08-18 13:10:44 -07:00
commit ccf128cd6d
3 changed files with 48 additions and 15 deletions

View file

@ -1519,6 +1519,8 @@ By default it shows the most relevant matches first. You can specify a different
# Sort by created in descending order
$ sqlite-utils search mydb.db documents searchterm -o 'created desc'
SQLite `advanced search syntax <https://www.sqlite.org/fts5.html#full_text_query_syntax>`__ is enabled by default. To run a search with automatic quoting use the ``--quote`` option.
You can specify a subset of columns to be returned using the ``-c`` option one or more times::
$ sqlite-utils search mydb.db documents searchterm -c title -c created

View file

@ -1375,6 +1375,7 @@ def _execute_query(
@click.option(
"--sql", "show_sql", is_flag=True, help="Show SQL query that would be run"
)
@click.option("--quote", is_flag=True, help="Apply FTS quoting rules to search term")
@output_options
@load_extension_option
@click.pass_context
@ -1385,6 +1386,7 @@ def search(
q,
order,
show_sql,
quote,
column,
limit,
nl,
@ -1420,21 +1422,31 @@ def search(
if show_sql:
click.echo(sql)
return
ctx.invoke(
query,
path=path,
sql=sql,
nl=nl,
arrays=arrays,
csv=csv,
tsv=tsv,
no_headers=no_headers,
table=table,
fmt=fmt,
json_cols=json_cols,
param=[("query", q)],
load_extension=load_extension,
)
if quote:
q = db.quote_fts(q)
try:
ctx.invoke(
query,
path=path,
sql=sql,
nl=nl,
arrays=arrays,
csv=csv,
tsv=tsv,
no_headers=no_headers,
table=table,
fmt=fmt,
json_cols=json_cols,
param=[("query", q)],
load_extension=load_extension,
)
except click.ClickException as e:
if "malformed MATCH expression" in str(e) or "unterminated string" in str(e):
raise click.ClickException(
"{}\n\nTry running this again with the --quote option".format(str(e))
)
else:
raise
@cli.command()

View file

@ -1994,6 +1994,25 @@ def test_search(tmpdir, fts, extra_arg, expected):
assert result.output.replace("\r", "") == expected
def test_search_quote(tmpdir):
db_path = str(tmpdir / "test.db")
db = Database(db_path)
db["creatures"].insert({"name": "dog."}).enable_fts(["name"])
# Without --quote should return an error
error_result = CliRunner().invoke(cli.cli, ["search", db_path, "creatures", 'dog"'])
assert error_result.exit_code == 1
assert error_result.output == (
"Error: unterminated string\n\n"
"Try running this again with the --quote option\n"
)
# With --quote it should work
result = CliRunner().invoke(
cli.cli, ["search", db_path, "creatures", 'dog"', "--quote"]
)
assert result.exit_code == 0
assert result.output.strip() == '[{"rowid": 1, "name": "dog."}]'
def test_indexes(tmpdir):
db_path = str(tmpdir / "test.db")
db = Database(db_path)