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.

Reply via email to