From 9f72910c7c1cc70486c825ddc53d0b293f1b0d8b Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 8 Jan 2013 10:57:15 -0500 Subject: [PATCH] :meth:`.Query.merge_result` can now load rows from an outer join where an entity may be ``None`` without throwing an error. [ticket:2640] --- doc/build/changelog/changelog_07.rst | 7 +++++++ lib/sqlalchemy/orm/query.py | 9 +++++---- test/orm/test_loading.py | 23 ++++++++++++++++++++++- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/doc/build/changelog/changelog_07.rst b/doc/build/changelog/changelog_07.rst index b62e86df6b..fdf5c1fa28 100644 --- a/doc/build/changelog/changelog_07.rst +++ b/doc/build/changelog/changelog_07.rst @@ -27,6 +27,13 @@ to the MSSQL dialect's "schema rendering" logic's failure to take .key into account. + .. 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/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 1be9777f44..286dbf6b3e 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -2419,10 +2419,11 @@ class Query(object): 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.NamedTuple(newrow, keys)) return iter(result) diff --git a/test/orm/test_loading.py b/test/orm/test_loading.py index 77afa17a0c..7b401a7cc1 100644 --- a/test/orm/test_loading.py +++ b/test/orm/test_loading.py @@ -1,5 +1,5 @@ from test.orm import _fixtures -from sqlalchemy.orm import Session, mapper +from sqlalchemy.orm import Session, mapper, aliased from test.lib.testing import eq_ from sqlalchemy.util import NamedTuple @@ -89,3 +89,24 @@ 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: NamedTuple(x, ['User', 'useralias']) + collection = [kt(u1, u2), kt(u1, None), kt(u2, u3)] + it = q.merge_result( + 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)] + ) + + -- 2.47.2