thanks, this is a simple issue that appears to be throughout the 0.6 series only, resolved in r26f423a667ca which you can get at http://hg.sqlalchemy.org/sqlalchemy/archive/26f423a667ca.tar.gz .
On Oct 26, 2010, at 2:41 PM, Lenza McElrath wrote: > Thanks for the quick response Michael. > > I do not know why all references to the object are lost. Adding the asserts > you suggested shows that the object is in the session and in the dirty list > as expected. > > I have been able to reproduce the issue with a simple test case. I have > untangled it from my infrastructure as much as possible, but you will have to > provide your own sessionmaker and BaseModel. Please let me know if you are > able to reproduce with this: http://pastebin.com/pC45S59E > > Interestingly, if I run the test on an existing row (as opposed to creating > the row in the test) the test passes. > > -Lenza > > On Mon, Oct 25, 2010 at 10:33 AM, Michael Bayer <[email protected]> > wrote: > > On Oct 25, 2010, at 1:07 PM, Lenza McElrath wrote: > >> I am running into a issue where it looks like SQLAlchemy is not performing >> the proper DB update when committing a session after modifying an object. >> This happens only when all references to the updated object are lost, and I >> update a mutable attribute BEFORE updating another attribute. It seems as >> if MutableAttrInstanceState.__resurrect is not properly resurrecting the >> object state. >> >> I have code that basically looks like this: >> >> def update_my_model(session, my_model_id): >> my_model = session.query(MyModel, id=my_model_id).one() >> my_model.mutable_attribute.mutate() >> my_model.normal_attribute = 42 >> return my_model >> >> session = self.logic.session_maker() >> update_my_model(session, my_model_id) >> session.commit() >> >> The above code does issues the SQL to update mutable_attribute, but not >> normal_attribute. Everything works if I move the mutable_attribute change >> to after the normal_attribute change, remove it completely, or assign the >> return value of the update_my_model call to a variable. >> >> I have been able to determine that in that case that fails (and only in that >> case) MutableAttrInstanceState._cleanup is being called as update_my_model >> returns. However, during the session.commit(), the call to >> self.manager.new_instance(state=self) in >> MutableAttrInstanceState.__resurrect is not returning an object that has >> normal_attribute set. From what I can tell the MutableAttrInstanceState >> instance should know about the update to normal_attribute >> (InstanceState.modified_event is being called when it is set). But I'm not >> sure of the inner-workings of MutableAttrInstanceState,so I haven't been >> able to confirm this. > > What is not explained here is how the reference would be lost in the first > place. The change to my_model.normal_attribute would place the object in > the session's "dirty" list which results in a strong reference being created > from the state to the object, which in turn is strongly referenced by the > Session's identity map. > > >> >> My mutable_attribute is rather complex, so it is entirely possible that it >> is behaving badly in some why. However, this seems like a strange failure >> mode for an issue with that attribute? Anyone have ideas on what is going >> on here, or what my next steps should be to track it down? If any >> information I have not provided would be helpful, please let me know. > > oh well definitely, try to create a simple test case. For example, if I > were to just take code like the above with a generic model, does that > reproduce the issue ? If you think something about your mutable attribute > is at fault, try replacing it with a plain dictionary and change a value > within. I can't really imagine how anything regarding your mutable type > could be involved unless it reaches out and modifies the environment > containing "my_model" somehow. > > If just the code above, I'd do things like: > > def update_my_model(session, my_model_id): > my_model = session.query(MyModel, id=my_model_id).one() > my_model.mutable_attribute.mutate() > assert my_model in session > my_model.normal_attribute = 42 > assert my_model in session.dirty > return my_model > > > > > > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/sqlalchemy?hl=en. > > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/sqlalchemy?hl=en. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
