summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2007-10-17 16:49:15 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2007-10-17 16:49:15 +0000
commitcb9321116fcdf350461410a5ecf8b892cfa210a5 (patch)
tree6f489d75696e996d38c473e0154caa8156bf7f9f
parent14c9d63672346adb59adfebb60660668771f20e4 (diff)
downloadsqlalchemy-cb9321116fcdf350461410a5ecf8b892cfa210a5.tar.gz
- 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]
-rw-r--r--CHANGES4
-rw-r--r--lib/sqlalchemy/orm/dynamic.py7
-rw-r--r--test/orm/dynamic.py13
-rw-r--r--test/testlib/fixtures.py7
4 files changed, 22 insertions, 9 deletions
diff --git a/CHANGES b/CHANGES
index a09d22be6..85ffc40de 100644
--- 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]
diff --git a/lib/sqlalchemy/orm/dynamic.py b/lib/sqlalchemy/orm/dynamic.py
index 1b91bd977..993756ede 100644
--- a/lib/sqlalchemy/orm/dynamic.py
+++ b/lib/sqlalchemy/orm/dynamic.py
@@ -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:
diff --git a/test/orm/dynamic.py b/test/orm/dynamic.py
index 1c294f4fc..7d0d748e3 100644
--- a/test/orm/dynamic.py
+++ b/test/orm/dynamic.py
@@ -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):
diff --git a/test/testlib/fixtures.py b/test/testlib/fixtures.py
index ada254c37..6baf16bf0 100644
--- a/test/testlib/fixtures.py
+++ b/test/testlib/fixtures.py
@@ -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