subquery load on with_polymorphic entity

Issue #3106 resolved
Mike Bayer repo owner created an issue
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class Employee(Base):
    __tablename__ = "employee"
    id = Column(Integer, primary_key=True)
    type = Column(String(100))
    cars = relationship("Car")
    __mapper_args__ = {
        "polymorphic_on": type,
    }

class Car(Base):
    __tablename__ = "car"
    id = Column(Integer, primary_key=True)
    employee_id = Column(Integer, ForeignKey(Employee.id))

class Engineer(Employee):
    __tablename__ = "engineer"
    id = Column(Integer, ForeignKey(Employee.id), primary_key=True)
    specialty = Column(String(100))
    __mapper_args__ = {
        "polymorphic_identity": "engineer",
    }

e = create_engine("postgresql://scott:tiger@localhost/test", echo=True)
c = e.connect()
t = c.begin()
Base.metadata.create_all(c)

session = Session(c)

session.add(Engineer())
session.flush()

E = with_polymorphic(Employee, [Engineer])

# needs:
# session.query(E).select_from(E).options(subqueryload(E.cars)).order_by(E.Engineer.specialty).first()

session.query(E).options(subqueryload(E.cars)).order_by(Engineer.specialty).first()

patch:

--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -725,7 +725,7 @@ class SubqueryLoader(AbstractRelationshipLoader):
         left_alias = self._generate_from_original_query(
                             orig_query, leftmost_mapper,
                             leftmost_attr, leftmost_relationship,
-                            entity.mapper
+                            entity.entity_zero
         )

         # generate another Query that will join the
@@ -744,7 +744,6 @@ class SubqueryLoader(AbstractRelationshipLoader):
                     self._prep_for_joins(left_alias, subq_path)
         q = q.order_by(*local_attr)
         q = q.add_columns(*local_attr)
-
         q = self._apply_joins(q, to_join, left_alias,
                             parent_alias, effective_entity)

@@ -779,7 +778,7 @@ class SubqueryLoader(AbstractRelationshipLoader):
     def _generate_from_original_query(self,
             orig_query, leftmost_mapper,
             leftmost_attr, leftmost_relationship,
-            entity_mapper
+            orig_entity
     ):
         # reformat the original query
         # to look only for significant columns
@@ -787,9 +786,8 @@ class SubqueryLoader(AbstractRelationshipLoader):

         # set a real "from" if not present, as this is more
         # accurate than just going off of the column expression
-        if not q._from_obj and entity_mapper.isa(leftmost_mapper):
-            q._set_select_from([entity_mapper], False)
-
+        if not q._from_obj and orig_entity.mapper.isa(leftmost_mapper):
+            q._set_select_from([orig_entity], False)
         target_cols = q._adapt_col_list(leftmost_attr)

         # select from the identity columns of the outer

Comments (4)

  1. Mike Bayer reporter
    • repair the _enable_single_crit method, it was named the same as the attribute and probably just replaced itself, so that is now _set_enable_single_crit
    • as a side effect of the main issue fixed here, correct the case in adjust_for_single_inheritance where the same mapper appears more than once in mapper_adapter_map; run through a set() for uniqueness.
    • Fixed bug in subquery eager loading in conjunction with :func:.with_polymorphic, the targeting of entities and columns in the subquery load has been made more accurate with respect to this type of entity and others. Fixes #3106

    → <<cset 2d8d1dcf60e0>>

  2. Mike Bayer reporter
    • repair the _enable_single_crit method, it was named the same as the attribute and probably just replaced itself, so that is now _set_enable_single_crit
    • as a side effect of the main issue fixed here, correct the case in adjust_for_single_inheritance where the same mapper appears more than once in mapper_adapter_map; run through a set() for uniqueness.
    • Fixed bug in subquery eager loading in conjunction with :func:.with_polymorphic, the targeting of entities and columns in the subquery load has been made more accurate with respect to this type of entity and others. Fixes #3106

    → <<cset 3ed5449ebb6c>>

  3. Log in to comment