From e3366e3544a2f0ec66fb129a1022be01d0683792 Mon Sep 17 00:00:00 2001 From: Julian Rother <julian@cccv.de> Date: Mon, 14 Feb 2022 22:36:45 +0100 Subject: [PATCH] Enable foreign key support for SQLite --- uffd/__init__.py | 4 +++- uffd/database.py | 19 ++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/uffd/__init__.py b/uffd/__init__.py index 55fa8360..611f107c 100644 --- a/uffd/__init__.py +++ b/uffd/__init__.py @@ -13,7 +13,7 @@ except ImportError: from werkzeug.exceptions import InternalServerError, Forbidden from flask_migrate import Migrate -from uffd.database import db, SQLAlchemyJSON +from uffd.database import db, SQLAlchemyJSON, customize_db_engine from uffd.template_helper import register_template_helper from uffd.navbar import setup_navbar from uffd.secure_redirect import secure_local_redirect @@ -79,6 +79,8 @@ def create_app(test_config=None): # pylint: disable=too-many-locals,too-many-sta db.init_app(app) Migrate(app, db, render_as_batch=True, directory=os.path.join(app.root_path, 'migrations')) + with app.app_context(): + customize_db_engine(db.engine) for module in [user, selfservice, role, mail, session, csrf, mfa, oauth2, services, rolemod, api, signup, invite]: for bp in module.bp: diff --git a/uffd/database.py b/uffd/database.py index 681581e1..68800c74 100644 --- a/uffd/database.py +++ b/uffd/database.py @@ -1,6 +1,6 @@ from collections import OrderedDict -from sqlalchemy import MetaData +from sqlalchemy import MetaData, event from flask_sqlalchemy import SQLAlchemy from flask.json import JSONEncoder @@ -15,6 +15,23 @@ metadata = MetaData(naming_convention=convention) db = SQLAlchemy(metadata=metadata) +def enable_sqlite_foreign_key_support(dbapi_connection, connection_record): + # pylint: disable=unused-argument + cursor = dbapi_connection.cursor() + cursor.execute('PRAGMA foreign_keys=ON') + cursor.close() + +# We want to enable SQLite foreign key support for app and test code, but not +# for migrations. +# The common way to add the handler to the Engine class (so it applies to all +# instances) would also affect the migrations. With flask_sqlalchemy v2.4 and +# newer we could overwrite SQLAlchemy.create_engine and add our handler there. +# However Debian Buster and Bullseye ship v2.1, so we do this here and call +# this function in create_app. +def customize_db_engine(engine): + if engine.name == 'sqlite': + event.listen(engine, 'connect', enable_sqlite_foreign_key_support) + class SQLAlchemyJSON(JSONEncoder): def default(self, o): if isinstance(o, db.Model): -- GitLab