I've come up with an implementation based on concrete table
inheritance, without touching any SQLA internals like Michael
suggested. I've also added a discriminator to both base classes,
'citizen_type' and 'employee_type'. The discriminator is set via the
before_insert() method of a MapperExtension which extends the Engineer
mapper.

I realize that going this way forfeits the advantages of the
polymorphic querying, but that's ok for my application. I can still
get the same resuts, it just takes a few subqueries after I query one
of the base classes.

I've run a few tests with this setup and it seems to work - the crux
is in the engineers.join(employees).join(citizens) table definition in
the Engineer mapper and the ForeignKey constraints.

I just wanted to put this out there to see if anyone notices any
issues I am not anticipating or if this model might be helpful to
someone in the future who wants to inherit from two independent base
classes. I realize that the Engineers inheriting from Employees and
Citizens example is a bit forced, sorry about that. This is not my
actual application, I just wanted to give a simple example. Perhaps a
better application would be having 'Dragon' inheriting from both
'Bird' and 'Lizard', as given in the Agile Data essay linked to
earlier.

Here's the setup:

employees = Table('employees', metadata,
  Column('employee_id', Integer, primary_key=True),
  Column('employee_type', String(30), nullable=False)
)

citizens = Table('citizens', metadata,
  Column('citizen_id', Integer, primary_key=True),
  Column('citizen_type', String(30), nullable=False)
)

An engineer who is both an employee and a citizen would have an
employee_id and a citizen_id:

engineers = Table('engineers', metadata,
  Column('id', Integer, primary_key=True)
  Column('employee_id', Integer,
ForeignKey('employees.employee_id')),
  Column('citizen_id', Integer, ForeignKey('citizens.citizen_id')),
  Column('engineer_info', String(50)),
)

And the classes look like:

class Employee(object):
    pass

class Citizen(object):
    pass

class Engineer(Employe, Citizen):
    pass

This is the mapper extension for setting the discriminators:

class EngineerExtension(MapperExtension):

  def __init__(self):
    MapperExtension.__init__(self)

  def before_insert(self, mapper, connection, instance):
    instance.employee_type = 'engineer'
    instance.citizen_type = 'engineer'

And the mappers:

mapper(Engineer, engineers.join(employees).join(citizens),
extension=EngineerExtension())
mapper(Employee, employees)
mapper(Citizen, citizens)

Any comments on this setup are welcome!

Sam
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to