[hooks/syncschema] only call "ALTER TABLE" once when changing a size constraint
authorAurelien Campeas <aurelien.campeas@pythonian.fr>
Wed, 23 Sep 2015 15:00:33 +0200
changeset 10585 80236876ee4d
parent 10584 743ed2b13a6f
child 10586 22f330f829ae
[hooks/syncschema] only call "ALTER TABLE" once when changing a size constraint Until now we would: - remove the old size constraint from the in-memory schema - call update_rdef_column which removes the size restriction from the column's type - add the new constraint object - call update_rdef_column which adds the size restriction back This breaks on SQL Server when the column is involved in an index (e.g. as part of a multi-column unique constraint), because in the intermediate stage the column's type is "nvarchar(max)", which is not indexable. Of course we must still detect the case where a size constraint is really dropped and update the db schema accordingly. Closes #5557633.
hooks/syncschema.py
--- a/hooks/syncschema.py	Wed Sep 02 15:24:46 2015 +0200
+++ b/hooks/syncschema.py	Wed Sep 23 15:00:33 2015 +0200
@@ -661,6 +661,16 @@
         syssource = cnx.repo.system_source
         cstrtype = self.oldcstr.type()
         if cstrtype == 'SizeConstraint':
+            # if the size constraint is being replaced with a new max size, we'll
+            # call update_rdef_column in CWConstraintAddOp, skip it here
+            for cstr in cnx.transaction_data.get('newsizecstr', ()):
+                rdefentity = cstr.reverse_constrained_by[0]
+                cstrrdef = cnx.vreg.schema.schema_by_eid(rdefentity.eid)
+                if cstrrdef == rdef:
+                    return
+
+            # we found that the size constraint for this rdef is really gone,
+            # not just replaced by another
             syssource.update_rdef_column(cnx, rdef)
             self.size_cstr_changed = True
         elif cstrtype == 'UniqueConstraint':
@@ -1114,6 +1124,11 @@
     events = ('after_add_entity', 'after_update_entity')
 
     def __call__(self):
+        if self.entity.cstrtype[0].name == 'SizeConstraint':
+            txdata = self._cw.transaction_data
+            if 'newsizecstr' not in txdata:
+                txdata['newsizecstr'] = set()
+            txdata['newsizecstr'].add(self.entity)
         CWConstraintAddOp(self._cw, entity=self.entity)