kunl
kunl

Reputation: 1195

Using transactions with peewee without using `atomic()`

We have a file db.py where a peewee database is defined:

db = PostgresqlExtDatabase('mom',
                           user=DB_CONFIG['username'],
                           password=DB_CONFIG['password'],
                           host=DB_CONFIG['host'],
                           port=DB_CONFIG['port'],
                           threadlocals=True,
                           register_hstore=False,
                           autocommit=True,
                           autorollback=True,
                           cursor_factory=DictCursor)

Calling db.execute("SOME RAW SQL UPDATE QUERY") works as expected. But calling a begin before that does not stop the DB from being modified.

db.begin()
db.execute("SOME RAW SQL UPDATE QUERY")  # <- Does not wait, db is updated immediately here
db.commit()

Am i doing this right?

I basically need to nest the raw sql in a transaction if one is already ongoing, else just execute it right away if there is no transaction begin called.

This works as expected if i do db.set_autocommit(False) then execute_sql then commit().
It also works inside the atomic() context manager.


To give some context, I am working on a web application, on logistics, and our codebase uses Flask and an SQLAlchemy scoped_session with autocommit set to True. It does not use the SQLAlchemy ORM (due to.. historical reasons) and instead just uses the Session object and its execute(), begin(), begin_nested(), rollback() and remove() methods.

The way it does it is by defining a Session Session = scoped_session(sessionmaker(autocommit=True)) in a file, and then calling session = Session() everywhere in the codebase, and executing the queries using session.execute("SQL") Sometimes, a session.begin() is called, so the query does not execute until the commit (or rollback).

We'd now really like to use peewee. But.. the codebase is built on this session. So this has to be spoofed. Going and changing every file is impossible, and not enough test cases to boot (for.. historical reasons).


Also I had some questions but I don't know where to ask them, so I hope you don't mind if I put them here:

I figured this will allow the codebase to make a transparent and seamless switch over to using peewee without having to change it everywhere. How can i do this in a better way?

Upvotes: 0

Views: 4911

Answers (2)

coleifer
coleifer

Reputation: 26245

The docs explain how to do this: http://docs.peewee-orm.com/en/latest/peewee/transactions.html#autocommit-mode

But, tl;dr, you need to disable autocommit before begin/commit/rollback will work like you expect:

db.set_autocommit(False)
db.begin()
try:
    user.delete_instance(recursive=True)
except:
    db.rollback()
    raise
else:
    try:
        db.commit()
    except:
        db.rollback()
        raise
finally:
    db.set_autocommit(True)

Upvotes: 5

gms
gms

Reputation: 335

The default value for autocommit is True but the default value of autorollback is False. Setting autorollback as True automatically rollback when an exception occurs while executing a query. Can't be sure but maybe this mess the situation. So, if you want try it with the autorollback as False

Upvotes: -1

Related Questions