]> git.ipfire.org Git - thirdparty/sqlalchemy/alembic.git/commitdiff
- implement "start migrations" event for impls
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 29 Nov 2011 21:09:13 +0000 (16:09 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 29 Nov 2011 21:09:13 +0000 (16:09 -0500)
- implement counter logic for SQL server constraint/default
drop so that variables are declared uniquely within
a full migration run, #12

alembic/context.py
alembic/ddl/impl.py
alembic/ddl/mssql.py
tests/test_mssql.py

index e737ed96a33baf1afc2c28fd19d14a676aa0cb5b..89bf606b149bcefd4f08fcf45beaf8730087f674 100644 (file)
@@ -88,6 +88,7 @@ class Context(object):
     def run_migrations(self, **kw):
 
         current_rev = rev = False
+        self.impl.start_migrations()
         for change, prev_rev, rev in self._migrations_fn(
                                         self._current_rev()):
             if current_rev is False:
index 8306fcb6c8b419f257b98ad01dec39f72198cf81..a109ed4ff104aac7fbbe677d2fde797deffbee43 100644 (file)
@@ -187,6 +187,14 @@ class DefaultImpl(object):
         conn_col_default = inspector_column['default']
         return conn_col_default != rendered_metadata_default
 
+    def start_migrations(self):
+        """A hook called when :meth:`.Context.run_migrations`
+        is called.
+        
+        Implementations can set up per-migration-run state here.
+        
+        """
+
     def emit_begin(self):
         """Emit the string ``BEGIN``, or the backend-specific
         equivalent, on the current connection context.
index 400f614751df009c98ce8219eed5c6307827fb99..44d72f1efe4c5f3370b0aa85956e5b3794405137 100644 (file)
@@ -1,12 +1,20 @@
 from alembic.ddl.impl import DefaultImpl
 from alembic.ddl.base import alter_table, AddColumn, ColumnName, \
     format_table_name, format_column_name, ColumnNullable, alter_column
+from alembic import util
 from sqlalchemy.ext.compiler import compiles
 
 class MSSQLImpl(DefaultImpl):
     __dialect__ = 'mssql'
     transactional_ddl = True
 
+    def start_migrations(self):
+        self.__dict__.pop('const_sym_counter', None)
+
+    @util.memoized_property
+    def const_sym_counter(self):
+        return 1
+
     def emit_begin(self):
         self._exec("BEGIN TRANSACTION")
 
@@ -29,30 +37,36 @@ class MSSQLImpl(DefaultImpl):
         drop_default = kw.pop('mssql_drop_default', False)
         if drop_default:
             self._exec(
-                _exec_drop_col_constraint(table_name, column, 'sys.default_constraints')
+                _exec_drop_col_constraint(self, 
+                        table_name, column, 
+                        'sys.default_constraints')
             )
         drop_check = kw.pop('mssql_drop_check', False)
         if drop_check:
             self._exec(
-                _exec_drop_col_constraint(table_name, column, 'sys.check_constraints')
+                _exec_drop_col_constraint(self, 
+                        table_name, column, 
+                        'sys.check_constraints')
             )
         super(MSSQLImpl, self).drop_column(table_name, column)
 
-
-def _exec_drop_col_constraint(tname, colname, type_):
+def _exec_drop_col_constraint(impl, tname, colname, type_):
     # from http://www.mssqltips.com/sqlservertip/1425/working-with-default-constraints-in-sql-server/
     # TODO: needs table formatting, etc.
-    return """declare @const_name varchar(256)
-select @const_name = [name] from %(type)s
+    counter = impl.const_sym_counter
+    impl.const_sym_counter += 1
+
+    return """declare @const_name_%(sym)s varchar(256)
+select @const_name_%(sym)s = [name] from %(type)s
 where parent_object_id = object_id('%(tname)s')
 and col_name(parent_object_id, parent_column_id) = '%(colname)s'
-exec('alter table %(tname)s drop constraint ' + @const_name)""" % {
+exec('alter table %(tname)s drop constraint ' + @const_name_%(sym)s)""" % {
         'type':type_,
         'tname':tname,
-        'colname':colname
+        'colname':colname,
+        'sym':counter
     }
 
-
 @compiles(AddColumn, 'mssql')
 def visit_add_column(element, compiler, **kw):
     return "%s %s" % (
index 9392c6c9c54dcf9002566775f26e161586e177e8..5a65318813990e408a26dad62e80c966b0784852 100644 (file)
@@ -49,16 +49,25 @@ class OpTest(TestCase):
     def test_drop_column_w_default(self):
         context = op_fixture('mssql')
         op.drop_column('t1', 'c1', mssql_drop_default=True)
-        context.assert_contains("exec('alter table t1 drop constraint ' + @const_name)")
+        op.drop_column('t1', 'c2', mssql_drop_default=True)
+        context.assert_contains("exec('alter table t1 drop constraint ' + @const_name_1)")
         context.assert_contains("ALTER TABLE t1 DROP COLUMN c1")
 
+        # counter increments
+        context.assert_contains("exec('alter table t1 drop constraint ' + @const_name_2)")
+        context.assert_contains("ALTER TABLE t1 DROP COLUMN c2")
 
     def test_drop_column_w_check(self):
         context = op_fixture('mssql')
         op.drop_column('t1', 'c1', mssql_drop_check=True)
-        context.assert_contains("exec('alter table t1 drop constraint ' + @const_name)")
+        op.drop_column('t1', 'c2', mssql_drop_check=True)
+        context.assert_contains("exec('alter table t1 drop constraint ' + @const_name_1)")
         context.assert_contains("ALTER TABLE t1 DROP COLUMN c1")
 
+        # counter increments
+        context.assert_contains("exec('alter table t1 drop constraint ' + @const_name_2)")
+        context.assert_contains("ALTER TABLE t1 DROP COLUMN c2")
+
     def test_alter_column_nullable(self):
         context = op_fixture('mssql')
         op.alter_column("t", "c", nullable=True)