- Improved the determination of the FROM clause

when placing SQL expressions in the query()
list of entities.  In particular scalar subqueries
should not "leak" their inner FROM objects out
into the enclosing query.
This commit is contained in:
Mike Bayer
2008-08-06 20:58:48 +00:00
parent 665cd4d36a
commit 2829092cb8
4 changed files with 49 additions and 4 deletions
+6
View File
@@ -16,6 +16,12 @@ CHANGES
Column objects such as Query(table.c.col) will
return the "key" attribute of the Column.
- Improved the determination of the FROM clause
when placing SQL expressions in the query()
list of entities. In particular scalar subqueries
should not "leak" their inner FROM objects out
into the enclosing query.
- sql
- Temporarily rolled back the "ORDER BY" enhancement
from [ticket:1068]. This feature is on hold
+13 -2
View File
@@ -1625,11 +1625,22 @@ class _ColumnEntity(_QueryEntity):
self.column = column
self.froms = set()
# look for ORM entities represented within the
# given expression. Try to count only entities
# for columns whos FROM object is in the actual list
# of FROMs for the overall expression - this helps
# subqueries which were built from ORM constructs from
# leaking out their entities into the main select construct
actual_froms = set(column._get_from_objects())
self.entities = util.OrderedSet(
elem._annotations['parententity']
for elem in visitors.iterate(column, {})
if 'parententity' in elem._annotations)
if 'parententity' in elem._annotations
and actual_froms.intersection(elem._get_from_objects())
)
if self.entities:
self.entity_zero = list(self.entities)[0]
else:
-2
View File
@@ -510,7 +510,6 @@ def make_test(select_type):
self.assertEquals(sess.query(Person).filter(Person.person_id==subq).one(), e1)
def test_mixed_entities(self):
sess = create_session()
@@ -537,7 +536,6 @@ def make_test(select_type):
[('pointy haired boss foo', ), ('dogbert foo',)]
)
row = sess.query(Engineer.name, Engineer.primary_language).filter(Engineer.name=='dilbert').first()
assert row.name == 'dilbert'
assert row.primary_language == 'java'
+30
View File
@@ -1207,6 +1207,36 @@ class MixedEntitiesTest(QueryTest):
q2 = q.select_from(sel).filter(users.c.id==8).filter(users.c.id>sel.c.id).values(users.c.name, sel.c.name, User.name)
self.assertEquals(list(q2), [(u'ed', u'jack', u'jack')])
def test_scalar_subquery(self):
"""test that a subquery constructed from ORM attributes doesn't leak out
those entities to the outermost query.
"""
sess = create_session()
subq = select([func.count()]).\
where(User.id==Address.user_id).\
correlate(users).\
label('count')
# we don't want Address to be outside of the subquery here
self.assertEquals(
list(sess.query(User, subq)[0:3]),
[(User(id=7,name=u'jack'), 1), (User(id=8,name=u'ed'), 3), (User(id=9,name=u'fred'), 1)]
)
# same thing without the correlate, as it should
# not be needed
subq = select([func.count()]).\
where(User.id==Address.user_id).\
label('count')
# we don't want Address to be outside of the subquery here
self.assertEquals(
list(sess.query(User, subq)[0:3]),
[(User(id=7,name=u'jack'), 1), (User(id=8,name=u'ed'), 3), (User(id=9,name=u'fred'), 1)]
)
def test_tuple_labeling(self):
sess = create_session()
for row in sess.query(User, Address).join(User.addresses).all():