]> git.ipfire.org Git - thirdparty/sqlalchemy/alembic.git/commitdiff
Use regular renderer for MySQL server default
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 11 Sep 2020 13:56:14 +0000 (09:56 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 11 Sep 2020 13:57:15 +0000 (09:57 -0400)
Fixed issue where the MySQL dialect would not correctly render the server
default of a column in an alter operation, if the operation were
programmatically generated from an autogenerate pass as it would not
accommodate for the full structure of the DefaultClause construct.

Change-Id: I2701b396067e80c75bacbb596e24bb1e75454d10
Fixes: #736
alembic/ddl/mysql.py
docs/build/unreleased/736.rst [new file with mode: 0644]
tests/test_mysql.py

index 96383fb2cc733c8a790ffdb1d12bb0d8e9bc3907..446eeb146ee290fe4b9188baa1cbfa47396f7b56 100644 (file)
@@ -15,7 +15,6 @@ from .base import format_server_default
 from .impl import DefaultImpl
 from .. import util
 from ..autogenerate import compare
-from ..util.compat import string_types
 from ..util.sqla_compat import _is_mariadb
 from ..util.sqla_compat import _is_type_bound
 
@@ -342,13 +341,6 @@ def _mysql_change_column(element, compiler, **kw):
     )
 
 
-def _render_value(compiler, expr):
-    if isinstance(expr, string_types):
-        return "'%s'" % expr
-    else:
-        return compiler.sql_compiler.process(expr)
-
-
 def _mysql_colspec(
     compiler, nullable, server_default, type_, autoincrement, comment
 ):
@@ -359,7 +351,7 @@ def _mysql_colspec(
     if autoincrement:
         spec += " AUTO_INCREMENT"
     if server_default is not False and server_default is not None:
-        spec += " DEFAULT %s" % _render_value(compiler, server_default)
+        spec += " DEFAULT %s" % format_server_default(compiler, server_default)
     if comment:
         spec += " COMMENT %s" % compiler.sql_compiler.render_literal_value(
             comment, sqltypes.String()
diff --git a/docs/build/unreleased/736.rst b/docs/build/unreleased/736.rst
new file mode 100644 (file)
index 0000000..ce166c7
--- /dev/null
@@ -0,0 +1,8 @@
+.. change::
+    :tags: bug, ops, mysql
+    :tickets: 736
+
+    Fixed issue where the MySQL dialect would not correctly render the server
+    default of a column in an alter operation, if the operation were
+    programmatically generated from an autogenerate pass as it would not
+    accommodate for the full structure of the DefaultClause construct.
index 4294a31557f566e06921d6d3a5a9a5c6837014b8..4ab43309c3920cc2184fbfebf7527fddaa3b9d5a 100644 (file)
@@ -1,6 +1,7 @@
 from sqlalchemy import Boolean
 from sqlalchemy import Column
 from sqlalchemy import DATETIME
+from sqlalchemy import Float
 from sqlalchemy import func
 from sqlalchemy import inspect
 from sqlalchemy import Integer
@@ -11,7 +12,10 @@ from sqlalchemy import TIMESTAMP
 
 from alembic import op
 from alembic import util
+from alembic.autogenerate import api
+from alembic.autogenerate import compare
 from alembic.migration import MigrationContext
+from alembic.operations import ops
 from alembic.testing import assert_raises_message
 from alembic.testing import config
 from alembic.testing.env import clear_staging_env
@@ -197,6 +201,35 @@ class MySQLOpTest(TestBase):
             "ALTER TABLE t CHANGE c c DATETIME NULL DEFAULT CURRENT_TIMESTAMP"
         )
 
+    def test_alter_column_modify_programmatic_default(self):
+        # test issue #736
+        # when autogenerate.compare creates the operation object
+        # programmatically, the server_default of the op has the full
+        # DefaultClause present.   make sure the usual renderer works.
+        context = op_fixture("mysql")
+
+        m1 = MetaData()
+
+        autogen_context = api.AutogenContext(context, m1)
+
+        operation = ops.AlterColumnOp("t", "c")
+        for fn in (
+            compare._compare_nullable,
+            compare._compare_type,
+            compare._compare_server_default,
+        ):
+            fn(
+                autogen_context,
+                operation,
+                None,
+                "t",
+                "c",
+                Column("c", Float(), nullable=False, server_default=text("0")),
+                Column("c", Float(), nullable=True, default=0),
+            )
+        op.invoke(operation)
+        context.assert_("ALTER TABLE t MODIFY c FLOAT NULL DEFAULT 0")
+
     def test_col_not_nullable(self):
         context = op_fixture("mysql")
         op.alter_column("t1", "c1", nullable=False, existing_type=Integer)