]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- fixed critical issue when, after options(eagerload()) is used,
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 18 Apr 2007 22:33:53 +0000 (22:33 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 18 Apr 2007 22:33:53 +0000 (22:33 +0000)
the mapper would then always apply query "wrapping" behavior
for all subsequent LIMIT/OFFSET/DISTINCT queries, even if no
eager loading was applied on those subsequent queries.

CHANGES
lib/sqlalchemy/orm/interfaces.py
lib/sqlalchemy/orm/strategies.py
test/orm/mapper.py
test/testbase.py

diff --git a/CHANGES b/CHANGES
index 5b65adfe89be734e1a22fc5e1e55cb0e5fc65557..c560f4fe71a713313c42c4b138dc6dceeaddfc48 100644 (file)
--- a/CHANGES
+++ b/CHANGES
     - slight tweak to raw execute() change to also support tuples
       for positional parameters, not just lists [ticket:523]
 - orm:
+    - fixed critical issue when, after options(eagerload()) is used,
+      the mapper would then always apply query "wrapping" behavior
+      for all subsequent LIMIT/OFFSET/DISTINCT queries, even if no
+      eager loading was applied on those subsequent queries.
     - added query.with_parent(someinstance) method.  searches for
       target instance using lazy join criterion from parent instance.
       takes optional string "property" to isolate the desired relation.
index 5c6a92325e47ea1ef85da8d88994ebcc03a75bf5..358e1297f2e42eef165877b34e286276b6abcffb 100644 (file)
@@ -149,8 +149,8 @@ class StrategizedProperty(MapperProperty):
         except KeyError:
             # cache the located strategy per class for faster re-lookup
             strategy = cls(self)
-            strategy.init()
             strategy.is_default = False
+            strategy.init()
             self._all_strategies[cls] = strategy
             return strategy
 
@@ -282,7 +282,7 @@ class LoaderStrategy(object):
     def init(self):
         self.parent = self.parent_property.parent
         self.key = self.parent_property.key
-
+    
     def init_class_attribute(self):
         pass
 
index e9d992d185dd592cc8db885add78906d4a9a603a..ee80b347757585c14fdabb64c638812c0e4129b7 100644 (file)
@@ -317,7 +317,8 @@ class EagerLoader(AbstractRelationLoader):
                 "to child class '%s': Cant use eager loading on a self "
                 "referential relationship." %
                 (self.key, repr(self.parent.class_), repr(self.mapper.class_)))
-        self.parent._eager_loaders.add(self.parent_property)
+        if self.is_default:
+            self.parent._eager_loaders.add(self.parent_property)
 
         self.clauses = {}
         self.clauses_by_lead_mapper = {}
index b2118b64740a24d2cde46cd5e8070021c3f1ddcb..d1c4cf5463a4d92a63e1fe8c5451f28326dc6b98 100644 (file)
@@ -541,6 +541,15 @@ class MapperTest(MapperSuperTest):
             assert len(u.addresses) == 3
         self.assert_sql_count(db, go, 0)
 
+        sess.clear()
+        
+        # test that eager loading doesnt modify parent mapper
+        def go():
+            u = sess.query(User).get_by(user_id=8)
+            assert u.user_id == 8
+            assert len(u.addresses) == 3
+        assert "tbl_row_count" not in self.capture_sql(db, go)
+        
     def testlazyoptionswithlimit(self):
         sess = create_session()
         mapper(User, users, properties = dict(
index aae455673fca326bf77d2f63615ddbda2ff2d061..1bcc5c142dee2a612ae631da0d48e4d09c12be4a 100644 (file)
@@ -224,6 +224,17 @@ class AssertMixin(PersistTest):
         finally:
             self.assert_(testdata.sql_count == count, "desired statement count %d does not match %d" % (count, testdata.sql_count))
 
+    def capture_sql(self, db, callable_):
+        global testdata
+        testdata = TestData(db)
+        buffer = StringIO.StringIO()
+        testdata.buffer = buffer
+        try:
+            callable_()
+            return buffer.getvalue()
+        finally:
+            testdata.buffer = None
+            
 class ORMTest(AssertMixin):
     keep_mappers = False
     keep_data = False
@@ -251,6 +262,7 @@ class TestData(object):
         self.logger = engine.logger
         self.set_assert_list(None, None)
         self.sql_count = 0
+        self.buffer = None
         
     def set_assert_list(self, unittest, list):
         self.unittest = unittest
@@ -270,6 +282,8 @@ class ExecutionContextWrapper(object):
         ctx = self.ctx
         statement = unicode(ctx.compiled)
         statement = re.sub(r'\n', '', ctx.statement)
+        if testdata.buffer is not None:
+            testdata.buffer.write(statement + "\n")
 
         if testdata.assert_list is not None:
             item = testdata.assert_list[-1]