zzzeek / test_sqlalchemy

0 stars 0 forks source link

expunge not fully effective? #861

Closed sqlalchemy-bot closed 16 years ago

sqlalchemy-bot commented 16 years ago

Issue created by Anonymous


Hi.

The attached code works with SQLAlchemy 0.3, but with SQLAlchemy 0.4 (from trunk) I get:

Traceback (most recent call last):
  File "orm_expunge.py", line 67, in ?
    transact(db, update, obj)
  File "orm_expunge.py", line 27, in transact
    ret = f(conn, sess, *args, **kwargs)
  File "orm_expunge.py", line 54, in update
    sess.save(oldobj)
  File "/home/manlio/projects/svn-external/sqlalchemy/trunk/lib/sqlalchemy/orm/session.py", line 794, in save
    self._save_impl(object, entity_name=entity_name)
  File "/home/manlio/projects/svn-external/sqlalchemy/trunk/lib/sqlalchemy/orm/session.py", line 962, in _save_impl
    raise exceptions.InvalidRequestError("Instance '%s' is already persistent" % mapperutil.instance_str(obj))
sqlalchemy.exceptions.InvalidRequestError: Instance 'Test@-0x4882bab4' is already persistent

Attachments: orm_expunge.py

sqlalchemy-bot commented 16 years ago

Michael Bayer (zzzeek) wrote:


sorry, the test script is incorrect; save() is not meant to be used for persistent objects; use update() or save_or_update(). this is a recent change in trunk so that people dont get confused by the meaning of save() and as I've been telling people I might replace all three of save/update/save_or_update with a single "add()" method. below, we assert that the expunge worked and also use update():

from sqlalchemy import engine, schema, orm, types

metadata = schema.MetaData()

test = schema.Table(
    'test', metadata,
    schema.Column('id', types.Integer, primary_key=True),
    schema.Column('x', types.String)
    )

class Test(object):
    def __init__(self, id, x):
        self.id = id
        self.x = x

test_mapper = orm.mapper(Test, test)

def transact(db, f, *args, **kwargs):
    conn = db.connect()
    trans = conn.begin()
    sess = orm.create_session(bind=conn)

    ret = f(conn, sess, *args, **kwargs)

    sess.flush()
    sess.close()
    trans.commit()
    conn.close()

    return ret

def insert(conn, sess):
    obj = Test(0, 'test')
    sess.save(obj)

def select(conn, sess):
    obj = sess.get(test_mapper, 0)

    obj.x = 'x'

    assert obj in sess

    # Do not update the database now
    sess.expunge(obj)

    assert obj not in sess

    return obj

def update(conn, sess, obj):
    oldobj = sess.get(test_mapper, 0)
    oldobj.x = obj.x

    sess.update(oldobj)

URL = 'sqlite://'
db = engine.create_engine(URL, echo=False)
metadata.bind = db

try:
    metadata.create_all()

    transact(db, insert)
    obj = transact(db, select)
    transact(db, update, obj)
finally:
    metadata.drop_all()
sqlalchemy-bot commented 16 years ago

Changes by Michael Bayer (zzzeek): set state to "invalid"