summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/build/changelog/changelog_11.rst8
-rw-r--r--lib/sqlalchemy/orm/query.py9
-rw-r--r--test/orm/inheritance/test_single.py120
3 files changed, 118 insertions, 19 deletions
diff --git a/doc/build/changelog/changelog_11.rst b/doc/build/changelog/changelog_11.rst
index b68f4aa29..27417a679 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 340e71d25..770345315 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -3802,11 +3802,16 @@ 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:
ezero = ent.entity_zero
diff --git a/test/orm/inheritance/test_single.py b/test/orm/inheritance/test_single.py
index d12d96977..5d3e4cf67 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