From 8eaf891a0858b1fccf4dcd456bbc16c94c44b9ea Mon Sep 17 00:00:00 2001 From: LDericher <40151420+ldericher@users.noreply.github.com> Date: Mon, 13 Sep 2021 23:50:29 +0200 Subject: [PATCH] carddb sqlite --- fftcgtool/card.py | 54 +++++++++++++++++++++++++++++++++++++++++++++ fftcgtool/carddb.py | 37 +++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/fftcgtool/card.py b/fftcgtool/card.py index 56da422..b051c05 100644 --- a/fftcgtool/card.py +++ b/fftcgtool/card.py @@ -1,6 +1,7 @@ from __future__ import annotations import re +import sqlite3 from dataclasses import dataclass from .code import Code @@ -102,6 +103,59 @@ class Card: content=content, ) + @classmethod + def sqlite_schema(cls, cursor: sqlite3.Cursor) -> None: + cursor.execute(""" + CREATE TABLE IF NOT EXISTS `cards_indices` ( + `code` TEXT, + `index` INTEGER, + PRIMARY KEY(`code`) + ) WITHOUT ROWID; + """) + + cursor.execute(""" + CREATE TABLE IF NOT EXISTS `cards_elements` ( + `code` TEXT, + `element` TEXT, + PRIMARY KEY(`code`,`element`), + FOREIGN KEY(`code`) REFERENCES `cards_indices`(`code`) + ) WITHOUT ROWID; + """) + + cursor.execute(""" + CREATE TABLE IF NOT EXISTS `cards_content` ( + `code` TEXT, + `language` TEXT, + `name` TEXT, + `text` TEXT, + `face` TEXT, + PRIMARY KEY(`code`,`language`), + FOREIGN KEY(`code`) REFERENCES `cards_indices`(`code`) + ) WITHOUT ROWID; + """) + + def sqlite_save(self, cursor: sqlite3.Cursor) -> None: + cursor.execute(""" + UPDATE INTO `cards_indices` (`code`, `index`) + VALUES (?, ?) + """, (self.code.short, self.index)) + + cursor.executemany(""" + UPDATE INTO `cards_content` (`code`, `language`, `name`, `text`, `face`) + VALUES(?, ?, ?, ?, ?) + """, ( + (self.code.short, language.short, content.name, content.text, content.face) + for language, content in self.__content.items() + )) + + cursor.executemany(""" + UPDATE INTO `cards_elements` (`code`, `element`) + VALUES (?, ?) + """, ( + (self.code.short, element) + for element in self.__elements + )) + def __repr__(self) -> str: return f"Card(code={self.code!r}, content={self.__content!r})" diff --git a/fftcgtool/carddb.py b/fftcgtool/carddb.py index b4fa0c2..41124b3 100644 --- a/fftcgtool/carddb.py +++ b/fftcgtool/carddb.py @@ -3,6 +3,7 @@ from __future__ import annotations import io import json import pickle +import sqlite3 import zipfile from os import PathLike from typing import IO @@ -96,6 +97,26 @@ class RWCardDB(CardDB): self.__db_path = db_path self._load(self.__db_path) + @classmethod + def sqlite_schema(cls, cursor: sqlite3.Cursor) -> None: + cursor.execute(""" + CREATE TABLE IF NOT EXISTS `faces_urls` ( + `face` TEXT, + `url` TEXT, + PRIMARY KEY(`face`), + FOREIGN KEY(`face`) REFERENCES `cards_content`(`face`) + ) WITHOUT ROWID; + """) + + cursor.execute(""" + CREATE VIEW IF NOT EXISTS `cards` AS + SELECT `code`, `index`, `element`, `language`, `name`, `text`, `url` + FROM `cards_indices` + JOIN `cards_elements` USING(`code`) + JOIN `cards_content` USING(`code`) + JOIN `faces_urls` USING(`face`); + """) + def save(self) -> None: with zipfile.ZipFile(self.__db_path, "w", compression=zipfile.ZIP_LZMA) as zip_file: # cards db @@ -106,6 +127,22 @@ class RWCardDB(CardDB): with zip_file.open(CardDB._MAPPING_FILE_NAME, "w") as file: file.write(json.dumps(self._face_to_url, indent=2).encode("utf-8")) + with sqlite3.connect(self.__db_path + ".db") as connection: + cursor = connection.cursor() + cursor.execute("PRAGMA auto_vacuum=FULL;") + Card.sqlite_schema(cursor) + self.sqlite_schema(cursor) + + for card in self._cards.values(): + card.sqlite_save(cursor) + + cursor.executemany(""" + UPDATE INTO `faces_urls` (`face`, `url`) + VALUES(?, ?) + """, self._face_to_url.items()) + + connection.commit() + def update(self, cards: Cards) -> None: for card in cards: self._cards[card.code] = card