Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 12, 2011 18:58:56

Kupuyc
От:
Зарегистрирован: 2011-08-10
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

Elixir, SQLite, foreign keys, cascade delete

Приветствую.

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

Проблема в том, при удалении одной из записей 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_* и указать связям что-то такое, при чем они будут корректно себя вести. Но все это даже при пристальном изучении решить проблему не позволяет. Прошу помощи.



Офлайн

#2 Дек. 16, 2011 13:36:49

Kupuyc
От:
Зарегистрирован: 2011-08-10
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

Elixir, SQLite, foreign keys, cascade delete

После часа рассматривания кода 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'))
Иначе фокуса не произойдет (с)



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version