Files
sqlalchemy/test/orm/inheritance/_poly_fixtures.py
T
Mike Bayer 95b10c4e8e - Fixed bug in subquery eager loading where a long chain of
eager loads across a polymorphic-subclass boundary in conjunction
with polymorphic loading would fail to locate the subclass-link in the
chain, erroring out with a missing property name on an
:class:`.AliasedClass`. fixes #3055
2014-05-25 13:45:32 -04:00

351 lines
11 KiB
Python

from sqlalchemy import Integer, String, ForeignKey, func, desc, and_, or_
from sqlalchemy.orm import interfaces, relationship, mapper, \
clear_mappers, create_session, joinedload, joinedload_all, \
subqueryload, subqueryload_all, polymorphic_union, aliased,\
class_mapper
from sqlalchemy import exc as sa_exc
from sqlalchemy.engine import default
from sqlalchemy.testing import AssertsCompiledSQL, fixtures
from sqlalchemy import testing
from sqlalchemy.testing.schema import Table, Column
from sqlalchemy.testing import assert_raises, eq_
class Company(fixtures.ComparableEntity):
pass
class Person(fixtures.ComparableEntity):
pass
class Engineer(Person):
pass
class Manager(Person):
pass
class Boss(Manager):
pass
class Machine(fixtures.ComparableEntity):
pass
class MachineType(fixtures.ComparableEntity):
pass
class Paperwork(fixtures.ComparableEntity):
pass
class _PolymorphicFixtureBase(fixtures.MappedTest, AssertsCompiledSQL):
run_inserts = 'once'
run_setup_mappers = 'once'
run_deletes = None
@classmethod
def define_tables(cls, metadata):
global people, engineers, managers, boss
global companies, paperwork, machines
companies = Table('companies', metadata,
Column('company_id', Integer,
primary_key=True,
test_needs_autoincrement=True),
Column('name', String(50)))
people = Table('people', metadata,
Column('person_id', Integer,
primary_key=True,
test_needs_autoincrement=True),
Column('company_id', Integer,
ForeignKey('companies.company_id')),
Column('name', String(50)),
Column('type', String(30)))
engineers = Table('engineers', metadata,
Column('person_id', Integer,
ForeignKey('people.person_id'),
primary_key=True),
Column('status', String(30)),
Column('engineer_name', String(50)),
Column('primary_language', String(50)))
machines = Table('machines', metadata,
Column('machine_id',
Integer, primary_key=True,
test_needs_autoincrement=True),
Column('name', String(50)),
Column('engineer_id', Integer,
ForeignKey('engineers.person_id')))
managers = Table('managers', metadata,
Column('person_id', Integer,
ForeignKey('people.person_id'),
primary_key=True),
Column('status', String(30)),
Column('manager_name', String(50)))
boss = Table('boss', metadata,
Column('boss_id', Integer,
ForeignKey('managers.person_id'),
primary_key=True),
Column('golf_swing', String(30)))
paperwork = Table('paperwork', metadata,
Column('paperwork_id', Integer,
primary_key=True,
test_needs_autoincrement=True),
Column('description', String(50)),
Column('person_id', Integer,
ForeignKey('people.person_id')))
@classmethod
def insert_data(cls):
cls.e1 = e1 = Engineer(
name="dilbert",
engineer_name="dilbert",
primary_language="java",
status="regular engineer",
paperwork=[
Paperwork(description="tps report #1"),
Paperwork(description="tps report #2")],
machines=[
Machine(name='IBM ThinkPad'),
Machine(name='IPhone')])
cls.e2 = e2 = Engineer(
name="wally",
engineer_name="wally",
primary_language="c++",
status="regular engineer",
paperwork=[
Paperwork(description="tps report #3"),
Paperwork(description="tps report #4")],
machines=[Machine(name="Commodore 64")])
cls.b1 = b1 = Boss(
name="pointy haired boss",
golf_swing="fore",
manager_name="pointy",
status="da boss",
paperwork=[Paperwork(description="review #1")])
cls.m1 = m1 = Manager(
name="dogbert",
manager_name="dogbert",
status="regular manager",
paperwork=[
Paperwork(description="review #2"),
Paperwork(description="review #3")])
cls.e3 = e3 = Engineer(
name="vlad",
engineer_name="vlad",
primary_language="cobol",
status="elbonian engineer",
paperwork=[
Paperwork(description='elbonian missive #3')],
machines=[
Machine(name="Commodore 64"),
Machine(name="IBM 3270")])
cls.c1 = c1 = Company(name="MegaCorp, Inc.")
c1.employees = [e1, e2, b1, m1]
cls.c2 = c2 = Company(name="Elbonia, Inc.")
c2.employees = [e3]
sess = create_session()
sess.add(c1)
sess.add(c2)
sess.flush()
sess.expunge_all()
cls.all_employees = [e1, e2, b1, m1, e3]
cls.c1_employees = [e1, e2, b1, m1]
cls.c2_employees = [e3]
def _company_with_emps_machines_fixture(self):
fixture = self._company_with_emps_fixture()
fixture[0].employees[0].machines = [
Machine(name="IBM ThinkPad"),
Machine(name="IPhone"),
]
fixture[0].employees[1].machines = [
Machine(name="Commodore 64")
]
return fixture
def _company_with_emps_fixture(self):
return [
Company(
name="MegaCorp, Inc.",
employees=[
Engineer(
name="dilbert",
engineer_name="dilbert",
primary_language="java",
status="regular engineer"
),
Engineer(
name="wally",
engineer_name="wally",
primary_language="c++",
status="regular engineer"),
Boss(
name="pointy haired boss",
golf_swing="fore",
manager_name="pointy",
status="da boss"),
Manager(
name="dogbert",
manager_name="dogbert",
status="regular manager"),
]),
Company(
name="Elbonia, Inc.",
employees=[
Engineer(
name="vlad",
engineer_name="vlad",
primary_language="cobol",
status="elbonian engineer")
])
]
def _emps_wo_relationships_fixture(self):
return [
Engineer(
name="dilbert",
engineer_name="dilbert",
primary_language="java",
status="regular engineer"),
Engineer(
name="wally",
engineer_name="wally",
primary_language="c++",
status="regular engineer"),
Boss(
name="pointy haired boss",
golf_swing="fore",
manager_name="pointy",
status="da boss"),
Manager(
name="dogbert",
manager_name="dogbert",
status="regular manager"),
Engineer(
name="vlad",
engineer_name="vlad",
primary_language="cobol",
status="elbonian engineer")
]
@classmethod
def setup_mappers(cls):
mapper(Company, companies,
properties={
'employees':relationship(
Person,
order_by=people.c.person_id)})
mapper(Machine, machines)
person_with_polymorphic,\
manager_with_polymorphic = cls._get_polymorphics()
mapper(Person, people,
with_polymorphic=person_with_polymorphic,
polymorphic_on=people.c.type,
polymorphic_identity='person',
order_by=people.c.person_id,
properties={
'paperwork':relationship(
Paperwork,
order_by=paperwork.c.paperwork_id)})
mapper(Engineer, engineers,
inherits=Person,
polymorphic_identity='engineer',
properties={
'machines':relationship(
Machine,
order_by=machines.c.machine_id)})
mapper(Manager, managers,
with_polymorphic=manager_with_polymorphic,
inherits=Person,
polymorphic_identity='manager')
mapper(Boss, boss,
inherits=Manager,
polymorphic_identity='boss')
mapper(Paperwork, paperwork)
class _Polymorphic(_PolymorphicFixtureBase):
select_type = ""
@classmethod
def _get_polymorphics(cls):
return None, None
class _PolymorphicPolymorphic(_PolymorphicFixtureBase):
select_type = "Polymorphic"
@classmethod
def _get_polymorphics(cls):
return '*', '*'
class _PolymorphicUnions(_PolymorphicFixtureBase):
select_type = "Unions"
@classmethod
def _get_polymorphics(cls):
people, engineers, managers, boss = \
cls.tables.people, cls.tables.engineers, \
cls.tables.managers, cls.tables.boss
person_join = polymorphic_union({
'engineer':people.join(engineers),
'manager':people.join(managers)},
None, 'pjoin')
manager_join = people.join(managers).outerjoin(boss)
person_with_polymorphic = (
[Person, Manager, Engineer], person_join)
manager_with_polymorphic = ('*', manager_join)
return person_with_polymorphic,\
manager_with_polymorphic
class _PolymorphicAliasedJoins(_PolymorphicFixtureBase):
select_type = "AliasedJoins"
@classmethod
def _get_polymorphics(cls):
people, engineers, managers, boss = \
cls.tables.people, cls.tables.engineers, \
cls.tables.managers, cls.tables.boss
person_join = people \
.outerjoin(engineers) \
.outerjoin(managers) \
.select(use_labels=True) \
.alias('pjoin')
manager_join = people \
.join(managers) \
.outerjoin(boss) \
.select(use_labels=True) \
.alias('mjoin')
person_with_polymorphic = (
[Person, Manager, Engineer], person_join)
manager_with_polymorphic = ('*', manager_join)
return person_with_polymorphic,\
manager_with_polymorphic
class _PolymorphicJoins(_PolymorphicFixtureBase):
select_type = "Joins"
@classmethod
def _get_polymorphics(cls):
people, engineers, managers, boss = \
cls.tables.people, cls.tables.engineers, \
cls.tables.managers, cls.tables.boss
person_join = people.outerjoin(engineers).outerjoin(managers)
manager_join = people.join(managers).outerjoin(boss)
person_with_polymorphic = (
[Person, Manager, Engineer], person_join)
manager_with_polymorphic = ('*', manager_join)
return person_with_polymorphic,\
manager_with_polymorphic