[hooks/syncschema] Turn DropColumnOp into a data operation
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 24 Sep 2015 12:18:00 +0200
changeset 10916 8e504786df3c
parent 10915 cf800aa43f48
child 10917 edea9c324396
[hooks/syncschema] Turn DropColumnOp into a data operation While writing a test for a migration issue where "NOT NULL" was added to an inlined relation column, I ran into a case where the same column was deleted twice, which of course results in an error. This is because the "ecrit_par" relation used by the test is ambiguous. I've hence turned the DropColumnOp into a data operation to ensure we'll delete the column only once in such case. Related to #6211101
hooks/syncschema.py
--- a/hooks/syncschema.py	Tue Nov 24 10:16:55 2015 +0100
+++ b/hooks/syncschema.py	Thu Sep 24 12:18:00 2015 +0200
@@ -159,24 +159,26 @@
         cnx.transaction_data.setdefault('pendingrtypes', set()).add(rtype)
 
 
-class DropColumn(hook.Operation):
+class DropColumn(hook.DataOperationMixIn, hook.Operation):
     """actually remove the attribut's column from entity table in the system
     database
     """
-    table = column = None # make pylint happy
     def precommit_event(self):
-        cnx, table, column = self.cnx, self.table, self.column
-        source = cnx.repo.system_source
-        # drop index if any
-        source.drop_index(cnx, table, column)
-        if source.dbhelper.alter_column_support:
-            cnx.system_sql('ALTER TABLE %s DROP COLUMN %s' % (table, column),
-                           rollback_on_failure=False)
-            self.info('dropped column %s from table %s', column, table)
-        else:
-            # not supported by sqlite for instance
-            self.error('dropping column not supported by the backend, handle '
-                       'it yourself (%s.%s)', table, column)
+        cnx = self.cnx
+        for etype, attr in self.get_data():
+            table = SQL_PREFIX + etype
+            column = SQL_PREFIX + attr
+            source = cnx.repo.system_source
+            # drop index if any
+            source.drop_index(cnx, table, column)
+            if source.dbhelper.alter_column_support:
+                cnx.system_sql('ALTER TABLE %s DROP COLUMN %s' % (table, column),
+                               rollback_on_failure=False)
+                self.info('dropped column %s from table %s', column, table)
+            else:
+                # not supported by sqlite for instance
+                self.error('dropping column not supported by the backend, handle '
+                           'it yourself (%s.%s)', table, column)
 
     # XXX revertprecommit_event
 
@@ -361,8 +363,7 @@
             # drop existant columns
             #if cnx.repo.system_source.dbhelper.alter_column_support:
             for etype in rschema.subjects():
-                DropColumn(cnx, table=SQL_PREFIX + str(etype),
-                           column=SQL_PREFIX + rtype)
+                DropColumn.get_instance(cnx).add_data((str(etype), rtype))
         else:
             for etype in rschema.subjects():
                 try:
@@ -607,8 +608,7 @@
             if rset[0][0] == 0 and not cnx.deleted_in_transaction(rdef.subject.eid):
                 ptypes = cnx.transaction_data.setdefault('pendingrtypes', set())
                 ptypes.add(rschema.type)
-                DropColumn(cnx, table=SQL_PREFIX + str(rdef.subject),
-                           column=SQL_PREFIX + str(rschema))
+                DropColumn.get_instance(cnx).add_data((str(rdef.subject), str(rschema)))
         elif lastrel:
             DropRelationTable(cnx, str(rschema))
         # then update the in-memory schema