Closed sqlalchemy-bot closed 6 years ago
Michael Bayer (@zzzeek) wrote:
that likely is the change which affected this, so, why do you want to look at the now nonexistent "updated_at" when you've just emitted a DELETE for that row?
Dmytro Starosud (@dima-starosud) wrote:
@zzzeek After every flush our system collects information about all the objects participating in that flush to be reported.
Michael Bayer (@zzzeek) wrote:
well, the change mentioned is intended to expire it for the purpose of updates, shouldn't matter for deletes, but often within the scope of post_update there are some linked effects that can't easily be unlinked, will have to look.
Michael Bayer (@zzzeek) wrote:
so we'd look at this as the patch:
if not uowtransaction.is_deleted(state) and postfetch_cols:
state._expire_attributes(state.dict,
[mapper._columntoproperty[c].key
for c in postfetch_cols if c in
mapper._columntoproperty]
)
however, if I even remove that whole block of code, none of the tests fail, so that is another regression in that when I made https://bitbucket.org/zzzeek/sqlalchemy/commits/9dee44ae2f8b#chg-test/orm/test_cycles.py I did not test this code so that means I have to be way more careful here and add tests for that too.
Dmytro Starosud (@dima-starosud) wrote:
@zzzeek thank you for a quick answer.
Sorry I am not curtain I clearly understood what you said. Are you going to prepare patch of 1.2 release, so we can upgrade to it?
Michael Bayer (@zzzeek) wrote:
it means I added code that was not tested which means I have to consider that also.
Michael Bayer (@zzzeek) wrote:
note that if I fix this you will still probably have issues, as the updated_at is still expired from any other UPDATES, so this modification to your test will still fail:
session = Session(e)
child1 = Child()
child2 = Child()
parent = Parent(children=[child1, child2], first_child=child1)
session.add(parent)
session.flush()
parent_id = parent.id
session.expunge_all()
parent = session.query(Parent).get(parent_id)
child2 = session.query(Child).order_by(Child.id)[1]
parent.first_child = child2
session.flush()
session.delete(parent)
session.flush()
print(parent.updated_at)
overall, you really can't depend on database-generated values to be present after an object is removed from the session.
Michael Bayer (@zzzeek) wrote:
as part of this fix I have identified another inconsistency which is that client-side updated_at defaults are also refreshed when the object is deleted as a result of the UPDATE that took place. I think that is also wrong. In this case, even though we are emitting an UPDATE and applying both client-side and server-side onupdates to that UPDATE, we ultimately DELETE the row. Previously, these interim values were discarded from memory as well regardless of how they got there. So I'm going to make it skip the entire post_update_onupdate added in #3472 if the object is set for DELETE.
Michael Bayer (@zzzeek) wrote:
https://gerrit.sqlalchemy.org/#/q/Ieac845348979df296bcf7e785c0353bdc6074220
Michael Bayer (@zzzeek) wrote:
Don't run postfetch_post_update for a DELETE
Fixed 1.2 regression caused by :ticket:3472
where the handling of an
"updated_at" style column within the context of a post-update operation
would also occur for a row that is to be deleted following the update,
meaning both that a column with a Python-side value generator would show
the now-deleted value that was emitted for the UPDATE before the DELETE
(which was not the previous behavor), as well as that a SQL- emitted value
generator would have the attribute expired, meaning the previous value
would be unreachable due to the row having been deleted and the object
detached from the session.The "postfetch" logic that was added as part of
:ticket:3472
is now skipped entirely for an object that ultimately is to
be deleted.
Fixes: #4327 Change-Id: Ieac845348979df296bcf7e785c0353bdc6074220
→ 1b5393db36a6
Michael Bayer (@zzzeek) wrote:
Don't run postfetch_post_update for a DELETE
Fixed 1.2 regression caused by :ticket:3472
where the handling of an
"updated_at" style column within the context of a post-update operation
would also occur for a row that is to be deleted following the update,
meaning both that a column with a Python-side value generator would show
the now-deleted value that was emitted for the UPDATE before the DELETE
(which was not the previous behavor), as well as that a SQL- emitted value
generator would have the attribute expired, meaning the previous value
would be unreachable due to the row having been deleted and the object
detached from the session.The "postfetch" logic that was added as part of
:ticket:3472
is now skipped entirely for an object that ultimately is to
be deleted.
Fixes: #4327 Change-Id: Ieac845348979df296bcf7e785c0353bdc6074220 (cherry picked from commit 1b5393db36a6c4353d41c7065b29a377d7c3b9b2)
→ 066c25ba8927
Dmytro Starosud (@dima-starosud) wrote:
Thanks @zzzeek for quick fix! Should I expect this in 1.2.12
? When do you think that version be released?
Michael Bayer (@zzzeek) wrote:
I'll likely release this week
Dmytro Starosud (@dima-starosud) wrote:
Cool! Thank you a lot!
Dmytro Starosud (@dima-starosud) wrote:
Hello @zzzeek !
Should I wait for more for 1.2.12
or it's better to find a workaround?
Thanks a lot in advance.
Michael Bayer (@zzzeek) wrote:
there should be a 1.2.12 in the coming days I can perhaps try this week
Changes by Michael Bayer (@zzzeek):
Changes by Michael Bayer (@zzzeek):
Changes by Michael Bayer (@zzzeek):
Migrated issue, originally created by Dmytro Starosud (@dima-starosud)
Regression from 1.1.15 to 1.2.11. Maybe related to this.
Please consider following code snippet.
With SQLAlchemy==1.1.15 it outputs
2018-08-23 12:06:19.291603
, nothing more and no failures.With SQLAlchemy==1.2.11 it outputs two stack traces: one from expire event and one when trying access
parent.updated_at
.Please clarify. Does this mean deleted instance cannot be used after flush any more?
Thanks a lot in advance.