Hi there, Using SQLAlchemy 1.0.9
I am dealing with some legacy code and came across the following issue. It appears that in a polymorphic relationship SQLAlchemy is not able to correctly determine what to load for a relationship when using a subselect (due to limit on query) and child class has a different field name for the primary key. Here is a reproducible test case to show the issue better: from uuid import uuid1 as uuid import sqlalchemy import sqlalchemy.orm from sqlalchemy import ( Column, Unicode, ForeignKey, CHAR, Boolean, UniqueConstraint ) from sqlalchemy.orm import relationship, backref, synonym from sqlalchemy.ext.declarative import declarative_base, declared_attr Base = declarative_base() class Context(Base): '''Represent a context.''' __tablename__ = 'context' context_type = Column(Unicode(32), nullable=False) __mapper_args__ = { 'polymorphic_on': context_type, 'polymorphic_identity': 'context' } id = Column(CHAR(36), primary_key=True, default=lambda: str(uuid())) class Task(Context): '''Represent a task.''' __tablename__ = 'task' __mapper_args__ = { 'polymorphic_identity': 'task' } # Change this and references to it to 'id' to fix issue. task_id = Column( CHAR(36), ForeignKey('context.id'), primary_key=True ) scopes = relationship('Scope', secondary='task_scope') class Scope(Base): '''Represent a Scope.''' __tablename__ = 'scope' id = Column(CHAR(36), primary_key=True, default=lambda: str(uuid())) class TaskScope(Base): '''Represent a relation between a scope and a task.''' __tablename__ = 'task_scope' id = Column(CHAR(36), primary_key=True, default=lambda: str(uuid())) scope_id = Column(CHAR(36), ForeignKey(Scope.id), nullable=False) task_id = Column(CHAR(36), ForeignKey(Task.task_id), nullable=False) def main(): '''Execute test.''' engine = sqlalchemy.create_engine('sqlite://') Base.metadata.create_all(engine) Session = sqlalchemy.orm.sessionmaker(bind=engine) session = Session() task = Task() scope = Scope() session.add(task) session.add(scope) session.commit() link = TaskScope(scope_id=scope.id, task_id=task.task_id) session.add(link) session.commit() query = session.query(Task).options( sqlalchemy.orm.load_only('context_type'), sqlalchemy.orm.joinedload('scopes').load_only() ).limit(10) print query results = query.all() print results if __name__ == '__main__': main() Running the above gives: sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such column: task.task_id [SQL: u'SELECT anon_1.context_context_type AS anon_1_context_context_type, anon_1.context_id AS anon_1_context_id, anon_2.scope_1_id AS scope_1_id \nFROM (SELECT context.context_type AS context_context_type, context.id AS context_id \nFROM context JOIN task ON context.id = task.task_id\n LIMIT ? OFFSET ?) AS anon_1 LEFT OUTER JOIN (SELECT task_scope_1.id AS task_scope_1_id, task_scope_1.scope_id AS task_scope_1_scope_id, task_scope_1.task_id AS task_scope_1_task_id, scope_1.id AS scope_1_id \nFROM task_scope AS task_scope_1 JOIN scope AS scope_1 ON scope_1.id = task_scope_1.scope_id) AS anon_2 ON task.task_id = anon_2.task_scope_1_task_id'] [parameters: (10, 0)] If you change 'task_id' to 'id' (and references to it) then the query will now work correctly. As I mentioned this is legacy code so there are many references to task_id throughout the code base unfortunately. I have found a workaround by using a synonym, but wanted to report the issue to see if the failure is expected and there is a requirement for the primary key field names to match or not. cheers, Martin -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.