From a954aafbcce6c6d1222baa8998898c59bac53609 Mon Sep 17 00:00:00 2001 From: thomasabishop Date: Thu, 7 Nov 2024 14:15:57 +0000 Subject: [PATCH] feature: establish sqlite and tables --- src/cli.py | 12 +++++++++--- src/controllers/controller.py | 14 ++++++++++++-- src/scratch.py | 1 - src/services/database_service.py | 29 ++++++++++++++++++++++++++++ src/services/sqlite_service.py | 27 ++++++++++++++++++++++++++ src/sql/create_tables.py | 33 ++++++++++++++++++++++++++++++++ src/sql/table_exists.py | 3 +++ 7 files changed, 113 insertions(+), 6 deletions(-) delete mode 100644 src/scratch.py create mode 100644 src/services/database_service.py create mode 100644 src/services/sqlite_service.py create mode 100644 src/sql/create_tables.py create mode 100644 src/sql/table_exists.py diff --git a/src/cli.py b/src/cli.py index facb7aa..648818d 100644 --- a/src/cli.py +++ b/src/cli.py @@ -2,9 +2,9 @@ import argparse import importlib from controllers.controller import Controller +from services.database_service import DatabaseService importlib.invalidate_caches() - file_path = "/home/thomas/repos/eolas-db/dev-data/Turing_completeness.md" @@ -12,15 +12,21 @@ def main(): parser = argparse.ArgumentParser( prog="eolas-db", description="Eolas database manager." ) - parser.add_argument("command", choices=["parse"], help="Command to execute") + parser.add_argument( + "command", choices=["parse", "populate"], help="Command to execute" + ) args = parser.parse_args() - controller = Controller() + database_service = DatabaseService("eolas") + controller = Controller(database_service) if args.command == "parse": parsed_entry = controller.parse_entry(file_path) print(parsed_entry) + if args.command == "populate": + controller.populate_database() + if __name__ == "__main__": main() diff --git a/src/controllers/controller.py b/src/controllers/controller.py index 8cbba1d..038886f 100644 --- a/src/controllers/controller.py +++ b/src/controllers/controller.py @@ -1,10 +1,20 @@ from services.parse_file_service import ParseFileService +from services.sqlite_service import SqliteService class Controller: - def __init__(self): - pass + def __init__(self, database_service): + self.database_service = database_service def parse_entry(self, file_path): parse_file_service = ParseFileService(file_path) return parse_file_service.parse() + + def populate_database(self): + connection = self.database_service.connect() + + if connection is None: + raise Exception("Failed to establish database connection") + + sqlite_service = SqliteService(connection) + sqlite_service.create_tables() diff --git a/src/scratch.py b/src/scratch.py deleted file mode 100644 index 8b13789..0000000 --- a/src/scratch.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/services/database_service.py b/src/services/database_service.py new file mode 100644 index 0000000..da769bc --- /dev/null +++ b/src/services/database_service.py @@ -0,0 +1,29 @@ +import sqlite3 +from typing import Optional + + +class DatabaseService: + def __init__(self, db_name): + self.db_name = db_name + self.db_path = "/home/thomas/repos/eolas-db/db" + self.connection: Optional[sqlite3.Connection] = None + + def connect(self) -> Optional[sqlite3.Connection]: + if self.connection is not None: + return self.connection + + try: + self.connection = sqlite3.connect(f"{self.db_path}/{self.db_name}.db") + print("INFO Database connection established") + return self.connection + + except Exception as e: + raise Exception(f"Problem connecting to database: {e}") + + def disconnect(self) -> None: + try: + if self.connection is not None: + self.connection.close() + self.connection = None + except Exception as e: + raise Exception(f"ERROR Problem disconnecting from database: {e}") diff --git a/src/services/sqlite_service.py b/src/services/sqlite_service.py new file mode 100644 index 0000000..066b2e8 --- /dev/null +++ b/src/services/sqlite_service.py @@ -0,0 +1,27 @@ +from sql.create_tables import ( + CREATE_BACKLINKS_TABLE, + CREATE_ENTRIES_TABLE, + CREATE_ENTRIES_TAGS_TABLE, + CREATE_TAGS_TABLE, +) + + +class SqliteService: + def __init__(self, connection): + self.connection = connection + self.cursor = connection.cursor() + + def create_tables(self): + tables = [ + CREATE_ENTRIES_TABLE, + CREATE_TAGS_TABLE, + CREATE_BACKLINKS_TABLE, + CREATE_ENTRIES_TAGS_TABLE, + ] + for create_statement in tables: + self.cursor.execute(create_statement) + + self.connection.commit() + + self.cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") + print(self.cursor.fetchall()) diff --git a/src/sql/create_tables.py b/src/sql/create_tables.py new file mode 100644 index 0000000..c5f13ed --- /dev/null +++ b/src/sql/create_tables.py @@ -0,0 +1,33 @@ +CREATE_ENTRIES_TABLE = """ +CREATE TABLE IF NOT EXISTS entries ( + title TEXT PRIMARY KEY UNIQUE, + last_modified STRING, + size INTEGER, + body TEXT +) +""" + +CREATE_TAGS_TABLE = """ +CREATE TABLE IF NOT EXISTS tags ( + name TEXT PRIMARY KEY UNIQUE, +) +""" + +CREATE_BACKLINKS_TABLE = """ +CREATE TABLE IF NOT EXISTS backlinks ( + source_entry_title TEXT, + target_entry_title TEXT, + FOREIGN KEY (source_entry_title) REFERENCES entries(title), + FOREIGN KEY (target_entry_title) REFERENCES entries(title), + PRIMARY KEY (source_entry_title, target_entry_title) +) +""" + +CREATE_ENTRIES_TAGS_TABLE = """ +CREATE TABLE IF NOT EXISTS entries_tags ( + entry_title TEXT, + tag_name TEXT, + FOREIGN KEY (entry_title) REFERENCES entries(title), + FOREIGN KEY (tag_name) REFERENCES tags(name), + PRIMARY KEY (entry_title, tag_name) +)""" diff --git a/src/sql/table_exists.py b/src/sql/table_exists.py new file mode 100644 index 0000000..5d8e034 --- /dev/null +++ b/src/sql/table_exists.py @@ -0,0 +1,3 @@ +TABLE_EXISTS = ( + "SELECT count(*) FROM sqlite_master WHERE type ='table' AND name=:table_name" +)