From 8879add39b009c47699d0341f72900b82fbdc1ea Mon Sep 17 00:00:00 2001 From: s3lph Date: Sat, 7 Dec 2024 22:02:00 +0100 Subject: [PATCH] feat: take a backup of the sqlite db before executing schema migrations --- .gitignore | 1 + matemat/db/wrapper.py | 26 +++++++++++++++++--------- package/debian/matemat/DEBIAN/postinst | 1 + 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 5bda33f..1f1139d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,6 @@ *.sqlite3 *.db +*.bak static/upload/ ./matemat.conf diff --git a/matemat/db/wrapper.py b/matemat/db/wrapper.py index bea257e..c493f2b 100644 --- a/matemat/db/wrapper.py +++ b/matemat/db/wrapper.py @@ -60,23 +60,31 @@ class DatabaseWrapper(object): def _setup(self) -> None: # Create or update schemas if necessary - with self.transaction() as c: - version: int = self._user_version - if version < 1: - # Don't use executescript, as it issues a COMMIT first + version: int = self._user_version + if version < 1: + # Don't use executescript, as it issues a COMMIT first + with self.transaction() as c: for command in SCHEMAS[self.SCHEMA_VERSION]: c.execute(command) - elif version < self.SCHEMA_VERSION: - self._upgrade(from_version=version, to_version=self.SCHEMA_VERSION) - elif version > self.SCHEMA_VERSION: - raise RuntimeError('Database schema is newer than supported by this version of Matemat.') - self._user_version = self.SCHEMA_VERSION + elif version < self.SCHEMA_VERSION: + self._upgrade(from_version=version, to_version=self.SCHEMA_VERSION) + elif version > self.SCHEMA_VERSION: + raise RuntimeError('Database schema is newer than supported by this version of Matemat.') + self._user_version = self.SCHEMA_VERSION # Enable foreign key enforcement cursor = self._sqlite_db.cursor() cursor.execute('PRAGMA foreign_keys=ON') def _upgrade(self, from_version: int, to_version: int) -> None: + if from_version >= to_version: + return + if self._filename != ':memory:': + bakfile = f'{self._filename}_{from_version}_{to_version}.bak' + bak = sqlite3.connect(bakfile) + with bak: + self._sqlite_db.backup(bak, pages=1) + bak.close() with self.transaction() as c: c.execute('PRAGMA foreign_keys=OFF') c.execute('PRAGMA legacy_alter_table=ON') diff --git a/package/debian/matemat/DEBIAN/postinst b/package/debian/matemat/DEBIAN/postinst index 44e19fe..96c856f 100755 --- a/package/debian/matemat/DEBIAN/postinst +++ b/package/debian/matemat/DEBIAN/postinst @@ -16,6 +16,7 @@ if [[ "$1" == "configure" ]]; then chmod 0750 /var/lib/matemat ln -sf /var/lib/matemat/upload /usr/lib/matemat/static/upload + systemctl daemon-reload || true deb-systemd-helper enable matemat.service deb-systemd-invoke restart matemat.service