Hey John -

Well, this one really kicked my ass for quite awhile, as each fix to the issue revealed that the entire approach of using aliases to eager load just doesnt generally work.  

the biggest issue being, if you map the Place class against the place table, as well as the output_place and input_place aliases, when you create new Place objects, they are "dependency-sorted" based on the original mapper, i.e. the "place" table mapper, which has no idea about the relationships inside the Transition.mapper, so it will screw up often if not always.

So while you can now stick an Alias object inside a relation(), you dont have to.  A more concise syntax that addresses the issue at a more specific spot has been added:

        Place.mapper = mapper(Place, place)
        Transition.mapper = mapper(Transition, transition, properties = dict(
            inputs = relation(Place.mapper, place_output, lazy=False, selectalias='op_alias'),
            outputs = relation(Place.mapper, place_input, lazy=False, selectalias='ip_alias'),
            )
        )

Which properly saves new Transition and Place objects and their relationships.  Upon select it produces a query like:

SELECT transition.transition_id AS transition_transition_id, transition.name AS transition_name, 
ip_alias.place_id AS ip_alias_place_id, ip_alias.name AS ip_alias_name, 
op_alias.place_id AS op_alias_place_id, op_alias.name AS op_alias_name
FROM transition LEFT OUTER JOIN place_input ON transition.transition_id = place_input.transition_id 
LEFT OUTER JOIN place AS ip_alias ON ip_alias.place_id = place_input.place_id 
LEFT OUTER JOIN place_output ON transition.transition_id = place_output.transition_id
 LEFT OUTER JOIN place AS op_alias ON op_alias.place_id = place_output.place_id 
ORDER BY transition.oid, place_input.oid, place_output.oid

But despite using the two alias names, the Place object is still mapped against the original 'place' table, and EagerLoader performs some translation upon the rows coming back in so that they appear to be selected against 'place' instead of 'ip_alias' or 'op_alias'.

There is also a test case based on the one you gave me inside test/double.py .

- mike


On Dec 1, 2005, at 1:10 PM, Shuo Yang wrote:


On 11/30/05, Michael Bayer <[EMAIL PROTECTED] > wrote:
Michael Bayer wrote:
> then if that doesnt work, you can also say:
>
>     Transition.mapper = mapper(Transition, transition, properties = dict(
>          inputs = relation(Place, output_place, place_output,
> primaryjoin=and_(output_place.c.foo==place_output.c.foo,
>           place.c.bar==place_output.c.bar)
> lazy=False),

err that should be:

     Transition.mapper = mapper(Transition, transition, properties = dict(
          inputs = relation(Place, output_place, place_output,
primaryjoin=place.c.bar==place_output.c.bar,
secondaryjoin=output_place.c.foo==place_output.c.foo,
   ...
lazy=False),

 
...
outputs = relation(Place, input_place, place_input, lazy=False),
  File "build/bdist.linux-i686/egg/sqlalchemy/mapper.py", line 89, in mapper
  File "build/bdist.linux-i686/egg/sqlalchemy/mapper.py", line 264, in _init_properties
  File "build/bdist.linux-i686/egg/sqlalchemy/mapper.py", line 1007, in init
  File "build/bdist.linux-i686/egg/sqlalchemy/mapper.py", line 682, in init
  File "build/bdist.linux-i686/egg/sqlalchemy/mapper.py", line 756, in _match_primaries
AttributeError: 'Alias' object has no attribute 'table'

Now it's this :p

Reply via email to