If I:

1) start a session (sess1)
2) store some data to sess1 without commit
3) start a second session and link to uncommited data from sess1
4) do a rollback on sess1

I'm finding that the rollback does absolutely nothing - the sess1 data
persists after the rollback.  It is making me not trust rollbacks!

I suspect this is not sqlalchemy that is at fault, but just in case
I've included a contrived example at the bottom of this post.

<assuming you check the code...>

Is this purely a weird sqlite concurrency/locking thing?  I'm not 100%
clear what behaviour I want/expect, but at this point I'm thinking
that the address attach to 'jack' should have failed because 'jack'
was not actually committed yet.  Otherwise it gets confusing what to
do about sess3 being invalid after sess3 is already done and over
with.

Jumping ahead with some assumptions... if managing this "properly" is
something to do with transactions that I'm simply not yet aware of
(I'm not a DBA), is there a DBMS agnostic way through sqlalchemy to
enable "proper" transaction management?

####

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Table, Column, Integer, String, MetaData,
ForeignKey
from sqlalchemy import create_engine
from sqlalchemy.orm import relationship, backref

engine = create_engine('sqlite:///:memory:', echo=True)
metadata = MetaData()

Base = declarative_base()
class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String, unique = True)

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "User('%s')" % self.name

class Address(Base):
    __tablename__ = 'addresses'
    id = Column(Integer, primary_key=True)
    email_address = Column(String, nullable=False)
    user_id = Column(Integer, ForeignKey('users.id'))
    user = relationship(User, backref=backref('addresses',
order_by=id))
    def __init__(self, email_address, UserId = None):
        self.email_address = email_address
        if UserId is not None:
            self.user_id = UserId
    def __repr__(self):
        return "<Address('%s')>" % self.email_address

Base.metadata.create_all(engine)

from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind = engine)
sess = Session()
sess.add_all([User('ed'), User('fred')])
sess.commit()

#sess2 will add a new user (jack), but we'll roll it back in the end
sess2 = Session()
jack = User('jack')
jack.addresses = [Address(email_address='j...@example.com'),
                  Address(email_address='j...@example.org')]
sess2.add(jack)
sess2.flush() #no commit
jack_id = jack.id #flush gets us the id without committing
#Now leave sess2 open without commit for a bit while we link to it in
sess3

#sess3 will create an address linked to jack (before he gets rolled
back)
sess3 = Session()
addr3 = Address("h...@hmm.com", jack_id) #but this id will be rolled
back
# adding to jack in another session succeeds even though jack is not
commited...
sess3.add(addr3)
sess3.commit()

#Now rollback sess2, which should get rid of jack... but doesn't??
sess2.rollback()

print Session().query(User).all()

####

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