From: Mike Bayer Date: Tue, 8 Jan 2013 15:55:46 +0000 (-0500) Subject: :meth:`.Query.merge_result` can now load rows from an outer join X-Git-Tag: rel_0_8_0~35^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=06ddce3215d771e3345e19c5d3a1857b23db69f1;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git :meth:`.Query.merge_result` can now load rows from an outer join where an entity may be ``None`` without throwing an error. [ticket:2640] --- diff --git a/doc/build/changelog/changelog_07.rst b/doc/build/changelog/changelog_07.rst index c778fb84b9..71bf4e368c 100644 --- a/doc/build/changelog/changelog_07.rst +++ b/doc/build/changelog/changelog_07.rst @@ -8,6 +8,13 @@ :version: 0.7.10 :released: + .. change:: + :tags: orm, bug + :tickets: 2640 + + :meth:`.Query.merge_result` can now load rows from an outer join + where an entity may be ``None`` without throwing an error. + .. change:: :tags: sqlite, bug :tickets: 2568 diff --git a/doc/build/changelog/changelog_08.rst b/doc/build/changelog/changelog_08.rst index caed97d60a..b8ae66e44d 100644 --- a/doc/build/changelog/changelog_08.rst +++ b/doc/build/changelog/changelog_08.rst @@ -6,6 +6,14 @@ .. changelog:: :version: 0.8.0 + .. change:: + :tags: orm, bug + :tickets: 2640 + + :meth:`.Query.merge_result` can now load rows from an outer join + where an entity may be ``None`` without throwing an error. + Also in 0.7.10. + .. change:: :tags: sql, bug :tickets: 2648 diff --git a/lib/sqlalchemy/orm/loading.py b/lib/sqlalchemy/orm/loading.py index baff076eb9..5937197fd9 100644 --- a/lib/sqlalchemy/orm/loading.py +++ b/lib/sqlalchemy/orm/loading.py @@ -129,10 +129,11 @@ def merge_result(query, iterator, load=True): for row in iterator: newrow = list(row) for i in mapped_entities: - newrow[i] = session._merge( - attributes.instance_state(newrow[i]), - attributes.instance_dict(newrow[i]), - load=load, _recursive={}) + if newrow[i] is not None: + newrow[i] = session._merge( + attributes.instance_state(newrow[i]), + attributes.instance_dict(newrow[i]), + load=load, _recursive={}) result.append(util.KeyedTuple(newrow, keys)) return iter(result) diff --git a/test/orm/test_loading.py b/test/orm/test_loading.py index 1d2df2c5b6..20dc082c51 100644 --- a/test/orm/test_loading.py +++ b/test/orm/test_loading.py @@ -1,5 +1,5 @@ from . import _fixtures -from sqlalchemy.orm import loading, Session +from sqlalchemy.orm import loading, Session, aliased from sqlalchemy.testing.assertions import eq_ from sqlalchemy.util import KeyedTuple @@ -92,3 +92,25 @@ class MergeResultTest(_fixtures.FixtureTest): [(1, 1), (2, 2), (7, 7), (8, 8)] ) eq_(it[0].keys(), ['User', 'id']) + + def test_none_entity(self): + s, (u1, u2, u3, u4) = self._fixture() + User = self.classes.User + + ua = aliased(User) + q = s.query(User, ua) + kt = lambda *x: KeyedTuple(x, ['User', 'useralias']) + collection = [kt(u1, u2), kt(u1, None), kt(u2, u3)] + it = loading.merge_result( + q, + collection + ) + eq_( + [ + (x and x.id or None, y and y.id or None) + for x, y in it + ], + [(u1.id, u2.id), (u1.id, None), (u2.id, u3.id)] + ) + +