Mike Bayer  committed 1b5d6c4

relation.order_by requires _literal_as_column conversion as well

  • Participants
  • Parent commits f347177
  • Branches default

Comments (0)

Files changed (5)

     - Class-bound attributes sent as arguments to 
       relation()'s remote_side and foreign_keys parameters 
       are now accepted, allowing them to be used with declarative.
+      Additionally fixed bugs involving order_by being
+      specified as a class-bound attribute in conjunction
+      with eager loading.
 - mysql
     - Quoting of MSEnum values for use in CREATE TABLE is now

File lib/sqlalchemy/engine/

 from sqlalchemy import exc, schema, util, types, log
 from sqlalchemy.sql import expression
 class Dialect(object):
     """Define the behavior of a specific database and DB-API combination.
     def _create_key_cache(self):
         # local copies to avoid circular ref against 'self'
         props = self.__props
-        context = self.context
         def lookup_key(key):
             """Given a key, which could be a ColumnElement, string, etc.,
             matches it to the appropriate key we got from the result set's

File lib/sqlalchemy/orm/

             if callable(getattr(self, attr)):
                 setattr(self, attr, getattr(self, attr)())
+        if self.order_by:
+            self.order_by = [expression._literal_as_column(x) for x in util.to_list(self.order_by)]
         self._foreign_keys = set(expression._literal_as_column(x) for x in util.to_set(self._foreign_keys))
         self.remote_side = set(expression._literal_as_column(x) for x in util.to_set(self.remote_side))

File lib/sqlalchemy/orm/

 import weakref
 import sqlalchemy.exceptions as sa_exc
-import sqlalchemy.orm.attributes
 from sqlalchemy import util, sql, engine
 from sqlalchemy.sql import util as sql_util, expression
 from sqlalchemy.orm import (
         """Return a new ``Query`` object corresponding to this ``Session``."""
         return self._query_cls(entities, self, **kwargs)
     def _autoflush(self):
         if self.autoflush and (self.transaction is None or self.transaction.autoflush):
     def expire_all(self):
         """Expires all persistent instances within this Session."""
         for state in self.identity_map.all_states():
             _expire_state(state, None)

File test/ext/

 from sqlalchemy.ext import declarative as decl
 from testlib import sa, testing
-from import MetaData, Table, Column, Integer, String, ForeignKey, ForeignKeyConstraint
-from import relation, create_session, class_mapper
+from import MetaData, Table, Column, Integer, String, ForeignKey, ForeignKeyConstraint, asc
+from import relation, create_session, class_mapper, eagerload
 from testlib.testing import eq_
 from orm._base import ComparableEntity
         a1 = sess.query(Address).filter( == 'two').one()
         eq_(a1, Address(email='two'))
         eq_(a1.user, User(name='u1'))
+    def test_eager_order_by(self):
+        class Address(Base, ComparableEntity):
+            __tablename__ = 'addresses'
+            id = Column('id', Integer, primary_key=True)
+            email = Column('email', String(50))
+            user_id = Column('user_id', Integer, ForeignKey(''))
+        class User(Base, ComparableEntity):
+            __tablename__ = 'users'
+            id = Column('id', Integer, primary_key=True)
+            name = Column('name', String(50))
+            addresses = relation("Address",
+        Base.metadata.create_all()
+        u1 = User(name='u1', addresses=[
+            Address(email='two'),
+            Address(email='one'),
+        ])
+        sess = create_session()
+        sess.flush()
+        sess.clear()
+        eq_(sess.query(User).options(eagerload(User.addresses)).all(), [User(name='u1', addresses=[
+            Address(email='one'),
+            Address(email='two'),
+        ])])
     def test_as_declarative(self):
         class User(ComparableEntity):
             __tablename__ = 'users'