Commiting a transaction from a PostgreSQL function in flask

馋奶兔 提交于 2019-12-07 03:42:05

问题


I'm a newbie to Flask and SQLAlchemy (been working with Django for the last 3 years). I need to call an existing PostgreSQL function that writes to 3 different tables in a database. This is out of my control (I just have to make it work). The function returns a record (custom Postgres type) with information about the results. Here is the code:

from flask.ext.sqlalchemy import SQLAlchemy

db = SQLAlchemy()

...

retval = db.engine.execute(
    'SELECT * FROM add_purchase(%s, %s, %s, %s, %s, %s, %s);',
    clean_data.account_id, amount, tax, deposit, clean_data.pos_id, 
    g.token_id, clean_data.external_reference_id).first()

app.logger.info(retval) # for debugging

db.session.commit()

The above code runs without error. From the log message, I can see the the correct data is getting returned from the database. However, if I go to psql, I cannot see the newly inserted data. It would seem that the transaction is never actually committed.

Most of the documentation and examples I can find are based on using SQLAlchemy's ORM. What am I doing wrong here?

Stack info:

Flask==0.10.1
Flask-SQLAlchemy==1.0
psycopg2==2.5.2
Python 2.7.3
Postgresql 9.3

Update

I have figured out a way to make it work, here is a sample that actually works for me:

from sqlalchemy import exc

...

connection = db.engine.connect()
trans = connection.begin()
try:
    retval = connection.execute(
        'SELECT * FROM add_purchase(%s, %s, %s, %s, %s, %s, %s);',
        clean_data.account_id, amount, tax, deposit,
        clean_data.pos_id, g.token_id,
        clean_data.external_reference_id).first()
except exc.SQLAlchemyError:
    trans.rollback()
    raise
else:
    trans.commit()

And I've reviewed the code in SQLAlchemy's connect method. It seems like calling "connect()" just gets a new connection from the pool (which seem to be set to size=5 by default - at least I'm not setting it to 5). So, I'm not sure if there is much harm in it. However, it seems like there should be away to make this code cleaner by making the example in the original question work. I'm still hoping someone can tell me how to do that.


回答1:


If you are using raw SQL with SQLAlchemy, then I think you have to issue the BEGIN and COMMIT statements yourself. Try adding something like this:

...
begin_retval = db.engine.execute('BEGIN;')
retval = db.engine.execute('SELECT * FROM add_purchase(%s, %s, %s, %s, %s, %s, %s);',
clean_data.account_id, amount, tax, deposit, clean_data.pos_id, 
g.token_id, clean_data.external_reference_id).first()
commit_retval = db.engine.execute('COMMIT;')
...


来源:https://stackoverflow.com/questions/21469884/commiting-a-transaction-from-a-postgresql-function-in-flask

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!