[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.
--- 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)