On Jun 28, 2012, at 6:38 AM, tonthon wrote: > Hi, > > I've got a problem understanding how to handle relationships with > polymorphism > Sorry for the db design (I took it overs as it is ). > > I've got a parent class Task > > class Task(DBBASE): > __tablename__ = 'task' > id = Column(Integer, primary_key=True) > amount = Column(Integer) > > and two child classes > > class Invoice(DBBASE): > __tablename__ = 'invoice' > id = Column(Integer, ForeignKey('task.id'), primary_key=True) > date = Column(Date) > project_id = Column(Integer, ForeignKey('project.id')) > project = relationship("Project", backref=backref('invoices', > order_by='Invoice.date')) > specific_attr1 = Column(Integer) > > class Esimation(DBBASE): > __tablename__ = 'estimation' > id = Column(Integer, ForeignKey('task.id'), primary_key=True) > date = Column(Date) > project_id = Column(Integer, ForeignKey('project.id')) > project = relationship("Project", backref=backref('estimations', > order_by='Invoice.date')) > specific_attr2 = Column(Integer) > specific_attr3 = Column(Integer) > > I'd like to query something like: > > dbession.query(Task).with_polymorphic([Invoice, > Estimation]).join(Invoice.project).join(Estimation.project).join(Project.client) > > I actually get an error : > (1066, "Not unique table/alias: 'project' ")
OK you need here to think about SQL. Task, Invoice, Estimation are all different tables. A particular row in Task will either have an Invoice, or Estimation row - but never both. So with_polymorphic() implies an outer join from Task to both of these tables. Once you're outer joining, anything that you join to from those joins, also needs to be an outer join else you'll get no rows back when the parent is NULL - so we are talking about Invoice.project as well as Estimation.project, and also each of those to Project.client - unfortunately you'll have to also join to client twice if you really need all of these columns present. The "not unique" error refers to the fact that a particular name can only be mentioned as a FROM target once in SQL. So you'll need to alias out those targets, like this: p1 = aliased(Project) p2 = aliased(Project) then use outerjoins and distinct joins to client: query(Task).with_polymorphic([Invoice, Estimation]).outerjoin(p1, Invoice.project).outerjoin(p2, Estimation.Project).outerjoin(p1.client).outerjoin(p2.client) the above query has a lot of outer joins and is generally not going to perform very well. Depending on what you're ultimately trying to do, you may want to join to a union of the estimation/invoice->project->client target, if you're looking to have a simple path from Task to Client (that is, query(Task).join(my_union, Task.id=my_union.c.id), and I'd create my_union using Table/select() objects directly for "select client.* from invoice_table->project->client UNION select client.* from estimation_table->project_client". I'd experiment with SQL directly to see what works best. (also this is joined inheritance, not concrete, since Invoice/Estimation join to Task with the "task.id" FK). -- 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 sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.