From: Mike Bayer Date: Mon, 12 Oct 2009 22:29:08 +0000 (+0000) Subject: - `expression.null()` is fully understood the same way X-Git-Tag: rel_0_6beta1~257 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=87824331c6f455a32e1e48a0bac5dcb3d77d551f;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - `expression.null()` is fully understood the same way None is when comparing an object/collection-referencing attribute within query.filter(), filter_by(), etc. [ticket:1415] --- diff --git a/CHANGES b/CHANGES index f6d3ef5e60..aec67f28c0 100644 --- a/CHANGES +++ b/CHANGES @@ -42,6 +42,11 @@ CHANGES - the "dont_load=True" flag on Session.merge() is deprecated and is now "load=False". + - `expression.null()` is fully understood the same way + None is when comparing an object/collection-referencing + attribute within query.filter(), filter_by(), etc. + [ticket:1415] + - many-to-one relations now fire off a lazyload in fewer cases, including in most cases will not fetch the "old" value when a new one is replaced. diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index f49f5fe88a..b99ce093a5 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -23,6 +23,7 @@ from sqlalchemy.orm.interfaces import ( MANYTOMANY, MANYTOONE, MapperProperty, ONETOMANY, PropComparator, StrategizedProperty, ) +from types import NoneType __all__ = ('ColumnProperty', 'CompositeProperty', 'SynonymProperty', 'ComparableProperty', 'RelationProperty', 'BackRef') @@ -471,7 +472,7 @@ class RelationProperty(StrategizedProperty): __hash__ = None def __eq__(self, other): - if other is None: + if isinstance(other, (NoneType, expression._Null)): if self.property.direction in [ONETOMANY, MANYTOMANY]: return ~self._criterion_exists() else: @@ -581,7 +582,7 @@ class RelationProperty(StrategizedProperty): return ~self._criterion_exists(criterion) def __ne__(self, other): - if other is None: + if isinstance(other, (NoneType, expression._Null)): if self.property.direction == MANYTOONE: return sql.or_(*[x!=None for x in self.property._foreign_keys]) else: diff --git a/test/orm/test_query.py b/test/orm/test_query.py index 0ec2b998d9..a9319608dc 100644 --- a/test/orm/test_query.py +++ b/test/orm/test_query.py @@ -737,6 +737,7 @@ class FilterTest(QueryTest): # generates an IS NULL assert [] == sess.query(Address).filter(Address.user == None).all() + assert [] == sess.query(Address).filter(Address.user == null()).all() assert [Order(id=5)] == sess.query(Order).filter(Order.address == None).all() @@ -755,17 +756,32 @@ class FilterTest(QueryTest): # many to one generates IS NULL assert [] == sess.query(Address).filter_by(user = None).all() + assert [] == sess.query(Address).filter_by(user = null()).all() # one to many generates WHERE NOT EXISTS assert [User(name='chuck')] == sess.query(User).filter_by(addresses = None).all() + assert [User(name='chuck')] == sess.query(User).filter_by(addresses = null()).all() def test_none_comparison(self): sess = create_session() + # scalar + eq_( + [Order(description="order 5")], + sess.query(Order).filter(Order.address_id==None).all() + ) + eq_( + [Order(description="order 5")], + sess.query(Order).filter(Order.address_id==null()).all() + ) + # o2o eq_([Address(id=1), Address(id=3), Address(id=4)], sess.query(Address).filter(Address.dingaling==None).order_by(Address.id).all()) + eq_([Address(id=1), Address(id=3), Address(id=4)], + sess.query(Address).filter(Address.dingaling==null()).order_by(Address.id).all()) eq_([Address(id=2), Address(id=5)], sess.query(Address).filter(Address.dingaling != None).order_by(Address.id).all()) + eq_([Address(id=2), Address(id=5)], sess.query(Address).filter(Address.dingaling != null()).order_by(Address.id).all()) # m2o eq_([Order(id=5)], sess.query(Order).filter(Order.address==None).all())