diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-03-03 19:15:55 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-03-03 20:00:07 -0500 |
| commit | 3c682d225d21faf751fe6c4d5bcb1efc0c5bf5f8 (patch) | |
| tree | cc8618e6ae2f8d10b197cf167c50982da6e40228 /lib/sqlalchemy/engine | |
| parent | 4c81d99bab0e884473abfcb573772aa5d94264c7 (diff) | |
| download | sqlalchemy-3c682d225d21faf751fe6c4d5bcb1efc0c5bf5f8.tar.gz | |
Run handle_error for any exceptions raised in execute_context()
Observing a SQLite connection/cursor being hung on
test_resultset -> PositionalTextTest -> test_dupe_col_obj.
this uses connectionless execution and the result object
fails to be constructed. When that happens, there is no path
for the cursor or connection to be closed / released.
Recent changes with the exception assertions in #4849 seem to
be causing a cycle to last a little longer than usual which
is exposing this issue for one particular test on SQLite.
As we want to get rid of weakref cleanup, evaluate
why we dont have handle_dbapi_exception for this whole
block, as after_cursor_execute can raise, result construction
can raise, autocommit can raise, close can raise, there
does not seem to be a reason these things should be outside
of the block that gets cleaned up.
Fixes: #5182
Change-Id: I640ac55e8c5f39d287f779fbb5dc0ab727218ca3
Diffstat (limited to 'lib/sqlalchemy/engine')
| -rw-r--r-- | lib/sqlalchemy/engine/base.py | 61 |
1 files changed, 31 insertions, 30 deletions
diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index 449f386ce..3a0cfbbe9 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -1281,42 +1281,43 @@ class Connection(Connectable): self.dialect.do_execute( cursor, statement, parameters, context ) - except BaseException as e: - self._handle_dbapi_exception( - e, statement, parameters, cursor, context - ) - if self._has_events or self.engine._has_events: - self.dispatch.after_cursor_execute( - self, - cursor, - statement, - parameters, - context, - context.executemany, - ) + if self._has_events or self.engine._has_events: + self.dispatch.after_cursor_execute( + self, + cursor, + statement, + parameters, + context, + context.executemany, + ) - if context.compiled: - context.post_exec() + if context.compiled: + context.post_exec() - result = context._setup_result_proxy() + result = context._setup_result_proxy() - if context.should_autocommit and self._root.__transaction is None: - self._root._commit_impl(autocommit=True) + if context.should_autocommit and self._root.__transaction is None: + self._root._commit_impl(autocommit=True) - # for "connectionless" execution, we have to close this - # Connection after the statement is complete. - if self.should_close_with_result: - assert not context._is_future_result + # for "connectionless" execution, we have to close this + # Connection after the statement is complete. + if self.should_close_with_result: + assert not context._is_future_result + + # ResultProxy already exhausted rows / has no rows. + # close us now + if result._soft_closed: + self.close() + else: + # ResultProxy will close this Connection when no more + # rows to fetch. + result._autoclose_connection = True + except BaseException as e: + self._handle_dbapi_exception( + e, statement, parameters, cursor, context + ) - # ResultProxy already exhausted rows / has no rows. - # close us now - if result._soft_closed: - self.close() - else: - # ResultProxy will close this Connection when no more - # rows to fetch. - result._autoclose_connection = True return result def _cursor_execute(self, cursor, statement, parameters, context=None): |
