SQLAlchemy: невозможно повторно включить внешние ключи SQLite

#python #sqlite #sqlalchemy

Вопрос:

При запуске моей программы моей базе данных sqlite в памяти необходимо временно отключить принудительное использование внешних ключей (для вставки данных из другой базы данных sqlite). Я могу установить foreign_keys=off , но по какой — то причине не могу включить его снова. Вот минимальный скрипт, который воспроизводит проблему (SQLAlchemy==1.3.22).

 from sqlalchemy import Column, Integer, create_engine, event
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session as DBSession, configure_mappers
import sqlalchemy.pool
import sqlite3


def get_mem_conn():
    return sqlite3.connect(':memory:', check_same_thread=False)


def get_engine():
    engine = create_engine(
        'sqlite://',
        creator=lambda: conn,
        poolclass=sqlalchemy.pool.StaticPool,
    )
    from sqlalchemy import event

    event.listen(engine, 'connect', _enable_fks)
    return engine


def display_fk_pragma(conn, msg):
    print(msg, conn.execute('pragma foreign_keys').fetchall())

def load_in_memory_db():

    display_fk_pragma(conn, 'before temporarily disabling')
    conn.execute('pragma foreign_keys=off')
    conn.execute('INSERT INTO groups DEFAULT VALUES')
    conn.execute('pragma foreign_keys=on')
    display_fk_pragma(conn, 'after turning back on')
    conn.commit()


def _enable_fks(c, _):
    c.execute('pragma foreign_keys=on')
    display_fk_pragma(c, 'after setting on in connect.listen')


Base = declarative_base()


class Group(Base):
    __tablename__ = 'groups'

    id = Column(Integer, primary_key=True)


def init_orm():
    configure_mappers()
    Base.metadata.create_all(engine)
    load_in_memory_db()


conn = get_mem_conn()

engine = get_engine()

db: DBSession = sessionmaker(bind=engine)()

init_orm()
 

Я ожидаю такого вывода:
после включения [(1,)]

Но я понимаю это: после включения [(0,)]

Интересно, что если я закомментирую оператор insert (или помещу его перед переключением), код будет работать нормально.

Есть какие-нибудь идеи? Я попытался воспроизвести это в sqlite CLI, но это работает так, как я ожидаю:

 SQLite version 3.35.4 2021-04-02 15:20:15
Enter ".help" for usage hints.
sqlite> pragma foreign_keys;
0
sqlite> pragma foreign_keys=on;
sqlite> pragma foreign_keys;
1
sqlite> create table groups (id primary key);
sqlite> pragma foreign_keys=off;
sqlite> pragma foreign_keys;
0
sqlite> insert into groups default values;
sqlite> pragma foreign_keys=on;
sqlite> pragma foreign_keys;
1
 

Комментарии:

1. Не уверен насчет 1.3, но 1.4, похоже, с этим проблем нет. Этот код , похоже, отлично работает для меня.

2. Хорошо, спасибо, что проверили это!