Re: [Sqlalchemy-tickets] [sqlalchemy] #2921: backref relationships with cascade delete-orphan throw
Brought to you by:
zzzeek
|
From: sqlalchemy <mi...@zz...> - 2014-01-27 18:47:24
|
#2921: backref relationships with cascade delete-orphan throw IntegrityError when
child is replaced
------------------------------+----------------------------------
Reporter: elmer | Owner: zzzeek
Type: defect | Status: new
Priority: high | Milestone: 0.9.xx
Component: orm | Severity: minor - half an hour
Resolution: | Keywords:
Progress State: needs tests |
------------------------------+----------------------------------
Changes (by zzzeek):
* priority: medium => high
* status_field: awaiting triage => needs tests
* component: (none) => orm
* severity: no triage selected yet => minor - half an hour
* milestone: => 0.9.xx
Comment:
Here's a patch that would the be the ORM's first foray into disabling
autoflush at certain places. Typically I never want to do this, but as
this is in the middle of attribute state being modified it might be
appropriate; but mostly making the case easy here is that all tests
continue to pass. i might be able to make this for 0.9.2.
{{{
#!diff
diff --git a/lib/sqlalchemy/orm/attributes.py
b/lib/sqlalchemy/orm/attributes.py
index e5f8550..08156a6 100644
--- a/lib/sqlalchemy/orm/attributes.py
+++ b/lib/sqlalchemy/orm/attributes.py
@@ -23,7 +23,7 @@ from .base import PASSIVE_NO_RESULT, ATTR_WAS_SET,
ATTR_EMPTY, NO_VALUE,\
NEVER_SET, NO_CHANGE, CALLABLES_OK, SQL_OK,
RELATED_OBJECT_OK,\
INIT_OK, NON_PERSISTENT_OK, LOAD_AGAINST_COMMITTED,
PASSIVE_OFF,\
PASSIVE_RETURN_NEVER_SET, PASSIVE_NO_INITIALIZE,
PASSIVE_NO_FETCH,\
- PASSIVE_NO_FETCH_RELATED, PASSIVE_ONLY_PERSISTENT
+ PASSIVE_NO_FETCH_RELATED, PASSIVE_ONLY_PERSISTENT,
NO_AUTOFLUSH
from .base import state_str, instance_str
@inspection._self_inspects
@@ -761,7 +761,8 @@ class ScalarObjectAttributeImpl(ScalarAttributeImpl):
"""
if self.dispatch._active_history:
- old = self.get(state, dict_, passive=PASSIVE_ONLY_PERSISTENT)
+ old = self.get(state, dict_, passive=PASSIVE_ONLY_PERSISTENT
+ | NO_AUTOFLUSH)
else:
old = self.get(state, dict_, passive=PASSIVE_NO_FETCH)
diff --git a/lib/sqlalchemy/orm/base.py b/lib/sqlalchemy/orm/base.py
index 577f9ff..b13396e 100644
--- a/lib/sqlalchemy/orm/base.py
+++ b/lib/sqlalchemy/orm/base.py
@@ -80,6 +80,13 @@ LOAD_AGAINST_COMMITTED =
util.symbol("LOAD_AGAINST_COMMITTED",
""", canonical=32
)
+NO_AUTOFLUSH = util.symbol("NO_AUTOFLUSH",
+"""loader callables should disable autoflush.
+
+.. versionadded:: 0.9.2
+
+""", canonical=64)
+
# pre-packaged sets of flags used as inputs
PASSIVE_OFF = util.symbol("PASSIVE_OFF",
"Callables can be emitted in all cases.",
diff --git a/lib/sqlalchemy/orm/strategies.py
b/lib/sqlalchemy/orm/strategies.py
index bd9b02d..14c2cf9 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -535,8 +535,9 @@ class LazyLoader(AbstractRelationshipLoader):
pending = not state.key
- # don't autoflush on pending
- if pending:
+ # don't autoflush on pending, or if
+ # NO_AUTOFLUSH is in passive flags
+ if pending or passive & attributes.NO_AUTOFLUSH:
q = q.autoflush(False)
if state.load_path:
}}}
--
Ticket URL: <http://www.sqlalchemy.org/trac/ticket/2921#comment:1>
sqlalchemy <http://www.sqlalchemy.org/>
The Database Toolkit for Python
|