diff --git a/pylib/anki/collection.py b/pylib/anki/collection.py index ace24214d..bc85d74df 100644 --- a/pylib/anki/collection.py +++ b/pylib/anki/collection.py @@ -245,16 +245,14 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""", return True return None - def close(self, save: bool = True) -> None: + def close(self, save: bool = True, downgrade: bool = False) -> None: "Disconnect from DB." if self.db: if save: self.save(trx=False) else: self.db.rollback() - if not self.server: - self.db.execute("pragma journal_mode = delete") - self.backend.close_collection() + self.backend.close_collection(downgrade=downgrade) self.db = None self.media.close() self._closeLog() @@ -296,7 +294,7 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""", self.save(trx=False) self.db.execute("vacuum") self.db.execute("analyze") - self.close(save=False) + self.close(save=False, downgrade=True) # Object creation helpers ########################################################################## diff --git a/pylib/anki/exporting.py b/pylib/anki/exporting.py index cba68560d..568e86c8e 100644 --- a/pylib/anki/exporting.py +++ b/pylib/anki/exporting.py @@ -280,7 +280,7 @@ class AnkiExporter(Exporter): self.count = self.dst.cardCount() self.dst.setMod() self.postExport() - self.dst.close() + self.dst.close(downgrade=True) def postExport(self) -> None: # overwrite to apply customizations to the deck before it's closed, @@ -402,7 +402,7 @@ class AnkiCollectionPackageExporter(AnkiPackageExporter): self.count = self.col.cardCount() v2 = self.col.schedVer() != 1 mdir = self.col.media.dir() - self.col.close() + self.col.close(downgrade=True) if not v2: z.write(self.col.path, "collection.anki2") else: diff --git a/pylib/anki/importing/anki2.py b/pylib/anki/importing/anki2.py index 8a4d308aa..a43e0b13f 100644 --- a/pylib/anki/importing/anki2.py +++ b/pylib/anki/importing/anki2.py @@ -40,7 +40,7 @@ class Anki2Importer(Importer): try: self._import() finally: - self.src.close(save=False) + self.src.close(save=False, downgrade=False) def _prepareFiles(self) -> None: importingV2 = self.file.endswith(".anki21") diff --git a/pylib/anki/sync.py b/pylib/anki/sync.py index 64a349316..a0faee227 100644 --- a/pylib/anki/sync.py +++ b/pylib/anki/sync.py @@ -638,7 +638,7 @@ class FullSyncer(HttpSyncer): def download(self) -> Optional[str]: hooks.sync_stage_did_change("download") localNotEmpty = self.col.db.scalar("select 1 from cards") - self.col.close() + self.col.close(downgrade=False) cont = self.req("download") tpath = self.col.path + ".tmp" if cont == "upgradeRequired": diff --git a/pylib/tests/shared.py b/pylib/tests/shared.py index a89252ada..819a7be7c 100644 --- a/pylib/tests/shared.py +++ b/pylib/tests/shared.py @@ -35,7 +35,7 @@ def getEmptyCol(): os.close(fd) os.unlink(nam) col = aopen(nam) - col.close() + col.close(downgrade=False) getEmptyCol.master = nam (fd, nam) = tempfile.mkstemp(suffix=".anki2") shutil.copy(getEmptyCol.master, nam) diff --git a/qt/aqt/main.py b/qt/aqt/main.py index 3f605db6f..c199b3890 100644 --- a/qt/aqt/main.py +++ b/qt/aqt/main.py @@ -440,6 +440,8 @@ close the profile or restart Anki.""" # Collection load/unload ########################################################################## + downgrade_on_close = True + def loadCollection(self) -> bool: try: self._loadCollection() @@ -450,7 +452,7 @@ close the profile or restart Anki.""" # clean up open collection if possible if self.col: try: - self.col.close(save=False) + self.col.close(save=False, downgrade=self.downgrade_on_close) except: pass self.col = None @@ -506,7 +508,7 @@ close the profile or restart Anki.""" except: corrupt = True try: - self.col.close() + self.col.close(downgrade=self.downgrade_on_close) except: corrupt = True finally: diff --git a/qt/aqt/sync.py b/qt/aqt/sync.py index 658874498..c43493fb6 100644 --- a/qt/aqt/sync.py +++ b/qt/aqt/sync.py @@ -400,7 +400,7 @@ class SyncThread(QThread): self.fireEvent("error", err) finally: # don't bump mod time unless we explicitly save - self.col.close(save=False) + self.col.close(save=False, downgrade=False) hooks.sync_stage_did_change.remove(syncEvent) hooks.sync_progress_did_change.remove(syncMsg) diff --git a/rslib/src/backend/mod.rs b/rslib/src/backend/mod.rs index 2caa7bad7..66b483ce9 100644 --- a/rslib/src/backend/mod.rs +++ b/rslib/src/backend/mod.rs @@ -336,7 +336,7 @@ impl Backend { let col_inner = col.take().unwrap(); if downgrade { let log = log::terminal(); - if let Err(e) = col_inner.downgrade_and_close() { + if let Err(e) = col_inner.close(downgrade) { error!(log, " failed: {:?}", e); } } diff --git a/rslib/src/collection.rs b/rslib/src/collection.rs index 8664fb036..a0e1b95c0 100644 --- a/rslib/src/collection.rs +++ b/rslib/src/collection.rs @@ -130,8 +130,8 @@ impl Collection { self.state.task_state == CollectionTaskState::Normal } - pub(crate) fn downgrade_and_close(self) -> Result<()> { - self.storage.downgrade_to_schema_11() + pub(crate) fn close(self, downgrade: bool) -> Result<()> { + self.storage.close(downgrade) } // fixme: invalidate when config changes diff --git a/rslib/src/storage/sqlite.rs b/rslib/src/storage/sqlite.rs index 892ecba14..1f8b962b5 100644 --- a/rslib/src/storage/sqlite.rs +++ b/rslib/src/storage/sqlite.rs @@ -204,6 +204,14 @@ impl SqliteStorage { Ok(storage) } + pub(crate) fn close(self, downgrade: bool) -> Result<()> { + if downgrade { + self.downgrade_to_schema_11()?; + self.db.pragma_update(None, "journal_mode", &"delete")?; + } + Ok(()) + } + // Standard transaction start/stop ////////////////////////////////////// diff --git a/rslib/src/storage/upgrades/mod.rs b/rslib/src/storage/upgrades/mod.rs index 85ca40a27..5f71d655d 100644 --- a/rslib/src/storage/upgrades/mod.rs +++ b/rslib/src/storage/upgrades/mod.rs @@ -19,7 +19,7 @@ impl SqliteStorage { Ok(()) } - pub(crate) fn downgrade_to_schema_11(self) -> Result<()> { + pub(super) fn downgrade_to_schema_11(&self) -> Result<()> { self.begin_trx()?; self.downgrade_tags_from_schema13()?; @@ -30,6 +30,8 @@ impl SqliteStorage { self.db .execute_batch(include_str!("schema12_downgrade.sql"))?; - self.commit_trx() + self.commit_trx()?; + + Ok(()) } }