mirror of
https://github.com/simonw/sqlite-utils.git
synced 2026-09-27 20:34:12 +02:00
disable-fts and .disable_fts(), closes #88
This commit is contained in:
parent
b0ca657f49
commit
f9473ace14
6 changed files with 96 additions and 0 deletions
|
|
@ -411,6 +411,10 @@ A better solution here is to use database triggers. You can set up database trig
|
||||||
|
|
||||||
$ sqlite-utils enable-fts mydb.db documents title summary --create-triggers
|
$ sqlite-utils enable-fts mydb.db documents title summary --create-triggers
|
||||||
|
|
||||||
|
To remove the FTS tables and triggers you created, use ``disable-fts``::
|
||||||
|
|
||||||
|
$ sqlite-utils disable-fts mydb.db documents
|
||||||
|
|
||||||
Vacuum
|
Vacuum
|
||||||
======
|
======
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1052,6 +1052,12 @@ A better solution is to use database triggers. You can set up database triggers
|
||||||
|
|
||||||
dogs.enable_fts(["name", "twitter"], fts_version="FTS4")
|
dogs.enable_fts(["name", "twitter"], fts_version="FTS4")
|
||||||
|
|
||||||
|
To remove the FTS tables and triggers you created, use the ``disable_fts()`` table method:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
dogs.disable_fts()
|
||||||
|
|
||||||
Optimizing a full-text search table
|
Optimizing a full-text search table
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -300,6 +300,19 @@ def populate_fts(path, table, column):
|
||||||
db[table].populate_fts(column)
|
db[table].populate_fts(column)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command(name="disable-fts")
|
||||||
|
@click.argument(
|
||||||
|
"path",
|
||||||
|
type=click.Path(exists=True, file_okay=True, dir_okay=False, allow_dash=False),
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
@click.argument("table")
|
||||||
|
def disable_fts(path, table):
|
||||||
|
"Disable FTS for specific table"
|
||||||
|
db = sqlite_utils.Database(path)
|
||||||
|
db[table].disable_fts()
|
||||||
|
|
||||||
|
|
||||||
def insert_upsert_options(fn):
|
def insert_upsert_options(fn):
|
||||||
for decorator in reversed(
|
for decorator in reversed(
|
||||||
(
|
(
|
||||||
|
|
|
||||||
|
|
@ -794,6 +794,25 @@ class Table(Queryable):
|
||||||
self.db.conn.executescript(sql)
|
self.db.conn.executescript(sql)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def disable_fts(self):
|
||||||
|
fts_table = self.detect_fts()
|
||||||
|
if fts_table:
|
||||||
|
self.db[fts_table].drop()
|
||||||
|
# Now delete the triggers that related to that table
|
||||||
|
sql = """
|
||||||
|
SELECT name FROM sqlite_master
|
||||||
|
WHERE type = 'trigger'
|
||||||
|
AND sql LIKE '% INSERT INTO [{}]%'
|
||||||
|
""".format(
|
||||||
|
fts_table
|
||||||
|
)
|
||||||
|
trigger_names = []
|
||||||
|
for row in self.db.conn.execute(sql).fetchall():
|
||||||
|
trigger_names.append(row[0])
|
||||||
|
with self.db.conn:
|
||||||
|
for trigger_name in trigger_names:
|
||||||
|
self.db.conn.execute("DROP TRIGGER IF EXISTS [{}]".format(trigger_name))
|
||||||
|
|
||||||
def detect_fts(self):
|
def detect_fts(self):
|
||||||
"Detect if table has a corresponding FTS virtual table and return it"
|
"Detect if table has a corresponding FTS virtual table and return it"
|
||||||
sql = """
|
sql = """
|
||||||
|
|
|
||||||
|
|
@ -393,6 +393,24 @@ def test_populate_fts(db_path):
|
||||||
assert [("martha",)] == search("martha")
|
assert [("martha",)] == search("martha")
|
||||||
|
|
||||||
|
|
||||||
|
def test_disable_fts(db_path):
|
||||||
|
db = Database(db_path)
|
||||||
|
assert {"Gosh", "Gosh2"} == set(db.table_names())
|
||||||
|
db["Gosh"].enable_fts(["c1"], create_triggers=True)
|
||||||
|
assert {
|
||||||
|
"Gosh_fts",
|
||||||
|
"Gosh_fts_idx",
|
||||||
|
"Gosh_fts_data",
|
||||||
|
"Gosh2",
|
||||||
|
"Gosh_fts_config",
|
||||||
|
"Gosh",
|
||||||
|
"Gosh_fts_docsize",
|
||||||
|
} == set(db.table_names())
|
||||||
|
exit_code = CliRunner().invoke(cli.cli, ["disable-fts", db_path, "Gosh"]).exit_code
|
||||||
|
assert 0 == exit_code
|
||||||
|
assert {"Gosh", "Gosh2"} == set(db.table_names())
|
||||||
|
|
||||||
|
|
||||||
def test_vacuum(db_path):
|
def test_vacuum(db_path):
|
||||||
result = CliRunner().invoke(cli.cli, ["vacuum", db_path])
|
result = CliRunner().invoke(cli.cli, ["vacuum", db_path])
|
||||||
assert 0 == result.exit_code
|
assert 0 == result.exit_code
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
search_records = [
|
search_records = [
|
||||||
{"text": "tanuki are tricksters", "country": "Japan", "not_searchable": "foo"},
|
{"text": "tanuki are tricksters", "country": "Japan", "not_searchable": "foo"},
|
||||||
{"text": "racoons are trash pandas", "country": "USA", "not_searchable": "bar"},
|
{"text": "racoons are trash pandas", "country": "USA", "not_searchable": "bar"},
|
||||||
|
|
@ -92,3 +94,37 @@ def test_enable_fts_w_triggers(fresh_db):
|
||||||
# Triggers will auto-populate FTS virtual table, not need to call populate_fts()
|
# Triggers will auto-populate FTS virtual table, not need to call populate_fts()
|
||||||
assert [("racoons are trash pandas", "USA", "bar")] == table.search("usa")
|
assert [("racoons are trash pandas", "USA", "bar")] == table.search("usa")
|
||||||
assert [] == table.search("bar")
|
assert [] == table.search("bar")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("create_triggers", [True, False])
|
||||||
|
def test_disable_fts(fresh_db, create_triggers):
|
||||||
|
table = fresh_db["searchable"]
|
||||||
|
table.insert(search_records[0])
|
||||||
|
table.enable_fts(["text", "country"], create_triggers=create_triggers)
|
||||||
|
assert {
|
||||||
|
"searchable",
|
||||||
|
"searchable_fts",
|
||||||
|
"searchable_fts_data",
|
||||||
|
"searchable_fts_idx",
|
||||||
|
"searchable_fts_docsize",
|
||||||
|
"searchable_fts_config",
|
||||||
|
} == set(fresh_db.table_names())
|
||||||
|
if create_triggers:
|
||||||
|
expected_triggers = {"searchable_ai", "searchable_ad", "searchable_au"}
|
||||||
|
else:
|
||||||
|
expected_triggers = set()
|
||||||
|
assert expected_triggers == set(
|
||||||
|
r[0]
|
||||||
|
for r in fresh_db.conn.execute(
|
||||||
|
"select name from sqlite_master where type = 'trigger'"
|
||||||
|
).fetchall()
|
||||||
|
)
|
||||||
|
# Now run .disable_fts() and confirm it worked
|
||||||
|
table.disable_fts()
|
||||||
|
assert (
|
||||||
|
0
|
||||||
|
== fresh_db.conn.execute(
|
||||||
|
"select count(*) from sqlite_master where type = 'trigger'"
|
||||||
|
).fetchone()[0]
|
||||||
|
)
|
||||||
|
assert ["searchable"] == fresh_db.table_names()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue