for constructing reasonable join conditions (otherwise you can get
full cartesian products). result set is the list of tuples, non-uniqued.
+ - eager loading will not "aliasize" "order by" clauses that were placed
+ in the select statement by something other than the eager loader
+ itself, to fix possibility of dupe columns as illustrated in
+ [ticket:495]. however, this means you have to be more careful with
+ the columns placed in the "order by" of Query.select(), that you have
+ explicitly named them in your criterion (i.e. you cant rely on the
+ eager loader adding them in for you)
+
- strings and columns can also be sent to the *args of instances() where
those exact result columns will be part of the result tuples.
def _is_self_referential(self):
return self.parent.mapped_table is self.target or self.parent.select_table is self.target
- def get_join(self, parent):
+ def get_join(self, parent, primary=True, secondary=True):
try:
- return self._parent_join_cache[parent]
+ return self._parent_join_cache[(parent, primary, secondary)]
except KeyError:
parent_equivalents = parent._get_inherited_column_equivalents()
primaryjoin = self.polymorphic_primaryjoin.copy_container()
sql_util.ClauseAdapter(parent.select_table, exclude=self.foreign_keys, equivalents=parent_equivalents).traverse(primaryjoin)
if secondaryjoin is not None:
- j = primaryjoin & secondaryjoin
+ if secondary and not primary:
+ j = secondaryjoin
+ elif primary and secondary:
+ j = primaryjoin & secondaryjoin
+ elif primary and not secondary:
+ j = primaryjoin
else:
j = primaryjoin
- self._parent_join_cache[parent] = j
+ self._parent_join_cache[(parent, primary, secondary)] = j
return j
def register_dependencies(self, uowcommit):
for key in keys:
prop = mapper.props[key]
if outerjoin:
- clause = clause.outerjoin(prop.select_table, prop.get_join(mapper))
+ if prop.secondary:
+ clause = clause.outerjoin(prop.secondary, prop.get_join(mapper, primary=True, secondary=False))
+ clause = clause.outerjoin(prop.select_table, prop.get_join(mapper, primary=False))
+ else:
+ clause = clause.outerjoin(prop.select_table, prop.get_join(mapper))
else:
- clause = clause.join(prop.select_table, prop.get_join(mapper))
+ if prop.secondary:
+ clause = clause.join(prop.secondary, prop.get_join(mapper, primary=True, secondary=False))
+ clause = clause.join(prop.select_table, prop.get_join(mapper, primary=False))
+ else:
+ clause = clause.join(prop.select_table, prop.get_join(mapper))
mapper = prop.mapper
return (clause, mapper)
if clauses.eager_order_by:
statement.order_by(*util.to_list(clauses.eager_order_by))
- elif getattr(statement, 'order_by_clause', None):
- clauses._aliasize_orderby(statement.order_by_clause, False)
statement.append_from(statement._outerjoin)
for value in self.select_mapper.props.values():
assert False
except AttributeError:
assert True
+
+ def testjoinviam2m(self):
+ """test the join_via and join_to functions"""
+ m = mapper(Order, orders, properties = {
+ 'items' : relation(mapper(Item, orderitems, properties = {
+ 'keywords' : relation(mapper(Keyword, keywords), itemkeywords)
+ }))
+ })
+
+ sess = create_session()
+ q = sess.query(m)
+
+ l = q.filter(keywords.c.name=='square').join(['items', 'keywords']).list()
+ self.assert_result(l, Order, order_result[1])
+
def testcustomjoin(self):
"""test that the from_obj parameter to query.select() can be used
def testmanytomany(self):
items = orderitems
-
m = mapper(Item, items, properties = dict(
keywords = relation(mapper(Keyword, keywords), itemkeywords, lazy=False, order_by=[keywords.c.keyword_id]),
))
{'item_id' : 1, 'keywords' : (Keyword, [{'keyword_id' : 2}, {'keyword_id' : 4}, {'keyword_id' : 6}])},
{'item_id' : 2, 'keywords' : (Keyword, [{'keyword_id' : 2}, {'keyword_id' : 5}, {'keyword_id' : 7}])},
)
+
def testmanytomanyoptions(self):
items = orderitems
keywordmapper = mapper(Keyword, keywords)
m = mapper(Item, items, properties = dict(
- keywords = relation(keywordmapper, itemkeywords, lazy = False),
+ keywords = relation(keywordmapper, itemkeywords, lazy = False, order_by=keywords.c.name),
))
data = [Item,
ctx.current.flush()
- l = ctx.current.query(m).select(items.c.item_name.in_(*[e['item_name'] for e in data[1:]]), order_by=[items.c.item_name, keywords.c.name])
+ l = ctx.current.query(m).select(items.c.item_name.in_(*[e['item_name'] for e in data[1:]]), order_by=[items.c.item_name])
self.assert_result(l, *data)
objects[4].item_name = 'item4updated'
# the reorganization of mapper construction affected this, but was fixed again
m = mapper(Item, items, properties = dict(
keywords = relation(mapper(IKAssociation, itemkeywords, properties = dict(
- keyword = relation(mapper(Keyword, keywords, non_primary=True), lazy = False, uselist = False)
+ keyword = relation(mapper(Keyword, keywords, non_primary=True), lazy = False, uselist = False, order_by=keywords.c.name)
), primary_key = [itemkeywords.c.item_id, itemkeywords.c.keyword_id]),
lazy = False)
))
ctx.current.flush()
ctx.current.clear()
- l = Query(m).select(items.c.item_name.in_(*[e['item_name'] for e in data[1:]]), order_by=[items.c.item_name, keywords.c.name])
+ l = Query(m).select(items.c.item_name.in_(*[e['item_name'] for e in data[1:]]), order_by=[items.c.item_name])
self.assert_result(l, *data)
def testm2mmultitable(self):
}]
item_keyword_result = [
-{'item_id' : 1, 'keywords' : (Keyword, [{'keyword_id' : 2}, {'keyword_id' : 4}, {'keyword_id' : 6}])},
+{'item_id' : 1, 'keywords' : (Keyword, [{'keyword_id' : 2, 'name':'red'}, {'keyword_id' : 4, 'name':'big'}, {'keyword_id' : 6, 'name':'round'}])},
{'item_id' : 2, 'keywords' : (Keyword, [{'keyword_id' : 2, 'name':'red'}, {'keyword_id' : 5, 'name':'small'}, {'keyword_id' : 7, 'name':'square'}])},
{'item_id' : 3, 'keywords' : (Keyword, [{'keyword_id' : 3,'name':'green'}, {'keyword_id' : 4,'name':'big'}, {'keyword_id' : 6,'name':'round'}])},
{'item_id' : 4, 'keywords' : (Keyword, [])},
{'item_id' : 5, 'keywords' : (Keyword, [])}
]
+order_result = [
+{'order_id' : 1, 'items':(Item, [])},
+{'order_id' : 2, 'items':(Item, [
+ {'item_id' : 1, 'keywords' : (Keyword, [{'keyword_id' : 2}, {'keyword_id' : 4}, {'keyword_id' : 6}])},
+ {'item_id' : 2, 'keywords' : (Keyword, [{'keyword_id' : 2, 'name':'red'}, {'keyword_id' : 5, 'name':'small'}, {'keyword_id' : 7, 'name':'square'}])},
+ ])},
+{'order_id' : 3, 'items':(Item, [
+ {'item_id' : 3, 'keywords' : (Keyword, [{'keyword_id' : 3,'name':'green'}, {'keyword_id' : 4,'name':'big'}, {'keyword_id' : 6,'name':'round'}])},
+ {'item_id' : 4, 'keywords' : (Keyword, [])},
+ {'item_id' : 5, 'keywords' : (Keyword, [])}
+ ])},
+{'order_id' : 4, 'items':(Item, [])},
+{'order_id' : 5, 'items':(Item, [])},
+]
#db.echo = True