Pull requests

#21 Declined
Repository
dairiki
Branch
bug.mysql-server_default
Repository
zzzeek
Branch
master

Fix exception on op.alter_column(..., server_default=None) in mysql

Author
  1. dairiki
Reviewers
Description

Attempting to remove an server_default from a column in mysql, e.g.

 op.alter_column('MyTable', 'mycol', server_default=None,
                           existing_type=sa.Integer(),
                           existing_nullable=False,
                           existing_server_default='42')

leads to an AttributeError: 'NoneType' object has no attribute '_compiler_dispatch' exception.

As a work-around, specifying server_default=False works (but I suspect this only works under mysql since False is really supposed to mean "no change to the server_default".)

This PR includes a new test in test_mysql.py which exercises the problem.

Comments (8)

  1. dairiki author

    This is a dup of issue #103, I think — though I don't (yet) agree with the “the whole of mysql.py needs to be expanded out with individual ALTER, CHANGE, and DEFAULT directives” comment there.

  2. dairiki author

    Yeah, I think that does the trick. I've tested this on a live mysql db with the use case which discovered this issue.

    Oop. There is one buglet when attempting to drop the server_default along with other column changes. Doing an op.alter_column(..., server_default=None, nullable=True, ...) results in AttributeError: 'NoneType' object has no attribute '_compiler_dispatch'.

    Here's a fix.

    diff --git a/alembic/ddl/mysql.py b/alembic/ddl/mysql.py
    index 3d954f6..de34a56 100644
    --- a/alembic/ddl/mysql.py
    +++ b/alembic/ddl/mysql.py
    @@ -177,7 +177,7 @@ def _mysql_colspec(compiler, nullable, server_default, type_,
         )
         if autoincrement:
             spec += " AUTO_INCREMENT"
    -    if server_default != False:
    +    if server_default != None and server_default != False:
             spec += " DEFAULT %s" % _render_value(compiler, server_default)
    
         return spec
    diff --git a/tests/test_mysql.py b/tests/test_mysql.py
    index f598d99..9621654 100644
    --- a/tests/test_mysql.py
    +++ b/tests/test_mysql.py
    @@ -127,6 +127,14 @@ class MySQLOpTest(TestCase):
                 "ALTER TABLE t1 MODIFY c1 INTEGER NOT NULL DEFAULT 'q'"
             )
    
    +    def test_col_multi_alter_drop_default(self):
    +        context = op_fixture('mysql')
    +        op.alter_column('t1', 'c1', nullable=True, server_default=None,
    +                        existing_type=Integer)
    +        context.assert_(
    +            "ALTER TABLE t1 MODIFY c1 INTEGER NULL"
    +        )
    +
         def test_col_alter_type_required(self):
             op_fixture('mysql')
             assert_raises_message(
    

    Edited to de-backwardize the patch.