On Feb 8, 2008, at 2:01 PM, Richard Levasseur wrote:

> Ok, so I'm talking about 2 slightly different things at once:  One  
> is that sqlalchemy doesn't call the mapper extensions when loading  
> the data from the inherited tables.  The second is that it can't  
> load instances unless a record in the inherited table exists.
>
> One:
> By "2 record fetch" I meant, a single instance of Child requires one  
> record to be fetched from `parents` and another record to be fetched  
> from `kids`, and sqlalchemy is correctly doing this with the  
> inherited tables.  What I'm pointing out is that, when it fetches  
> the record from the child table, it doesn't run the mapper  
> extensions (unless i'm doing it wrong).
> 1) session.query(Parent).get(id)
> 2) select ... from parents ...
> 3) translate_row and translate row extensions
> 4) populate instance and populate instance extensions
> 5) I'm polymorphic and am a Child, so query kids: select ... from  
> kids ...
> 6) populate instance (with the data from kids), but extensions  
> aren't run.  (I don't see any calls to translate_row?)
> 7) return instance

thats actually correct - the second query to the child table is not a  
top-level ORM query, its internal to the get() call, so we currently  
don't have any extension hooks there (all of that "call a second  
query" functionality was just introduced in 0.4.)

However, the whole "_post_instance" step where that happens is  
optional.  In your case, I really think you want to be using a  
polymorphic join or union so that the mapper can load parents and  
children from one query.  You do this by specifying the "select_table"  
argument to the mapper(), and usually its an outerjoin among all the  
involved tables or in some cases can be a big UNION of all the  
separate subtables.  But if your select_table only includes the base  
table, that will work too, it just wont populate the secondary  
attributes unless you did something else to make it happen (like in  
your extension).

If you do that, the whole _post_instance() thing won't happen at all;  
your translate_row() will get the only row dealt with, as will your  
populate_instance().  So you *can* in theory issue a second SQL query  
within your own populate_instance() call that simulates what  
_post_instance() does, if you wanted to.  Or I would think you could  
just load everything in one shot here using a series of outerjoins  
among all the tables; theres an example in the docs and in the  
examples/polymorphic  folder illustrating how to load in that way.

>
> Two:
> I've attached an example, essentially this:
>
> Table("parents", Column("id"), Column("type"))
> Table("kids", Column("child_id"), Column("parent_id",  
> FK("parents.id")))
> engine.execute("insert into parents (id, type) values(1, 'child')")  
> # not inserting child record
> session.query(Parent).get(1) # gives an error, "NoneType not  
> iteratable"; the row is None
>
> Note that no record exists in `kids`, this is intentional, it isn't  
> always guaranteed to be there because of the way the system behaves  
> (the workflow engine may change the type outside the application)
>
> It works in our current app (custom php) because when we save the  
> record, we check if the `child_id` is null, if it is we insert,  
> otherwise we update.  During loading, if the `child_id` is null, we  
> just set everything else to null.


yup, works if you do it like this:

mapper(Parent, parents, polymorphic_on=parents.c.type,
       polymorphic_identity="parent",  
select_table=parents.outerjoin(kids), primary_key=[parents.c.id])
mapper(Child, kids, inherits=Parent, polymorphic_identity="child")

note the "primary_key=[parents.c.id]" there, which is to override the  
fact that parents.outerjoin(kids) in fact has a primary key of  
[parents.c.id, kids.c.cid].



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