Add type hints and refactor SQLite foreign key enforcement setup
This commit is contained in:
@@ -7,10 +7,11 @@
|
|||||||
"""
|
"""
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.engine.interfaces import DBAPICursor, DBAPIConnection
|
||||||
from sqlalchemy.orm import DeclarativeBase, sessionmaker, Session
|
from sqlalchemy.orm import DeclarativeBase, sessionmaker, Session
|
||||||
|
from sqlalchemy.pool import ConnectionPoolEntry
|
||||||
|
|
||||||
from .config import Settings, get_settings
|
from .config import Settings, get_settings
|
||||||
|
|
||||||
@@ -51,9 +52,6 @@ class DataSource:
|
|||||||
def __create_engine(cls, url: str) -> sa.Engine:
|
def __create_engine(cls, url: str) -> sa.Engine:
|
||||||
"""Constructs and returns the database engine.
|
"""Constructs and returns the database engine.
|
||||||
|
|
||||||
The foreign key enforcement is enabled on every connection
|
|
||||||
of a SQLite engine.
|
|
||||||
|
|
||||||
:param url: The SQLAlchemy database URL.
|
:param url: The SQLAlchemy database URL.
|
||||||
:return: The database engine.
|
:return: The database engine.
|
||||||
"""
|
"""
|
||||||
@@ -65,24 +63,10 @@ class DataSource:
|
|||||||
poolclass=sa.StaticPool)
|
poolclass=sa.StaticPool)
|
||||||
else:
|
else:
|
||||||
engine = sa.create_engine(url)
|
engine = sa.create_engine(url)
|
||||||
if engine.url.get_backend_name() == "sqlite":
|
if engine.dialect.name == "sqlite":
|
||||||
sa.event.listen(engine, "connect",
|
cls.__enable_sqlite_foreign_keys(engine)
|
||||||
cls.__enable_sqlite_foreign_keys)
|
|
||||||
return engine
|
return engine
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def __enable_sqlite_foreign_keys(dbapi_connection: Any,
|
|
||||||
_: Any) -> None:
|
|
||||||
"""Enables the foreign key enforcement on a new connection.
|
|
||||||
|
|
||||||
:param dbapi_connection: The DBAPI connection.
|
|
||||||
:param _: The connection record (unused).
|
|
||||||
:return: None.
|
|
||||||
"""
|
|
||||||
cursor: Any = dbapi_connection.cursor()
|
|
||||||
cursor.execute("PRAGMA foreign_keys=ON")
|
|
||||||
cursor.close()
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __resolve_sqlite_relative_url(url: str) -> str:
|
def __resolve_sqlite_relative_url(url: str) -> str:
|
||||||
"""Resolves the SQLite relative URL to the instance folder.
|
"""Resolves the SQLite relative URL to the instance folder.
|
||||||
@@ -101,6 +85,31 @@ class DataSource:
|
|||||||
path = base / "instance" / path
|
path = base / "instance" / path
|
||||||
return f"sqlite:///{path}"
|
return f"sqlite:///{path}"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def __enable_sqlite_foreign_keys(engine: sa.Engine) -> None:
|
||||||
|
"""Turns on the foreign key enforcement of SQLite.
|
||||||
|
|
||||||
|
The ``foreign_keys`` pragma is turned on for every
|
||||||
|
connection of the engine, so that the ``ON DELETE``
|
||||||
|
actions of the schema run.
|
||||||
|
|
||||||
|
:param engine: The SQLite database engine.
|
||||||
|
:return: None.
|
||||||
|
"""
|
||||||
|
def on_connect(dbapi_connection: DBAPIConnection,
|
||||||
|
_: ConnectionPoolEntry) -> None:
|
||||||
|
"""Turns on the pragma on a new connection.
|
||||||
|
|
||||||
|
:param dbapi_connection: The DB-API connection.
|
||||||
|
:param _: The connection record (unused).
|
||||||
|
:return: None.
|
||||||
|
"""
|
||||||
|
cursor: DBAPICursor = dbapi_connection.cursor()
|
||||||
|
cursor.execute("PRAGMA foreign_keys=ON")
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
|
sa.event.listen(engine, "connect", on_connect)
|
||||||
|
|
||||||
|
|
||||||
ds: DataSource = DataSource()
|
ds: DataSource = DataSource()
|
||||||
"""The data source."""
|
"""The data source."""
|
||||||
|
|||||||
Reference in New Issue
Block a user