diff options
Diffstat (limited to 'lib/sqlalchemy/orm')
-rw-r--r-- | lib/sqlalchemy/orm/context.py | 10 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/interfaces.py | 2 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/query.py | 87 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/session.py | 21 |
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) |