- the "properties" accessor on Mapper is removed; it now throws an informative
exception explaining the usage of mapper.get_property() and
mapper.iterate_properties
+
+ - added having() method to Query, applies HAVING to the generated statement
+ in the same way as filter() appends to the WHERE clause.
- The behavior of query.options() is now fully based on paths, i.e. an
option such as eagerload_all('x.y.z.y.x') will apply eagerloading to
self._statement = None
self._params = {}
self._criterion = None
+ self._having = None
self._column_aggregate = None
self._joinpoint = self.mapper
self._aliases = None
else:
q._group_by = q._group_by + util.to_list(criterion)
return q
-
+
+ def having(self, criterion):
+ """apply a HAVING criterion to the quer and return the newly resulting ``Query``."""
+
+ if isinstance(criterion, basestring):
+ criterion = sql.text(criterion)
+
+ if criterion is not None and not isinstance(criterion, sql.ClauseElement):
+ raise exceptions.ArgumentError("having() argument must be of type sqlalchemy.sql.ClauseElement or string")
+
+
+ if self._aliases is not None:
+ criterion = self._aliases.adapt_clause(criterion)
+
+ q = self._clone()
+ if q._having is not None:
+ q._having = q._having & criterion
+ else:
+ q._having = criterion
+ return q
+
def join(self, prop, id=None, aliased=False, from_joinpoint=False):
"""create a join of this ``Query`` object's criterion
to a relationship and return the newly resulting ``Query``.
def _select_args(self):
"""Return a dictionary of attributes that can be applied to a ``sql.Select`` statement.
"""
- return {'limit':self._limit, 'offset':self._offset, 'distinct':self._distinct, 'group_by':self._group_by or None}
+ return {'limit':self._limit, 'offset':self._offset, 'distinct':self._distinct, 'group_by':self._group_by or None, 'having':self._having or None}
def _get_entity_clauses(self, m):
sess = create_session()
assert sess.query(Order).apply_sum(Order.user_id * Order.address_id).filter(Order.id.in_([2, 3, 4])).one() == 79
+ def test_having(self):
+ sess = create_session()
+ assert [User(name=u'ed',id=8)] == sess.query(User).group_by([c for c in User.c]).join('addresses').having(func.count(Address.c.id)> 2).all()
+ assert [User(name=u'jack',id=7), User(name=u'fred',id=9)] == sess.query(User).group_by([c for c in User.c]).join('addresses').having(func.count(Address.c.id)< 2).all()
+
class CountTest(QueryTest):
def test_basic(self):
assert 4 == create_session().query(User).count()