]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Add Executable to DefaultGenerator
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 23 Jun 2021 20:34:05 +0000 (16:34 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 23 Jun 2021 20:42:33 +0000 (16:42 -0400)
Fixed the class hierarchy for the :class:`_schema.Sequence` and the more
general :class:`_schema.DefaultGenerator` base, as these are "executable"
as statements they need to include :class:`_sql.Executable` in their
hierarchy, not just :class:`_roles.StatementRole` as was applied
arbitrarily to :class:`_schema.Sequence` previously. The fix allows
:class:`_schema.Sequence` to work in all ``.execute()`` methods including
with :meth:`_orm.Session.execute` which was not working in the case that a
``do_orm_execute()`` handler was also established.

Fixes: #6668
Change-Id: I0d192258c7cbd1bce2552f9e748e8fdd680dc45f

doc/build/changelog/unreleased_14/6668.rst [new file with mode: 0644]
lib/sqlalchemy/engine/base.py
lib/sqlalchemy/sql/schema.py
test/orm/test_session.py

diff --git a/doc/build/changelog/unreleased_14/6668.rst b/doc/build/changelog/unreleased_14/6668.rst
new file mode 100644 (file)
index 0000000..4898641
--- /dev/null
@@ -0,0 +1,13 @@
+.. change::
+    :tags: bug, sql, orm
+    :tickets: 6668
+
+    Fixed the class hierarchy for the :class:`_schema.Sequence` and the more
+    general :class:`_schema.DefaultGenerator` base, as these are "executable"
+    as statements they need to include :class:`_sql.Executable` in their
+    hierarchy, not just :class:`_roles.StatementRole` as was applied
+    arbitrarily to :class:`_schema.Sequence` previously. The fix allows
+    :class:`_schema.Sequence` to work in all ``.execute()`` methods including
+    with :meth:`_orm.Session.execute` which was not working in the case that a
+    ``do_orm_execute()`` handler was also established.
+
index 64f638a50d0210a68e9a757a3a601527ceb8fc76..c21677a81efe1a1a8d8f790b05b2af51d07281b6 100644 (file)
@@ -1835,7 +1835,7 @@ class Connection(Connectable):
 
         if self._echo:
             self._log_info(statement)
-            self._log_info("%r", parameters)
+            self._log_info("[raw sql] %r", parameters)
         try:
             for fn in (
                 ()
index 221d49db9a0fb0fd74a3a456bd9d0429f3da6367..484cdddc88446d688086ff57a8e9af31b8e4fc71 100644 (file)
@@ -41,6 +41,7 @@ from . import visitors
 from .base import _bind_or_error
 from .base import DedupeColumnCollection
 from .base import DialectKWArgs
+from .base import Executable
 from .base import SchemaEventTarget
 from .coercions import _document_text_coercion
 from .elements import ClauseElement
@@ -2464,7 +2465,7 @@ class ForeignKey(DialectKWArgs, SchemaItem):
             self._set_target_column(_column)
 
 
-class DefaultGenerator(SchemaItem):
+class DefaultGenerator(Executable, SchemaItem):
     """Base class for column *default* values."""
 
     __visit_name__ = "default_generator"
@@ -2678,7 +2679,7 @@ class IdentityOptions(object):
         self.order = order
 
 
-class Sequence(IdentityOptions, roles.StatementRole, DefaultGenerator):
+class Sequence(IdentityOptions, DefaultGenerator):
     """Represents a named database sequence.
 
     The :class:`.Sequence` object represents the name and configurational
index 421e6320b2f19fd2339679ca5c23b6c14aacc5b5..e4010c635fe7c447dfa20d8d7459956dea1be828 100644 (file)
@@ -48,15 +48,25 @@ class ExecutionTest(_fixtures.FixtureTest):
     run_inserts = None
     __backend__ = True
 
+    @testing.combinations(
+        (True,), (False,), argnames="add_do_orm_execute_event"
+    )
     @testing.requires.sequences
-    def test_sequence_execute(self, connection):
-        seq = Sequence("some_sequence")
-        seq.create(connection)
-        try:
-            sess = Session(connection)
-            eq_(sess.execute(seq), connection.dialect.default_sequence_base)
-        finally:
-            seq.drop(connection)
+    def test_sequence_execute(
+        self, connection, metadata, add_do_orm_execute_event
+    ):
+        seq = Sequence("some_sequence", metadata=metadata)
+        metadata.create_all(connection)
+        sess = Session(connection)
+
+        if add_do_orm_execute_event:
+            evt = mock.Mock(return_value=None)
+            event.listen(
+                sess, "do_orm_execute", lambda ctx: evt(ctx.statement)
+            )
+        eq_(sess.execute(seq), connection.dialect.default_sequence_base)
+        if add_do_orm_execute_event:
+            eq_(evt.mock_calls, [mock.call(seq)])
 
     def test_parameter_execute(self):
         users = self.tables.users