drop lock() and setAutocommit()

We no longer need to worry about pysqlite implicitly beginning
transactions, and can be more explicit about beginning/ending
transactions

save() now also has a trx argument controlling whether a
transaction should be started / left open
This commit is contained in:
Damien Elmes 2020-03-06 10:56:34 +10:00
parent 63e3357068
commit 90de4a267d
5 changed files with 31 additions and 32 deletions

View file

@ -219,8 +219,10 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""",
json.dumps(self.conf),
)
def save(self, name: Optional[str] = None, mod: Optional[int] = None) -> None:
"Flush, commit DB, and take out another write lock."
def save(
self, name: Optional[str] = None, mod: Optional[int] = None, trx: bool = True
) -> None:
"Flush, commit DB, and take out another write lock if trx=True."
# let the managers conditionally flush
self.models.flush()
self.decks.flush()
@ -229,8 +231,14 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""",
if self.db.mod:
self.flush(mod=mod)
self.db.commit()
self.lock()
self.db.mod = False
if trx:
self.db.begin()
elif not trx:
# if no changes were pending but calling code expects to be
# outside of a transaction, we need to roll back
self.db.rollback()
self._markOp(name)
self._lastSave = time.time()
@ -241,20 +249,13 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""",
return True
return None
def lock(self) -> None:
self.db.begin()
def close(self, save: bool = True) -> None:
"Disconnect from DB."
if self.db:
if save:
self.save()
else:
self.db.rollback()
self.save(trx=False)
if not self.server:
self.db.setAutocommit(True)
self.db.execute("pragma journal_mode = delete")
self.db.setAutocommit(False)
self.db.close()
self.db = None
self.backend = None
@ -271,8 +272,8 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""",
def rollback(self) -> None:
self.db.rollback()
self.db.begin()
self.load()
self.lock()
def modSchema(self, check: bool) -> None:
"Mark schema modified. Call this first so user can abort if necessary."
@ -303,10 +304,10 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""",
self.modSchema(check=False)
self.ls = self.scm
# ensure db is compacted before upload
self.db.setAutocommit(True)
self.save(trx=False)
self.db.execute("vacuum")
self.db.execute("analyze")
self.close()
self.close(save=False)
# Object creation helpers
##########################################################################
@ -1012,11 +1013,10 @@ and type=0""",
return len(to_fix)
def optimize(self) -> None:
self.db.setAutocommit(True)
self.save(trx=False)
self.db.execute("vacuum")
self.db.execute("analyze")
self.db.setAutocommit(False)
self.lock()
self.db.begin()
# Logging
##########################################################################

View file

@ -1,6 +1,14 @@
# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
"""
A convenience wrapper over pysqlite.
Anki's Collection class now uses dbproxy.py instead of this class,
but this class is still used by aqt's profile manager, and a number
of add-ons rely on it.
"""
import os
import time
from sqlite3 import Cursor

View file

@ -7,8 +7,8 @@ from typing import Any, Iterable, List, Optional, Sequence, Union
import anki
# fixme: threads
# fixme: col.reopen()
# fixme: col.close()/col.reopen() & journal_mode=delete
# fixme: setAutocommit()
# fixme: transaction/lock handling
# fixme: progress
@ -47,12 +47,6 @@ class DBProxy:
def rollback(self) -> None:
self._backend.db_rollback()
def setAutocommit(self, autocommit: bool) -> None:
if autocommit:
self.commit()
else:
self.begin()
# Querying
################

View file

@ -65,10 +65,7 @@ class Anki2Importer(Importer):
self._importCards()
self._importStaticMedia()
self._postImport()
self.dst.db.setAutocommit(True)
self.dst.db.execute("vacuum")
self.dst.db.execute("analyze")
self.dst.db.setAutocommit(False)
self.dst.optimize()
# Notes
######################################################################

View file

@ -40,15 +40,12 @@ def Collection(path: str, server: Optional[ServerData] = None) -> _Collection:
path, media_dir, media_db, log_path, server=server is not None
)
db = DBProxy(weakref.proxy(backend), path)
db.begin()
db.setAutocommit(True)
# initial setup required?
create = db.scalar("select models = '{}' from col")
if create:
initial_db_setup(db)
db.setAutocommit(False)
# add db to col and do any remaining upgrades
col = _Collection(db, backend=backend, server=server)
if create:
@ -59,6 +56,8 @@ def Collection(path: str, server: Optional[ServerData] = None) -> _Collection:
addForwardReverse(col)
addBasicModel(col)
col.save()
else:
db.begin()
return col
@ -67,6 +66,7 @@ def Collection(path: str, server: Optional[ServerData] = None) -> _Collection:
def initial_db_setup(db: DBProxy) -> None:
db.begin()
_addColVars(db, *_getColVars(db))