diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-03-19 13:03:44 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-03-19 13:03:44 -0400 |
commit | 2a1a79b6ce53f2e1dc4cd48bbca5c5a148b8b285 (patch) | |
tree | 40acfcb869ba3747e531c172627d2bccd13d18f4 | |
parent | 89a8e0d187b8967c9b8291bcdc3078335704dbfa (diff) | |
download | sqlalchemy-2a1a79b6ce53f2e1dc4cd48bbca5c5a148b8b285.tar.gz |
- The :meth:`.ConnectionEvents.after_cursor_execute` event is now
emitted for the "_cursor_execute()" method of :class:`.Connection`;
this is the "quick" executor that is used for things like
when a sequence is executed ahead of an INSERT statement, as well as
for dialect startup checks like unicode returns, charset, etc.
the :meth:`.ConnectionEvents.before_cursor_execute` event was already
invoked here. The "executemany" flag is now always set to False
here, as this event always corresponds to a single execution.
Previously the flag could be True if we were acting on behalf of
an executemany INSERT statement.
-rw-r--r-- | doc/build/changelog/changelog_09.rst | 14 | ||||
-rw-r--r-- | lib/sqlalchemy/engine/base.py | 15 | ||||
-rw-r--r-- | test/engine/test_execute.py | 42 |
3 files changed, 67 insertions, 4 deletions
diff --git a/doc/build/changelog/changelog_09.rst b/doc/build/changelog/changelog_09.rst index 87606c8d8..dcec53d1e 100644 --- a/doc/build/changelog/changelog_09.rst +++ b/doc/build/changelog/changelog_09.rst @@ -15,6 +15,20 @@ :version: 0.9.4 .. change:: + :tags: bug, engine + + The :meth:`.ConnectionEvents.after_cursor_execute` event is now + emitted for the "_cursor_execute()" method of :class:`.Connection`; + this is the "quick" executor that is used for things like + when a sequence is executed ahead of an INSERT statement, as well as + for dialect startup checks like unicode returns, charset, etc. + the :meth:`.ConnectionEvents.before_cursor_execute` event was already + invoked here. The "executemany" flag is now always set to False + here, as this event always corresponds to a single execution. + Previously the flag could be True if we were acting on behalf of + an executemany INSERT statement. + + .. change:: :tags: bug, orm Added support for the not-quite-yet-documented ``insert=True`` diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index 888a15fee..d3024640b 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -986,8 +986,7 @@ class Connection(Connectable): statement, parameters = \ fn(self, cursor, statement, parameters, context, - context.executemany - if context is not None else False) + False) if self._echo: self.engine.logger.info(statement) @@ -996,14 +995,22 @@ class Connection(Connectable): self.dialect.do_execute( cursor, statement, - parameters) + parameters, + context) except Exception as e: self._handle_dbapi_exception( e, statement, parameters, cursor, - None) + context) + + if self._has_events: + self.dispatch.after_cursor_execute(self, cursor, + statement, + parameters, + context, + False) def _safe_close_cursor(self, cursor): """Close the given cursor, catching exceptions diff --git a/test/engine/test_execute.py b/test/engine/test_execute.py index d3bd3c2cd..6efcdcb89 100644 --- a/test/engine/test_execute.py +++ b/test/engine/test_execute.py @@ -1235,6 +1235,48 @@ class EngineEventsTest(fixtures.TestBase): canary.be1.assert_call_count(2) canary.be2.assert_call_count(2) + def test_cursor_events_ctx_execute_scalar(self): + canary = Mock() + e1 = testing_engine(config.db_url) + + event.listen(e1, "before_cursor_execute", canary.bce) + event.listen(e1, "after_cursor_execute", canary.ace) + + stmt = str(select([1]).compile(dialect=e1.dialect)) + + with e1.connect() as conn: + dialect = conn.dialect + + ctx = dialect.execution_ctx_cls._init_statement( + dialect, conn, conn.connection, stmt, {}) + + ctx._execute_scalar(stmt, Integer()) + + eq_(canary.bce.mock_calls, + [call(conn, ctx.cursor, stmt, ctx.parameters[0], ctx, False)]) + eq_(canary.ace.mock_calls, + [call(conn, ctx.cursor, stmt, ctx.parameters[0], ctx, False)]) + + def test_cursor_events_execute(self): + canary = Mock() + e1 = testing_engine(config.db_url) + + event.listen(e1, "before_cursor_execute", canary.bce) + event.listen(e1, "after_cursor_execute", canary.ace) + + stmt = str(select([1]).compile(dialect=e1.dialect)) + + with e1.connect() as conn: + + result = conn.execute(stmt) + + ctx = result.context + eq_(canary.bce.mock_calls, + [call(conn, ctx.cursor, stmt, ctx.parameters[0], ctx, False)]) + eq_(canary.ace.mock_calls, + [call(conn, ctx.cursor, stmt, ctx.parameters[0], ctx, False)]) + + def test_argument_format_execute(self): def before_execute(conn, clauseelement, multiparams, params): assert isinstance(multiparams, (list, tuple)) |