#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. Хорошо, спасибо, что проверили это!