sqlite-utils optimize command, .optimize() and .detect_fts() table methods

This commit is contained in:
Simon Willison 2019-01-24 20:35:51 -08:00
commit 0a8194e730
7 changed files with 146 additions and 4 deletions

View file

@ -37,3 +37,21 @@ def table_names(path, fts4, fts5):
def vacuum(path):
"""Run VACUUM against the database"""
sqlite_utils.Database(path).vacuum()
@cli.command()
@click.argument(
"path",
type=click.Path(exists=True, file_okay=True, dir_okay=False, allow_dash=False),
required=True,
)
@click.option("--no-vacuum", help="Don't run VACUUM", default=False, is_flag=True)
def optimize(path, no_vacuum):
"""Optimize all FTS tables and then run VACUUM - should shrink the database file"""
db = sqlite_utils.Database(path)
tables = db.table_names(fts4=True) + db.table_names(fts5=True)
with db.conn:
for table in tables:
db[table].optimize()
if not no_vacuum:
db.vacuum()

View file

@ -243,6 +243,40 @@ class Table:
self.db.conn.executescript(sql)
return self
def detect_fts(self):
"Detect if table has a corresponding FTS virtual table and return it"
rows = self.db.conn.execute(
"""
SELECT name FROM sqlite_master
WHERE rootpage = 0
AND (
sql LIKE '%VIRTUAL TABLE%USING FTS%content="{table}"%'
OR (
tbl_name = "{table}"
AND sql LIKE '%VIRTUAL TABLE%USING FTS%'
)
)
""".format(
table=self.name
)
).fetchall()
if len(rows) == 0:
return None
else:
return rows[0][0]
def optimize(self):
fts_table = self.detect_fts()
if fts_table is not None:
self.db.conn.execute(
"""
INSERT INTO [{table}] ([{table}]) VALUES ("optimize");
""".format(
table=fts_table
)
)
return self
def detect_column_types(self, records):
all_column_types = {}
for record in records: