You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
4.2 KiB
Python
144 lines
4.2 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import (
|
|
List,
|
|
Mapping,
|
|
)
|
|
|
|
from pony import orm
|
|
|
|
from .custom_types import SafeStr
|
|
from .entities import (
|
|
db,
|
|
)
|
|
from .sql_helpers import (
|
|
sql_cleanup,
|
|
sql_where_in,
|
|
)
|
|
from .sql_names import (
|
|
COLLECTION_TABLE,
|
|
COLLECTION_LINK_TABLE,
|
|
ELEMENT_TABLE,
|
|
ELEMENT_BLOCKING_CACHE_TABLE,
|
|
)
|
|
from ..common import trim
|
|
from ..extras import LazyValue
|
|
|
|
|
|
CUSTOM_TABLE_DEFINITIONS: Mapping[SafeStr, LazyValue[str]] = {
|
|
SafeStr(table_name): lambda: trim(table_sql())
|
|
for table_name, table_sql in {
|
|
ELEMENT_BLOCKING_CACHE_TABLE: lambda: f"""
|
|
CREATE TABLE {ELEMENT_BLOCKING_CACHE_TABLE}(
|
|
collection INT(11) NOT NULL,
|
|
element1 INT(11) NOT NULL,
|
|
element2 INT(11) NOT NULL
|
|
) SELECT
|
|
c.id AS collection,
|
|
l1.element AS element1,
|
|
l2.element AS element2
|
|
FROM
|
|
{COLLECTION_TABLE} c
|
|
INNER JOIN {COLLECTION_LINK_TABLE} l1 ON
|
|
c.id = l1.collection
|
|
INNER JOIN {COLLECTION_LINK_TABLE} l2 ON
|
|
c.id = l2.collection
|
|
INNER JOIN {ELEMENT_TABLE} e1 ON
|
|
l1.element = e1.id
|
|
INNER JOIN {ELEMENT_TABLE} e2 ON
|
|
l2.element = e2.id
|
|
WHERE
|
|
(
|
|
l1.season,
|
|
l1.episode,
|
|
e1.release_date,
|
|
e1.id
|
|
) <(
|
|
l2.season,
|
|
l2.episode,
|
|
e2.release_date,
|
|
e2.id
|
|
) AND c.watch_in_order
|
|
GROUP BY
|
|
collection,
|
|
element1,
|
|
element2;
|
|
ALTER TABLE
|
|
`{ELEMENT_BLOCKING_CACHE_TABLE}` ADD PRIMARY KEY(`element1`, `element2`, `collection`);
|
|
ALTER TABLE
|
|
`{ELEMENT_BLOCKING_CACHE_TABLE}` ADD INDEX(`collection`);
|
|
""",
|
|
}.items()
|
|
}
|
|
|
|
|
|
def table_exists(table_name: SafeStr) -> bool:
|
|
return db.provider.table_exists(
|
|
connection=db.get_connection(),
|
|
table_name=table_name,
|
|
)
|
|
|
|
|
|
@orm.db_session
|
|
def setup_custom_tables() -> None:
|
|
"""
|
|
Creates & fills custom tables (especially cache tables) if they do not exist.
|
|
This should not destroy already existing data and should behave indempotent.
|
|
"""
|
|
for table_name, table_sql in CUSTOM_TABLE_DEFINITIONS.items():
|
|
if not table_exists(table_name):
|
|
db.execute(table_sql())
|
|
|
|
|
|
def update_element_lookup_cache(collection_ids: List[int] = []):
|
|
logging.info(
|
|
f"Rebuild {ELEMENT_BLOCKING_CACHE_TABLE} for {len(collection_ids) if collection_ids else 'all'} collections …"
|
|
)
|
|
|
|
def filter_clause(c_id: str):
|
|
return sql_where_in(c_id, collection_ids) if collection_ids else "true"
|
|
|
|
orm.flush()
|
|
sql = [
|
|
f"""
|
|
DELETE QUICK FROM {ELEMENT_BLOCKING_CACHE_TABLE}
|
|
WHERE {filter_clause("collection")};
|
|
""",
|
|
f"""
|
|
INSERT INTO {ELEMENT_BLOCKING_CACHE_TABLE} (collection, element1, element2) SELECT
|
|
c.id AS collection,
|
|
l1.element AS element1,
|
|
l2.element AS element2
|
|
FROM
|
|
{COLLECTION_TABLE} c
|
|
INNER JOIN {COLLECTION_LINK_TABLE} l1 ON
|
|
c.id = l1.collection
|
|
INNER JOIN {COLLECTION_LINK_TABLE} l2 ON
|
|
c.id = l2.collection
|
|
INNER JOIN {ELEMENT_TABLE} e1 ON
|
|
l1.element = e1.id
|
|
INNER JOIN {ELEMENT_TABLE} e2 ON
|
|
l2.element = e2.id
|
|
WHERE
|
|
(
|
|
l1.season,
|
|
l1.episode,
|
|
e1.release_date,
|
|
e1.id
|
|
) <(
|
|
l2.season,
|
|
l2.episode,
|
|
e2.release_date,
|
|
e2.id
|
|
) AND c.watch_in_order
|
|
AND {filter_clause("c.id")}
|
|
GROUP BY
|
|
collection,
|
|
element1,
|
|
element2
|
|
""",
|
|
]
|
|
for q in sql:
|
|
db.execute(sql_cleanup(q))
|