- changed status to resolved
merge is calling expire on pending/transient instances
-
InstanceState.expire_attributes
should raise ifself.key
isNone
-
InstanceState
should gainhas_identity
and we should loseorm.util._state_has_identity
so this check always available -
ColumnProperty.merge
should be checkinghas_identity
before expiring#!python from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.orm import attributes from sqlalchemy import exc
metadata = MetaData() foo = Table('foo', metadata, Column('id', Integer, primary_key=True), Column('data', String) ) engine = create_engine('sqlite://', echo=True) metadata.create_all(engine)
class Foo(object): pass
mapper(Foo, foo) session = sessionmaker()()
f1 = Foo() session.add(f1)
state = attributes.instance_state(f1) attributes.instance_state(f1).expire_attributes(state.dict, 'data')
try: print f1.data except exc.UnboundExecutionError: # should not be hitting the DB print "raised !"
session.bind = engine f2 = Foo() f2.id = 2 f2 = session.merge(f2)
session.bind = None try: f2.data except exc.UnboundExecutionError: # should not be hitting the DB print "raised !"
also see related test in #1681
Comments (2)
-
reporter -
reporter - removed milestone
Removing milestone: 0.6.1 (automated comment)
- Log in to comment
6ea6673376609ce6a5e26f9f20425cffee96bcd8. Interestingly, disallowing
state.expire_attributes()
on a "pending" state is not at all an option here, since expiration occurs within theflush()
process for states that have just become persistent, but don't yet have their key assigned. In some cases the loader is even fired off before the flush finishes and hence beforestate.key
is assigned. The key assignment currently happens at the end in most cases in_register_newly_persistent()
since we bookkeep for some "key switch" scenarios there after all SQL has been emitted.