summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authormike bayer <mike_mp@zzzcomputing.com>2020-08-05 04:49:57 +0000
committerGerrit Code Review <gerrit@bbpush.zzzcomputing.com>2020-08-05 04:49:57 +0000
commitba9380ef28871b2274ab0bab75e5efddf2ced467 (patch)
treea69613dca1434c25ed2b8bfb877338206213f4e4 /doc
parentc813fe1678c4edbce32f0652353ed70f0a14566f (diff)
parent14fdd6260a578488bdad95b738ea6af5c2fcd13c (diff)
downloadsqlalchemy-ba9380ef28871b2274ab0bab75e5efddf2ced467.tar.gz
Merge "Establish future behavior for Session cascade backrefs, bind"
Diffstat (limited to 'doc')
-rw-r--r--doc/build/changelog/migration_14.rst47
-rw-r--r--doc/build/changelog/unreleased_14/5150.rst17
-rw-r--r--doc/build/errors.rst49
-rw-r--r--doc/build/orm/cascades.rst13
4 files changed, 123 insertions, 3 deletions
diff --git a/doc/build/changelog/migration_14.rst b/doc/build/changelog/migration_14.rst
index ff4d58da7..08ff190b8 100644
--- a/doc/build/changelog/migration_14.rst
+++ b/doc/build/changelog/migration_14.rst
@@ -1396,6 +1396,53 @@ configured to raise an exception using the Python warnings filter.
:ticket:`4662`
+.. _change_5150:
+
+cascade_backrefs behavior deprecated for removal in 2.0
+-------------------------------------------------------
+
+SQLAlchemy has long had a behavior of cascading objects into the
+:class:`_orm.Session` based on backref assignment. Given ``User`` below
+already in a :class:`_orm.Session`, assigning it to the ``Address.user``
+attribute of an ``Address`` object, assuming a bidrectional relationship
+is set up, would mean that the ``Address`` also gets put into the
+:class:`_orm.Session` at that point::
+
+ u1 = User()
+ session.add(u1)
+
+ a1 = Address()
+ a1.user = u1 # <--- adds "a1" to the Session
+
+The above behavior was an unintended side effect of backref behavior, in that
+since ``a1.user`` implies ``u1.addresses.append(a1)``, ``a1`` would get
+cascaded into the :class:`_orm.Session`. This remains the default behavior
+throughout 1.4. At some point, a new flag :paramref:`_orm.relationship.cascade_backrefs`
+was added to disable to above behavior, as it can be surprising and also gets in
+the way of some operations where the object would be placed in the :class:`_orm.Session`
+too early and get prematurely flushed.
+
+In 2.0, the default behavior will be that "cascade_backrefs" is False, and
+additionally there will be no "True" behavior as this is not generally a desirable
+behavior. When 2.0 deprecation warnings are enabled, a warning will be emitted
+when a "backref cascade" actually takes place. To get the new behavior, either
+set :paramref:`_orm.relationship.cascade_backrefs` to ``False`` on the target
+relationship, as is already supported in 1.3 and earlier, or alternatively make
+use of the :paramref:`_orm.Session.future` flag to :term:`2.0-style` mode::
+
+ Session = sessionmaker(engine, future=True)
+
+ with Session() as session:
+ u1 = User()
+ session.add(u1)
+
+ a1 = Address()
+ a1.user = u1 # <--- will not add "a1" to the Session
+
+
+
+:ticket:`5150`
+
.. _change_4994:
Persistence-related cascade operations disallowed with viewonly=True
diff --git a/doc/build/changelog/unreleased_14/5150.rst b/doc/build/changelog/unreleased_14/5150.rst
new file mode 100644
index 000000000..1d72185ec
--- /dev/null
+++ b/doc/build/changelog/unreleased_14/5150.rst
@@ -0,0 +1,17 @@
+.. change::
+ :tags: bug, orm
+ :tickets: 5150
+
+ 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.
+
+ .. seealso::
+
+ :ref:`change_5150`
diff --git a/doc/build/errors.rst b/doc/build/errors.rst
index 961aa4d70..d4659101a 100644
--- a/doc/build/errors.rst
+++ b/doc/build/errors.rst
@@ -118,6 +118,55 @@ are part of SQLAlchemy 1.4 and are there to help migrate an application to the
the 1.x series, as well as the current goals and progress of SQLAlchemy
2.0.
+.. _error_c9bf:
+
+A bind was located via legacy bound metadata, but since future=True is set on this Session, this bind is ignored.
+-------------------------------------------------------------------------------------------------------------------
+
+The concept of "bound metadata" is being removed in SQLAlchemy 2.0. This
+refers to the :paramref:`_schema.MetaData.bind` parameter on the
+:class:`_schema.MetaData` object that in turn allows objects like the ORM
+:class:`_orm.Session` to associate a particular mapped class with an
+:class:`_orm.Engine`. In SQLAlchemy 2.0, the :class:`_orm.Session` must be
+linked to each :class:`_orm.Engine` directly. That is, instead of instantating
+the :class:`_orm.Session` or
+:class:`_orm.sessionmaker` without any arguments, and associating the
+:class:`_engine.Engine` with the :class:`_schema.MetaData`::
+
+ engine = create_engine("sqlite://")
+ Session = sessionmaker()
+ metadata = MetaData(bind=engine)
+ Base = declarative_base(metadata=metadata)
+
+ class MyClass(Base):
+ # ...
+
+
+ session = Session()
+ session.add(MyClass())
+ session.commit()
+
+The :class:`_engine.Engine` must instead be associated directly with the
+:class:`_orm.sessionmaker` or :class:`_orm.Session`. The
+:class:`_schema.MetaData` object should no longer be associated with any
+engine::
+
+
+ engine = create_engine("sqlite://")
+ Session = sessionmaker(engine)
+ Base = declarative_base()
+
+ class MyClass(Base):
+ # ...
+
+
+ session = Session()
+ session.add(MyClass())
+ session.commit()
+
+In SQLAlchemy 1.4, this :term:`2.x style` behavior is enabled when the
+:paramref:`_orm.Session.future` flag is set on :class:`_orm.sessionmaker`
+or :class:`_orm.Session`.
Connections and Transactions
============================
diff --git a/doc/build/orm/cascades.rst b/doc/build/orm/cascades.rst
index 332ccc5fa..8631dedbe 100644
--- a/doc/build/orm/cascades.rst
+++ b/doc/build/orm/cascades.rst
@@ -559,9 +559,16 @@ operation should be propagated down to referred objects.
Controlling Cascade on Backrefs
-------------------------------
-The :ref:`cascade_save_update` cascade by default takes place on attribute change events
-emitted from backrefs. This is probably a confusing statement more
-easily described through demonstration; it means that, given a mapping such as this::
+.. note:: This section applies to a behavior that is removed in SQLAlchemy 2.0.
+ By setting the :paramref:`_orm.Session.future` flag on a given
+ :class:`_orm.Session`, the 2.0 behavior will be achieved which is
+ essentially that the :paramref:`_orm.relationship.cascade_backrefs` flag is
+ ignored. See the section :ref:`change_5150` for notes.
+
+In :term:`1.x style` ORM usage, the :ref:`cascade_save_update` cascade by
+default takes place on attribute change events emitted from backrefs. This is
+probably a confusing statement more easily described through demonstration; it
+means that, given a mapping such as this::
mapper(Order, order_table, properties={
'items' : relationship(Item, backref='order')