]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- removed __len__ from "dynamic" collection as it would require issuing
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 17 Oct 2007 16:49:15 +0000 (16:49 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 17 Oct 2007 16:49:15 +0000 (16:49 +0000)
  a SQL "count()" operation, thus forcing all list evaluations to issue
  redundant SQL [ticket:818]

CHANGES
lib/sqlalchemy/orm/dynamic.py
test/orm/dynamic.py
test/testlib/fixtures.py

diff --git a/CHANGES b/CHANGES
index a09d22be60643c53a9ce5daf6915638130f7cd54..85ffc40def007f89415dfa31bb21e5e1d7e70012 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -17,6 +17,10 @@ CHANGES
   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]
   
index 1b91bd977cab4e694e89f4ad0b44c507ae9d157c..993756edeb0fa87cf2083a21709ccf12535cfffa 100644 (file)
@@ -71,13 +71,6 @@ class AppenderQuery(Query):
         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:
index 1c294f4fcfea684a797f0cd23ed78b1d19849dd6..7d0d748e3d2041b6531acae01d88337f75010a9b 100644 (file)
@@ -26,6 +26,19 @@ class DynamicTest(QueryTest):
         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):
index ada254c375afb528749e20c057d371f4e1cf090b..6baf16bf07c7317f34b4718138a6aea3fa7887ad 100644 (file)
@@ -42,10 +42,13 @@ class Base(object):
                     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