Как избежать ошибки SQLAlchemy IntegrityError при ограничении уникальности при замене уникальных значений - PullRequest
0 голосов
/ 09 июля 2020

У меня есть следующие модели SQLAlchemy (абстрагированные от фактической реализации)

class Parent():
    id = Column(postgresql.UUID, primary_key=True)

class Child():
    id = Column(postgresql.UUID, primary_key=True)
    parent_id = (postgresql.UUID,sqlalchemy.ForeignKey(Parent.id), nullable=False, index=True)
    order = sa_schema.Column(postgresql.SMALLINT)

И у меня есть ограничение уникальности для parent_id и order, поэтому порядок дочерних элементов в родительском элементе уникален. Я хочу написать код, позволяющий переупорядочить этих детей, например, если у меня есть дети AB C DE в этом порядке и я хочу изменить порядок дочернего элемента B с 2 на 4, я изменяю C с 3 на 2, и D от 4 до 3. Все это работает, но когда я go фиксирую транзакцию, я получаю IntegrityError о том, что одна из пар order / parent_id уже существует (каждый раз она случайная). Я уже отключил автогрипп sh, кто-нибудь знает, как я могу это сделать sh? Пример кода (очевидно, это касается только случая, когда заказ увеличивается):

    children_to_update = session.query(models.Child).filter(
        models.Child.parent_id == parent_id,
        models.Child.order <= new_order,
        models.Child.order > original_order,
    ).with_for_update(nowait=True).all()
    for child_to_update in children_to_update:
        child_to_update.order = child_to_update.order - 1
        session.add(child_to_update)

    original_child.order = new_order
    session.add(original_child)
    session.commit()

1 Ответ

2 голосов
/ 09 июля 2020

Чтобы эта работа работала, вам сначала нужно сделать ваше уникальное ограничение на (parent_id, order) откладываемым.

Затем вам нужно отложить ограничение до вашего запроса, отправив set constraints <constraint name|all> deferred;

отложенное ограничение будет проверяться автоматически на commit.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...