From 88a799379fa57f4c220c9cbad89cf7d407147d0b Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 3 Jan 2009 20:52:34 +0000 Subject: [PATCH] - query.order_by() accepts None which will remove any pending order_by state from the query, as well as cancel out any mapper/relation configured ordering. This is primarily useful for overriding the ordering specified on a dynamic_loader(). [ticket:1079] --- CHANGES | 8 +++++++- lib/sqlalchemy/orm/query.py | 13 ++++++++----- test/orm/dynamic.py | 12 ++++++++++++ test/orm/mapper.py | 25 ++++++++++++++----------- 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/CHANGES b/CHANGES index e8d6664209..bd0bd870a4 100644 --- a/CHANGES +++ b/CHANGES @@ -40,7 +40,13 @@ CHANGES - dynamic_loader accepts a query_class= to customize the Query classes used for both the dynamic collection and the queries built from it. - + + - query.order_by() accepts None which will remove any pending + order_by state from the query, as well as cancel out any + mapper/relation configured ordering. This is primarily useful + for overriding the ordering specified on a dynamic_loader(). + [ticket:1079] + - sql - RowProxy objects can be used in place of dictionary arguments sent to connection.execute() and friends. [ticket:935] diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index a4e9275e71..e733cc0242 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -653,12 +653,15 @@ class Query(object): def order_by(self, *criterion): """apply one or more ORDER BY criterion to the query and return the newly resulting ``Query``""" - criterion = [self._adapt_clause(expression._literal_as_text(o), True, True) for o in criterion] - - if self._order_by is False: - self._order_by = criterion + if len(criterion) == 1 and criterion[0] is None: + self._order_by = None else: - self._order_by = self._order_by + criterion + criterion = [self._adapt_clause(expression._literal_as_text(o), True, True) for o in criterion] + + if self._order_by is False or self._order_by is None: + self._order_by = criterion + else: + self._order_by = self._order_by + criterion @_generative(__no_statement_condition, __no_limit_offset) @util.accepts_a_list_as_starargs(list_deprecation='pending') diff --git a/test/orm/dynamic.py b/test/orm/dynamic.py index 5c15541401..010999ac54 100644 --- a/test/orm/dynamic.py +++ b/test/orm/dynamic.py @@ -42,6 +42,18 @@ class DynamicTest(_fixtures.FixtureTest): u = sess.query(User).get(8) eq_(list(u.addresses), [Address(email_address=u'ed@wood.com'), Address(email_address=u'ed@lala.com'), Address(email_address=u'ed@bettyboop.com')]) + # test cancellation of None, replacement with something else + eq_( + list(u.addresses.order_by(None).order_by(Address.email_address)), + [Address(email_address=u'ed@bettyboop.com'), Address(email_address=u'ed@lala.com'), Address(email_address=u'ed@wood.com')] + ) + + # test cancellation of None, replacement with nothing + eq_( + set(u.addresses.order_by(None)), + set([Address(email_address=u'ed@bettyboop.com'), Address(email_address=u'ed@lala.com'), Address(email_address=u'ed@wood.com')]) + ) + @testing.resolve_artifact_names def test_count(self): mapper(User, users, properties={ diff --git a/test/orm/mapper.py b/test/orm/mapper.py index d486c3b041..2e6b0fed46 100644 --- a/test/orm/mapper.py +++ b/test/orm/mapper.py @@ -519,20 +519,23 @@ class MapperTest(_fixtures.FixtureTest): eq_(l, [self.static.user_result[0]]) @testing.resolve_artifact_names - def test_order_by(self): - """Ordering at the mapper and query level""" + def test_cancel_order_by(self): + mapper(User, users, order_by=users.c.name.desc()) - # TODO: make a unit test out of these various combinations - #m = mapper(User, users, order_by=desc(users.c.name)) - mapper(User, users, order_by=None) - #mapper(User, users) - - #l = create_session().query(User).select(order_by=[desc(users.c.name), asc(users.c.user_id)]) - l = create_session().query(User).all() - #l = create_session().query(User).select(order_by=[]) - #l = create_session().query(User).select(order_by=None) + assert "order by users.name desc" in str(create_session().query(User).statement).lower() + assert "order by" not in str(create_session().query(User).order_by(None).statement).lower() + assert "order by users.name asc" in str(create_session().query(User).order_by(User.name.asc()).statement).lower() + eq_( + create_session().query(User).all(), + [User(id=7, name=u'jack'), User(id=9, name=u'fred'), User(id=8, name=u'ed'), User(id=10, name=u'chuck')] + ) + eq_( + create_session().query(User).order_by(User.name).all(), + [User(id=10, name=u'chuck'), User(id=8, name=u'ed'), User(id=9, name=u'fred'), User(id=7, name=u'jack')] + ) + # 'Raises a "expression evaluation not supported" error at prepare time @testing.fails_on('firebird', 'FIXME: unknown') @testing.resolve_artifact_names -- 2.47.3