Files
MIND/backend/db.py
2023-01-19 21:29:15 +01:00

140 lines
3.3 KiB
Python

#-*- coding: utf-8 -*-
from sqlite3 import Connection, Row
from threading import current_thread
from typing import Union
from flask import g
__DATABASE_VERSION__ = 1
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
i = f'{cls}{current_thread()}'
if i not in cls._instances:
cls._instances[i] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[i]
class DBConnection(Connection, metaclass=Singleton):
file = ''
def __init__(self, timeout: float) -> None:
super().__init__(self.file, timeout=timeout)
super().cursor().execute("PRAGMA foreign_keys = ON;")
return
def get_db(output_type: Union[dict, tuple]=tuple):
"""Get a database cursor instance. Coupled to Flask's g.
Args:
output_type (Union[dict, tuple], optional): The type of output: a tuple or dictionary with the row values. Defaults to tuple.
Returns:
Cursor: The Cursor instance to use
"""
try:
cursor = g.cursor
except AttributeError:
db = DBConnection(timeout=20.0)
cursor = g.cursor = db.cursor()
if output_type is dict:
cursor.row_factory = Row
else:
cursor.row_factory = None
return g.cursor
def close_db(e=None) -> None:
"""Savely closes the database connection
"""
try:
cursor = g.cursor
db = cursor.connection
cursor.close()
delattr(g, 'cursor')
db.commit()
except AttributeError:
pass
return
def migrate_db(current_db_version: int) -> None:
"""
Migrate a Noted database from it's current version
to the newest version supported by the Noted version installed.
"""
print('Migrating database to newer version...')
cursor = get_db()
return
def setup_db() -> None:
"""Setup the database
"""
cursor = get_db()
cursor.executescript("""
CREATE TABLE IF NOT EXISTS users(
id INTEGER PRIMARY KEY,
username VARCHAR(255) UNIQUE NOT NULL,
salt VARCHAR(40) NOT NULL,
hash VARCHAR(100) NOT NULL
);
CREATE TABLE IF NOT EXISTS notification_services(
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL,
title VARCHAR(255),
url TEXT,
FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE TABLE IF NOT EXISTS reminders(
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL,
title VARCHAR(255) NOT NULL,
text TEXT,
time INTEGER NOT NULL,
notification_service INTEGER NOT NULL,
repeat_quantity VARCHAR(15),
repeat_interval INTEGER,
original_time INTEGER,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (notification_service) REFERENCES notification_services(id)
);
CREATE TABLE IF NOT EXISTS templates(
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL,
title VARCHAR(255) NOT NULL,
text TEXT,
notification_service INTEGER NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (notification_service) REFERENCES notification_services(id)
);
CREATE TABLE IF NOT EXISTS config(
key VARCHAR(255) PRIMARY KEY,
value TEXT NOT NULL
);
""")
cursor.execute("""
INSERT OR IGNORE INTO config(key, value)
VALUES ('database_version', ?);
""",
(__DATABASE_VERSION__,)
)
current_db_version = int(cursor.execute("SELECT value FROM config WHERE key = 'database_version' LIMIT 1;").fetchone()[0])
if current_db_version < __DATABASE_VERSION__:
migrate_db(current_db_version)
cursor.execute(
"UPDATE config SET value = ? WHERE key = 'database_version' LIMIT 1;",
(__DATABASE_VERSION__,)
)
return