]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- New Query methods: query.label(name), query.as_scalar(),
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 23 Oct 2010 17:07:56 +0000 (13:07 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 23 Oct 2010 17:07:56 +0000 (13:07 -0400)
return the query's statement as a scalar subquery
with /without label [ticket:1920];
query.with_entities(*ent), replaces the SELECT list of
the query with new entities.
Roughly equivalent to a generative form of query.values()
which accepts mapped entities as well as column
expressions.

CHANGES
lib/sqlalchemy/orm/query.py
test/orm/test_query.py

diff --git a/CHANGES b/CHANGES
index 97a3cceb9b1c16b5cc4c5459049ab612519f83d8..c48e5b2dc193181f236ba6258b19e86374639be0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -14,6 +14,15 @@ CHANGES
     the session isn't available, and straight 'select'
     loading, not 'joined' or 'subquery', is desired.
     [ticket:1914]
+  
+  - New Query methods: query.label(name), query.as_scalar(),
+    return the query's statement as a scalar subquery
+    with /without label [ticket:1920];
+    query.with_entities(*ent), replaces the SELECT list of 
+    the query with new entities. 
+    Roughly equivalent to a generative form of query.values()
+    which accepts mapped entities as well as column 
+    expressions.
     
   - Fixed recursion bug which could occur when moving
     an object from one reference to another, with 
index 17603e04a435e695eee14a9de42c01c2fd2b8f7e..a1ed19243948e9589994fd3a6f1fb1c849715603 100644 (file)
@@ -425,8 +425,8 @@ class Query(object):
         return stmt._annotate({'_halt_adapt': True})
 
     def subquery(self):
-        """return the full SELECT statement represented by this Query
-        embedded within an Alias.
+        """return the full SELECT statement represented by this :class:`.Query`
+        embedded within an :class:`.Alias`.
 
         Eager JOIN generation within the query is disabled.
 
@@ -436,7 +436,33 @@ class Query(object):
 
         """
         return self.enable_eagerloads(False).statement.alias()
+    
+    def label(self, name):
+        """Return the full SELECT statement represented by this :class:`.Query`, converted 
+        to a scalar subquery with a label of the given name.
+        
+        Analagous to :meth:`sqlalchemy.sql._SelectBaseMixin.label`.
+        
+        New in 0.6.5.
+
+        """
+        
+        return self.enable_eagerloads(False).statement.label(name)
+
 
+    def as_scalar(self):
+        """Return the full SELECT statement represented by this :class:`.Query`, converted 
+        to a scalar subquery.
+        
+        Analagous to :meth:`sqlalchemy.sql._SelectBaseMixin.as_scalar`.
+
+        New in 0.6.5.
+        
+        """
+        
+        return self.enable_eagerloads(False).statement.as_scalar()
+        
+        
     def __clause_element__(self):
         return self.enable_eagerloads(False).with_labels().statement
 
@@ -758,7 +784,36 @@ class Query(object):
             # end Py2K
         except StopIteration:
             return None
+    
+    @_generative()
+    def with_entities(self, *entities):
+        """Return a new :class:`.Query` replacing the SELECT list with the given
+        entities.
+        
+        e.g.::
+
+            # Users, filtered on some arbitrary criterion
+            # and then ordered by related email address
+            q = session.query(User).\\
+                        join(User.address).\\
+                        filter(User.name.like.('%ed%')).\\
+                        order_by(Address.email)
 
+            # given *only* User.id==5, Address.email, and 'q', what 
+            # would the *next* User in the result be ?
+            subq = q.with_entities(Address.email).\\
+                        order_by(None).\\
+                        filter(User.id==5).\\
+                        subquery()
+            q = q.join((subq, subq.c.email < Address.email)).\\
+                        limit(1)
+
+        New in 0.6.5.
+        
+        """
+        self._set_entities(entities)
+        
+        
     @_generative()
     def add_columns(self, *column):
         """Add one or more column expressions to the list 
index a812035ebf16765e55c3e041c70246302b5ead68..d96fa7384615b8630e567d39aa75873065b30698 100644 (file)
@@ -664,6 +664,29 @@ class ExpressionTest(QueryTest, AssertsCompiledSQL):
         q = session.query(User).filter(User.id==q)
         
         eq_(User(id=7), q.one())
+    
+    def test_label(self):
+        session = create_session()
+
+        q = session.query(User.id).filter(User.id==7).label('foo')
+        self.assert_compile(
+            session.query(q), 
+            "SELECT (SELECT users.id FROM users WHERE users.id = :id_1) AS foo", 
+            use_default_dialect=True
+        )
+    
+    def test_as_scalar(self):
+        session = create_session()
+
+        q = session.query(User.id).filter(User.id==7).as_scalar()
+        
+        self.assert_compile(session.query(User).filter(User.id.in_(q)),
+                            'SELECT users.id AS users_id, users.name '
+                            'AS users_name FROM users WHERE users.id '
+                            'IN (SELECT users.id FROM users WHERE '
+                            'users.id = :id_1)',
+                            use_default_dialect=True)
+        
         
     def test_param_transfer(self):
         session = create_session()
@@ -2863,18 +2886,34 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
         eq_(list(q2), [(u'jack',), (u'ed',)])
     
         q = sess.query(User)
-        q2 = q.order_by(User.id).values(User.name, User.name + " " + cast(User.id, String(50)))
-        eq_(list(q2), [(u'jack', u'jack 7'), (u'ed', u'ed 8'), (u'fred', u'fred 9'), (u'chuck', u'chuck 10')])
-    
-        q2 = q.join('addresses').filter(User.name.like('%e%')).order_by(User.id, Address.id).values(User.name, Address.email_address)
-        eq_(list(q2), [(u'ed', u'ed@wood.com'), (u'ed', u'ed@bettyboop.com'), (u'ed', u'ed@lala.com'), (u'fred', u'fred@fred.com')])
-    
-        q2 = q.join('addresses').filter(User.name.like('%e%')).order_by(desc(Address.email_address)).slice(1, 3).values(User.name, Address.email_address)
+        q2 = q.order_by(User.id).\
+                values(User.name, User.name + " " + cast(User.id, String(50)))
+        eq_(
+            list(q2), 
+            [(u'jack', u'jack 7'), (u'ed', u'ed 8'), 
+            (u'fred', u'fred 9'), (u'chuck', u'chuck 10')]
+        )
+    
+        q2 = q.join('addresses').\
+                filter(User.name.like('%e%')).\
+                order_by(User.id, Address.id).\
+                values(User.name, Address.email_address)
+        eq_(list(q2), 
+                [(u'ed', u'ed@wood.com'), (u'ed', u'ed@bettyboop.com'), 
+                (u'ed', u'ed@lala.com'), (u'fred', u'fred@fred.com')])
+    
+        q2 = q.join('addresses').\
+                filter(User.name.like('%e%')).\
+                order_by(desc(Address.email_address)).\
+                slice(1, 3).values(User.name, Address.email_address)
         eq_(list(q2), [(u'ed', u'ed@wood.com'), (u'ed', u'ed@lala.com')])
     
         adalias = aliased(Address)
-        q2 = q.join(('addresses', adalias)).filter(User.name.like('%e%')).values(User.name, adalias.email_address)
-        eq_(list(q2), [(u'ed', u'ed@wood.com'), (u'ed', u'ed@bettyboop.com'), (u'ed', u'ed@lala.com'), (u'fred', u'fred@fred.com')])
+        q2 = q.join(('addresses', adalias)).\
+                filter(User.name.like('%e%')).\
+                values(User.name, adalias.email_address)
+        eq_(list(q2), [(u'ed', u'ed@wood.com'), (u'ed', u'ed@bettyboop.com'), 
+                        (u'ed', u'ed@lala.com'), (u'fred', u'fred@fred.com')])
     
         q2 = q.values(func.count(User.name))
         assert q2.next() == (4,)
@@ -2883,11 +2922,15 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
         eq_(list(q2), [(u'ed', u'ed', u'ed')])
 
         # using User.xxx is alised against "sel", so this query returns nothing
-        q2 = q.select_from(sel).filter(User.id==8).filter(User.id>sel.c.id).values(User.name, sel.c.name, User.name)
+        q2 = q.select_from(sel).\
+                filter(User.id==8).\
+                filter(User.id>sel.c.id).values(User.name, sel.c.name, User.name)
         eq_(list(q2), [])
 
         # whereas this uses users.c.xxx, is not aliased and creates a new join
-        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)
+        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)
         eq_(list(q2), [(u'ed', u'jack', u'jack')])
 
     @testing.fails_on('mssql', 'FIXME: unknown')
@@ -2899,19 +2942,34 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
         sel = users.select(User.id.in_([7, 8])).alias()
         q = sess.query(User)
         u2 = aliased(User)
-        q2 = q.select_from(sel).filter(u2.id>1).order_by(User.id, sel.c.id, u2.id).values(User.name, sel.c.name, u2.name)
-        eq_(list(q2), [(u'jack', u'jack', u'jack'), (u'jack', u'jack', u'ed'), (u'jack', u'jack', u'fred'), (u'jack', u'jack', u'chuck'), (u'ed', u'ed', u'jack'), (u'ed', u'ed', u'ed'), (u'ed', u'ed', u'fred'), (u'ed', u'ed', u'chuck')])
+        q2 = q.select_from(sel).\
+                    filter(u2.id>1).\
+                    order_by(User.id, sel.c.id, u2.id).\
+                    values(User.name, sel.c.name, u2.name)
+        eq_(list(q2), [(u'jack', u'jack', u'jack'), (u'jack', u'jack', u'ed'), 
+                        (u'jack', u'jack', u'fred'), (u'jack', u'jack', u'chuck'), 
+                        (u'ed', u'ed', u'jack'), (u'ed', u'ed', u'ed'), 
+                        (u'ed', u'ed', u'fred'), (u'ed', u'ed', u'chuck')])
 
     @testing.fails_on('mssql', 'FIXME: unknown')
-    @testing.fails_on('oracle', "Oracle doesn't support boolean expressions as columns")
-    @testing.fails_on('postgresql+pg8000', "pg8000 parses the SQL itself before passing on to PG, doesn't parse this")
-    @testing.fails_on('postgresql+zxjdbc', "zxjdbc parses the SQL itself before passing on to PG, doesn't parse this")
+    @testing.fails_on('oracle',
+                      "Oracle doesn't support boolean expressions as "
+                      "columns")
+    @testing.fails_on('postgresql+pg8000',
+                      "pg8000 parses the SQL itself before passing on "
+                      "to PG, doesn't parse this")
+    @testing.fails_on('postgresql+zxjdbc',
+                      "zxjdbc parses the SQL itself before passing on "
+                      "to PG, doesn't parse this")
     def test_values_with_boolean_selects(self):
-        """Tests a values clause that works with select boolean evaluations"""
+        """Tests a values clause that works with select boolean
+        evaluations"""
         sess = create_session()
 
         q = sess.query(User)
-        q2 = q.group_by(User.name.like('%j%')).order_by(desc(User.name.like('%j%'))).values(User.name.like('%j%'), func.count(User.name.like('%j%')))
+        q2 = q.group_by(User.name.like('%j%')).\
+                    order_by(desc(User.name.like('%j%'))).\
+                    values(User.name.like('%j%'), func.count(User.name.like('%j%')))
         eq_(list(q2), [(True, 1), (False, 3)])
 
         q2 = q.order_by(desc(User.name.like('%j%'))).values(User.name.like('%j%'))
@@ -2933,7 +2991,8 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
         # we don't want Address to be outside of the subquery here
         eq_(
             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)]
+            [(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
@@ -2945,7 +3004,8 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
         # we don't want Address to be outside of the subquery here
         eq_(
             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)]
+            [(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):
@@ -3016,30 +3076,47 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
             (u'fred', u'fred@fred.com')
         ])
     
-        eq_(sess.query(User.name, func.count(Address.email_address)).outerjoin(User.addresses).group_by(User.id, User.name).order_by(User.id).all(), 
+        eq_(sess.query(User.name, func.count(Address.email_address)).\
+                    outerjoin(User.addresses).group_by(User.id, User.name).\
+                    order_by(User.id).all(), 
             [(u'jack', 1), (u'ed', 3), (u'fred', 1), (u'chuck', 0)]
         )
 
-        eq_(sess.query(User, func.count(Address.email_address)).outerjoin(User.addresses).group_by(User).order_by(User.id).all(), 
-            [(User(name='jack',id=7), 1), (User(name='ed',id=8), 3), (User(name='fred',id=9), 1), (User(name='chuck',id=10), 0)]
+        eq_(sess.query(User, func.count(Address.email_address)).\
+                    outerjoin(User.addresses).group_by(User).\
+                    order_by(User.id).all(), 
+            [(User(name='jack',id=7), 1), (User(name='ed',id=8), 3), 
+            (User(name='fred',id=9), 1), (User(name='chuck',id=10), 0)]
         )
 
-        eq_(sess.query(func.count(Address.email_address), User).outerjoin(User.addresses).group_by(User).order_by(User.id).all(), 
-            [(1, User(name='jack',id=7)), (3, User(name='ed',id=8)), (1, User(name='fred',id=9)), (0, User(name='chuck',id=10))]
+        eq_(sess.query(func.count(Address.email_address), User).\
+                outerjoin(User.addresses).group_by(User).\
+                order_by(User.id).all(), 
+            [(1, User(name='jack',id=7)), (3, User(name='ed',id=8)), 
+            (1, User(name='fred',id=9)), (0, User(name='chuck',id=10))]
         )
     
         adalias = aliased(Address)
-        eq_(sess.query(User, func.count(adalias.email_address)).outerjoin(('addresses', adalias)).group_by(User).order_by(User.id).all(), 
-            [(User(name='jack',id=7), 1), (User(name='ed',id=8), 3), (User(name='fred',id=9), 1), (User(name='chuck',id=10), 0)]
+        eq_(sess.query(User, func.count(adalias.email_address)).\
+                outerjoin(('addresses', adalias)).group_by(User).\
+                order_by(User.id).all(), 
+            [(User(name='jack',id=7), 1), (User(name='ed',id=8), 3), 
+            (User(name='fred',id=9), 1), (User(name='chuck',id=10), 0)]
         )
 
-        eq_(sess.query(func.count(adalias.email_address), User).outerjoin((User.addresses, adalias)).group_by(User).order_by(User.id).all(),
-            [(1, User(name=u'jack',id=7)), (3, User(name=u'ed',id=8)), (1, User(name=u'fred',id=9)), (0, User(name=u'chuck',id=10))]
+        eq_(sess.query(func.count(adalias.email_address), User).\
+                outerjoin((User.addresses, adalias)).group_by(User).\
+                order_by(User.id).all(),
+            [(1, User(name=u'jack',id=7)), (3, User(name=u'ed',id=8)), 
+                (1, User(name=u'fred',id=9)), (0, User(name=u'chuck',id=10))]
         )
 
         # select from aliasing + explicit aliasing
         eq_(
-            sess.query(User, adalias.email_address, adalias.id).outerjoin((User.addresses, adalias)).from_self(User, adalias.email_address).order_by(User.id, adalias.id).all(),
+            sess.query(User, adalias.email_address, adalias.id).\
+                    outerjoin((User.addresses, adalias)).\
+                    from_self(User, adalias.email_address).\
+                    order_by(User.id, adalias.id).all(),
             [
                 (User(name=u'jack',id=7), u'jack@bean.com'), 
                 (User(name=u'ed',id=8), u'ed@wood.com'), 
@@ -3052,7 +3129,9 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
     
         # anon + select from aliasing
         eq_(
-            sess.query(User).join(User.addresses, aliased=True).filter(Address.email_address.like('%ed%')).from_self().all(),
+            sess.query(User).join(User.addresses, aliased=True).\
+                    filter(Address.email_address.like('%ed%')).\
+                    from_self().all(),
             [
                 User(name=u'ed',id=8), 
                 User(name=u'fred',id=9), 
@@ -3061,26 +3140,39 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
 
         # test eager aliasing, with/without select_from aliasing
         for q in [
-            sess.query(User, adalias.email_address).outerjoin((User.addresses, adalias)).options(joinedload(User.addresses)).order_by(User.id, adalias.id).limit(10),
-            sess.query(User, adalias.email_address, adalias.id).outerjoin((User.addresses, adalias)).from_self(User, adalias.email_address).options(joinedload(User.addresses)).order_by(User.id, adalias.id).limit(10),
+            sess.query(User, adalias.email_address).\
+                    outerjoin((User.addresses, adalias)).\
+                    options(joinedload(User.addresses)).\
+                    order_by(User.id, adalias.id).limit(10),
+            sess.query(User, adalias.email_address, adalias.id).\
+                    outerjoin((User.addresses, adalias)).\
+                    from_self(User, adalias.email_address).\
+                    options(joinedload(User.addresses)).\
+                    order_by(User.id, adalias.id).limit(10),
         ]:
             eq_(
 
                 q.all(),
-                [(User(addresses=[Address(user_id=7,email_address=u'jack@bean.com',id=1)],name=u'jack',id=7), u'jack@bean.com'), 
+                [(User(addresses=[
+                            Address(user_id=7,email_address=u'jack@bean.com',id=1)],
+                            name=u'jack',id=7), u'jack@bean.com'), 
                 (User(addresses=[
                                     Address(user_id=8,email_address=u'ed@wood.com',id=2), 
                                     Address(user_id=8,email_address=u'ed@bettyboop.com',id=3), 
-                                    Address(user_id=8,email_address=u'ed@lala.com',id=4)],name=u'ed',id=8), u'ed@wood.com'), 
+                                    Address(user_id=8,email_address=u'ed@lala.com',id=4)],
+                                        name=u'ed',id=8), u'ed@wood.com'), 
                 (User(addresses=[
                             Address(user_id=8,email_address=u'ed@wood.com',id=2), 
                             Address(user_id=8,email_address=u'ed@bettyboop.com',id=3), 
-                            Address(user_id=8,email_address=u'ed@lala.com',id=4)],name=u'ed',id=8), u'ed@bettyboop.com'), 
+                            Address(user_id=8,email_address=u'ed@lala.com',id=4)],name=u'ed',id=8), 
+                                        u'ed@bettyboop.com'), 
                 (User(addresses=[
                             Address(user_id=8,email_address=u'ed@wood.com',id=2), 
                             Address(user_id=8,email_address=u'ed@bettyboop.com',id=3), 
-                            Address(user_id=8,email_address=u'ed@lala.com',id=4)],name=u'ed',id=8), u'ed@lala.com'), 
-                (User(addresses=[Address(user_id=9,email_address=u'fred@fred.com',id=5)],name=u'fred',id=9), u'fred@fred.com'), 
+                            Address(user_id=8,email_address=u'ed@lala.com',id=4)],name=u'ed',id=8), 
+                                        u'ed@lala.com'), 
+                (User(addresses=[Address(user_id=9,email_address=u'fred@fred.com',id=5)],name=u'fred',id=9), 
+                                        u'fred@fred.com'), 
 
                 (User(addresses=[],name=u'chuck',id=10), None)]
         )
@@ -3089,7 +3181,9 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
         sess = create_session()
     
         def go():
-            results = sess.query(User).limit(1).options(joinedload('addresses')).add_column(User.name).all()
+            results = sess.query(User).limit(1).\
+                        options(joinedload('addresses')).\
+                        add_column(User.name).all()
             eq_(results, [(User(name='jack'), 'jack')])
         self.assert_sql_count(testing.db, go, 1)
     
@@ -3100,26 +3194,41 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
         oalias = aliased(Order)
 
         for q in [
-            sess.query(Order, oalias).filter(Order.user_id==oalias.user_id).filter(Order.user_id==7).filter(Order.id>oalias.id).order_by(Order.id, oalias.id),
-            sess.query(Order, oalias).from_self().filter(Order.user_id==oalias.user_id).filter(Order.user_id==7).filter(Order.id>oalias.id).order_by(Order.id, oalias.id),
+            sess.query(Order, oalias).\
+                    filter(Order.user_id==oalias.user_id).filter(Order.user_id==7).\
+                    filter(Order.id>oalias.id).order_by(Order.id, oalias.id),
+            sess.query(Order, oalias).from_self().filter(Order.user_id==oalias.user_id).\
+                    filter(Order.user_id==7).filter(Order.id>oalias.id).\
+                    order_by(Order.id, oalias.id),
         
             # same thing, but reversed.  
-            sess.query(oalias, Order).from_self().filter(oalias.user_id==Order.user_id).filter(oalias.user_id==7).filter(Order.id<oalias.id).order_by(oalias.id, Order.id),
+            sess.query(oalias, Order).from_self().filter(oalias.user_id==Order.user_id).\
+                            filter(oalias.user_id==7).filter(Order.id<oalias.id).\
+                            order_by(oalias.id, Order.id),
         
             # here we go....two layers of aliasing
-            sess.query(Order, oalias).filter(Order.user_id==oalias.user_id).filter(Order.user_id==7).filter(Order.id>oalias.id).from_self().order_by(Order.id, oalias.id).limit(10).options(joinedload(Order.items)),
+            sess.query(Order, oalias).filter(Order.user_id==oalias.user_id).\
+                            filter(Order.user_id==7).filter(Order.id>oalias.id).\
+                            from_self().order_by(Order.id, oalias.id).\
+                            limit(10).options(joinedload(Order.items)),
 
             # gratuitous four layers
-            sess.query(Order, oalias).filter(Order.user_id==oalias.user_id).filter(Order.user_id==7).filter(Order.id>oalias.id).from_self().from_self().from_self().order_by(Order.id, oalias.id).limit(10).options(joinedload(Order.items)),
+            sess.query(Order, oalias).filter(Order.user_id==oalias.user_id).\
+                            filter(Order.user_id==7).filter(Order.id>oalias.id).from_self().\
+                            from_self().from_self().order_by(Order.id, oalias.id).\
+                            limit(10).options(joinedload(Order.items)),
 
         ]:
     
             eq_(
             q.all(),
             [
-                (Order(address_id=1,description=u'order 3',isopen=1,user_id=7,id=3), Order(address_id=1,description=u'order 1',isopen=0,user_id=7,id=1)), 
-                (Order(address_id=None,description=u'order 5',isopen=0,user_id=7,id=5), Order(address_id=1,description=u'order 1',isopen=0,user_id=7,id=1)), 
-                (Order(address_id=None,description=u'order 5',isopen=0,user_id=7,id=5), Order(address_id=1,description=u'order 3',isopen=1,user_id=7,id=3))                
+                (Order(address_id=1,description=u'order 3',isopen=1,user_id=7,id=3), 
+                        Order(address_id=1,description=u'order 1',isopen=0,user_id=7,id=1)), 
+                (Order(address_id=None,description=u'order 5',isopen=0,user_id=7,id=5), 
+                        Order(address_id=1,description=u'order 1',isopen=0,user_id=7,id=1)), 
+                (Order(address_id=None,description=u'order 5',isopen=0,user_id=7,id=5), 
+                        Order(address_id=1,description=u'order 3',isopen=1,user_id=7,id=3))                
             ]
         )
         
@@ -3127,10 +3236,16 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
         # ensure column expressions are taken from inside the subquery, not restated at the top
         q = sess.query(Order.id, Order.description, literal_column("'q'").label('foo')).\
             filter(Order.description == u'order 3').from_self()
-        self.assert_compile(q, 
-            "SELECT anon_1.orders_id AS anon_1_orders_id, anon_1.orders_description AS anon_1_orders_description, "
-            "anon_1.foo AS anon_1_foo FROM (SELECT orders.id AS orders_id, orders.description AS orders_description, "
-            "'q' AS foo FROM orders WHERE orders.description = :description_1) AS anon_1", use_default_dialect=True)
+        self.assert_compile(q,
+                            "SELECT anon_1.orders_id AS "
+                            "anon_1_orders_id, anon_1.orders_descriptio"
+                            "n AS anon_1_orders_description, "
+                            "anon_1.foo AS anon_1_foo FROM (SELECT "
+                            "orders.id AS orders_id, "
+                            "orders.description AS orders_description, "
+                            "'q' AS foo FROM orders WHERE "
+                            "orders.description = :description_1) AS "
+                            "anon_1", use_default_dialect=True)
         eq_(
             q.all(),
             [(3, u'order 3', 'q')]
@@ -3142,7 +3257,8 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
         test_session = create_session()
 
         (user7, user8, user9, user10) = test_session.query(User).all()
-        (address1, address2, address3, address4, address5) = test_session.query(Address).all()
+        (address1, address2, address3, address4, address5) = \
+                        test_session.query(Address).all()
 
         expected = [(user7, address1),
             (user8, address2),
@@ -3158,7 +3274,9 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
         sess.expunge_all()
 
         for address_entity in (Address, aliased(Address)):
-            q = sess.query(User).add_entity(address_entity).outerjoin(('addresses', address_entity)).order_by(User.id, address_entity.id)
+            q = sess.query(User).add_entity(address_entity).\
+                            outerjoin(('addresses', address_entity)).\
+                            order_by(User.id, address_entity.id)
             eq_(q.all(), expected)
             sess.expunge_all()
 
@@ -3167,11 +3285,14 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
             eq_(q.all(), [(user8, address3)])
             sess.expunge_all()
 
-            q = sess.query(User, address_entity).join(('addresses', address_entity)).filter_by(email_address='ed@bettyboop.com')
+            q = sess.query(User, address_entity).join(('addresses', address_entity)).\
+                                    filter_by(email_address='ed@bettyboop.com')
             eq_(q.all(), [(user8, address3)])
             sess.expunge_all()
 
-            q = sess.query(User, address_entity).join(('addresses', address_entity)).options(joinedload('addresses')).filter_by(email_address='ed@bettyboop.com')
+            q = sess.query(User, address_entity).join(('addresses', address_entity)).\
+                                    options(joinedload('addresses')).\
+                                    filter_by(email_address='ed@bettyboop.com')
             eq_(list(util.OrderedSet(q.all())), [(user8, address3)])
             sess.expunge_all()
 
@@ -3200,6 +3321,24 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
         l = q.select_from(users.outerjoin(adalias)).filter(adalias.c.email_address=='ed@bettyboop.com').all()
         assert l == [(user8, address3)]
 
+    def test_with_entities(self):
+        sess = create_session()
+        
+        q = sess.query(User).filter(User.id==7).order_by(User.name)
+        
+        self.assert_compile(
+            q.with_entities(User.id,Address).\
+                    filter(Address.user_id == User.id),
+                    'SELECT users.id AS users_id, addresses.id '
+                    'AS addresses_id, addresses.user_id AS '
+                    'addresses_user_id, addresses.email_address'
+                    ' AS addresses_email_address FROM users, '
+                    'addresses WHERE users.id = :id_1 AND '
+                    'addresses.user_id = users.id ORDER BY '
+                    'users.name', 
+                use_default_dialect=True)
+        
+        
     def test_multi_columns(self):
         sess = create_session()
 
@@ -3233,18 +3372,22 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
             ]
 
         q = sess.query(User)
-        q = q.group_by(users).order_by(User.id).outerjoin('addresses').add_column(func.count(Address.id).label('count'))
+        q = q.group_by(users).order_by(User.id).outerjoin('addresses').\
+                                add_column(func.count(Address.id).label('count'))
         eq_(q.all(), expected)
         sess.expunge_all()
     
         adalias = aliased(Address)
         q = sess.query(User)
-        q = q.group_by(users).order_by(User.id).outerjoin(('addresses', adalias)).add_column(func.count(adalias.id).label('count'))
+        q = q.group_by(users).order_by(User.id).outerjoin(('addresses', adalias)).\
+                                add_column(func.count(adalias.id).label('count'))
         eq_(q.all(), expected)
         sess.expunge_all()
 
         # TODO: figure out why group_by(users) doesn't work here
-        s = select([users, func.count(addresses.c.id).label('count')]).select_from(users.outerjoin(addresses)).group_by(*[c for c in users.c]).order_by(User.id)
+        s = select([users, func.count(addresses.c.id).label('count')]).\
+                        select_from(users.outerjoin(addresses)).\
+                        group_by(*[c for c in users.c]).order_by(User.id)
         q = sess.query(User)
         l = q.add_column("count").from_statement(s).all()
         assert l == expected
@@ -3267,7 +3410,10 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
         assert q.all() == expected
 
         # test with a straight statement
-        s = select([users, func.count(addresses.c.id).label('count'), ("Name:" + users.c.name).label('concat')], from_obj=[users.outerjoin(addresses)], group_by=[c for c in users.c], order_by=[users.c.id])
+        s = select([users, func.count(addresses.c.id).label('count'), 
+                            ("Name:" + users.c.name).label('concat')], 
+                            from_obj=[users.outerjoin(addresses)], 
+                            group_by=[c for c in users.c], order_by=[users.c.id])
         q = create_session().query(User)
         l = q.add_column("count").add_column("concat").from_statement(s).all()
         assert l == expected
@@ -4149,7 +4295,10 @@ class ExternalColumnsTest(QueryTest):
     
         mapper(User, users, properties={
             'concat': column_property((users.c.id * 2)),
-            'count': column_property(select([func.count(addresses.c.id)], users.c.id==addresses.c.user_id).correlate(users).as_scalar())
+            'count': column_property(
+                            select([func.count(addresses.c.id)], users.c.id==addresses.c.user_id).\
+                            correlate(users).\
+                            as_scalar())
         })
 
         mapper(Address, addresses, properties={
@@ -4182,7 +4331,10 @@ class ExternalColumnsTest(QueryTest):
         for x in range(2):
             sess.expunge_all()
             def go():
-               eq_(sess.query(Address).options(joinedload('user')).order_by(Address.id).all(), address_result)
+               eq_(sess.query(Address).\
+                            options(joinedload('user')).\
+                            order_by(Address.id).all(), 
+                    address_result)
             self.assert_sql_count(testing.db, go, 1)
     
         ualias = aliased(User)
@@ -4192,7 +4344,10 @@ class ExternalColumnsTest(QueryTest):
         )
 
         eq_(
-                sess.query(Address, ualias.count).join(('user', ualias)).join('user', aliased=True).order_by(Address.id).all(),
+                sess.query(Address, ualias.count).\
+                            join(('user', ualias)).\
+                            join('user', aliased=True).\
+                            order_by(Address.id).all(),
                 [
                     (Address(id=1), 1),
                     (Address(id=2), 3),