]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Fixed bug where :meth:`.Query.get` would fail to consistently
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 10 Feb 2014 21:33:48 +0000 (16:33 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 10 Feb 2014 21:34:19 +0000 (16:34 -0500)
raise the :class:`.InvalidRequestError` that invokes when called
on a query with existing criterion, when the given identity is
already present in the identity map. [ticket:2951]

doc/build/changelog/changelog_08.rst
lib/sqlalchemy/orm/query.py
test/orm/test_query.py

index f9e0b9a45615936feaeae922237a6898eebdd258..83c660e79c7b2adc0bdd22261051cc0b62dad05d 100644 (file)
 .. changelog::
     :version: 0.8.5
 
+    .. change::
+        :tags: bug, orm
+        :tickets: 2951
+        :versions: 0.9.3
+
+        Fixed bug where :meth:`.Query.get` would fail to consistently
+        raise the :class:`.InvalidRequestError` that invokes when called
+        on a query with existing criterion, when the given identity is
+        already present in the identity map.
+
     .. change::
         :tags: bug, mysql
         :tickets: 2933
index aed97a14407937d1119e83bde03678e33211038e..f1c8d21dac77376732831bdd7d2171dba2dc435d 100644 (file)
@@ -351,20 +351,26 @@ class Query(object):
         return equivs
 
     def _get_condition(self):
-        self._order_by = self._distinct = False
-        return self._no_criterion_condition("get")
+        return self._no_criterion_condition("get", order_by=False, distinct=False)
 
-    def _no_criterion_condition(self, meth):
+    def _get_existing_condition(self):
+        self._no_criterion_assertion("get", order_by=False, distinct=False)
+
+    def _no_criterion_assertion(self, meth, order_by=True, distinct=True):
         if not self._enable_assertions:
             return
         if self._criterion is not None or \
                 self._statement is not None or self._from_obj or \
                 self._limit is not None or self._offset is not None or \
-                self._group_by or self._order_by or self._distinct:
+                self._group_by or (order_by and self._order_by) or \
+                (distinct and self._distinct):
             raise sa_exc.InvalidRequestError(
                                 "Query.%s() being called on a "
                                 "Query with existing criterion. " % meth)
 
+    def _no_criterion_condition(self, meth, order_by=True, distinct=True):
+        self._no_criterion_assertion(meth, order_by, distinct)
+
         self._from_obj = ()
         self._statement = self._criterion = None
         self._order_by = self._group_by = self._distinct = False
@@ -811,6 +817,7 @@ class Query(object):
             instance = loading.get_from_identity(
                 self.session, key, attributes.PASSIVE_OFF)
             if instance is not None:
+                self._get_existing_condition()
                 # reject calls for id in identity map but class
                 # mismatch.
                 if not issubclass(instance.__class__, mapper.class_):
index 6c1d97173aa85fcd8060c8fbed8c79c4649c80d7..4be93bf1733fc822d2acf79ba0b14b42b43b6aec 100644 (file)
@@ -427,6 +427,24 @@ class GetTest(QueryTest):
         # order_by()/get() doesn't raise
         s.query(User).order_by(User.id).get(8)
 
+    def test_no_criterion_when_already_loaded(self):
+        """test that get()/load() does not use preexisting filter/etc. criterion,
+        even when we're only using the identity map."""
+
+        User, Address = self.classes.User, self.classes.Address
+
+
+        s = create_session()
+
+        u1 = s.query(User).get(7)
+
+        q = s.query(User).join('addresses').filter(Address.user_id==8)
+        assert_raises(sa_exc.InvalidRequestError, q.get, 7)
+        assert_raises(sa_exc.InvalidRequestError, s.query(User).filter(User.id==7).get, 19)
+
+        # order_by()/get() doesn't raise
+        s.query(User).order_by(User.id).get(8)
+
     def test_unique_param_names(self):
         users = self.tables.users