summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/session.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/orm/session.py')
-rw-r--r--lib/sqlalchemy/orm/session.py101
1 files changed, 46 insertions, 55 deletions
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index 339c57bdc..e9d4ac2c6 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -102,23 +102,26 @@ CLOSED = util.symbol("CLOSED")
class ORMExecuteState(util.MemoizedSlots):
- """Stateful object used for the :meth:`.SessionEvents.do_orm_execute`
+ """Represents a call to the :meth:`_orm.Session.execute` method, as passed
+ to the :meth:`.SessionEvents.do_orm_execute` event hook.
.. versionadded:: 1.4
+
"""
__slots__ = (
"session",
"statement",
"parameters",
- "_execution_options",
- "_merged_execution_options",
+ "execution_options",
+ "local_execution_options",
"bind_arguments",
"_compile_state_cls",
"_starting_event_idx",
"_events_todo",
"_future",
+ "_update_execution_options",
)
def __init__(
@@ -135,7 +138,10 @@ class ORMExecuteState(util.MemoizedSlots):
self.session = session
self.statement = statement
self.parameters = parameters
- self._execution_options = execution_options
+ self.local_execution_options = execution_options
+ self.execution_options = statement._execution_options.union(
+ execution_options
+ )
self.bind_arguments = bind_arguments
self._compile_state_cls = compile_state_cls
self._events_todo = list(events_todo)
@@ -182,9 +188,8 @@ class ORMExecuteState(util.MemoizedSlots):
.. seealso::
- :ref:`examples_caching` - includes example use of the
- :meth:`.SessionEvents.do_orm_execute` hook as well as the
- :meth:`.ORMExecuteState.invoke_query` method.
+ :ref:`do_orm_execute_re_executing` - background and examples on the
+ appropriate usage of :meth:`_orm.ORMExecuteState.invoke_statement`.
"""
@@ -203,11 +208,9 @@ class ORMExecuteState(util.MemoizedSlots):
else:
_params = self.parameters
+ _execution_options = self.local_execution_options
if execution_options:
- _execution_options = dict(self._execution_options)
- _execution_options.update(execution_options)
- else:
- _execution_options = self._execution_options
+ _execution_options = _execution_options.union(execution_options)
return self.session.execute(
statement,
@@ -255,42 +258,9 @@ class ORMExecuteState(util.MemoizedSlots):
def _is_crud(self):
return isinstance(self.statement, (dml.Update, dml.Delete))
- @property
- def execution_options(self):
- """Placeholder for execution options.
-
- Raises an informative message, as there are local options
- vs. merged options that can be viewed, via the
- :attr:`.ORMExecuteState.local_execution_options` and
- :attr:`.ORMExecuteState.merged_execution_options` methods.
-
-
- """
- raise AttributeError(
- "Please use .local_execution_options or "
- ".merged_execution_options"
- )
-
- @property
- def local_execution_options(self):
- """Dictionary view of the execution options passed to the
- :meth:`.Session.execute` method. This does not include options
- that may be associated with the statement being invoked.
-
- """
- return util.immutabledict(self._execution_options)
-
- @property
- def merged_execution_options(self):
- """Dictionary view of all execution options merged together;
- this includes those of the statement as well as those passed to
- :meth:`.Session.execute`, with the local options taking precedence.
-
- """
- return self._merged_execution_options
-
- def _memoized_attr__merged_execution_options(self):
- return self.statement._execution_options.union(self._execution_options)
+ def update_execution_options(self, **opts):
+ # TODO: no coverage
+ self.local_execution_options = self.local_execution_options.union(opts)
def _orm_compile_options(self):
opts = self.statement._compile_options
@@ -329,6 +299,20 @@ class ORMExecuteState(util.MemoizedSlots):
return None
@property
+ def is_relationship_load(self):
+ """Return True if this load is loading objects on behalf of a
+ relationship.
+
+ This means, the loader in effect is either a LazyLoader,
+ SelectInLoader, SubqueryLoader, or similar, and the entire
+ SELECT statement being emitted is on behalf of a relationship
+ load.
+
+ """
+ path = self.loader_strategy_path
+ return path is not None and not path.is_root
+
+ @property
def load_options(self):
"""Return the load_options that will be used for this execution."""
@@ -337,7 +321,7 @@ class ORMExecuteState(util.MemoizedSlots):
"This ORM execution is not against a SELECT statement "
"so there are no load options."
)
- return self._execution_options.get(
+ return self.execution_options.get(
"_sa_orm_load_options", context.QueryContext.default_load_options
)
@@ -351,7 +335,7 @@ class ORMExecuteState(util.MemoizedSlots):
"This ORM execution is not against an UPDATE or DELETE "
"statement so there are no update options."
)
- return self._execution_options.get(
+ return self.execution_options.get(
"_sa_orm_update_options",
persistence.BulkUDCompileState.default_update_options,
)
@@ -1003,8 +987,6 @@ class Session(_SessionClassMethods):
:ref:`migration_20_toplevel`
- :ref:`migration_20_result_rows`
-
:param info: optional dictionary of arbitrary data to be associated
with this :class:`.Session`. Is available via the
:attr:`.Session.info` attribute. Note the dictionary is copied at
@@ -1282,7 +1264,7 @@ class Session(_SessionClassMethods):
the operation will release the current SAVEPOINT but not commit
the outermost database transaction.
- If :term:`2.x-style` use is in effect via the
+ If :term:`2.0-style` use is in effect via the
:paramref:`_orm.Session.future` flag, the outermost database
transaction is committed unconditionally, automatically releasing any
SAVEPOINTs in effect.
@@ -1416,7 +1398,7 @@ class Session(_SessionClassMethods):
self,
statement,
params=None,
- execution_options=util.immutabledict(),
+ execution_options=util.EMPTY_DICT,
bind_arguments=None,
future=False,
_parent_execute_state=None,
@@ -1576,6 +1558,8 @@ class Session(_SessionClassMethods):
else:
compile_state_cls = None
+ execution_options = util.coerce_to_immutabledict(execution_options)
+
if compile_state_cls is not None:
(
statement,
@@ -1591,8 +1575,11 @@ class Session(_SessionClassMethods):
else:
bind_arguments.setdefault("clause", statement)
if future:
- execution_options = util.immutabledict().merge_with(
- execution_options, {"future_result": True}
+ # not sure if immutabledict is working w/ this syntax
+ # execution_options =
+ # execution_options.union(future_result=True)
+ execution_options = execution_options.union(
+ {"future_result": True}
)
if _parent_execute_state:
@@ -1619,6 +1606,10 @@ class Session(_SessionClassMethods):
if result:
return result
+ # TODO: coverage for this pattern
+ statement = orm_exec_state.statement
+ execution_options = orm_exec_state.local_execution_options
+
bind = self.get_bind(**bind_arguments)
conn = self._connection_for_bind(bind, close_with_result=True)