summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/session.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2020-08-01 15:05:53 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2020-08-01 19:41:04 -0400
commit14fdd6260a578488bdad95b738ea6af5c2fcd13c (patch)
tree4801e916ea7e2008857dae0be86898d8adadfd1c /lib/sqlalchemy/orm/session.py
parent3d5a64ac09b55514da6fd30f0f085348c2d10496 (diff)
downloadsqlalchemy-14fdd6260a578488bdad95b738ea6af5c2fcd13c.tar.gz
Establish future behavior for Session cascade backrefs, bind
The behavior of the :paramref:`_orm.relationship.cascade_backrefs` flag will be reversed in 2.0 and set to ``False`` unconditionally, such that backrefs don't cascade save-update operations from a forwards-assignment to a backwards assignment. A 2.0 deprecation warning is emitted when the parameter is left at its default of ``True`` at the point at which such a cascade operation actually takes place. The new behavior can be established as always by setting the flag to ``False`` on a specific :func:`_orm.relationship`, or more generally can be set up across the board by setting the the :paramref:`_orm.Session.future` flag to True. Additionally in the interests of expediency, this commit will also move Session away from making use of bound metadata if the future=True flag is set. An application that sets future=True should ideally have to change as little else as possible for full 2.0 behavior. Fixes: #5150 Change-Id: I490d1d61f09c62ffc2de983208aeed25dfe48aec
Diffstat (limited to 'lib/sqlalchemy/orm/session.py')
-rw-r--r--lib/sqlalchemy/orm/session.py27
1 files changed, 23 insertions, 4 deletions
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index 01163b8d4..25aedd52d 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -1937,16 +1937,34 @@ class Session(_SessionClassMethods):
# now we are in legacy territory. looking for "bind" on tables
# that are via bound metadata. this goes away in 2.0.
+
+ future_msg = ""
+ future_code = ""
+
if mapper and clause is None:
clause = mapper.persist_selectable
if clause is not None:
if clause.bind:
- return clause.bind
+ if self.future:
+ future_msg = (
+ " A bind was located via legacy bound metadata, but "
+ "since future=True is set on this Session, this "
+ "bind is ignored."
+ )
+ else:
+ return clause.bind
if mapper:
if mapper.persist_selectable.bind:
- return mapper.persist_selectable.bind
+ if self.future:
+ future_msg = (
+ " A bind was located via legacy bound metadata, but "
+ "since future=True is set on this Session, this "
+ "bind is ignored."
+ )
+ else:
+ return mapper.persist_selectable.bind
context = []
if mapper is not None:
@@ -1955,8 +1973,9 @@ class Session(_SessionClassMethods):
context.append("SQL expression")
raise sa_exc.UnboundExecutionError(
- "Could not locate a bind configured on %s or this Session"
- % (", ".join(context))
+ "Could not locate a bind configured on %s or this Session.%s"
+ % (", ".join(context), future_msg),
+ code=future_code,
)
def query(self, *entities, **kwargs):