collection doesn't contain the item, supports noload collections
[ticket:813]
+- removed __len__ from "dynamic" collection as it would require issuing
+ a SQL "count()" operation, thus forcing all list evaluations to issue
+ redundant SQL [ticket:818]
+
- inline optimizations added to locate_dirty() which can greatly speed up
repeated calls to flush(), as occurs with autoflush=True [ticket:816]
else:
return sess
- def __len__(self):
- sess = self.__session()
- if sess is None:
- return len(self.attr.get_history(self.state)._added_items)
- else:
- return self._clone(sess).count()
-
def __iter__(self):
sess = self.__session()
if sess is None:
assert [User(id=7, addresses=[Address(id=1, email_address='jack@bean.com')])] == q.filter(User.id==7).all()
assert fixtures.user_address_result == q.all()
+ def test_no_count(self):
+ mapper(User, users, properties={
+ 'addresses':dynamic_loader(mapper(Address, addresses))
+ })
+ sess = create_session()
+ q = sess.query(User)
+
+ # dynamic collection cannot implement __len__() (at least one that returns a live database
+ # result), else additional count() queries are issued when evaluating in a list context
+ def go():
+ assert [User(id=7, addresses=[Address(id=1, email_address='jack@bean.com')])] == q.filter(User.id==7).all()
+ self.assert_sql_count(testbase.db, go, 2)
+
class FlushTest(FixtureTest):
def test_basic(self):
class Fixture(Base):
except AttributeError:
#print "Other class does not have attribute named '%s'" % attr
return False
- if len(value) != len(getattr(other, attr)):
+ if not hasattr(value, '__len__'):
+ value = list(iter(value))
+ otherattr = list(iter(otherattr))
+ if len(value) != len(otherattr):
#print "Length of collection '%s' does not match that of other" % attr
return False
- for (us, them) in zip(value, getattr(other, attr)):
+ for (us, them) in zip(value, otherattr):
if us != them:
#print "1. Attribute named '%s' does not match other" % attr
return False