Hi there, I've been playing with concrete inheritance a bit these days (trying to implement it into Elixir). I've run into several problems, which might be known limitations, but I'd like to know for sure or be shown what I've done wrong...
The two problems I get involve a chain of classes inheriting from one another: class C inherits from class B which inherits from class A. The first problem is that I can get a polymorphic load starting from class B. I'd like it to return instances of class C, along with the instances from class B. Querying class A works as expected though (return instances of A, B and C). See multi_level_concrete.py for what I tried. (It's a hacked/standalone version of the unit tests found in SA itself). FWIW, I run them with nosetest. The second (probably related) problem is that I can't get relationships to work polymorphically. I'd like to have a relationship to the B class. Since I've read in the doc that the relation is not inherited automatically, I tried duplicating manually, but then it doesn't work polymorphically... Anyway, see concrete_with_relations.py for my experimentations. Thanks in advance for any pointer on this, -- Gaƫtan de Menten http://openhex.org --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~----------~----~----~----~------~----~------~--~---
from sqlalchemy import * from sqlalchemy.orm import * metadata = MetaData('sqlite:///') companies = Table('companies', metadata, Column('id', Integer, primary_key=True), Column('name', String(50))) 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')) ) hackers_table = Table('hackers', metadata, Column('employee_id', Integer, primary_key=True), Column('name', String(50)), Column('engineer_info', String(50)), Column('company_id', Integer, ForeignKey('companies.id')), Column('nickname', String(50)) ) metadata.create_all() #metadata.bind.echo = True def test_relation_1(): class Company(object): def __init__(self, name): self.name = name 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 Hacker(Engineer): def __init__(self, name, nickname, engineer_info): self.name = name self.nickname = nickname self.engineer_info = engineer_info def __repr__(self): return self.__class__.__name__ + " " + self.name + " '" + \ self.nickname + "' " + self.engineer_info pjoin = polymorphic_union({ 'manager':managers_table, 'engineer':engineers_table, 'hacker':hackers_table }, 'type', 'pjoin') mapper(Company, companies, properties={ 'engineers':relation(Engineer, lazy=False, enable_typechecks=False) }) employee_mapper = mapper(Employee, pjoin, polymorphic_on=pjoin.c.type) 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', properties={'company': relation(Company)}) hacker_mapper = mapper(Hacker, hackers_table, inherits=engineer_mapper, concrete=True, polymorphic_identity='hacker', properties={'company': relation(Company)}) session = create_session() c = Company('Super') session.save(Manager('Tom', 'knows how to manage things')) c.engineers.append(Engineer('Jerry', 'knows how to program')) c.engineers.append(Hacker('Kurt', 'Badass', 'knows how to hack')) assert len(c.engineers) == 2 session.save(c) session.flush() session.clear() assert set([repr(x) for x in session.query(Employee).all()]) == \ set(["Engineer Jerry knows how to program", "Manager Tom knows how to manage things", "Hacker Kurt 'Badass' knows how to hack"]) assert set([repr(x) for x in session.query(Manager).all()]) == set(["Manager Tom knows how to manage things"]) res = session.query(Company).one().engineers print res assert set([repr(x) for x in res]) == \ set(["Engineer Jerry knows how to program", "Hacker Kurt 'Badass' knows how to hack"]) def test_relation_2(): metadata.drop_all() metadata.create_all() class Company(object): def __init__(self, name): self.name = name 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 Hacker(Engineer): def __init__(self, name, nickname, engineer_info): self.name = name self.nickname = nickname self.engineer_info = engineer_info def __repr__(self): return self.__class__.__name__ + " " + self.name + " '" + \ self.nickname + "' " + self.engineer_info pjoin = polymorphic_union({ 'manager':managers_table, 'engineer':engineers_table, 'hacker':hackers_table }, 'type', 'pjoin') mapper(Company, companies, properties={ 'engineers': relation(Engineer, lazy=False, enable_typechecks=False, backref='company') }) employee_mapper = mapper(Employee, pjoin, polymorphic_on=pjoin.c.type) 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') hacker_mapper = mapper(Hacker, hackers_table, inherits=engineer_mapper, concrete=True, polymorphic_identity='hacker') session = create_session() c = Company('Super') session.save(Manager('Tom', 'knows how to manage things')) c.engineers.append(Engineer('Jerry', 'knows how to program')) c.engineers.append(Hacker('Kurt', 'Badass', 'knows how to hack')) session.save(c) session.flush() session.clear() assert set([repr(x) for x in session.query(Employee).all()]) == \ set(["Engineer Jerry knows how to program", "Manager Tom knows how to manage things", "Hacker Kurt 'Badass' knows how to hack"]) assert set([repr(x) for x in session.query(Manager).all()]) == set(["Manager Tom knows how to manage things"]) res = session.query(Company).one().engineers print res assert set([repr(x) for x in res]) == \ set(["Engineer Jerry knows how to program", "Hacker Kurt 'Badass' knows how to hack"])
from sqlalchemy import * from sqlalchemy.orm import * metadata = MetaData('sqlite:///') companies = Table('companies', metadata, Column('id', Integer, primary_key=True), Column('name', String(50))) 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')) ) hackers_table = Table('hackers', metadata, Column('employee_id', Integer, primary_key=True), Column('name', String(50)), Column('engineer_info', String(50)), Column('company_id', Integer, ForeignKey('companies.id')), Column('nickname', String(50)) ) metadata.create_all() #metadata.bind.echo = True class Company(object): def __init__(self, name): self.name = name def test_multi_level_1(): 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 Hacker(Engineer): def __init__(self, name, nickname, engineer_info): self.name = name self.nickname = nickname self.engineer_info = engineer_info def __repr__(self): return self.__class__.__name__ + " " + self.name + " '" + \ self.nickname + "' " + self.engineer_info pjoin = polymorphic_union({ 'manager': managers_table, 'engineer': engineers_table, 'hacker': hackers_table }, 'type', 'pjoin') pjoin2 = polymorphic_union({ 'engineer': engineers_table, 'hacker': hackers_table }, 'type', 'pjoin2') employee_mapper = mapper(Employee, pjoin, polymorphic_on=pjoin.c.type) 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') hacker_mapper = mapper(Hacker, hackers_table, inherits=engineer_mapper, concrete=True, polymorphic_identity='hacker') session = create_session() session.save(Manager('Tom', 'knows how to manage things')) session.save(Engineer('Jerry', 'knows how to program')) session.save(Hacker('Kurt', 'Badass', 'knows how to hack')) session.flush() session.clear() assert set([repr(x) for x in session.query(Employee).all()]) == \ set(["Engineer Jerry knows how to program", "Manager Tom knows how to manage things", "Hacker Kurt 'Badass' knows how to hack"]) assert set([repr(x) for x in session.query(Manager).all()]) == set(["Manager Tom knows how to manage things"]) assert set([repr(x) for x in session.query(Engineer).all()]) == \ set(["Engineer Jerry knows how to program", "Hacker Kurt 'Badass' knows how to hack"]) def test_multi_level_2(): metadata.drop_all() 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 Hacker(Engineer): def __init__(self, name, nickname, engineer_info): self.name = name self.nickname = nickname self.engineer_info = engineer_info def __repr__(self): return self.__class__.__name__ + " " + self.name + " '" + \ self.nickname + "' " + self.engineer_info pjoin = polymorphic_union({ 'manager': managers_table, 'engineer': engineers_table, 'hacker': hackers_table }, 'type', 'pjoin') pjoin2 = polymorphic_union({ 'engineer': engineers_table, 'hacker': hackers_table }, 'type', 'pjoin2') employee_mapper = mapper(Employee, pjoin, polymorphic_on=pjoin.c.type) manager_mapper = mapper(Manager, managers_table, inherits=employee_mapper, concrete=True, polymorphic_identity='manager') engineer_mapper = mapper(Engineer, pjoin2, polymorphic_on=pjoin2.c.type, inherits=employee_mapper, concrete=True, polymorphic_identity='engineer') hacker_mapper = mapper(Hacker, hackers_table, inherits=engineer_mapper, concrete=True, polymorphic_identity='hacker') session = create_session() session.save(Manager('Tom', 'knows how to manage things')) session.save(Engineer('Jerry', 'knows how to program')) session.save(Hacker('Kurt', 'Badass', 'knows how to hack')) session.flush() session.clear() assert set([repr(x) for x in session.query(Employee).all()]) == \ set(["Engineer Jerry knows how to program", "Manager Tom knows how to manage things", "Hacker Kurt 'Badass' knows how to hack"]) assert set([repr(x) for x in session.query(Manager).all()]) == set(["Manager Tom knows how to manage things"]) assert set([repr(x) for x in session.query(Engineer).all()]) == \ set(["Engineer Jerry knows how to program", "Hacker Kurt 'Badass' knows how to hack"])