SqlAlchmey добавить новую строку в таблицу на основе значений других строк - PullRequest
0 голосов
/ 09 февраля 2020

В следующем коде я пытаюсь добавить новую строку в таблицу TransferRequest, если в таблице есть строка, которая:

1 - значение столбца partnerId такое же как то, что я ожидаю

2- и статус этой строки теперь open

и после вставки я хочу изменить статус отфильтрованной строки на booked

        partner = db.session.query(TransferRequest).filter(TransferRequest.id == partner_id).one()
        if partner.status == RequestStatus.open.value:
            request = TransferRequest()
            #set values

            db.session.add(request)
            db.session.commit()

            db.session.query(TransferRequest). \
                filter(TransferRequest.id == partner_id). \
                update({"status": RequestStatus.booked.value,
                        "partnerId": request.id})
            db.session.commit()

            return "success"
        else:
            return "failure"

Проблема в том, что когда я запрашиваю элемент с указанным c id и проверяю его статус, после достижения условия if возможно, что кто-то еще изменит статус строки с open до booked. В этом случае я не должен вставлять строку и не должен выполнять команду update после вставки.

Я ищу способ выполнить все эти 3 запроса в транзакции, чтобы все ситуации с данными блокируются от первого оператора до конечного оператора. (или, конечно, любые другие решения, которые могут решить проблему)

1 Ответ

1 голос
/ 09 февраля 2020

Я думаю, что основной проблемой в вашем коде является использование commit () дважды. Который фиксирует все в базе данных (как транзакция) и затем снимает блокировку базовой транзакции. Во-вторых, я должен также добавить with_for_update () к вашему запросу select, чтобы заблокировать определенные c строки. Завершите sh однократной фиксацией, чтобы сохранить ваши изменения и снять блокировки. Примером может быть:

    session = sessionmaker(bind=engine, autocommit=False)

    partner = session.query(TransferRequest).with_for_update().filter(TransferRequest.id == partner_id).one()
    if partner.status == RequestStatus.open.value:
        request = TransferRequest()
        #set values

        session.add(request)
        session.flush()

        session.query(TransferRequest). \
            filter(TransferRequest.id == partner_id). \
            update({"status": RequestStatus.booked.value,
                    "partnerId": request.id})
        session.commit()

        return "success"
    else:
        return "failure"
...