On 08/02/2016 04:24 AM, Lenar Imamutdinov wrote:
Thank you for the comprehensive answer. Without going too much into
details, I have a table where file associated with each database record,
and the name of that file is based on object id. This is what's
happening now when I'm doing an INSERT:
1. Model instance is created
2. Explicit flush is done to get the id
3. File is created, the id is used for its name
4. Filename is written back to the instance
5. Commit

It works perfectly, but I would like to avoid explicit flushing and do
all that file creating stuff somewhere implicitly before commit. This
code is used inside the library so the solution should be
database-specifics tolerant as much as possible too.

Actually, I'm starting to realize that refresh_flush event is not very
good for this task, because it's called from within the flushing process
and all object modifications remain ignored, so I cannot write the
filename to the object from the event handler. What I need is the event
that hooks to the model class, happens before commit, when the flush is
already done, but I can modify the object and trigger another flush on
exit if the object has been indeed modified. Is there anything like this
in current SQLAlchemy?

well the after_flush() event would be where you could do that, you can in fact trigger a second flush in there.

This is a use case that is actually detected, as we've seen the case where event handlers go into an endless loop (e.g. flush = do my event = do another flush); it will stop after 100 loops around to prevent this. So you'd need to make sure your routine has no chance of going into an endless loop.






On Friday, July 29, 2016 at 5:35:01 PM UTC+3, Mike Bayer wrote:

    Thanks for the great test case and this would be appropriate to be
    posted as a bug, since it is a complete description.

    So, the reason the primary key is not included right now is because
    primary keys are populated in many different ways on the object,
    meaning
    if your code relies upon refresh_flush(), it will break if you
    switch to
    another database, or use an old version of Postgresql that doesn't
    support RETURNING, or the table/dialect is set up to no longer use
    RETURNING, etc.   The primary key is not actually populated at that
    point the way the other defaults are (it was already populated
    previously, so I guess to the event consumer, it doesn't make that much
    difference).

    Looking at where refresh_flush is called, there is still inconsistency
    for other kinds of defaults too; if you use eager_defaults with a MySQL
    database and server-side defaults it looks like you'd get called in the
    ordinary refresh() event anyway (that is, if you try to eager_defaults
    against a server_default="0", a Postgresql DB will call
    refresh_flush, a
    MySQL DB will call refresh()).

    Still, a primary key that's an autoincrement will never come back for
    MySQL within either of these events - there's no RETURNING for MySQL
    (and others).

    refresh_flush() is very new and not widely used and it is likely
    harmless to just add what we have here (not to mention document it
    either way).  But for any change I'd first ask, what are you trying to
    do?   The primary keys are excluded from "refresh" because they are not
    usually a part of that concept, primary keys are "first class" and
    always get pulled no matter what, you can grab them in after_insert(),
    for example.





    On 07/29/2016 04:25 AM, Lenar Imamutdinov wrote:
    > Hello!
    >
    > Looks like the refresh_flush event is not triggered when the only
    field
    > to update after flush is the primary key fed from RETURNING clause.
    > However it should, as far as I understand what is mentioned in the
    > documentation.
    >
    > Environment: SQLAlchemy 1.0.14, PostgreSQL 9.5, Python 3.4
    >
    > Here is how to reproduce this problem:
    >
    >     from sqlalchemy.ext.declarative import declarative_base
    >     from sqlalchemy import Column, Integer
    >     from sqlalchemy import create_engine
    >     from sqlalchemy.orm import Session
    >     from sqlalchemy import event
    >
    >     Base = declarative_base()
    >
    >     def receive_refresh_flush(target, context, attrs):
    >         print('refresh_flush received')
    >
    >     class Test(Base):
    >         __tablename__ = 'refresh_flush_test'
    >         id = Column(Integer, primary_key=True)
    >         # uncomment the field below to receive the event
    >         # dummy = Column(Integer, default=0)
    >
    >     engine =
    create_engine('postgresql://test:test@localhost:5432/test')
    >     Base.metadata.create_all(engine)
    >     session = Session(engine)
    >
    >     event.listen(Test, 'refresh_flush', receive_refresh_flush)
    >
    >     obj = Test()
    >     session.add(obj)
    >     session.commit()
    >
    > --
    > You received this message because you are subscribed to the Google
    > Groups "sqlalchemy" group.
    > To unsubscribe from this group and stop receiving emails from it,
    send
    > an email to sqlalchemy+...@googlegroups.com <javascript:>
    > <mailto:sqlalchemy+unsubscr...@googlegroups.com <javascript:>>.
    > To post to this group, send email to sqlal...@googlegroups.com
    <javascript:>
    > <mailto:sqlal...@googlegroups.com <javascript:>>.
    > Visit this group at https://groups.google.com/group/sqlalchemy
    <https://groups.google.com/group/sqlalchemy>.
    > For more options, visit https://groups.google.com/d/optout
    <https://groups.google.com/d/optout>.

--
You received this message because you are subscribed to the Google
Groups "sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to sqlalchemy+unsubscr...@googlegroups.com
<mailto:sqlalchemy+unsubscr...@googlegroups.com>.
To post to this group, send email to sqlalchemy@googlegroups.com
<mailto:sqlalchemy@googlegroups.com>.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to