mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-23 17:11:39 -04:00
Warn on merge of already-pending object
A warning is now emitted for the case where a transient object is being
merged into the session with :meth:`.Session.merge` when that object is
already transient in the :class:`.Session`. This warns for the case where
the object would normally be double-inserted.
Fixes: #4647
Change-Id: Ie5223a59a2856664bf283017e962caf8c4230536
(cherry picked from commit 23a1c60982)
This commit is contained in:
+9
@@ -0,0 +1,9 @@
|
||||
.. change::
|
||||
:tags: bug, orm
|
||||
:tickets: 4647
|
||||
|
||||
A warning is now emitted for the case where a transient object is being
|
||||
merged into the session with :meth:`.Session.merge` when that object is
|
||||
already transient in the :class:`.Session`. This warns for the case where
|
||||
the object would normally be double-inserted.
|
||||
|
||||
@@ -2110,6 +2110,13 @@ class Session(_SessionClassMethods):
|
||||
key = state.key
|
||||
|
||||
if key is None:
|
||||
if state in self._new:
|
||||
util.warn(
|
||||
"Instance %s is already pending in this Session yet is "
|
||||
"being merged again; this is probably not what you want "
|
||||
"to do" % state_str(state)
|
||||
)
|
||||
|
||||
if not load:
|
||||
raise sa_exc.InvalidRequestError(
|
||||
"merge() with load=False option does not support "
|
||||
|
||||
@@ -26,6 +26,7 @@ from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
from sqlalchemy.orm.interfaces import MapperOption
|
||||
from sqlalchemy.testing import assert_raises_message
|
||||
from sqlalchemy.testing import eq_
|
||||
from sqlalchemy.testing import expect_warnings
|
||||
from sqlalchemy.testing import fixtures
|
||||
from sqlalchemy.testing import in_
|
||||
from sqlalchemy.testing import not_in_
|
||||
@@ -84,6 +85,36 @@ class MergeTest(_fixtures.FixtureTest):
|
||||
|
||||
self.assert_sql_count(testing.db, go, 0)
|
||||
|
||||
def test_warn_transient_already_pending_nopk(self):
|
||||
User, users = self.classes.User, self.tables.users
|
||||
|
||||
mapper(User, users)
|
||||
sess = create_session()
|
||||
u = User(name="fred")
|
||||
|
||||
sess.add(u)
|
||||
|
||||
with expect_warnings(
|
||||
"Instance <User.*> is already pending in this Session yet is "
|
||||
"being merged again; this is probably not what you want to do"
|
||||
):
|
||||
u2 = sess.merge(u)
|
||||
|
||||
def test_warn_transient_already_pending_pk(self):
|
||||
User, users = self.classes.User, self.tables.users
|
||||
|
||||
mapper(User, users)
|
||||
sess = create_session()
|
||||
u = User(id=1, name="fred")
|
||||
|
||||
sess.add(u)
|
||||
|
||||
with expect_warnings(
|
||||
"Instance <User.*> is already pending in this Session yet is "
|
||||
"being merged again; this is probably not what you want to do"
|
||||
):
|
||||
u2 = sess.merge(u)
|
||||
|
||||
def test_transient_to_pending_collection(self):
|
||||
User, Address, addresses, users = (
|
||||
self.classes.User,
|
||||
|
||||
Reference in New Issue
Block a user