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.py72
1 files changed, 52 insertions, 20 deletions
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index 5ad8bcf2f..a398da793 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -116,6 +116,8 @@ class ORMExecuteState(util.MemoizedSlots):
"_merged_execution_options",
"bind_arguments",
"_compile_state_cls",
+ "_starting_event_idx",
+ "_events_todo",
)
def __init__(
@@ -126,6 +128,7 @@ class ORMExecuteState(util.MemoizedSlots):
execution_options,
bind_arguments,
compile_state_cls,
+ events_todo,
):
self.session = session
self.statement = statement
@@ -133,6 +136,10 @@ class ORMExecuteState(util.MemoizedSlots):
self._execution_options = execution_options
self.bind_arguments = bind_arguments
self._compile_state_cls = compile_state_cls
+ self._events_todo = list(events_todo)
+
+ def _remaining_events(self):
+ return self._events_todo[self._starting_event_idx + 1 :]
def invoke_statement(
self,
@@ -200,7 +207,11 @@ class ORMExecuteState(util.MemoizedSlots):
_execution_options = self._execution_options
return self.session.execute(
- statement, _params, _execution_options, _bind_arguments
+ statement,
+ _params,
+ _execution_options,
+ _bind_arguments,
+ _parent_execute_state=self,
)
@property
@@ -1376,6 +1387,8 @@ class Session(_SessionClassMethods):
params=None,
execution_options=util.immutabledict(),
bind_arguments=None,
+ _parent_execute_state=None,
+ _add_event=None,
**kw
):
r"""Execute a SQL expression construct or string statement within
@@ -1521,8 +1534,16 @@ class Session(_SessionClassMethods):
compile_state_cls = None
if compile_state_cls is not None:
- execution_options = compile_state_cls.orm_pre_session_exec(
- self, statement, params, execution_options, bind_arguments
+ (
+ statement,
+ execution_options,
+ ) = compile_state_cls.orm_pre_session_exec(
+ self,
+ statement,
+ params,
+ execution_options,
+ bind_arguments,
+ _parent_execute_state is not None,
)
else:
bind_arguments.setdefault("clause", statement)
@@ -1531,22 +1552,28 @@ class Session(_SessionClassMethods):
execution_options, {"future_result": True}
)
- if self.dispatch.do_orm_execute:
- # run this event whether or not we are in ORM mode
- skip_events = bind_arguments.get("_sa_skip_events", False)
- if not skip_events:
- orm_exec_state = ORMExecuteState(
- self,
- statement,
- params,
- execution_options,
- bind_arguments,
- compile_state_cls,
- )
- for fn in self.dispatch.do_orm_execute:
- result = fn(orm_exec_state)
- if result:
- return result
+ if _parent_execute_state:
+ events_todo = _parent_execute_state._remaining_events()
+ else:
+ events_todo = self.dispatch.do_orm_execute
+ if _add_event:
+ events_todo = list(events_todo) + [_add_event]
+
+ if events_todo:
+ orm_exec_state = ORMExecuteState(
+ self,
+ statement,
+ params,
+ execution_options,
+ bind_arguments,
+ compile_state_cls,
+ events_todo,
+ )
+ for idx, fn in enumerate(events_todo):
+ orm_exec_state._starting_event_idx = idx
+ result = fn(orm_exec_state)
+ if result:
+ return result
bind = self.get_bind(**bind_arguments)
@@ -1729,7 +1756,12 @@ class Session(_SessionClassMethods):
self._add_bind(table, bind)
def get_bind(
- self, mapper=None, clause=None, bind=None, _sa_skip_events=None
+ self,
+ mapper=None,
+ clause=None,
+ bind=None,
+ _sa_skip_events=None,
+ _sa_skip_for_implicit_returning=False,
):
"""Return a "bind" to which this :class:`.Session` is bound.