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()
- if context.is_crud or context.is_text:
- result = context._setup_crud_result_proxy()
- else:
- result = context.get_result_proxy()
- if result._metadata is None:
- result._soft_close()
+ if context.is_crud or context.is_text:
+ result = context._setup_crud_result_proxy()
+ else:
+ result = context.get_result_proxy()
+ if result._metadata is None:
+ result._soft_close()
- 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:
+ # 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
+ )
- # for "connectionless" execution, we have to close this
- # Connection after the statement is complete.
- if self.should_close_with_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
return result
def _cursor_execute(self, cursor, statement, parameters, context=None):
from sqlalchemy import Sequence
from sqlalchemy import String
from sqlalchemy import testing
+from sqlalchemy import text
from sqlalchemy import TypeDecorator
from sqlalchemy import util
from sqlalchemy import VARCHAR
):
assert_raises(MySpecialException, conn.get_isolation_level)
+ @testing.only_on("sqlite")
+ def test_cursor_close_resultset_failed_connectionless(self):
+ engine = engines.testing_engine()
+
+ the_conn = []
+ the_cursor = []
+
+ @event.listens_for(engine, "after_cursor_execute")
+ def go(
+ connection, cursor, statement, parameters, context, executemany
+ ):
+ the_cursor.append(cursor)
+ the_conn.append(connection)
+
+ c1, c2 = column("a"), column("b")
+
+ with mock.patch(
+ "sqlalchemy.engine.result.ResultProxy",
+ Mock(side_effect=tsa.exc.InvalidRequestError("duplicate col")),
+ ):
+ # result should fail
+ assert_raises(
+ tsa.exc.InvalidRequestError,
+ engine.execute,
+ text("select 1 as a, 2 as q, 3 as z").columns(c1, c2, c2),
+ )
+
+ # cursor is closed
+ assert_raises_message(
+ engine.dialect.dbapi.ProgrammingError,
+ "Cannot operate on a closed cursor",
+ the_cursor[0].execute,
+ "select 1",
+ )
+
+ # connection is closed
+ assert the_conn[0].closed
+
+ @testing.only_on("sqlite")
+ def test_cursor_close_resultset_failed_explicit(self):
+ engine = engines.testing_engine()
+
+ the_cursor = []
+
+ @event.listens_for(engine, "after_cursor_execute")
+ def go(
+ connection, cursor, statement, parameters, context, executemany
+ ):
+ the_cursor.append(cursor)
+
+ c1, c2 = column("a"), column("b")
+
+ conn = engine.connect()
+
+ with mock.patch(
+ "sqlalchemy.engine.result.ResultProxy",
+ Mock(side_effect=tsa.exc.InvalidRequestError("duplicate col")),
+ ):
+ assert_raises(
+ tsa.exc.InvalidRequestError,
+ conn.execute,
+ text("select 1 as a, 2 as q, 3 as z").columns(c1, c2, c2),
+ )
+
+ # cursor is closed
+ assert_raises_message(
+ engine.dialect.dbapi.ProgrammingError,
+ "Cannot operate on a closed cursor",
+ the_cursor[0].execute,
+ "select 1",
+ )
+
+ # connection not closed
+ assert not conn.closed
+
+ conn.close()
+
class HandleInvalidatedOnConnectTest(fixtures.TestBase):
__requires__ = ("sqlite",)