summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/orm')
-rw-r--r--lib/sqlalchemy/orm/context.py10
-rw-r--r--lib/sqlalchemy/orm/interfaces.py2
-rw-r--r--lib/sqlalchemy/orm/query.py87
-rw-r--r--lib/sqlalchemy/orm/session.py21
4 files changed, 31 insertions, 89 deletions
diff --git a/lib/sqlalchemy/orm/context.py b/lib/sqlalchemy/orm/context.py
index 5e9cf9cce..12759f018 100644
--- a/lib/sqlalchemy/orm/context.py
+++ b/lib/sqlalchemy/orm/context.py
@@ -216,6 +216,16 @@ class ORMCompileState(CompileState):
statement._execution_options,
)
+ if "yield_per" in execution_options or load_options._yield_per:
+ execution_options = execution_options.union(
+ {
+ "stream_results": True,
+ "max_row_buffer": execution_options.get(
+ "yield_per", load_options._yield_per
+ ),
+ }
+ )
+
bind_arguments["clause"] = statement
# new in 1.4 - the coercions system is leveraged to allow the
diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py
index b1ff1a049..64f561cbd 100644
--- a/lib/sqlalchemy/orm/interfaces.py
+++ b/lib/sqlalchemy/orm/interfaces.py
@@ -499,6 +499,8 @@ class PropComparator(operators.ColumnOperators):
.. seealso::
+ :ref:`orm_queryguide_join_on_augmented`
+
:ref:`loader_option_criteria`
:func:`.with_loader_criteria`
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index 277dda6fb..f79c19849 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -770,66 +770,18 @@ class Query(
(e.g. approximately 1000) is used, even with DBAPIs that buffer
rows (which are most).
- The :meth:`_query.Query.yield_per` method **is not compatible
- subqueryload eager loading or joinedload eager loading when
- using collections**. It is potentially compatible with "select in"
- eager loading, **provided the database driver supports multiple,
- independent cursors** (pysqlite and psycopg2 are known to work,
- MySQL and SQL Server ODBC drivers do not).
-
- Therefore in some cases, it may be helpful to disable
- eager loads, either unconditionally with
- :meth:`_query.Query.enable_eagerloads`::
-
- q = sess.query(Object).yield_per(100).enable_eagerloads(False)
-
- Or more selectively using :func:`.lazyload`; such as with
- an asterisk to specify the default loader scheme::
-
- q = sess.query(Object).yield_per(100).\
- options(lazyload('*'), joinedload(Object.some_related))
-
- .. warning::
-
- Use this method with caution; if the same instance is
- present in more than one batch of rows, end-user changes
- to attributes will be overwritten.
-
- In particular, it's usually impossible to use this setting
- with eagerly loaded collections (i.e. any lazy='joined' or
- 'subquery') since those collections will be cleared for a
- new load when encountered in a subsequent result batch.
- In the case of 'subquery' loading, the full result for all
- rows is fetched which generally defeats the purpose of
- :meth:`~sqlalchemy.orm.query.Query.yield_per`.
-
- Also note that while
- :meth:`~sqlalchemy.orm.query.Query.yield_per` will set the
- ``stream_results`` execution option to True, currently
- this is only understood by
- :mod:`~sqlalchemy.dialects.postgresql.psycopg2`,
- :mod:`~sqlalchemy.dialects.mysql.mysqldb` and
- :mod:`~sqlalchemy.dialects.mysql.pymysql` dialects
- which will stream results using server side cursors
- instead of pre-buffer all rows for this query. Other
- DBAPIs **pre-buffer all rows** before making them
- available. The memory use of raw database rows is much less
- than that of an ORM-mapped object, but should still be taken into
- consideration when benchmarking.
-
- .. seealso::
-
- :ref:`engine_stream_results`
+ As of SQLAlchemy 1.4, the :meth:`_orm.Query.yield_per` method is
+ equvalent to using the ``yield_per`` execution option at the ORM level.
+ See the section :ref:`orm_queryguide_yield_per` for further background
+ on this option.
"""
self.load_options += {"_yield_per": count}
- self._execution_options = self._execution_options.union(
- {"stream_results": True, "max_row_buffer": count}
- )
@util.deprecated_20(
":meth:`_orm.Query.get`",
alternative="The method is now available as :meth:`_orm.Session.get`",
+ becomes_legacy=True,
)
def get(self, ident):
"""Return an instance based on the given primary key identifier,
@@ -983,10 +935,10 @@ class Query(
def autoflush(self, setting):
"""Return a Query with a specific 'autoflush' setting.
- Note that a Session with autoflush=False will
- not autoflush, even if this flag is set to True at the
- Query level. Therefore this flag is usually used only
- to disable autoflush for a specific Query.
+ As of SQLAlchemy 1.4, the :meth:`_orm.Query.autoflush` method
+ is equvalent to using the ``autoflush`` execution option at the
+ ORM level. See the section :ref:`orm_queryguide_autoflush` for
+ further background on this option.
"""
self.load_options += {"_autoflush": setting}
@@ -997,22 +949,10 @@ class Query(
that will expire and refresh all instances
as they are loaded, or reused from the current :class:`.Session`.
- :meth:`.populate_existing` does not improve behavior when
- the ORM is used normally - the :class:`.Session` object's usual
- behavior of maintaining a transaction and expiring all attributes
- after rollback or commit handles object state automatically.
- This method is not intended for general use.
-
- .. versionadded:: 1.4
-
- The :meth:`.populate_existing` method is equivalent to passing the
- ``populate_existing=True`` option to the
- :meth:`_orm.Query.execution_options` method.
-
- .. seealso::
-
- :ref:`session_expire` - in the ORM :class:`_orm.Session`
- documentation
+ As of SQLAlchemy 1.4, the :meth:`_orm.Query.populate_existing` method
+ is equvalent to using the ``populate_existing`` execution option at the
+ ORM level. See the section :ref:`orm_queryguide_populate_existing` for
+ further background on this option.
"""
self.load_options += {"_populate_existing": True}
@@ -1031,6 +971,7 @@ class Query(
@util.deprecated_20(
":meth:`_orm.Query.with_parent`",
alternative="Use the :func:`_orm.with_parent` standalone construct.",
+ becomes_legacy=True,
)
@util.preload_module("sqlalchemy.orm.relationships")
def with_parent(self, instance, property=None, from_entity=None): # noqa
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index af70de101..2fc2ad68c 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -957,18 +957,8 @@ class Session(_SessionClassMethods):
:ref:`session_committing`
-
- :param future: if True, use 2.0 style behavior for the
- :meth:`_orm.Session.execute` method. Future mode includes the
- following behaviors:
-
- * The :class:`_engine.Result` object returned by the
- :meth:`_orm.Session.execute` method will return new-style tuple
- :class:`_engine.Row` objects
-
- * The :meth:`_orm.Session.execute` method will invoke ORM style
- queries given objects like :class:`_sql.Select`,
- :class:`_sql.Update` and :class:`_sql.Delete` against ORM entities
+ :param future: if True, use 2.0 style transactional and engine
+ behavior. Future mode includes the following behaviors:
* The :class:`_orm.Session` will not use "bound" metadata in order
to locate an :class:`_engine.Engine`; the engine or engines in use
@@ -984,9 +974,6 @@ class Session(_SessionClassMethods):
flag on a :func:`_orm.relationship` will always assume
"False" behavior.
- The "future" flag is also available on a per-execution basis
- using the :paramref:`_orm.Session.execute.future` flag.
-
.. versionadded:: 1.4
.. seealso::
@@ -1929,7 +1916,9 @@ class Session(_SessionClassMethods):
def query(self, *entities, **kwargs):
"""Return a new :class:`_query.Query` object corresponding to this
- :class:`.Session`."""
+ :class:`_orm.Session`.
+
+ """
return self._query_cls(entities, self, **kwargs)