diff --git a/config/conf.json b/config/conf.json index f62352e..71e9ebd 100644 --- a/config/conf.json +++ b/config/conf.json @@ -1,6 +1,6 @@ { "PATH": { - "SCHEMA": "schema/comments_ddl.sql", + "SCHEMA": "src/schema/comments_ddl.sql", "MAIN": "database/comments.db", "BACKUP": "database/comments.backup.db", "DEFAULT": "database/default.db", diff --git a/schema/comments_ddl.sql b/schema/comments_ddl.sql deleted file mode 100644 index c7c5d15..0000000 --- a/schema/comments_ddl.sql +++ /dev/null @@ -1,64 +0,0 @@ - -PRAGMA FOREIGN_KEYS = ON; - --- tables --- DROP TABLE IF EXISTS COMMENT; --- DROP TABLE IF EXISTS CHANNEL; - --- DROP TABLE IF EXISTS COMMENT; -CREATE TABLE IF NOT EXISTS COMMENT ( - CommentId TEXT NOT NULL, - LbryClaimId TEXT NOT NULL, - ChannelId TEXT DEFAULT NULL, - Body TEXT NOT NULL, - ParentId TEXT DEFAULT NULL, - Signature TEXT DEFAULT NULL, - Timestamp INTEGER NOT NULL, - SigningTs TEXT DEFAULT NULL, - CONSTRAINT COMMENT_PRIMARY_KEY PRIMARY KEY (CommentId) ON CONFLICT IGNORE, - CONSTRAINT COMMENT_SIGNATURE_SK UNIQUE (Signature) ON CONFLICT ABORT, - CONSTRAINT COMMENT_CHANNEL_FK FOREIGN KEY (ChannelId) REFERENCES CHANNEL(ClaimId) - ON DELETE NO ACTION ON UPDATE NO ACTION, - CONSTRAINT COMMENT_PARENT_FK FOREIGN KEY (ParentId) REFERENCES COMMENT(CommentId) - ON UPDATE CASCADE ON DELETE NO ACTION -- setting null implies comment is top level -); - --- ALTER TABLE COMMENT ADD COLUMN SigningTs TEXT DEFAULT NULL; - --- DROP TABLE IF EXISTS CHANNEL; -CREATE TABLE IF NOT EXISTS CHANNEL( - ClaimId TEXT NOT NULL, - Name TEXT NOT NULL, - CONSTRAINT CHANNEL_PK PRIMARY KEY (ClaimId) - ON CONFLICT IGNORE -); - - --- indexes --- DROP INDEX IF EXISTS COMMENT_CLAIM_INDEX; -CREATE INDEX IF NOT EXISTS CLAIM_COMMENT_INDEX ON COMMENT (LbryClaimId, CommentId); - -CREATE INDEX IF NOT EXISTS CHANNEL_COMMENT_INDEX ON COMMENT(ChannelId, CommentId); - --- VIEWS -DROP VIEW IF EXISTS COMMENTS_ON_CLAIMS; -CREATE VIEW IF NOT EXISTS COMMENTS_ON_CLAIMS (comment_id, claim_id, timestamp, channel_name, channel_id, channel_url, signature, signing_ts, parent_id, comment) AS - SELECT C.CommentId, C.LbryClaimId, C.Timestamp, CHAN.Name, CHAN.ClaimId, 'lbry://' || CHAN.Name || '#' || CHAN.ClaimId, C.Signature, C.SigningTs, C.ParentId, C.Body - FROM COMMENT AS C - LEFT OUTER JOIN CHANNEL CHAN on C.ChannelId = CHAN.ClaimId - ORDER BY C.Timestamp DESC; - - - -DROP VIEW IF EXISTS COMMENT_REPLIES; -CREATE VIEW IF NOT EXISTS COMMENT_REPLIES (Author, CommentBody, ParentAuthor, ParentCommentBody) AS - SELECT AUTHOR.Name, OG.Body, PCHAN.Name, PARENT.Body FROM COMMENT AS OG - JOIN COMMENT AS PARENT - ON OG.ParentId = PARENT.CommentId - JOIN CHANNEL AS PCHAN ON PARENT.ChannelId = PCHAN.ClaimId - JOIN CHANNEL AS AUTHOR ON OG.ChannelId = AUTHOR.ClaimId - ORDER BY OG.Timestamp; - --- this is the default channel for anyone who wants to publish anonymously --- INSERT INTO CHANNEL --- VALUES ('9cb713f01bf247a0e03170b5ed00d5161340c486', '@Anonymous'); diff --git a/schema/db_helpers.py b/schema/db_helpers.py deleted file mode 100644 index ddc7b2e..0000000 --- a/schema/db_helpers.py +++ /dev/null @@ -1,31 +0,0 @@ -import logging -import sqlite3 - -from src.settings import config - -logger = logging.getLogger(__name__) - - -def setup_database(db_path): - logger.info('Creating db schema from %s in %s', - config['PATH']['SCHEMA'], db_path) - with sqlite3.connect(db_path) as conn: - with open(config['PATH']['SCHEMA'], 'r') as ddl: - with conn: - conn.executescript(ddl.read()) - - -def teardown_database(db_path): - logger.info('Dropping all tables from %s', db_path) - with sqlite3.connect(db_path) as conn: - conn.executescript(""" - DROP VIEW IF EXISTS COMMENTS_ON_CLAIMS; - DROP VIEW IF EXISTS COMMENT_REPLIES; - DROP TABLE IF EXISTS COMMENT; - DROP TABLE IF EXISTS CHANNEL; - """) - - -def backup_database(conn: sqlite3.Connection, back_fp): - with sqlite3.connect(back_fp) as back: - conn.backup(back) diff --git a/src/app.py b/src/app.py index 6e3aad2..f8b2290 100644 --- a/src/app.py +++ b/src/app.py @@ -9,7 +9,7 @@ import aiojobs.aiohttp import asyncio from aiohttp import web -import schema.db_helpers +from src.schema.db_helpers import setup_database, backup_database from src.database import obtain_connection, DatabaseWriter from src.handles import api_endpoint, get_api_endpoint @@ -19,9 +19,9 @@ logger = logging.getLogger(__name__) async def setup_db_schema(app): if not pathlib.Path(app['db_path']).exists(): logger.info('Setting up schema in %s', app['db_path']) - schema.db_helpers.setup_database(app['db_path']) + setup_database(app['db_path'], app['config']['PATH']['SCHEMA']) else: - logger.info('Database already exists in %s, skipping setup', app['db_path']) + logger.info(f'Database already exists in {app["db_path"]}, skipping setup') async def close_comment_scheduler(app): @@ -35,7 +35,7 @@ async def database_backup_routine(app): await asyncio.sleep(app['config']['BACKUP_INT']) with app['reader'] as conn: logger.debug('backing up database') - schema.db_helpers.backup_database(conn, app['backup']) + backup_database(conn, app['backup']) except asyncio.CancelledError: pass diff --git a/tests/database_test.py b/tests/database_test.py index d8c5ee3..27307bc 100644 --- a/tests/database_test.py +++ b/tests/database_test.py @@ -5,8 +5,9 @@ from faker.providers import internet from faker.providers import lorem from faker.providers import misc -from src.database import get_comments_by_id, get_comment_ids, \ - get_claim_comments +from src.database import get_comments_by_id +from src.database import get_comment_ids +from src.database import get_claim_comments from src.writes import create_comment_or_error from tests.testcase import DatabaseTestCase diff --git a/tests/testcase.py b/tests/testcase.py index 5da1a70..979d36e 100644 --- a/tests/testcase.py +++ b/tests/testcase.py @@ -123,7 +123,7 @@ class DatabaseTestCase(unittest.TestCase): super().setUp() if pathlib.Path(config['PATH']['TEST']).exists(): teardown_database(config['PATH']['TEST']) - setup_database(config['PATH']['TEST']) + setup_database(config['PATH']['TEST'], config['PATH']['SCHEMA']) self.conn = obtain_connection(config['PATH']['TEST']) def tearDown(self) -> None: