alastair -
the thing i am working on currently in 0.2 is:
mapper(Person, people)
mapper(Engineer, engineers, inherits=class_mapper(Person))
mapper(Manager, managers, inherits=class_mapper(Person))
people_mapper = mapper(
Person, person_join,
polymorphic_on=person_join.c.type,
polymorphic_map={'engineer':Engineer,
'manager':Manager},
non_primary=True
)
so no MapperExtension would be needed anymore. itll have to keep
track of using the proper mappers to generate identity_keys and all
that. perhaps, after the above is working, the syntax could get even
more sparse and not require the explicit three mappers ahead of time,
but im not sure about that yet.
The same arguments would also be just as useful with a single Mapper
that is doing single-table inheritance.
I think the original polymorph blog post and subsequent discussion,
while it wasnt an extremely useful thing by itself, was the natural
evolution of adding a full-blown feature to the Mapper.
On Apr 27, 2006, at 10:41 AM, Alastair Houghton wrote:
Hi all,
As is probably obvious from some of my previous posts, I'm trying
to use a polymorphic mapper (via a MapperExtension). As is
probably also obvious, there seem to be a few problems. Anyway, I
think I've got to the bottom of one of them; in Michael's example
"polymorph2.py", the MapperExtension looks like this:
# MapperExtension object.
class PersonLoader(MapperExtension):
def create_instance(self, mapper, row, imap, class_):
if row[person_join.c.type] =='engineer':
return Engineer()
elif row[person_join.c.type] =='manager':
return Manager()
else:
return Person()
def populate_instance(self, mapper, session, instance, row,
identitykey, imap, isnew):
if row[person_join.c.type] =='engineer':
Engineer.mapper.populate_instance(session,
instance, row, identitykey, imap, isnew, frommapper=mapper)
return False
elif row[person_join.c.type] =='manager':
Manager.mapper.populate_instance(session, instance,
row, identitykey, imap, isnew, frommapper=mapper)
return False
else:
return sqlalchemy.mapping.EXT_PASS
which is fine *except* that if you look carefully, you'll spot that
you can easily end up with more than one instance of e.g. Engineer
or Manager for the same person_id, because the _instance() method
in mapper.py initially generates the identity_key (which is the key
SQLAlchemy uses to ensure that object instances are unique) from
the Person mapper, not from the Engineer or Manager mappers. As a
result, it won't find a pre-existing Engineer or Manager object,
and all sorts of crazy behaviour can then ensue.
There are a few possible approaches to fixing this:
1. Add another method to the MapperExtension class to find the
mapper to use for identity key generation. This has the advantage
that it's straightforward, and it also maintains the existing
MapperExtension-based approach. However, the disadvantage is that
the MapperExtension code required for polymorphism is getting less
and less obvious.
2. Add a method to MapperExtension specifically to support
polymorphism, and push the (effects of) the code above down into
Mapper. This has the advantage that the implementation of
polymorphism won't require mapping the row data into the required
form for the target class's mapper twice (like it does at the
moment), and it also would simplify using a MapperExtension for
this purpose. But perhaps this is too specialised a change to a
generic extension mechanism?
3. Add polymorphism support directly to the Mapper class itself.
So instead of writing
mapper(Person, person_join, extension=personLoaderExtension)
you might write
mapper(Person, person_join, type_selector=person_join.c.type,
type_map={ 'engineer': Engineer, 'manager': Manager })
This would be easier to understand IMO, and doesn't preclude use of
a MapperExtension for any other purpose.
I want to use this functionality, so I'm happy to do the work and
submit a patch; I'm just trying to work out what everyone prefers
syntax/design-wise.
Kind regards,
Alastair.
--
http://www.alastairs-place.net
-------------------------------------------------------
Using Tomcat but need to do more? Need to support web services,
security?
Get stuff done quickly with pre-integrated technology to make your
job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache
Geronimo
http://sel.as-us.falkag.net/sel?
cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Sqlalchemy-users mailing list
Sqlalchemy-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users
-------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Sqlalchemy-users mailing list
Sqlalchemy-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users