From: Mike Bayer Date: Fri, 18 Dec 2009 17:24:20 +0000 (+0000) Subject: - relation() with uselist=False will emit a warning when X-Git-Tag: rel_0_6beta1~128 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0683cc486d07fa1d1a381ffe647842be15c455f4;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - 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] --- diff --git a/CHANGES b/CHANGES index 079814e038..2fa791be19 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 7c56e1182a..01da0f23a4 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 a97c2fb242..88871426fb 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,