On Nov 21, 2012, at 9:26 PM, Kevin Q wrote: > I want to avoid double joining on the same table. I know query._from_obj is > where the query stores the join elements. However, it's not there if the join > is from query.options(joinedload('some_relation')). For example, I have the > following table relations: > > User: > * userid > * name > > Thing > * thingid > * name > * userid > > Thing.user = relation(User, User.userid==Thing.userid) > > If I call: > > query = > session.query(Thing).options(joinedload('user')).filter(User.name=='blah').all() > > This will generate the following query: > SELECT thing.thingid, thing.name, thing.userid, user1.userid, user1.name > FROM thing INNER JOIN user AS user1 > INNER JOIN user > WHERE user.name == 'blah' > > Notice the double join there.
that example doesn't actually make sense. Your query only specifies joinedload('user'), which would only create "thing INNER JOIN user AS user1". I don't see anything about that query which would also create "INNER JOIN user", are you omitting an extra join() call ? > Now, I wouldn't do that if I'm writing the query in a single function, but if > the code is modular, the child object loading and filtering is done in > separate functions, with the query being passed around. Is there a way for me > to detect whether a query already has a join on a certain table, whether the > join is from query.join() or query.options(joinedload(x))? I tend not to use this approach in an extended way, not only because there aren't very public APIs for this, but also it's not necessarily simple to determine "A joins to B" since "A" can join to "B" in any number of ways, with different criterion, A or B could be wrapped in a subquery for some reason, etc. The structure of the query can be more complicated than one which you'd want to be introspecting in order to get at various decisions for subsequent transformations. It's best if all the decisions for how the Query can be built can be made in one place, exporting not the Query object itself for remote transformations but rather some other "intent-collecting" structure which can be interpreted in one step at the end. You can get the joins if you look into query._from_obj, but to get at eagerloads it's fairly tedious as you'd need to dig through query._attributes. Basically I try to keep the number of non-coordinated functions which each participate in modifying the structure of a particular Query to a minimum, and if you're needing to dig in and find who's been applying eagerloads and options, I'd want to pull back on how many unrelated actors are all affecting the same structure. If you truly need lots of non-coordinated functions to establish possibly-conflicting intentions upon a Query, another approach is to build a stateful structure around Query that represents the Query-specific activities which your non-coordinating functions all take. Basically your own coarse grained "Query" interface that then knows how to intelligently build the Query object based on the state given to it. Again, the approach here is one of bringing together all those actors that would modify a Query into one system so that they can coordinate closely, but that system is also one which provides a successful API to non-coordinated functions. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.