]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- [bug] An error is emitted when uselist=False
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 6 Aug 2012 02:53:56 +0000 (22:53 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 6 Aug 2012 02:53:56 +0000 (22:53 -0400)
    is combined with a "dynamic" loader.
    This is a warning in 0.7.9.

CHANGES
doc/build/orm/collections.rst
lib/sqlalchemy/orm/dynamic.py
test/orm/test_dynamic.py

diff --git a/CHANGES b/CHANGES
index f228486b2a3ee7f90e6e6dd991bd5f2e1ff4fe36..d480f812a91fbe98e979b6bb751821a811ab453d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -213,6 +213,10 @@ underneath "0.7.xx".
     or remove operation is received on the
     now-detached collection.  [ticket:2476]
 
+  - [bug] An error is emitted when uselist=False
+    is combined with a "dynamic" loader.
+    This is a warning in 0.7.9.
+
   - [removed] Deprecated identifiers removed:
 
     * allow_null_pks mapper() argument
@@ -441,6 +445,10 @@ are also present in 0.8.
     disabled on subclasses, unless overridden
     explicitly.
 
+  - [bug] A warning is emitted when lazy='dynamic'
+    is combined with uselist=False.  This is an
+    exception raise in 0.8.
+
 - sql
   - [bug] Fixed CTE bug whereby positional
     bound parameters present in the CTEs themselves
index e11fc009ea1e2a50cd9fd0e04ac309f0c1a09f05..822fcd3be6f9af17a1a0336a8a7affb8e782f26b 100644 (file)
@@ -84,6 +84,12 @@ Note that eager/lazy loading options cannot be used in conjunction dynamic relat
    The :func:`~.orm.dynamic_loader` function is essentially the same
    as :func:`~.orm.relationship` with the ``lazy='dynamic'`` argument specified.
 
+.. warning::
+
+   The "dynamic" loader applies to **collections only**.   It is not valid
+   to use "dynamic" loaders with many-to-one, one-to-one, or uselist=False
+   relationships.   Newer versions of SQLAlchemy emit warnings or exceptions
+   in these cases.
 
 Setting Noload
 ---------------
index 6d532e669b3568075afe79605a06fadf6ac608a1..59857557676b9b3d0b298641d3edbc9a570cbd61 100644 (file)
@@ -11,7 +11,7 @@ basic add/delete mutation.
 
 """
 
-from .. import log, util
+from .. import log, util, exc
 from ..sql import operators
 from . import (
     attributes, object_session, util as orm_util, strategies,
@@ -22,7 +22,11 @@ from .query import Query
 class DynaLoader(strategies.AbstractRelationshipLoader):
     def init_class_attribute(self, mapper):
         self.is_class_level = True
-
+        if not self.uselist:
+            raise exc.InvalidRequestError(
+                    "On relationship %s, 'dynamic' loaders cannot be used with "
+                    "many-to-one/one-to-one relationships and/or "
+                    "uselist=False." % self.parent_property)
         strategies._register_attribute(self,
             mapper,
             useobject=True,
index 07f01822b908d7d07e2d574237e6ed0c29a78ffe..fd8793778a8382115e6d74fa8a65612f94ad013c 100644 (file)
@@ -1,8 +1,8 @@
 from test.lib.testing import eq_, ne_
 import operator
-from sqlalchemy.orm import dynamic_loader, backref
+from sqlalchemy.orm import dynamic_loader, backref, configure_mappers
 from test.lib import testing
-from sqlalchemy import Integer, String, ForeignKey, desc, select, func
+from sqlalchemy import Integer, String, ForeignKey, desc, select, func, exc
 from test.lib.schema import Table, Column
 from sqlalchemy.orm import mapper, relationship, create_session, Query, attributes, exc as orm_exc
 from sqlalchemy.orm.dynamic import AppenderMixin
@@ -62,7 +62,7 @@ class DynamicTest(_fixtures.FixtureTest, AssertsCompiledSQL):
                                 self.classes.User)
 
         mapper(User, users, properties={
-            'addresses':dynamic_loader(mapper(Address, addresses))
+            'addresses': dynamic_loader(mapper(Address, addresses))
         })
         sess = create_session()
         u = sess.query(User).get(8)
@@ -73,6 +73,40 @@ class DynamicTest(_fixtures.FixtureTest, AssertsCompiledSQL):
             email_address='e'
         )
 
+    def test_no_uselist_false(self):
+        users, Address, addresses, User = (self.tables.users,
+                                self.classes.Address,
+                                self.tables.addresses,
+                                self.classes.User)
+        mapper(Address, addresses)
+        mapper(User, users, properties={
+                "addresses": relationship(Address, lazy='dynamic', uselist=False)
+            })
+        assert_raises_message(
+            exc.InvalidRequestError,
+            "On relationship User.addresses, 'dynamic' loaders cannot be "
+            "used with many-to-one/one-to-one relationships and/or "
+            "uselist=False.",
+            configure_mappers
+        )
+
+    def test_no_m2o(self):
+        users, Address, addresses, User = (self.tables.users,
+                                self.classes.Address,
+                                self.tables.addresses,
+                                self.classes.User)
+        mapper(Address, addresses, properties={
+                'user': relationship(User, lazy='dynamic')
+            })
+        mapper(User, users)
+        assert_raises_message(
+            exc.InvalidRequestError,
+            "On relationship Address.user, 'dynamic' loaders cannot be "
+            "used with many-to-one/one-to-one relationships and/or "
+            "uselist=False.",
+            configure_mappers
+        )
+
     def test_order_by(self):
         users, Address, addresses, User = (self.tables.users,
                                 self.classes.Address,