Найти - Пользователи
Полная версия: Elixir, SQLite, foreign keys, cascade delete
Начало » Базы данных » Elixir, SQLite, foreign keys, cascade delete
1
Kupuyc
Приветствую.

Столкнулся с непонятной мне штукой из-за которой скоро, похоже, забянят в Гугле.

Проблема в том, при удалении одной из записей ORM пытается для всех дочек выставить в null ключевое поле, выполняя для них update. Т.к. поле не может быть null - ошибка. Само удаление дочек делается через foreign keys силами SQLite.
Сущности объявлены следующим образом:
class Identification(Entity):
id = Field(Integer, primary_key = True)
analysis = ManyToOne("Analysis", colname = "analysisId")
organismProfile = Field(PickleType)
antibiogram = OneToMany("AntibiogramItem")

using_options(tablename = "identification")

def delete(self):
super(Identification, self).delete()
session.commit()


class AntibiogramItem(Entity):
id = Field(Integer, primary_key = True)
identification = ManyToOne("Identification", colname = "identificationId")
itemIndex = Field(Integer)
antibiotic = Field(Unicode(100))

using_options(tablename = "antibiogram")
Identification::delete() прикручен только для целей отладки. Вот при его вызове (точнее при отправке всех запросов движку БД) и идет ненужный update-запрос:
2011-12-12 22:06:33,025 INFO sqlalchemy.engine.base.Engine (12,)
2011-12-12 22:06:35,039 INFO sqlalchemy.engine.base.Engine UPDATE antibiogram SET "identificationId"=? WHERE antibiogram.id = ?
2011-12-12 22:06:35,039 INFO sqlalchemy.engine.base.Engine (None, 277)
2011-12-12 22:06:35,039 INFO sqlalchemy.engine.base.Engine ROLLBACK
По коду Elixir также сложно понять что необходимо чтобы данного поведения избежать. Из документации SQLAlchemy следует, что необходимо задавать некоторые ключи вроде passive_* и указать связям что-то такое, при чем они будут корректно себя вести. Но все это даже при пристальном изучении решить проблему не позволяет. Прошу помощи.
Kupuyc
После часа рассматривания кода SQLAlchemy под дебаггером получилось решить вопрос следующим образом:

class Identification(Entity):
id = Field(Integer, primary_key = True)
analysis = ManyToOne("Analysis", colname = "analysisId")
organismProfile = Field(PickleType)
antibiogram = OneToMany("AntibiogramItem", passive_deletes = "all")

using_options(tablename = "identification")
Самое обидное, что после установления этого факта стало ясно - в документации это все упоминалось.

Еще был нюанс с тем, что хоть каскадное удаление через внешние ключи и было в DDL таблицы, но активировать его работу нужно при коннекте:

from elixir import metadata
from sqlalchemy import event
event.listen(metadata.bind.engine, "connect", lambda connect_db, connect_record: connect_db.execute('pragma foreign_keys = ON'))
Иначе фокуса не произойдет (с)
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB