I just came across this issue where if an IntegrityError is raised on
session.commit() then the offending object that caused the error is
automatically removed from the session.  If the object is a "child"
object is related to "parent" object and the child object is in
session.new then it is removed from the parent's collection. If it's
not in the session.new then it is removed from the session but not the
parent's collection.

Is this the intended result?  If so, why?

I think this is best explained with code:

--------+ cut +----------

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

uri = 'sqlite:///:memory:'

Base = declarative_base()

class User(Base):
    __tablename__ = 'user'
    name = Column(String, primary_key=True)
    address = relation('Address', uselist=False, cascade='all, delete-
orphan')
    phones = relation('Phone', cascade='all, delete-orphan',
                      backref=backref('accession', uselist=False))

class Address(Base):
    __tablename__ = 'address'
    address = Column(String, primary_key=True)
    user_key = Column(String, ForeignKey('user.name'))

class Phone(Base):
    __tablename__ = 'phone'
    number = Column(String, primary_key=True)
    user_key = Column(String, ForeignKey('user.name'))

engine = create_engine(uri)
Base.metadata.bind = engine
Base.metadata.create_all()
session = sessionmaker()()

def test1():
    """Create the users and address and commit() the changes and then
    later add the phone number...in this case the phone number will be
    removed from user.phones and the session
    """
    user = User(name='Bob')
    address = Address(address='Somewhere')
    user.address = address
    session.add_all([user, address])
    session.commit()

    phone = Phone()
    user.phones.append(phone)
    session.add(phone)

    try:
        session.commit()
    except Exception, e:
        session.rollback()
        print e

    assert phone in user.phones # fails
    assert phone in session # fails


def test2():
    """Create the users and address and commit() the changes and then
    later add the phone number...in this case the phone number will
    still be in user.phones but removed from the session
    """
    user = User(name='Bob')
    address = Address(address='Somewhere')
    phone = Phone()
    user.phones.append(phone)
    user.address = address
    session.add_all([user, address, phone])

    objs = list(session)

    try:
        session.commit()
    except Exception, e:
        session.rollback()
        print e

    # if we re-add all the objects that were in the session before the
    # commit and fix the problem then then everything works fine...
    # is there a downside to this?
    #session.add_all(objs)
    #phone.number=1
    #session.commit()

    assert user.address == address # passes
    assert phone in user.phones # passes
    assert phone in session # fails

#test1()
test2()

-------------------------
--~--~---------~--~----~------------~-------~--~----~
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 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to