summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2009-12-18 17:24:20 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2009-12-18 17:24:20 +0000
commit0683cc486d07fa1d1a381ffe647842be15c455f4 (patch)
treed21a1791b7c8dba91b8b8864da4b1561dac9bb17
parente8e446e92a59ed1cf347a8d224991fc828602ab0 (diff)
downloadsqlalchemy-0683cc486d07fa1d1a381ffe647842be15c455f4.tar.gz
- relation() with uselist=False will emit a warning when
an eager load locates more than one valid value for the row, typically due to primaryjoin/secondaryjoin conditions which aren't appropriate for LEFT OUTER JOIN. [ticket:1643]
-rw-r--r--CHANGES5
-rw-r--r--lib/sqlalchemy/orm/strategies.py8
-rw-r--r--test/orm/test_eager_relations.py13
3 files changed, 24 insertions, 2 deletions
diff --git a/CHANGES b/CHANGES
index 079814e03..2fa791be1 100644
--- a/CHANGES
+++ b/CHANGES
@@ -69,6 +69,11 @@ CHANGES
in filter criterion against the dynamic relation.
[ticket:1531]
+ - relation() with uselist=False will emit a warning when
+ an eager load locates more than one valid value for the row,
+ typically due to primaryjoin/secondaryjoin conditions which
+ aren't appropriate for LEFT OUTER JOIN. [ticket:1643]
+
- an explicit check occurs when a synonym() is used with
map_column=True, when a ColumnProperty (deferred or otherwise)
exists separately in the properties dictionary sent to mapper
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index 7c56e1182..01da0f23a 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -794,7 +794,13 @@ class EagerLoader(AbstractRelationLoader):
else:
# call _instance on the row, even though the object has been created,
# so that we further descend into properties
- _instance(row, None)
+ existing = _instance(row, None)
+ if existing is not None \
+ and key in dict_ \
+ and existing is not dict_[key]:
+ util.warn(
+ "Multiple rows returned with "
+ "uselist=False for eagerly-loaded attribute '%s' " % self)
else:
def execute(state, dict_, row, isnew, **flags):
if isnew or (state, key) not in context.attributes:
diff --git a/test/orm/test_eager_relations.py b/test/orm/test_eager_relations.py
index a97c2fb24..88871426f 100644
--- a/test/orm/test_eager_relations.py
+++ b/test/orm/test_eager_relations.py
@@ -7,7 +7,7 @@ from sqlalchemy.orm import eagerload, deferred, undefer, eagerload_all, backref
from sqlalchemy import Integer, String, Date, ForeignKey, and_, select, func
from sqlalchemy.test.schema import Table, Column
from sqlalchemy.orm import mapper, relation, create_session, lazyload, aliased
-from sqlalchemy.test.testing import eq_
+from sqlalchemy.test.testing import eq_, assert_raises
from sqlalchemy.test.assertsql import CompiledSQL
from test.orm import _base, _fixtures
from sqlalchemy.util import OrderedDict as odict
@@ -774,6 +774,17 @@ class EagerTest(_fixtures.FixtureTest, testing.AssertsCompiledSQL):
], q.order_by(User.id).all())
self.assert_sql_count(testing.db, go, 1)
+ @testing.resolve_artifact_names
+ def test_uselist_false_warning(self):
+ """test that multiple rows received by a uselist=False raises a warning."""
+
+ mapper(User, users, properties={
+ 'order':relation(Order, uselist=False)
+ })
+ mapper(Order, orders)
+ s = create_session()
+ assert_raises(sa.exc.SAWarning, s.query(User).options(eagerload(User.order)).all)
+
@testing.resolve_artifact_names
def test_wide(self):
mapper(Order, orders, properties={'items':relation(Item, secondary=order_items, lazy=False,