diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-12-11 10:34:44 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-12-11 11:46:48 -0500 |
commit | c46279d1c215b7af956e40cb29afafba29d9143f (patch) | |
tree | db93eef98b764a522dce45329b1565928ba2b903 /lib/sqlalchemy/orm/session.py | |
parent | a15aeba4fb22503c1eb235fdc2e7a574136ca7dc (diff) | |
download | sqlalchemy-c46279d1c215b7af956e40cb29afafba29d9143f.tar.gz |
Revise attribute refresh for with_loader_criteria, related
Added new attribute :attr:`_orm.ORMExecuteState.is_column_load` to indicate
that a :meth:`_orm.SessionEvents.do_orm_execute` handler that a particular
operation is a primary-key-directed column attribute load, such as from an
expiration or a deferred attribute, and that WHERE criteria or additional
loader options should not be added to the query. This has been added to
the examples which illustrate the :func:`_orm.with_loader_criteria` option.
The :func:`_orm.with_loader_criteria` option has been modified so that it
will never apply its criteria to the SELECT statement for an ORM refresh
operation, such as that invoked by :meth:`_orm.Session.refresh` or whenever
an expired attribute is loaded. These queries are only against the
primary key row of the object that is already present in memory so there
should not be additional criteria added.
Added doc caveats for using lambdas.
Added test coverage for most ORMExecuteState flags and fixed a few
basic access issues.
Change-Id: I6707e4cf0dc95cdfb8ce93e5ca22ead86074baa7
References: #5760
Fixes: #5761
Fixes: #5762
Diffstat (limited to 'lib/sqlalchemy/orm/session.py')
-rw-r--r-- | lib/sqlalchemy/orm/session.py | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index 2a531b118..f6943cc5f 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -272,6 +272,8 @@ class ORMExecuteState(util.MemoizedSlots): self.local_execution_options = self.local_execution_options.union(opts) def _orm_compile_options(self): + if not self.is_select: + return None opts = self.statement._compile_options if isinstance(opts, context.ORMCompileState.default_compile_options): return opts @@ -308,6 +310,33 @@ class ORMExecuteState(util.MemoizedSlots): return None @property + def is_column_load(self): + """Return True if the operation is refreshing column-oriented + attributes on an existing ORM object. + + This occurs during operations such as :meth:`_orm.Session.refresh`, + as well as when an attribute deferred by :func:`_orm.defer` is + being loaded, or an attribute that was expired either directly + by :meth:`_orm.Session.expire` or via a commit operation is being + loaded. + + Handlers will very likely not want to add any options to queries + when such an operation is occurring as the query should be a straight + primary key fetch which should not have any additional WHERE criteria, + and loader options travelling with the instance + will have already been added to the query. + + .. versionadded:: 1.4.0b2 + + .. seealso:: + + :attr:`_orm.ORMExecuteState.is_relationship_load` + + """ + opts = self._orm_compile_options() + return opts is not None and opts._for_refresh_state + + @property def is_relationship_load(self): """Return True if this load is loading objects on behalf of a relationship. @@ -317,7 +346,19 @@ class ORMExecuteState(util.MemoizedSlots): SELECT statement being emitted is on behalf of a relationship load. + Handlers will very likely not want to add any options to queries + when such an operation is occurring, as loader options are already + capable of being propigated to relationship loaders and should + be already present. + + .. seealso:: + + :attr:`_orm.ORMExecuteState.is_column_load` + """ + opts = self._orm_compile_options() + if opts is None: + return False path = self.loader_strategy_path return path is not None and not path.is_root |