diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-08-01 15:05:53 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-08-01 19:41:04 -0400 |
commit | 14fdd6260a578488bdad95b738ea6af5c2fcd13c (patch) | |
tree | 4801e916ea7e2008857dae0be86898d8adadfd1c /lib/sqlalchemy/orm/session.py | |
parent | 3d5a64ac09b55514da6fd30f0f085348c2d10496 (diff) | |
download | sqlalchemy-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.py | 27 |
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): |