From: Mike Bayer Date: Mon, 19 Dec 2016 17:39:15 +0000 (-0500) Subject: Add real .entities to _BundleEntity X-Git-Tag: rel_1_1_5~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=675f021368a375c330c07d0826e30049f2f0e016;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Add real .entities to _BundleEntity Fixed bug where the single-table inheritance query criteria would not be inserted into the query in the case that the :class:`.Bundle` construct were used as the selection criteria. Change-Id: Ib7c128ceef5c3220a098cdfd0270c43a2a67716d Fixes: #3874 --- diff --git a/doc/build/changelog/changelog_11.rst b/doc/build/changelog/changelog_11.rst index b68f4aa29e..27417a6792 100644 --- a/doc/build/changelog/changelog_11.rst +++ b/doc/build/changelog/changelog_11.rst @@ -21,6 +21,14 @@ .. changelog:: :version: 1.1.5 + .. change:: 3874 + :tags: bug, orm + :tickets: 3874 + + Fixed bug where the single-table inheritance query criteria would not + be inserted into the query in the case that the :class:`.Bundle` + construct were used as the selection criteria. + .. change:: pg_timestamp_zero_prec :tags: bug, postgresql diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 340e71d25e..7703453157 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -3802,10 +3802,15 @@ class _BundleEntity(_QueryEntity): else: _ColumnEntity(self, expr, namespace=self) - self.entities = () - self.supports_single_entity = self.bundle.single_entity + @property + def entities(self): + entities = [] + for ent in self._entities: + entities.extend(ent.entities) + return entities + @property def entity_zero(self): for ent in self._entities: diff --git a/test/orm/inheritance/test_single.py b/test/orm/inheritance/test_single.py index d12d969772..5d3e4cf677 100644 --- a/test/orm/inheritance/test_single.py +++ b/test/orm/inheritance/test_single.py @@ -51,12 +51,12 @@ class SingleInheritanceTest(testing.AssertsCompiledSQL, fixtures.MappedTest): mapper(Engineer, inherits=Employee, polymorphic_identity='engineer') mapper(JuniorEngineer, inherits=Engineer, polymorphic_identity='juniorengineer') - def test_single_inheritance(self): - Employee, JuniorEngineer, Manager, Engineer = (self.classes.Employee, - self.classes.JuniorEngineer, - self.classes.Manager, - self.classes.Engineer) - + def _fixture_one(self): + Employee, JuniorEngineer, Manager, Engineer = ( + self.classes.Employee, + self.classes.JuniorEngineer, + self.classes.Manager, + self.classes.Engineer) session = create_session() @@ -65,6 +65,16 @@ class SingleInheritanceTest(testing.AssertsCompiledSQL, fixtures.MappedTest): e2 = JuniorEngineer(name='Ed', engineer_info='oh that ed') session.add_all([m1, e1, e2]) session.flush() + return session, m1, e1, e2 + + def test_single_inheritance(self): + Employee, JuniorEngineer, Manager, Engineer = ( + self.classes.Employee, + self.classes.JuniorEngineer, + self.classes.Manager, + self.classes.Engineer) + + session, m1, e1, e2 = self._fixture_one() assert session.query(Employee).all() == [m1, e1, e2] assert session.query(Engineer).all() == [e1, e2] @@ -80,18 +90,12 @@ class SingleInheritanceTest(testing.AssertsCompiledSQL, fixtures.MappedTest): assert row.employee_id == e1.employee_id def test_multi_qualification(self): - JuniorEngineer, Manager, Engineer = (self.classes.JuniorEngineer, - self.classes.Manager, - self.classes.Engineer) - - session = create_session() - - m1 = Manager(name='Tom', manager_data='knows how to manage things') - e1 = Engineer(name='Kurt', engineer_info='knows how to hack') - e2 = JuniorEngineer(name='Ed', engineer_info='oh that ed') + JuniorEngineer, Manager, Engineer = ( + self.classes.JuniorEngineer, + self.classes.Manager, + self.classes.Engineer) - session.add_all([m1, e1, e2]) - session.flush() + session, m1, e1, e2 = self._fixture_one() ealias = aliased(Engineer) eq_( @@ -130,6 +134,88 @@ class SingleInheritanceTest(testing.AssertsCompiledSQL, fixtures.MappedTest): # [] # ) + def test_column_qualification(self): + Employee, JuniorEngineer, Manager, Engineer = ( + self.classes.Employee, + self.classes.JuniorEngineer, + self.classes.Manager, + self.classes.Engineer) + + session, m1, e1, e2 = self._fixture_one() + + m1id, e1id, e2id = m1.employee_id, e1.employee_id, e2.employee_id + + def scalar(q): + return [x for x, in q] + + eq_( + scalar(session.query(Employee.employee_id)), + [m1id, e1id, e2id] + ) + + eq_( + scalar(session.query(Engineer.employee_id)), + [e1id, e2id] + ) + + eq_( + scalar(session.query(Manager.employee_id)), [m1id] + ) + + # this currently emits "WHERE type IN (?, ?) AND type IN (?, ?)", + # so no result. + eq_( + session.query(Manager.employee_id, Engineer.employee_id).all(), + [] + ) + + eq_( + scalar(session.query(JuniorEngineer.employee_id)), + [e2id] + ) + + def test_bundle_qualification(self): + Employee, JuniorEngineer, Manager, Engineer = ( + self.classes.Employee, + self.classes.JuniorEngineer, + self.classes.Manager, + self.classes.Engineer) + + session, m1, e1, e2 = self._fixture_one() + + m1id, e1id, e2id = m1.employee_id, e1.employee_id, e2.employee_id + + def scalar(q): + return [x[0] for x, in q] + + eq_( + scalar(session.query(Bundle("name", Employee.employee_id))), + [m1id, e1id, e2id] + ) + + eq_( + scalar(session.query(Bundle("name", Engineer.employee_id))), + [e1id, e2id] + ) + + eq_( + scalar(session.query(Bundle("name", Manager.employee_id))), [m1id] + ) + + # this currently emits "WHERE type IN (?, ?) AND type IN (?, ?)", + # so no result. + eq_( + session.query( + Bundle("name", Manager.employee_id, Engineer.employee_id) + ).all(), + [] + ) + + eq_( + scalar(session.query(Bundle("name", JuniorEngineer.employee_id))), + [e2id] + ) + def test_from_self(self): Engineer = self.classes.Engineer