On Sun, Nov 26, 2017 at 11:19 AM, Mischa S <mis...@jetbridge.com> wrote:
> I want to have a polymorphic table that gets its identity from a column in a
> "type" table. I have a "task" table and a "task_type" table. I want to be
> able to create task subclasses that say something like:
>
>     __mapper_args__ = {
>         'polymorphic_identity': 'do_stuff_task',
>     }
>
> (Assuming that a row with do_stuff_task is created in the task_type table)
>
>
> Currently in my base Task class I do:
>
>     task_type_name =
> column_property(select([TaskType.task_type]).where(TaskType.id ==
> task_type_id).as_scalar())
>
>     __mapper_args__ = {
>         'polymorphic_on': task_type_name,
>     }
>
>
> If I try to get say, a user.do_stuff_tasks relationship it emits the
> following SQL:
>
> SELECT
>   (SELECT task_type.task_type
>    FROM task_type
>    WHERE task_type.id = task.task_type_id)
> FROM task
> WHERE 123 = task.user_id
>   AND
>     (SELECT task_type.task_type
>      FROM task_type
>      WHERE task_type.id = task.task_type_id) IN ('do_stuff_task');
>
>
> This is technically correct, however this query is highly problematic for
> us. It does a scan on task in the subquery, which is extremely unpleasant
> and basically takes forever.
> What I want is something more like:
>
> SELECT *
> FROM task st
> JOIN task_type stt ON st.task_type_id=stt.id
> WHERE stt.task_type='do_stuff_task'
>   AND st.user_id=123;
>
> Is there some way to rewrite the column_property or polymorphic identity
> condition to combine the WHERE conditions in the JOIN instead of doing two
> subselects?
>
>
> Thanks!

Is it strictly necessary for your Task class to be polymorphic? Could
you make TaskType polymorphic instead, and then delegate from Task to
TaskType? Something like this:

class Task(Base):
    def execute(self):
        self.task_type.execute(self)

class TaskType(Base):
    name = sa.Column(sa.String(16))
    __mapper_args__ = {
        'polymorphic_on': name,
    }
    def execute(self, task):
        raise NotImplemented

class DoStuffTaskType(TaskType):
    __mapper_args__ = {
        'polymorphic_on': 'do_stuff_task',
    }
    def execute(self, task):
        # do stuff

Simon

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
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 https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to