Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Record queries errors on some Postgres queries #1261

Open
stl-gilesbartonowen opened this issue Sep 30, 2023 · 0 comments
Open

Record queries errors on some Postgres queries #1261

stl-gilesbartonowen opened this issue Sep 30, 2023 · 0 comments

Comments

@stl-gilesbartonowen
Copy link

Although the flask documentation claims it passes ExecutionContext objects optionally, it appears it sometimes passes PGExecutionContext_psycopg2 objects, which are not guaranteed to have a .statement attribute. This means that line 111 in record_queries.py will throw the following:

  File <FILE>, line 41, in <FN>
    return context.fire_sequence(model_id_seq, None)
  File "/usr/local/webapp/flask/lib/python3.8/site-packages/sqlalchemy/dialects/postgresql/base.py", line 2837, in fire_sequence
    return self._execute_scalar(
  File "/usr/local/webapp/flask/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 1658, in _execute_scalar
    conn._cursor_execute(self.cursor, stmt, parameters, context=self)
  File "/usr/local/webapp/flask/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 2189, in _cursor_execute
    self.dispatch.after_cursor_execute(
  File "/usr/local/webapp/flask/lib/python3.8/site-packages/sqlalchemy/event/attr.py", line 487, in __call__
    fn(*args, **kw)
  File "/usr/local/webapp/flask/lib/python3.8/site-packages/sqlalchemy/event/attr.py", line 174, in wrap_kw
    return fn(**argdict)
  File "/usr/local/webapp/flask/lib/python3.8/site-packages/flask_sqlalchemy/record_queries.py", line 111, in _record_end
    statement=context.statement,
sqlalchemy.exc.StatementError: (builtins.AttributeError) 'PGExecutionContext_psycopg2' object has no attribute 'statement'

I appreciate this is somewhat an issue with Flask but I think this can be handled in a safe way within flask-alchemy, especially given when these contexts are passed in they don't actually have the fired sequence sql in, but rather the broader insert. The listener functions are called with "statement" as a kwarg so I think there's a strong argument to use that primarily.

This is the case I've found so far:

from sqlalchemy.sql  import Sequence

db = SQLAlchemy()

field_sequence = Sequence("field_sequence")

def get_default_field(context):
    if context.get_current_parameters()['set_field']:
        return context.fire_sequence(field_sequence, None)

class MyModel(db.Model):
    set_field = db.Column(db.Boolean)
    field = db.Column(db.BigInteger, default=get_default_field, nullable=True)


m = MyModel(set_field=True)
db.session.add(m)
db.session.flush()

Environment:

  • Python version: 3.8.16
  • Flask-SQLAlchemy version: 3.1.1
  • Flask version: 2.3.3
  • SQLAlchemy version: 2.0.21
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Development

No branches or pull requests

1 participant