On 25/02/2011 17:13, Michael Bayer wrote:
can't reproduce.  See attached.    This test includes randomization of all key 
data structures in the UOW which smokes out any issues in dependency sorting.

Okay, so after about an hour of stripping down code, please find attached a minimal reproducible test case.

As noted in the comments, if sessionmaker isn't used, all is well.

Even if sessionmaker is used, if the user is passed to Grant instead of the username, all is well.

However, if you pass the username *and* use sessionmaker, you'll intermittently get:

IntegrityError: (IntegrityError) (1452, 'Cannot add or update a child row: a foreign key constraint fails (`acl_tests`.`grant`, CONSTRAINT `grant_ibfk_1` FOREIGN KEY (`username`) REFERENCES `user` (`username`) ON DELETE CASCADE)') 'INSERT INTO `grant` (username) VALUES (%s)' ('testname',)

...as the insert of the grant is tried before the insert of the user.

I'm using:

Python 2.6.6
SQLAlchemy 0.6.6
MySQL_python 1.2.3

The MySQL server is running version 5.1.49-3 of debian's mysql-server package.

Good luck!

Chris

--
Simplistix - Content Management, Batch Processing & Python Consulting
           - http://www.simplistix.co.uk

--
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to [email protected].
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.

from sqlalchemy import Column, String, ForeignKey, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, scoped_session, sessionmaker, Session
from unittest import TestCase, main

Base = declarative_base()

class User(Base):
    __tablename__ = 'user'
    __table_args__ = {'mysql_engine':'InnoDB'}
    username = Column(String(50), primary_key=True)
    grants = relationship("Grant",
                          cascade="all",
                          lazy="dynamic")
class Grant(Base):
    __tablename__ = 'grant'
    __table_args__ = {'mysql_engine':'InnoDB'}
    username = Column(String(50),
                      ForeignKey('user.username',ondelete='cascade'),
                      primary_key=True)
    user = relationship("User")

class TestCascades(TestCase):

    def test_delete_user(self):

        engine = create_engine('mysql://scott:tiger@localhost/test',
                               echo=True)

        # uncomment the following line and run until IntegrityErrors
        # appear! (it's intermittent, though, so don't be surprised
        # if it passes a few times...)
        Session = sessionmaker()

        session = Session(bind=engine)
        
        Base.metadata.drop_all(session.bind)
        Base.metadata.create_all(session.bind)

        user = User(username='testname')
        session.add(user)
        # passing the username rather than the user object here is
        # also important, if the user object is passed, things work
        # as expected regardless of whether or not sessionmaker is used.
        session.add(Grant(username=user.username))
        
        self.assertEqual(session.query(User).count(),1)

if __name__ == '__main__':
    main()

Reply via email to