mirror of
https://github.com/simonw/sqlite-utils.git
synced 2026-07-23 17:34:32 +02:00
db.enable_counts() method, closes #213
This commit is contained in:
parent
1cad7fad3e
commit
9a5c92b63e
3 changed files with 55 additions and 3 deletions
|
|
@ -1706,6 +1706,12 @@ This will create the ``_counts`` table if it does not already exist, with the fo
|
|||
|
||||
Once enabled, table counts can be accessed by querying the ``counts`` table. The count records will be automatically kept up-to-date by the triggers when rows are added or deleted to the table.
|
||||
|
||||
You can enable cached counts for every table in a database (except for virtual tables and the ``_counts`` table itself) using the database ``enable_counts()`` method:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
db.enable_counts()
|
||||
|
||||
Creating indexes
|
||||
================
|
||||
|
||||
|
|
|
|||
|
|
@ -145,6 +145,11 @@ class InvalidColumns(Exception):
|
|||
|
||||
|
||||
class Database:
|
||||
_counts_table_name = "_counts"
|
||||
_counts_table_create = "CREATE TABLE IF NOT EXISTS [{}]([table] TEXT PRIMARY KEY, count INTEGER DEFAULT 0);".format(
|
||||
_counts_table_name
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
filename_or_conn=None,
|
||||
|
|
@ -279,6 +284,19 @@ class Database:
|
|||
if self.journal_mode != "delete":
|
||||
self.execute("PRAGMA journal_mode=delete;")
|
||||
|
||||
def _ensure_counts_table(self):
|
||||
with self.conn:
|
||||
self.execute(self._counts_table_create)
|
||||
|
||||
def enable_counts(self):
|
||||
self._ensure_counts_table()
|
||||
for table in self.tables:
|
||||
if (
|
||||
table.virtual_table_using is None
|
||||
and table.name != self._counts_table_name
|
||||
):
|
||||
table.enable_counts()
|
||||
|
||||
def execute_returning_dicts(self, sql, params=None):
|
||||
cursor = self.execute(sql, params or tuple())
|
||||
keys = [d[0] for d in cursor.description]
|
||||
|
|
@ -1178,7 +1196,7 @@ class Table(Queryable):
|
|||
sql = (
|
||||
textwrap.dedent(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS [{counts_table}]([table] TEXT PRIMARY KEY, count INTEGER DEFAULT 0);
|
||||
{create_counts_table}
|
||||
CREATE TRIGGER IF NOT EXISTS [{table}{counts_table}_insert] AFTER INSERT ON [{table}]
|
||||
BEGIN
|
||||
INSERT OR REPLACE INTO [{counts_table}]
|
||||
|
|
@ -1206,7 +1224,8 @@ class Table(Queryable):
|
|||
)
|
||||
.strip()
|
||||
.format(
|
||||
counts_table="_counts",
|
||||
create_counts_table=self.db._counts_table_create,
|
||||
counts_table=self.db._counts_table_name,
|
||||
table=self.name,
|
||||
table_quoted=self.db.escape(self.name),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
def test_enable_counts(fresh_db):
|
||||
def test_enable_counts_specific_table(fresh_db):
|
||||
foo = fresh_db["foo"]
|
||||
assert fresh_db.table_names() == []
|
||||
for i in range(10):
|
||||
|
|
@ -25,3 +25,30 @@ def test_enable_counts(fresh_db):
|
|||
foo.delete_where()
|
||||
assert foo.count == 0
|
||||
assert list(fresh_db["_counts"].rows) == [{"count": 0, "table": "foo"}]
|
||||
|
||||
|
||||
def test_enable_counts_all_tables(fresh_db):
|
||||
foo = fresh_db["foo"]
|
||||
bar = fresh_db["bar"]
|
||||
foo.insert({"name": "Cleo"})
|
||||
bar.insert({"name": "Cleo"})
|
||||
foo.enable_fts(["name"])
|
||||
fresh_db.enable_counts()
|
||||
assert set(fresh_db.table_names()) == {
|
||||
"foo",
|
||||
"bar",
|
||||
"foo_fts",
|
||||
"foo_fts_data",
|
||||
"foo_fts_idx",
|
||||
"foo_fts_docsize",
|
||||
"foo_fts_config",
|
||||
"_counts",
|
||||
}
|
||||
assert list(fresh_db["_counts"].rows) == [
|
||||
{"count": 1, "table": "foo"},
|
||||
{"count": 1, "table": "bar"},
|
||||
{"count": 3, "table": "foo_fts_data"},
|
||||
{"count": 1, "table": "foo_fts_idx"},
|
||||
{"count": 1, "table": "foo_fts_docsize"},
|
||||
{"count": 1, "table": "foo_fts_config"},
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue