Michael Bayer wrote:
> The most crucial, although not the issue in this specific example, is  
> that the "relations" table is used both as the "secondary" table in a  
> relation(), and is also mapped directly to the Relation class.  SQLA  
> does not track this fact and even in a working mapping will attempt to  
> insert multiple, redundant rows into the table if you had, for  
> example, appended to the "records" collection and also created a  
> Relation object.

Right; this did seem wrong in the first place.

> The next issue which is the specific cause of the problem here is that  
> SQLA's topological sort is based off of the relationships between  
> classes and objects, and not directly the foreign key relationships  
> between tables.   Specifically, there is no stated relationship  
> between the Record class and the Soup/Collection classes - yet you  
> append a Record object to the "records" collection which is only meant  
> to store "Soup" objects.  SQLA sees no dependency between the  
> Collection and Record mappers in this case, and the order of table  
> insertion is undefined.  This collection append is only possible due  
> to the "enable_typechecks=False" setting which essentially causes SQLA  
> to operate in a slightly "broken" mode to allow very specific use  
> cases to work (which are not this one- hence SQLA's behavior is still  
> undefined).   "enable_typechecks" , as the initial error message  
> implied when it mentioned "polymorphic mapping", is meant to be used  
> only with inheritance scenarios, and only with objects that are  
> subclasses of the collected object.   It suggests that a certain  
> degree of typechecking should remain even if "enable_typechecks" is  
> set to False (something for me to consider in 0.5).

Thank you for clarifying this; at a certain point it was clear to us 
that SQLA was not equipped to understand what we were doing. I think we 
somehow expected it to look at the FKs.

> I've considered someday doing a rewrite of UOW that ultimately bases  
> topological off of ForeignKey and the actual rows to be inserted, and  
> that's it.   It's nothing that will happen anytime soon as its a huge  
> job and our current UOW is extremely stable and does a spectacular job  
> for almost two years at this point.  But even then, while such an  
> approach might prevent this specific symptom with this specific  
> mapping, it seems like a bad idea in any case to support placing  
> arbitrary, unrelated types into collections that have been defined as  
> storing a certain type.   I'm not sure at all if that approach to UOW  
> wouldn't ultmately have all the same constraints as our current  
> approach anyway.

Certainly stable is good; strictly looking at FKs only might ultimately 
make for a simpler implementation though.

> Fortunately, the solution here is very simple as your table setup is a  
> pure classic joined table inheritance configuration.   The attached  
> script (just one script; sorry, all the buildout stuff seemed a little  
> superfluous here) illustrates a straightforward mapping against these  
> tables which only requires that Record and Collection subclass Soup  
> (which is the nature of the joins on those tables).  The joins  
> themselves are generated automatically by SQLA so theres no need to  
> spell those out.  The "enable_typechecks" flag is still in use here in  
> its stated use case; that you have a collection which can "flush"  
> subtypes of Soup, but when queried later, will only return Soup  
> objects.  You can improve upon that by using a polymorphic  
> discriminator (see the docs for info on that).

Hmm, this solution hadn't occured to me; but it makes a lot of sense. 
This is great.

For what it's worth, we do have a polymorphic "rebuilder" function in 
place to bring back to life these soup items.

With regards to buildout---it's a habit acquired from the Zope 
community; it really is a lot less overhead that you might think :-)

> The script illustrates using the "secondary" table in the "records"  
> collection; this is what seems reasonable considering that there is no  
> other meaningful data in the "relations" table (the surrogate PK in  
> that table is also superfluous).  If there are meaningful columns in  
> your actual application's version of the table, then you'd want to do  
> away with "secondary" and use the association object pattern.

We did start out without the secondary table, manually setting up 
relations, because in fact, we're trying to do an ordered list, which 
requires a ``position`` column.

I'll try to adapt all this into our existing package* and see how it 
works. Your help is much appreciated.

\malthe

*) http://pypi.python.org/pypi/z3c.dobbin

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