cubicweb/hooks/syncschema.py
changeset 11362 ebe75d73acdd
parent 11359 2da2dd60331c
child 11406 8ed625765a5c
child 11717 d41832121b29
--- a/cubicweb/hooks/syncschema.py	Fri Jun 17 13:26:13 2016 +0200
+++ b/cubicweb/hooks/syncschema.py	Mon Jun 20 18:00:00 2016 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -31,6 +31,7 @@
 from hashlib import md5
 
 from yams.schema import BASE_TYPES, BadSchemaDefinition, RelationDefinitionSchema
+from yams.constraints import UniqueConstraint
 from yams import buildobjs as ybo, convert_default_value
 
 from logilab.common.decorators import clear_cache
@@ -41,6 +42,7 @@
                              CONSTRAINTS, UNIQUE_CONSTRAINTS, ETYPE_NAME_MAP)
 from cubicweb.server import hook, schemaserial as ss, schema2sql as y2sql
 from cubicweb.server.sqlutils import SQL_PREFIX
+from cubicweb.server.schema2sql import unique_index_name
 from cubicweb.hooks.synccomputed import RecomputeAttributeOperation
 
 # core entity and relation types which can't be removed
@@ -291,19 +293,47 @@
     oldname = newname = None  # make pylint happy
 
     def rename(self, oldname, newname):
-        self.cnx.vreg.schema.rename_entity_type(oldname, newname)
+        cnx = self.cnx
+        source = cnx.repo.system_source
+        dbhelper = source.dbhelper
         # we need sql to operate physical changes on the system database
-        sqlexec = self.cnx.system_sql
-        dbhelper = self.cnx.repo.system_source.dbhelper
-        sql = dbhelper.sql_rename_table(SQL_PREFIX+oldname,
-                                        SQL_PREFIX+newname)
+        sqlexec = cnx.system_sql
+        cnx.vreg.schema.rename_entity_type(oldname, newname)
+        old_table = SQL_PREFIX + oldname
+        new_table = SQL_PREFIX + newname
+        eschema = cnx.vreg.schema.eschema(newname)
+        # drop old indexes before the renaming
+        for rschema in eschema.subject_relations():
+            if rschema.inlined or (rschema.final and eschema.rdef(rschema.type).indexed):
+                source.drop_index(cnx, old_table, SQL_PREFIX + rschema.type)
+            if rschema.final and any(isinstance(cstr, UniqueConstraint)
+                                     for cstr in eschema.rdef(rschema.type).constraints):
+                source.drop_index(cnx, old_table, SQL_PREFIX + rschema.type, unique=True)
+        sql = dbhelper.sql_rename_table(old_table, new_table)
         sqlexec(sql)
         self.info('renamed table %s to %s', oldname, newname)
         sqlexec('UPDATE entities SET type=%(newname)s WHERE type=%(oldname)s',
                 {'newname': newname, 'oldname': oldname})
-        for eid, (etype, extid, auri) in self.cnx.repo._type_source_cache.items():
+        for eid, (etype, extid, auri) in cnx.repo._type_source_cache.items():
             if etype == oldname:
-                self.cnx.repo._type_source_cache[eid] = (newname, extid, auri)
+                cnx.repo._type_source_cache[eid] = (newname, extid, auri)
+        # recreate the indexes
+        for rschema in eschema.subject_relations():
+            if rschema.inlined or (rschema.final and eschema.rdef(rschema.type).indexed):
+                source.create_index(cnx, new_table, SQL_PREFIX + rschema.type)
+            if rschema.final and any(isinstance(cstr, UniqueConstraint)
+                                     for cstr in eschema.rdef(rschema.type).constraints):
+                source.create_index(cnx, new_table, SQL_PREFIX + rschema.type, unique=True)
+        for attrs in eschema._unique_together or ():
+            columns = ['%s%s' % (SQL_PREFIX, attr) for attr in attrs]
+            old_index_name = unique_index_name(oldname, columns)
+            for sql in dbhelper.sqls_drop_multicol_unique_index(
+                    new_table, columns, old_index_name):
+                sqlexec(sql)
+            new_index_name = unique_index_name(newname, columns)
+            for sql in dbhelper.sqls_create_multicol_unique_index(
+                    new_table, columns, new_index_name):
+                sqlexec(sql)
         # XXX transaction records
 
     def precommit_event(self):