summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/engine
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2020-03-03 19:15:55 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2020-03-03 20:00:07 -0500
commit3c682d225d21faf751fe6c4d5bcb1efc0c5bf5f8 (patch)
treecc8618e6ae2f8d10b197cf167c50982da6e40228 /lib/sqlalchemy/engine
parent4c81d99bab0e884473abfcb573772aa5d94264c7 (diff)
downloadsqlalchemy-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.py61
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):