which improves upon the experimental version of this feature first introduced
in SQLAlchemy 1.4.
* the :class:`_orm.Session` "bulk" operations described at
- :ref:`bulk_operations`, which are superseded by the above mentioned
+ bulk_operations, which are superseded by the above mentioned
ORM Bulk Insert feature.
To get a sense of the scale of the operation, below are performance
extensions = [
"sphinx.ext.autodoc",
- "zzzeeksphinx",
"changelog",
"sphinx_paramlinks",
"sphinx_copybutton",
]
-needs_extensions = {"zzzeeksphinx": "1.2.1"}
# Add any paths that contain templates here, relative to this directory.
# not sure why abspath() is needed here, some users
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
-html_theme = "zzzeeksphinx"
+html_theme = "nature"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# Additional templates that should be rendered to pages, maps page names to
# template names.
-html_additional_pages = {"notfound": "notfound.html"}
+# html_additional_pages = {"notfound": "notfound.html"}
# If false, no module index is generated.
html_domain_indices = False
Using Lambdas to add significant speed gains to statement production
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. deepalchemy:: This technique is generally non-essential except in very performance
- intensive scenarios, and intended for experienced Python programmers.
- While fairly straightforward, it involves metaprogramming concepts that are
- not appropriate for novice Python developers. The lambda approach can be
- applied to at a later time to existing code with a minimal amount of effort.
-
Python functions, typically expressed as lambdas, may be used to generate
SQL expressions which are cacheable based on the Python code location of
the lambda function itself as well as the closure variables within the
.. autoclass:: Composite
-.. .. autoclass:: CompositeProperty
- .. :members:
-
.. autoclass:: AttributeEventToken
:members:
.. _bulk_operations:
-Bulk Operations
-===============
-
-.. legacy::
-
- SQLAlchemy 2.0 has integrated the :class:`_orm.Session` "bulk insert" and
- "bulk update" capabilities into 2.0 style :meth:`_orm.Session.execute`
- method, making direct use of :class:`_dml.Insert` and :class:`_dml.Update`
- constructs. See the document at :doc:`queryguide/dml` for documentation,
- including :ref:`orm_queryguide_legacy_bulk_insert` which illustrates migration
- from the older methods to the new methods.
.. doctest-disable:
-.. deepalchemy:: This option is an advanced-use feature mostly intended
- to be used with the ref_horizontal_sharding_toplevel extension. For
- typical cases of loading objects with identical primary keys from different
- "shards" or partitions, consider using individual :class:`_orm.Session`
- objects per shard first.
-
The "identity token" is an arbitrary value that can be associated within
the :term:`identity key` of newly loaded objects. This element exists
Previous: |prev| | Next: |next|
-.. footer_topic:: |tutorial_title|
-
- Next Query Guide Section: |next|
Subquery Eager Loading
----------------------
-.. legacy:: The :func:`_orm.subqueryload` eager loader is mostly legacy
- at this point, superseded by the :func:`_orm.selectinload` strategy
- which is of much simpler design, more flexible with features such as
- :ref:`Yield Per <orm_queryguide_yield_per>`, and emits more efficient SQL
- statements in most cases. As :func:`_orm.subqueryload` relies upon
- re-interpreting the original SELECT statement, it may fail to work
- efficiently when given very complex source queries.
-
- :func:`_orm.subqueryload` may continue to be useful for the specific
- case of an eager loaded collection for objects that use composite primary
- keys, on the Microsoft SQL Server backend that continues to not have
- support for the "tuple IN" syntax.
Subquery loading is similar in operation to selectin eager loading, however
the SELECT statement which is emitted is derived from the original statement,
Re-Executing Statements
^^^^^^^^^^^^^^^^^^^^^^^
-.. deepalchemy:: the statement re-execution feature involves a slightly
- intricate recursive sequence, and is intended to solve the fairly hard
- problem of being able to re-route the execution of a SQL statement into
- various non-SQL contexts. The twin examples of "dogpile caching" and
- "horizontal sharding", linked below, should be used as a guide for when this
- rather advanced feature is appropriate to be used.
-
The :class:`_orm.ORMExecuteState` is capable of controlling the execution of
the given statement; this includes the ability to either not invoke the
statement at all, allowing a pre-constructed result set retrieved from a cache to
git+https://github.com/sqlalchemyorg/changelog.git#egg=changelog
git+https://github.com/sqlalchemyorg/sphinx-paramlinks.git#egg=sphinx-paramlinks
-git+https://github.com/sqlalchemyorg/zzzeeksphinx.git#egg=zzzeeksphinx
sphinx-copybutton==0.5.1
sphinx-autobuild
typing-extensions
-.. highlight:: pycon+sql
+ highlight:: pycon+sql
.. |prev| replace:: :doc:`data`
.. |next| replace:: :doc:`data_select`
will be expressed in the VALUES clause of the :class:`_sql.Insert`
construct automatically.
-.. deepalchemy::
-
- Hi, welcome to the first edition of **Deep Alchemy**. The person on the
- left is known as **The Alchemist**, and you'll note they are **not** a wizard,
- as the pointy hat is not sticking upwards. The Alchemist comes around to
- describe things that are generally **more advanced and/or tricky** and
- additionally **not usually needed**, but for whatever reason they feel you
- should know about this thing that SQLAlchemy can do.
-
- In this edition, towards the goal of having some interesting data in the
- ``address_table`` as well, below is a more advanced example illustrating
- how the :meth:`_sql.Insert.values` method may be used explicitly while at
- the same time including for additional VALUES generated from the
- parameters. A :term:`scalar subquery` is constructed, making use of the
- :func:`_sql.select` construct introduced in the next section, and the
- parameters used in the subquery are set up using an explicit bound
- parameter name, established using the :func:`_sql.bindparam` construct.
-
- This is some slightly **deeper** alchemy just so that we can add related
- rows without fetching the primary key identifiers from the ``user_table``
- operation into the application. Most Alchemists will simply use the ORM
- which takes care of things like this for us.
-
- .. sourcecode:: pycon+sql
-
- >>> from sqlalchemy import select, bindparam
- >>> scalar_subq = (
- ... select(user_table.c.id)
- ... .where(user_table.c.name == bindparam("username"))
- ... .scalar_subquery()
- ... )
-
- >>> with engine.connect() as conn:
- ... result = conn.execute(
- ... insert(address_table).values(user_id=scalar_subq),
- ... [
- ... {
- ... "username": "spongebob",
- ... "email_address": "spongebob@sqlalchemy.org",
- ... },
- ... {"username": "sandy", "email_address": "sandy@sqlalchemy.org"},
- ... {"username": "sandy", "email_address": "sandy@squirrelpower.org"},
- ... ],
- ... )
- ... conn.commit()
- {execsql}BEGIN (implicit)
- INSERT INTO address (user_id, email_address) VALUES ((SELECT user_account.id
- FROM user_account
- WHERE user_account.name = ?), ?)
- [...] [('spongebob', 'spongebob@sqlalchemy.org'), ('sandy', 'sandy@sqlalchemy.org'),
- ('sandy', 'sandy@squirrelpower.org')]
- COMMIT{stop}
-
- With that, we have some more interesting data in our tables that we will
- make use of in the upcoming sections.
-
.. tip:: A true "empty" INSERT that inserts only the "defaults" for a table
without including any explicit values at all is generated if we indicate
:meth:`_sql.Insert.values` with no arguments; not every database backend
.. |tutorial_title| replace:: SQLAlchemy Unified Tutorial
.. |next| replace:: :doc:`engine`
-.. footer_topic:: |tutorial_title|
-
- Next Section: |next|
-
.. _unified_tutorial:
.. rst-class:: orm_core
Previous: |prev| | Next: |next|
-.. footer_topic:: |tutorial_title|
-
- Next Tutorial Section: |next|
class ShardedQuery(Query[_T]):
- """Query class used with :class:`.ShardedSession`.
-
- .. legacy:: The :class:`.ShardedQuery` is a subclass of the legacy
- :class:`.Query` class. The :class:`.ShardedSession` now supports
- 2.0 style execution via the :meth:`.ShardedSession.execute` method.
-
- """
+ """Query class used with :class:`.ShardedSession`."""
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
"""Serializer/Deserializer objects for usage with SQLAlchemy query structures,
allowing "contextual" deserialization.
-.. legacy::
-
- The serializer extension is **legacy** and should not be used for
- new development.
Any SQLAlchemy query structure, either based on sqlalchemy.sql.*
or sqlalchemy.orm.* can be used. The mappers, Tables, Columns, Session
left hand side within a Declarative mapping. See the section
ref_dynamic_relationship for examples.
- .. legacy:: The "dynamic" lazy loader strategy is the legacy form of
- what is now the "write_only" strategy described in the section
- ref_write_only_relationship.
.. seealso::
to indicate that the ``lazy="dynamic"`` loader strategy should be used
for a particular :func:`_orm.relationship`.
- .. legacy:: The "dynamic" lazy loader strategy is the legacy form of what
- is now the "write_only" strategy described in the section
- ref_write_only_relationship.
E.g.::
Dynamic collections act like Query() objects for read operations and support
basic add/delete mutation.
-.. legacy:: the "dynamic" loader is a legacy feature, superseded by the
- "write_only" loader.
"""
"""Event for after the legacy :meth:`_orm.Query.update` method
has been called.
- .. legacy:: The :meth:`_orm.SessionEvents.after_bulk_update` method
- is a legacy event hook as of SQLAlchemy 2.0. The event
- **does not participate** in :term:`2.0 style` invocations
- using :func:`_dml.update` documented at
- :ref:`orm_queryguide_update_delete_where`. For 2.0 style use,
- the :meth:`_orm.SessionEvents.do_orm_execute` hook will intercept
- these calls.
:param update_context: an "update context" object which contains
details about the update, including these attributes:
"""Event for after the legacy :meth:`_orm.Query.delete` method
has been called.
- .. legacy:: The :meth:`_orm.SessionEvents.after_bulk_delete` method
- is a legacy event hook as of SQLAlchemy 2.0. The event
- **does not participate** in :term:`2.0 style` invocations
- using :func:`_dml.delete` documented at
- :ref:`orm_queryguide_update_delete_where`. For 2.0 style use,
- the :meth:`_orm.SessionEvents.do_orm_execute` hook will intercept
- these calls.
:param delete_context: a "delete context" object which contains
details about the update, including these attributes:
"""Represent events within the construction of a :class:`_query.Query`
object.
- .. legacy:: The :class:`_orm.QueryEvents` event methods are legacy
- as of SQLAlchemy 2.0, and only apply to direct use of the
- :class:`_orm.Query` object. They are not used for :term:`2.0 style`
- statements. For events to intercept and modify 2.0 style ORM use,
- use the :meth:`_orm.SessionEvents.do_orm_execute` hook.
The :class:`_orm.QueryEvents` hooks are now superseded by the
"""ORM-level SQL construction object.
- .. legacy:: The ORM :class:`.Query` object is a legacy construct
- as of SQLAlchemy 2.0. See the notes at the top of
- :ref:`query_api_toplevel` for an overview, including links to migration
- documentation.
:class:`_query.Query` objects are normally initially generated using the
:meth:`~.Session.query` method of :class:`.Session`, and in
:class:`_query.Query` object against the class and the current
:class:`.Session` when called.
- .. legacy:: The :meth:`_orm.scoped_session.query_property` accessor
- is specific to the legacy :class:`.Query` object and is not
- considered to be part of :term:`2.0-style` ORM use.
e.g.::
Proxied for the :class:`_orm.Session` class on
behalf of the :class:`_orm.scoping.scoped_session` class.
- .. legacy::
-
- This method is a legacy feature as of the 2.0 series of
- SQLAlchemy. For modern bulk INSERT and UPDATE, see
- the sections :ref:`orm_queryguide_bulk_insert` and
- :ref:`orm_queryguide_bulk_update`.
-
- For general INSERT and UPDATE of existing ORM mapped objects,
- prefer standard :term:`unit of work` data management patterns,
- introduced in the :ref:`unified_tutorial` at
- :ref:`tutorial_orm_data_manipulation`. SQLAlchemy 2.0
- now uses :ref:`engine_insertmanyvalues` with modern dialects
- which solves previous issues of bulk INSERT slowness.
:param objects: a sequence of mapped object instances. The mapped
objects are persisted as is, and are **not** associated with the
Proxied for the :class:`_orm.Session` class on
behalf of the :class:`_orm.scoping.scoped_session` class.
- .. legacy::
-
- This method is a legacy feature as of the 2.0 series of
- SQLAlchemy. For modern bulk INSERT and UPDATE, see
- the sections :ref:`orm_queryguide_bulk_insert` and
- :ref:`orm_queryguide_bulk_update`. The 2.0 API shares
- implementation details with this method and adds new features
- as well.
:param mapper: a mapped class, or the actual :class:`_orm.Mapper`
object,
Proxied for the :class:`_orm.Session` class on
behalf of the :class:`_orm.scoping.scoped_session` class.
- .. legacy::
-
- This method is a legacy feature as of the 2.0 series of
- SQLAlchemy. For modern bulk INSERT and UPDATE, see
- the sections :ref:`orm_queryguide_bulk_insert` and
- :ref:`orm_queryguide_bulk_update`. The 2.0 API shares
- implementation details with this method and adds new features
- as well.
:param mapper: a mapped class, or the actual :class:`_orm.Mapper`
object,
) -> None:
"""Perform a bulk save of the given list of objects.
- .. legacy::
-
- This method is a legacy feature as of the 2.0 series of
- SQLAlchemy. For modern bulk INSERT and UPDATE, see
- the sections :ref:`orm_queryguide_bulk_insert` and
- :ref:`orm_queryguide_bulk_update`.
-
- For general INSERT and UPDATE of existing ORM mapped objects,
- prefer standard :term:`unit of work` data management patterns,
- introduced in the :ref:`unified_tutorial` at
- :ref:`tutorial_orm_data_manipulation`. SQLAlchemy 2.0
- now uses :ref:`engine_insertmanyvalues` with modern dialects
- which solves previous issues of bulk INSERT slowness.
-
:param objects: a sequence of mapped object instances. The mapped
objects are persisted as is, and are **not** associated with the
:class:`.Session` afterwards.
) -> None:
"""Perform a bulk insert of the given list of mapping dictionaries.
- .. legacy::
-
- This method is a legacy feature as of the 2.0 series of
- SQLAlchemy. For modern bulk INSERT and UPDATE, see
- the sections :ref:`orm_queryguide_bulk_insert` and
- :ref:`orm_queryguide_bulk_update`. The 2.0 API shares
- implementation details with this method and adds new features
- as well.
-
:param mapper: a mapped class, or the actual :class:`_orm.Mapper`
object,
representing the single kind of object represented within the mapping
) -> None:
"""Perform a bulk update of the given list of mapping dictionaries.
- .. legacy::
-
- This method is a legacy feature as of the 2.0 series of
- SQLAlchemy. For modern bulk INSERT and UPDATE, see
- the sections :ref:`orm_queryguide_bulk_insert` and
- :ref:`orm_queryguide_bulk_update`. The 2.0 API shares
- implementation details with this method and adds new features
- as well.
:param mapper: a mapped class, or the actual :class:`_orm.Mapper`
object,
of fetching server-side expressions and defaults, for supporting
backends only.
- .. deepalchemy::
-
- The :meth:`.UpdateBase.return_defaults` method is used by the ORM
- for its internal work in fetching newly generated primary key
- and server default values, in particular to provide the underyling
- implementation of the :paramref:`_orm.Mapper.eager_defaults`
- ORM feature as well as to allow RETURNING support with bulk
- ORM inserts. Its behavior is fairly idiosyncratic
- and is not really intended for general use. End users should
- stick with using :meth:`.UpdateBase.returning` in order to
- add RETURNING clauses to their INSERT, UPDATE and DELETE
- statements.
Normally, a single row INSERT statement will automatically populate the
:attr:`.CursorResult.inserted_primary_key` attribute when executed,