[schema hooks] properly check for changes of schema properties avoid useless costly operation (such as full-text reindexing all entities of a type). Refactor inlined handling and fix a bug trying to reindex a final entity type on the way. stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 09 Mar 2010 10:53:38 +0100
branchstable
changeset 4839 f482dbdf2f8c
parent 4838 d4187a08ccdf
child 4840 c02a340cd1da
[schema hooks] properly check for changes of schema properties avoid useless costly operation (such as full-text reindexing all entities of a type). Refactor inlined handling and fix a bug trying to reindex a final entity type on the way.
entities/schemaobjs.py
hooks/syncschema.py
--- a/entities/schemaobjs.py	Tue Mar 09 10:51:08 2010 +0100
+++ b/entities/schemaobjs.py	Tue Mar 09 10:53:38 2010 +0100
@@ -56,30 +56,21 @@
             return u'%s <<%s>>' % (self.dc_title(), ', '.join(stereotypes))
         return self.dc_title()
 
-    def inlined_changed(self, inlined):
-        """check inlining is necessary and possible:
-
-        * return False if nothing has changed
-        * raise ValidationError if inlining is'nt possible
-        * eventually return True
+    def check_inlined_allowed(self):
+        """check inlining is possible, raise ValidationError if not possible
         """
-        rschema = self._cw.vreg.schema.rschema(self.name)
-        if inlined == rschema.inlined:
-            return False
-        if inlined:
-            # don't use the persistent schema, we may miss cardinality changes
-            # in the same transaction
-            for rdef in self.reverse_relation_type:
-                card = rdef.cardinality[0]
-                if not card in '?1':
-                    rtype = self.name
-                    stype = rdef.stype
-                    otype = rdef.otype
-                    msg = self._cw._("can't set inlined=%(inlined)s, "
-                                     "%(stype)s %(rtype)s %(otype)s "
-                                     "has cardinality=%(card)s")
-                    raise ValidationError(self.eid, {'inlined': msg % locals()})
-        return True
+        # don't use the persistent schema, we may miss cardinality changes
+        # in the same transaction
+        for rdef in self.reverse_relation_type:
+            card = rdef.cardinality[0]
+            if not card in '?1':
+                rtype = self.name
+                stype = rdef.stype
+                otype = rdef.otype
+                msg = self._cw._("can't set inlined=%(inlined)s, "
+                                 "%(stype)s %(rtype)s %(otype)s "
+                                 "has cardinality=%(card)s")
+                raise ValidationError(self.eid, {'inlined': msg % locals()})
 
     def db_key_name(self):
         """XXX goa specific"""
--- a/hooks/syncschema.py	Tue Mar 09 10:51:08 2010 +0100
+++ b/hooks/syncschema.py	Tue Mar 09 10:53:38 2010 +0100
@@ -226,25 +226,26 @@
 
 class SourceDbCWRTypeUpdate(hook.Operation):
     """actually update some properties of a relation definition"""
-    rschema = entity = None # make pylint happy
+    rschema = entity = values = None # make pylint happy
 
     def precommit_event(self):
+        rschema = self.rschema
+        if rschema.final:
+            return
         session = self.session
-        rschema = self.rschema
-        entity = self.entity
-        if 'fulltext_container' in entity.edited_attributes:
+        if 'fulltext_container' in self.values:
             ftiupdates = session.transaction_data.setdefault(
                 'fti_update_etypes', set())
             for subjtype, objtype in rschema.rdefs:
                 ftiupdates.add(subjtype)
                 ftiupdates.add(objtype)
             UpdateFTIndexOp(session)
-        if rschema.final or not 'inlined' in entity.edited_attributes:
+        if not 'inlined' in self.values:
             return # nothing to do
-        inlined = entity.inlined
+        inlined = self.values['inlined']
         # check in-lining is necessary / possible
-        if not entity.inlined_changed(inlined):
-            return # nothing to do
+        if inlined:
+            self.entity.check_inlined_allowed()
         # inlined changed, make necessary physical changes!
         sqlexec = self.session.system_sql
         rtype = rschema.type
@@ -925,26 +926,22 @@
 
 class BeforeUpdateCWRTypeHook(DelCWRTypeHook):
     """check name change, handle final"""
-    __regid__ = 'checkupdatecwrtype'
+    __regid__ = 'syncupdatecwrtype'
     events = ('before_update_entity',)
 
     def __call__(self):
-        check_valid_changes(self._cw, self.entity)
-
-
-class AfterUpdateCWRTypeHook(DelCWRTypeHook):
-    __regid__ = 'syncupdatecwrtype'
-    events = ('after_update_entity',)
-
-    def __call__(self):
         entity = self.entity
+        check_valid_changes(self._cw, entity)
         newvalues = {}
         for prop in ('symmetric', 'inlined', 'fulltext_container'):
             if prop in entity.edited_attributes:
-                newvalues[prop] = entity[prop]
+                old, new = hook.entity_oldnewvalue(entity, prop)
+                if old != new:
+                    newvalues[prop] = entity[prop]
         if newvalues:
             rschema = self._cw.vreg.schema.rschema(entity.name)
-            SourceDbCWRTypeUpdate(self._cw, rschema=rschema, entity=entity)
+            SourceDbCWRTypeUpdate(self._cw, rschema=rschema, entity=entity,
+                                  values=newvalues)
             MemSchemaCWRTypeUpdate(self._cw, rschema=rschema, values=newvalues)
 
 
@@ -1024,8 +1021,8 @@
 class AfterUpdateCWRDefHook(SyncSchemaHook):
     __regid__ = 'syncaddcwattribute'
     __select__ = SyncSchemaHook.__select__ & implements('CWAttribute',
-                                                               'CWRelation')
-    events = ('after_update_entity',)
+                                                        'CWRelation')
+    events = ('before_update_entity',)
 
     def __call__(self):
         entity = self.entity
@@ -1040,7 +1037,9 @@
             if prop == 'order':
                 prop = 'ordernum'
             if prop in entity.edited_attributes:
-                newvalues[prop] = entity[prop]
+                old, new = hook.entity_oldnewvalue(entity, prop)
+                if old != new:
+                    newvalues[prop] = entity[prop]
         if newvalues:
             subjtype = entity.stype.name
             MemSchemaRDefUpdate(self._cw, kobj=(subjtype, desttype),