eager loading to polymorphic select_table mapper not working

Issue #712 resolved
Mike Bayer repo owner created an issue

can be seen in joined-table loading:

Index: test/orm/inheritance/polymorph.py
===================================================================
--- test/orm/inheritance/polymorph.py   (revision 3165)
+++ test/orm/inheritance/polymorph.py   (working copy)
@@ -263,14 +263,20 @@
         session.flush()
         session.clear()
         id = c.company_id
-        c = session.query(Company).get(id)
-        for e in c.employees:
-            print e, e._instance_key, e.company
-        if include_base:
-            assert sets.Set([getattr(e, 'status', None)) for e in c.employees]((e.get_name(),)) == sets.Set([haired boss', 'AAB'), ('dilbert', 'BBA'), ('joesmith', None), ('wally', 'CGG'), ('jsmith', 'ABA')](('pointy))
+        def go():
+            c = session.query(Company).get(id)
+            for e in c.employees:
+                print e, e._instance_key, e.company
+            if include_base:
+                assert sets.Set([getattr(e, 'status', None)) for e in c.employees]((e.get_name(),)) == sets.Set([haired boss', 'AAB'), ('dilbert', 'BBA'), ('joesmith', None), ('wally', 'CGG'), ('jsmith', 'ABA')](('pointy))
+            else:
+                assert sets.Set([e.status) for e in c.employees]((e.get_name(),)) == sets.Set([haired boss', 'AAB'), ('dilbert', 'BBA'), ('wally', 'CGG'), ('jsmith', 'ABA')](('pointy))
+            print "\n"
+
+        if not lazy_relation and polymorphic_fetch=='union':
+            self.assert_sql_count(testbase.db, go, 1)
         else:
-            assert sets.Set([e.status) for e in c.employees]((e.get_name(),)) == sets.Set([haired boss', 'AAB'), ('dilbert', 'BBA'), ('wally', 'CGG'), ('jsmith', 'ABA')](('pointy))
-        print "\n"
+            go()

         # test selecting from the query, using the base mapped table (people) as the selection criterion.
         # in the case of the polymorphic Person query, the "people" selectable should be adapted to be "person_join"

Also add the attached as a test in the concrete unit tests, with a similar eager count:

from sqlalchemy import *
from sqlalchemy.orm import *
import sets

# this example illustrates a polymorphic load of two classes

metadata = MetaData('sqlite://')
#metadata.bind.echo = 'debug'

import logging
logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.DEBUG)
logging.getLogger('sqlalchemy.orm.strategies').setLevel(logging.DEBUG)

companies = Table('companies', metadata, 
   Column('id', Integer, primary_key=True),
   Column('name', String(50)))

employees_table = Table('employees', metadata, 
    Column('employee_id', Integer, primary_key=True),
    Column('name', String(50)),
    Column('company_id', Integer, ForeignKey('companies.id'))
)

managers_table = Table('managers', metadata, 
    Column('employee_id', Integer, primary_key=True),
    Column('name', String(50)),
    Column('manager_data', String(50)),
    Column('company_id', Integer, ForeignKey('companies.id'))
)

engineers_table = Table('engineers', metadata, 
    Column('employee_id', Integer, primary_key=True),
    Column('name', String(50)),
    Column('engineer_info', String(50)),
    Column('company_id', Integer, ForeignKey('companies.id'))
)

metadata.create_all()


class Employee(object):
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return self.__class__.__name__ + " " + self.name

class Manager(Employee):
    def __init__(self, name, manager_data):
        self.name = name
        self.manager_data = manager_data
    def __repr__(self):
        return self.__class__.__name__ + " " + self.name + " " +  self.manager_data

class Engineer(Employee):
    def __init__(self, name, engineer_info):
        self.name = name
        self.engineer_info = engineer_info
    def __repr__(self):
        return self.__class__.__name__ + " " + self.name + " " +  self.engineer_info

class Company(object):
    pass

pjoin = polymorphic_union({
    'employee':employees_table,
    'manager':managers_table,
    'engineer':engineers_table
}, 'type', 'pjoin')

employee_mapper = mapper(Employee, employees_table, select_table=pjoin, polymorphic_on=pjoin.c.type, polymorphic_identity='employee')
manager_mapper = mapper(Manager, managers_table, inherits=employee_mapper, concrete=True, polymorphic_identity='manager')
engineer_mapper = mapper(Engineer, engineers_table, inherits=employee_mapper, concrete=True, polymorphic_identity='engineer')
mapper(Company, companies, properties={
    'employees':relation(Employee)
})

sess = create_session()
c = Company()
sess.save(c)
c.employees.append(Manager(name='pointy haired boss', manager_data='manager1'))
c.employees.append(Engineer(name='dilbert', engineer_info='java'))
c.employees.append(Employee(name='joesmith', ))
c.employees.append(Engineer(name='wally', engineer_info='python'))
c.employees.append(Manager(name='jsmith', manager_data='manager2'))
sess.flush()
sess.clear()
co = sess.query(Company).options(eagerload('employees')).all()
print co
print "------------------------"
# should not lazy load here
print co[0](0).employees
#    print e

Comments (2)

  1. Log in to comment