- session.update() raises an error when updating an instance that is already in the session with a different identity
- adjusted zoomarks lower limits so I can get a nice clean run
- Fixed a truncation error when re-assigning a subset of a collection
(obj.relation = obj.relation[1:]) [ticket:834]
-- Added proxying of __contains__ and __iter__ methods for scoped sessions.
+- Added proxying of save_or_update, __contains__ and __iter__ methods for
+ scoped sessions.
+
+- session.update() raises an error when updating an instance that is already
+ in the session with a different identity.
0.4.0
-----
def do(self, *args, **kwargs):
return getattr(self.registry(), name)(*args, **kwargs)
return do
-for meth in ('get', 'load', 'close', 'save', 'commit', 'update', 'flush', 'query', 'delete', 'merge', 'clear', 'refresh', 'expire', 'expunge', 'rollback', 'begin', 'begin_nested', 'connection', 'execute', 'scalar', 'get_bind', 'is_modified', '__contains__', '__iter__'):
+for meth in ('get', 'load', 'close', 'save', 'commit', 'update', 'save_or_update', 'flush', 'query', 'delete', 'merge', 'clear', 'refresh', 'expire', 'expunge', 'rollback', 'begin', 'begin_nested', 'connection', 'execute', 'scalar', 'get_bind', 'is_modified', '__contains__', '__iter__'):
setattr(ScopedSession, meth, instrument(meth))
def makeprop(name):
"""Bring the given detached (saved) instance into this
``Session``.
- If there is a persistent instance with the same identifier
- already associated with this ``Session``, an exception is thrown.
+ If there is a persistent instance with the same instance key, but
+ different identity already associated with this ``Session``, an
+ InvalidRequestError exception is thrown.
This operation cascades the `save_or_update` method to
associated instances if the relation is mapped with
return
if not hasattr(obj, '_instance_key'):
raise exceptions.InvalidRequestError("Instance '%s' is not persisted" % mapperutil.instance_str(obj))
+ elif self.identity_map.get(obj._instance_key, obj) is not obj:
+ raise exceptions.InvalidRequestError("Instance '%s' is with key %s already persisted with a different identity" % (mapperutil.instance_str(obj), obj._instance_key))
self._attach(obj)
def _register_persistent(self, obj):
# set up an invoice
i1 = Invoice()
i1.date = datetime.datetime.now()
- i1.company = c1
+ i1.company = a
item1 = Item()
item1.code = 'aaaa'
log = []
sess.commit()
assert log == ['before_commit', 'after_commit']
+
+ def test_duplicate_update(self):
+ mapper(User, users)
+ Session = sessionmaker()
+ sess = Session()
+
+ u1 = User()
+ sess.save(u1)
+ sess.flush()
+ assert u1.user_id is not None
+
+ sess.expunge(u1)
+
+ assert u1 not in sess
+
+ u2 = sess.query(User).get(u1.user_id)
+ assert u2 is not None and u2 is not u1
+ assert u2 in sess
+ self.assertRaises(Exception, lambda: sess.update(u1))
+
+ sess.expunge(u2)
+ assert u2 not in sess
+
+ u1.user_name = "John"
+ u2.user_name = "Doe"
+
+ sess.update(u1)
+ assert u1 in sess
+
+ sess.flush()
+
+ sess.clear()
+
+ u3 = sess.query(User).get(u1.user_id)
+ assert u3 is not u1 and u3 is not u2 and u3.user_name == u1.user_name
+
class ScopedSessionTest(ORMTest):
def define_tables(self, metadata):
# check it again, identity should be different but ids the same
nu = Session.get(m, u.user_id)
self.assert_(u is not nu and u.user_id == nu.user_id and nu.user_name == 'savetester')
-
+ Session.close()
+
# change first users name and save
Session.update(u)
u.user_name = 'modifiedname'
metadata.create_all()
@testing.supported('postgres')
- @profiling.profiled('populate', call_range=(3580, 4400), always=True)
+ @profiling.profiled('populate', call_range=(3360, 4400), always=True)
def test_1a_populate(self):
Zoo = metadata.tables['Zoo']
Animal = metadata.tables['Animal']
MotherID=bai_yun)
@testing.supported('postgres')
- @profiling.profiled('insert', call_range=(195, 250), always=True)
+ @profiling.profiled('insert', call_range=(180, 250), always=True)
def test_2_insert(self):
Animal = metadata.tables['Animal']
i = Animal.insert()
tick = i.execute(Species='Tick', Name='Tick %d' % x, Legs=8)
@testing.supported('postgres')
- @profiling.profiled('properties', call_range=(3080, 3430), always=True)
+ @profiling.profiled('properties', call_range=(3060, 3430), always=True)
def test_3_properties(self):
Zoo = metadata.tables['Zoo']
Animal = metadata.tables['Animal']
ticks = fullobject(Animal.select(Animal.c.Species=='Tick'))
@testing.supported('postgres')
- @profiling.profiled('expressions', call_range=(11600, 13200), always=True)
+ @profiling.profiled('expressions', call_range=(11450, 13200), always=True)
def test_4_expressions(self):
Zoo = metadata.tables['Zoo']
Animal = metadata.tables['Animal']
assert len(fulltable(Animal.select(func.date_part('day', Animal.c.LastEscape) == 21))) == 1
@testing.supported('postgres')
- @profiling.profiled('aggregates', call_range=(1050, 1270), always=True)
+ @profiling.profiled('aggregates', call_range=(1020, 1270), always=True)
def test_5_aggregates(self):
Animal = metadata.tables['Animal']
Zoo = metadata.tables['Zoo']
legs.sort()
@testing.supported('postgres')
- @profiling.profiled('editing', call_range=(1330, 1390), always=True)
+ @profiling.profiled('editing', call_range=(1300, 1390), always=True)
def test_6_editing(self):
Zoo = metadata.tables['Zoo']
assert SDZ['Founded'] == datetime.date(1935, 9, 13)
@testing.supported('postgres')
- @profiling.profiled('multiview', call_range=(2870, 3155), always=True)
+ @profiling.profiled('multiview', call_range=(2850, 3155), always=True)
def test_7_multiview(self):
Zoo = metadata.tables['Zoo']
Animal = metadata.tables['Animal']
s.flush()
s.clear()
+ user = s.query(User).get(user_id)
blog = s.query(Blog).get(blog_id)
post = blog.posts[0]
comment = Comment(subject="some subject", body="some body")