diff options
| author | mike bayer <mike_mp@zzzcomputing.com> | 2020-08-05 04:49:57 +0000 |
|---|---|---|
| committer | Gerrit Code Review <gerrit@bbpush.zzzcomputing.com> | 2020-08-05 04:49:57 +0000 |
| commit | ba9380ef28871b2274ab0bab75e5efddf2ced467 (patch) | |
| tree | a69613dca1434c25ed2b8bfb877338206213f4e4 /doc | |
| parent | c813fe1678c4edbce32f0652353ed70f0a14566f (diff) | |
| parent | 14fdd6260a578488bdad95b738ea6af5c2fcd13c (diff) | |
| download | sqlalchemy-ba9380ef28871b2274ab0bab75e5efddf2ced467.tar.gz | |
Merge "Establish future behavior for Session cascade backrefs, bind"
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/build/changelog/migration_14.rst | 47 | ||||
| -rw-r--r-- | doc/build/changelog/unreleased_14/5150.rst | 17 | ||||
| -rw-r--r-- | doc/build/errors.rst | 49 | ||||
| -rw-r--r-- | doc/build/orm/cascades.rst | 13 |
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') |
