if its not doing a topological sort properly, particularly if you get different results based on if a .py file is compiled or not, then theres a dependency there which SA is not picking up on, so the topological results are random. Your "users" and "groups" mappers should be associated with the "principals" mapper via a standard inheritance relationship, using the "inherits" keyword. your "group_members" table should be associated with the "group" mapper through a many-to-many relationship against the "principals" mapper. this is all before any "polymorphic" mapper is even contstructed; everything regarding saving objects should work prior to its being defined at all. when the "polymorphic" mapper is added in, its used only for selecting and should have no impact on the commit operation.

On Apr 1, 2006, at 9:52 AM, Alastair Houghton wrote:

Hi all,

I'm trying to make something similar to Michael's polymorphism sample (from his blog) work, but I'm finding that SQLAlchemy isn't respecting the ordering restrictions imposed by the ForeignKey() constraints on my tables. Here are the table definitions:

sec_principals = Table('sec_principals', db,
Column('principal_id', Integer, primary_key=True),
                       Column('name', String(64), nullable=False),
                       mysql_engine='InnoDB')

sec_users = Table('sec_users', db,
                  Column('user_id', Integer,
                         ForeignKey('sec_principals.principal_id'),
                         primary_key=True),
                  Column('first_name', String(32), nullable=False),
                  Column('last_name', String(32), nullable=False),
                  Column('email_address', String(64), nullable=False),
                  Column('password', String(48), nullable=False),
                  mysql_engine='InnoDB')

sec_groups = Table('sec_groups', db,
                   Column('group_id', Integer,
                          ForeignKey('sec_principals.principal_id'),
                          primary_key=True),
                   Column('description', String(64)),
                   mysql_engine='InnoDB')

sec_group_members = Table('sec_group_members', db,
                          Column('group_id', Integer,
                                 ForeignKey('sec_groups.group_id'),
                                 nullable=False),
                          Column('member_id', Integer,
ForeignKey ('sec_principals.principal_id'),
                                 nullable=False),
                          mysql_engine='InnoDB')

and the problem I'm seeing is that when I do

  u = User(name='alastair', ...)
  g = Group(name='Users', ...)
  g.members.append(u)
  objectstore.commit()

SQLAlchemy keeps trying to insert into sec_group_members before it has inserted the user record in sec_users. Obviously this will fail because the user doesn't have an ID until it's been inserted.

Surely this should work without requiring an additional objectstore.commit()? Or am I doing something wrong here?

(I should also perhaps note that, bizarrely, this behaviour only seems to occur when Python has generated .pyc files for the package containing the tables and mapping definitions...)

In case it matters, my mappers look like this:

principal_join = select(
    [sec_principals,
     sec_users.c.first_name,
     sec_users.c.last_name,
     sec_users.c.email_address,
     sec_users.c.password,
     column("'user'").label('type')],
    sec_principals.c.principal_id==sec_users.c.user_id).union_all(
    select(
    [sec_principals,
     sec_groups.c.description,
     column("'group'").label('type')],
sec_principals.c.principal_id==sec_groups.c.group_id)).alias ('pjoin')

class PrincipalLoader(MapperExtension):
    def create_instance(self, mapper, row, imap, class_):
        if row['pjoin_type'] == 'user':
            return User()
        elif row['pjoin_type'] == 'group':
            return Group()
        else:
            return Principal()

principalLoaderExtension = PrincipalLoader()
assign_mapper(Principal, sec_principals)
Principal.dumb_mapper = Principal.mapper
Principal.mapper = mapper(Principal,
                          principal_join,
                          extension=principalLoaderExtension)
assign_mapper(User, sec_users, inherits=Principal.dumb_mapper)
assign_mapper(Group, sec_groups, inherits=Principal.dumb_mapper)
Principal.dumb_mapper.add_property('groups',
relation(Group.mapper, sec_group_members,
                                            backref='members'))
Group.mapper.add_property('members',
relation(Principal.mapper, sec_group_members,
                                   backref='groups'))
Principal.mapper.add_property('groups',
relation(Group.mapper, sec_group_members,
                                       backref='members'))

I'm using the latest SQLAlchemy from Subversion (i.e. revision 1234), in case that's relevant.

Kind regards,

Alastair.

--
http://www.alastairs-place.net




-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language that extends applications into web and mobile media. Attend the live webcast and join the prime developer group breaking into this new coding territory! http://sel.as-us.falkag.net/sel? cmd=lnk&kid=110944&bid=241720&dat=121642
_______________________________________________
Sqlalchemy-users mailing list
Sqlalchemy-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
_______________________________________________
Sqlalchemy-users mailing list
Sqlalchemy-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users

Reply via email to