Oh, yes, of course, I forgot that foreign keys aren’t immediately updated when 
you manipulate a relationship. Your suggested change sounds exactly right.

Thanks again,

Simon


On 25 Jan 2014, at 02:30, Michael Bayer <mike...@zzzcomputing.com> wrote:

> 
> 
> well since create_version() is called within before_flush(), the net effect 
> of any changes on local many-to-one relationships can only be taken into 
> account by looking at these attributes.  The test in test_versioning called 
> test_relationship illustrates this.
> 
> so the diff is like this, the test still passes:
> 
> diff --git a/examples/versioned_history/history_meta.py 
> b/examples/versioned_history/history_meta.py
> index 8cb5234..e8d3ed2 100644
> --- a/examples/versioned_history/history_meta.py
> +++ b/examples/versioned_history/history_meta.py
> @@ -6,6 +6,7 @@ from sqlalchemy.orm.exc import UnmappedClassError, 
> UnmappedColumnError
> from sqlalchemy import Table, Column, ForeignKeyConstraint, Integer
> from sqlalchemy import event
> from sqlalchemy.orm.properties import RelationshipProperty
> +from sqlalchemy.orm.attributes import PASSIVE_NO_FETCH_RELATED
> 
> def col_references_table(col, table):
>     for fk in col.foreign_keys:
> @@ -160,7 +161,7 @@ def create_version(obj, session, deleted = False):
>         # check those too
>         for prop in obj_mapper.iterate_properties:
>             if isinstance(prop, RelationshipProperty) and \
> -                attributes.get_history(obj, prop.key).has_changes():
> +                attributes.get_history(obj, prop.key, 
> passive=PASSIVE_NO_FETCH_RELATED).has_changes():
>                 for p in prop.local_columns:
>                     if p.foreign_keys:
>                         obj_changed = True
> 
> 
> 
> 
> On Jan 24, 2014, at 5:48 PM, Simon King <si...@simonking.org.uk> wrote:
> 
>> I see the same behaviour on 0.8.2 and 0.9.1.
>> 
>> Before making any changes I’d just like to understand what the code is 
>> trying to do. As far as I can tell, the first loop works up the inheritance 
>> chain, looking at each column to see if it changed, which is all fine.
>> 
>> But then, if it hasn’t found any columns that have changed, it goes into the 
>> second loop, over obj_mapper.iterate_properties. I guess it is looking for 
>> relationships which don’t correspond to columns on the object itself (eg. 
>> the other side of a 1-to-many relationship). I can’t think of a situation 
>> where this will produce something that can actually be written to the 
>> history table.
>> 
>> I removed the second loop altogether and in the very simple test it behaved 
>> exactly as I would have expected, but perhaps it’ll fail in more complicate 
>> scenarios?
>> 
>> Thanks again,
>> 
>> Simon
>> 
>> On 24 Jan 2014, at 18:00, Michael Bayer <mike...@zzzcomputing.com> wrote:
>> 
>>> without looking too deeply, you can modify that get_history() call to not 
>>> emit any SQL, assuming you’re on 0.9 (maybe on 0.8 also but the API has 
>>> been fixed up).
>>> 
>>> Take a look at passing the “passive” flag to get_history(), or 
>>> alternatively using inspect().attrs.data.history:
>>> 
>>> http://docs.sqlalchemy.org/en/rel_0_9/changelog/migration_09.html#attributes-get-history-will-query-from-the-db-by-default-if-value-not-present
>>> 
>>> 
>>> I’m not sure if you’re on 0.8 or 0.9 but I would think 0.9 if that’s 
>>> emitting SQL?   again, haven’t looked closely.
>>> 
>>> if this fixes your issue we might want to update the recipe also, not sure.
>>> 
>>> 
>>> 
>>> On Jan 24, 2014, at 11:22 AM, Simon King <si...@simonking.org.uk> wrote:
>>> 
>>>> Hi again,
>>>> 
>>>> While testing the complicated relationship from the other thread, I
>>>> noticed that I was generating a lot of queries that I couldn't
>>>> immediately explain. After a bit of digging, it turned out that it was
>>>> due to my use of code based on the "versioned objects" example at
>>>> http://docs.sqlalchemy.org/en/rel_0_9/_modules/examples/versioned_history/history_meta.html.
>>>> 
>>>> In the test script below we have 3 classes. Users belong to Companies,
>>>> and Companies reference a single Terms row. In the example, only the
>>>> Company class is versioned.
>>>> 
>>>> The test script inserts a single user, company and terms row, then in
>>>> new transaction loads the company and adds a new user. If you look at
>>>> the SQL output, you should see that it loads the company.terms
>>>> relationship, which doesn't seem like it should be necessary.
>>>> 
>>>> I think it's due to the following code from history_meta.py:
>>>> 
>>>> if not obj_changed:
>>>>     # not changed, but we have relationships.  OK
>>>>     # check those too
>>>>     for prop in obj_mapper.iterate_properties:
>>>>         if isinstance(prop, RelationshipProperty) and \
>>>>             attributes.get_history(obj, prop.key).has_changes():
>>>>             for p in prop.local_columns:
>>>>                 if p.foreign_keys:
>>>>                     obj_changed = True
>>>>                     break
>>>>             if obj_changed is True:
>>>>                 break
>>>> 
>>>> I can't figure out the circumstances when this should be necessary -
>>>> can someone explain it to me?
>>>> 
>>>> Thanks a lot,
>>>> 
>>>> Simon
>>>> 
>>>> -- 
>>>> 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 http://groups.google.com/group/sqlalchemy.
>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>> 
>> 
>> -- 
>> 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 http://groups.google.com/group/sqlalchemy.
>> For more options, visit https://groups.google.com/groups/opt_out.
> 

-- 
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 http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to