[schema migration] make some stuff to ease file 1.9 migration : we want to kill the Image entity so that existing image are turned into (existing entity type) File entities
--- a/hooks/syncschema.py Thu May 20 20:50:00 2010 +0200
+++ b/hooks/syncschema.py Thu May 20 20:50:03 2010 +0200
@@ -34,7 +34,8 @@
from cubicweb import ValidationError
from cubicweb.selectors import implements
-from cubicweb.schema import META_RTYPES, VIRTUAL_RTYPES, CONSTRAINTS, display_name
+from cubicweb.schema import (META_RTYPES, VIRTUAL_RTYPES, CONSTRAINTS,
+ ETYPE_NAME_MAP, display_name)
from cubicweb.server import hook, schemaserial as ss
from cubicweb.server.sqlutils import SQL_PREFIX
@@ -815,9 +816,10 @@
if name in CORE_ETYPES:
raise ValidationError(self.entity.eid, {None: self._cw._('can\'t be deleted')})
# delete every entities of this type
- self._cw.execute('DELETE %s X' % name)
+ if not name in ETYPE_NAME_MAP:
+ self._cw.execute('DELETE %s X' % name)
+ MemSchemaCWETypeDel(self._cw, name)
DropTable(self._cw, table=SQL_PREFIX + name)
- MemSchemaCWETypeDel(self._cw, name)
class AfterDelCWETypeHook(DelCWETypeHook):
@@ -982,7 +984,11 @@
def __call__(self):
session = self._cw
- rdef = session.vreg.schema.schema_by_eid(self.eidfrom)
+ try:
+ rdef = session.vreg.schema.schema_by_eid(self.eidfrom)
+ except KeyError:
+ self.critical('cant get schema rdef associated to %s', self.eidfrom)
+ return
subjschema, rschema, objschema = rdef.as_triple()
pendings = session.transaction_data.get('pendingeids', ())
pendingrdefs = session.transaction_data.setdefault('pendingrdefs', set())
@@ -1003,7 +1009,6 @@
# we have to update physical schema systematically for final and inlined
# relations, but only if it's the last instance for this relation type
# for other relations
-
if (rschema.final or rschema.inlined):
rset = execute('Any COUNT(X) WHERE X is %s, X relation_type R, '
'R eid %%(x)s, X from_entity E, E name %%(name)s'
--- a/schema.py Thu May 20 20:50:00 2010 +0200
+++ b/schema.py Thu May 20 20:50:03 2010 +0200
@@ -568,7 +568,14 @@
rdef.name = rdef.name.lower()
rdef.subject = bw_normalize_etype(rdef.subject)
rdef.object = bw_normalize_etype(rdef.object)
- rdefs = super(CubicWebSchema, self).add_relation_def(rdef)
+ try:
+ rdefs = super(CubicWebSchema, self).add_relation_def(rdef)
+ except BadSchemaDefinition:
+ reversed_etype_map = dict( (v, k) for k, v in ETYPE_NAME_MAP.iteritems() )
+ if rdef.subject in reversed_etype_map or rdef.object in reversed_etype_map:
+ self.warning('huuuu')
+ return
+ raise
if rdefs:
try:
self._eid_index[rdef.eid] = rdefs
--- a/server/migractions.py Thu May 20 20:50:00 2010 +0200
+++ b/server/migractions.py Thu May 20 20:50:03 2010 +0200
@@ -51,7 +51,8 @@
from yams.schema2sql import eschema2sql, rschema2sql
from cubicweb import AuthenticationError
-from cubicweb.schema import (META_RTYPES, VIRTUAL_RTYPES,
+from cubicweb.schema import (ETYPE_NAME_MAP, META_RTYPES, VIRTUAL_RTYPES,
+ PURE_VIRTUAL_RTYPES,
CubicWebRelationSchema, order_eschemas)
from cubicweb.dbapi import get_repository, repo_connect
from cubicweb.migration import MigrationHelper, yes
@@ -851,9 +852,23 @@
`oldname` is a string giving the name of the existing entity type
`newname` is a string giving the name of the renamed entity type
"""
- self.rqlexec('SET ET name %(newname)s WHERE ET is CWEType, ET name %(oldname)s',
- {'newname' : unicode(newname), 'oldname' : oldname},
- ask_confirm=False)
+ schema = self.repo.schema
+ if newname in schema:
+ assert oldname in ETYPE_NAME_MAP, \
+ '%s should be mappend to %s in ETYPE_NAME_MAP' % (oldname, newname)
+ attrs = ','.join([SQL_PREFIX + rschema.type
+ for rschema in schema[newname].subject_relations()
+ if (rschema.final or rschema.inlined)
+ and not rschema in PURE_VIRTUAL_RTYPES])
+ self.sqlexec('INSERT INTO %s%s(%s) SELECT %s FROM %s%s' % (
+ SQL_PREFIX, newname, attrs, attrs, SQL_PREFIX, oldname))
+ # use rql to propagate deletion. XXX we may miss some stuff since
+ # only the bootstrap schema is set.
+ self.rqlexec('DELETE CWEType ET WHERE ET name %(n)s', {'n': oldname})
+ else:
+ self.rqlexec('SET ET name %(newname)s WHERE ET is CWEType, ET name %(oldname)s',
+ {'newname' : unicode(newname), 'oldname' : oldname},
+ ask_confirm=False)
if commit:
self.commit()
--- a/server/schemaserial.py Thu May 20 20:50:00 2010 +0200
+++ b/server/schemaserial.py Thu May 20 20:50:03 2010 +0200
@@ -27,7 +27,9 @@
from yams import schema as schemamod, buildobjs as ybo
-from cubicweb.schema import CONSTRAINTS, ETYPE_NAME_MAP, VIRTUAL_RTYPES
+from cubicweb import CW_SOFTWARE_ROOT
+from cubicweb.schema import (CONSTRAINTS, ETYPE_NAME_MAP,
+ VIRTUAL_RTYPES, PURE_VIRTUAL_RTYPES)
from cubicweb.server import sqlutils
def group_mapping(cursor, interactive=True):
@@ -100,17 +102,28 @@
sidx[eid] = eschema
continue
if etype in ETYPE_NAME_MAP:
+ needcopy = False
netype = ETYPE_NAME_MAP[etype]
# can't use write rql queries at this point, use raw sql
- session.system_sql('UPDATE %(p)sCWEType SET %(p)sname=%%(n)s WHERE %(p)seid=%%(x)s'
- % {'p': sqlutils.SQL_PREFIX},
- {'x': eid, 'n': netype})
- session.system_sql('UPDATE entities SET type=%(n)s WHERE type=%(x)s',
- {'x': etype, 'n': netype})
+ sqlexec = session.system_sql
+ if sqlexec('SELECT 1 FROM %(p)sCWEType WHERE %(p)sname=%%(n)s'
+ % {'p': sqlutils.SQL_PREFIX}, {'n': netype}).fetchone():
+ # the new type already exists, we should merge
+ assert etype.lower() != netype.lower()
+ needcopy = True
+ else:
+ # the new type doesn't exist, we should rename
+ sqlexec('UPDATE %(p)sCWEType SET %(p)sname=%%(n)s WHERE %(p)seid=%%(x)s'
+ % {'p': sqlutils.SQL_PREFIX}, {'x': eid, 'n': netype})
+ if etype.lower() != netype.lower():
+ sqlexec('ALTER TABLE %s%s RENAME TO %s%s' % (
+ sqlutils.SQL_PREFIX, etype, sqlutils.SQL_PREFIX, netype))
+ sqlexec('UPDATE entities SET type=%(n)s WHERE type=%(x)s',
+ {'x': etype, 'n': netype})
session.commit(False)
try:
- session.system_sql('UPDATE deleted_entities SET type=%(n)s WHERE type=%(x)s',
- {'x': etype, 'n': netype})
+ sqlexec('UPDATE deleted_entities SET type=%(n)s WHERE type=%(x)s',
+ {'x': etype, 'n': netype})
except:
pass
tocleanup = [eid]
@@ -118,6 +131,12 @@
if etype == eidetype)
repo.clear_caches(tocleanup)
session.commit(False)
+ if needcopy:
+ from logilab.common.testlib import mock_object
+ sidx[eid] = mock_object(type=netype)
+ # copy / CWEType entity removal expected to be done through
+ # rename_entity_type in a migration script
+ continue
etype = netype
etype = ybo.EntityType(name=etype, description=desc, eid=eid)
eschema = schema.add_entity_type(etype)