server/schemaserial.py
changeset 11057 0b59724cb3f2
parent 11052 058bb3dc685f
child 11058 23eb30449fe5
--- a/server/schemaserial.py	Mon Jan 04 18:40:30 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,656 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""functions for schema / permissions (de)serialization using RQL"""
-from __future__ import print_function
-
-__docformat__ = "restructuredtext en"
-
-import os
-import json
-import sys
-
-from six import PY2, text_type, string_types
-
-from logilab.common.shellutils import ProgressBar, DummyProgressBar
-
-from yams import BadSchemaDefinition, schema as schemamod, buildobjs as ybo
-
-from cubicweb import Binary
-from cubicweb.schema import (KNOWN_RPROPERTIES, CONSTRAINTS, ETYPE_NAME_MAP,
-                             VIRTUAL_RTYPES)
-from cubicweb.server import sqlutils, schema2sql as y2sql
-
-
-def group_mapping(cnx, interactive=True):
-    """create a group mapping from an rql cursor
-
-    A group mapping has standard group names as key (managers, owners at least)
-    and the actual CWGroup entity's eid as associated value.
-    In interactive mode (the default), missing groups'eid will be prompted
-    from the user.
-    """
-    res = {}
-    for eid, name in cnx.execute('Any G, N WHERE G is CWGroup, G name N',
-                                    build_descr=False):
-        res[name] = eid
-    if not interactive:
-        return res
-    missing = [g for g in ('owners', 'managers', 'users', 'guests') if not g in res]
-    if missing:
-        print('some native groups are missing but the following groups have been found:')
-        print('\n'.join('* %s (%s)' % (n, eid) for n, eid in res.items()))
-        print()
-        print('enter the eid of a to group to map to each missing native group')
-        print('or just type enter to skip permissions granted to a group')
-        for group in missing:
-            while True:
-                value = raw_input('eid for group %s: ' % group).strip()
-                if not value:
-                    continue
-                try:
-                    eid = int(value)
-                except ValueError:
-                    print('eid should be an integer')
-                    continue
-                for eid_ in res.values():
-                    if eid == eid_:
-                        break
-                else:
-                    print('eid is not a group eid')
-                    continue
-                res[name] = eid
-                break
-    return res
-
-def cstrtype_mapping(cnx):
-    """cached constraint types mapping"""
-    map = dict(cnx.execute('Any T, X WHERE X is CWConstraintType, X name T'))
-    return map
-
-# schema / perms deserialization ##############################################
-
-def deserialize_schema(schema, cnx):
-    """return a schema according to information stored in an rql database
-    as CWRType and CWEType entities
-    """
-    repo = cnx.repo
-    dbhelper = repo.system_source.dbhelper
-
-    # Computed Rtype
-    with cnx.ensure_cnx_set:
-        tables = set(t.lower() for t in dbhelper.list_tables(cnx.cnxset.cu))
-        has_computed_relations = 'cw_cwcomputedrtype' in tables
-    # computed attribute
-    try:
-        cnx.system_sql("SELECT cw_formula FROM cw_CWAttribute")
-        has_computed_attributes = True
-    except Exception:
-        cnx.rollback()
-        has_computed_attributes = False
-
-    # XXX bw compat (3.6 migration)
-    sqlcu = cnx.system_sql("SELECT * FROM cw_CWRType WHERE cw_name='symetric'")
-    if sqlcu.fetchall():
-        sql = dbhelper.sql_rename_col('cw_CWRType', 'cw_symetric', 'cw_symmetric',
-                                      dbhelper.TYPE_MAPPING['Boolean'], True)
-        sqlcu.execute(sql)
-        sqlcu.execute("UPDATE cw_CWRType SET cw_name='symmetric' WHERE cw_name='symetric'")
-        cnx.commit()
-    ertidx = {}
-    copiedeids = set()
-    permsidx = deserialize_ertype_permissions(cnx)
-    schema.reading_from_database = True
-    # load every entity types
-    for eid, etype, desc in cnx.execute(
-        'Any X, N, D WHERE X is CWEType, X name N, X description D',
-        build_descr=False):
-        # base types are already in the schema, skip them
-        if etype in schemamod.BASE_TYPES:
-            # just set the eid
-            eschema = schema.eschema(etype)
-            eschema.eid = eid
-            ertidx[eid] = etype
-            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
-            sqlexec = cnx.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 copy (eg make existing
-                # instances of the old type instances of the new type)
-                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():
-                    alter_table_sql = dbhelper.sql_rename_table(sqlutils.SQL_PREFIX+etype,
-                                                                sqlutils.SQL_PREFIX+netype)
-                    sqlexec(alter_table_sql)
-            sqlexec('UPDATE entities SET type=%(n)s WHERE type=%(x)s',
-                    {'x': etype, 'n': netype})
-            cnx.commit(False)
-            tocleanup = [eid]
-            tocleanup += (eid for eid, cached in repo._type_source_cache.items()
-                          if etype == cached[0])
-            repo.clear_caches(tocleanup)
-            cnx.commit(False)
-            if needcopy:
-                ertidx[eid] = netype
-                copiedeids.add(eid)
-                # copy / CWEType entity removal expected to be done through
-                # rename_entity_type in a migration script
-                continue
-            etype = netype
-        ertidx[eid] = etype
-        eschema = schema.add_entity_type(
-            ybo.EntityType(name=etype, description=desc, eid=eid))
-        set_perms(eschema, permsidx)
-    # load inheritance relations
-    for etype, stype in cnx.execute(
-        'Any XN, ETN WHERE X is CWEType, X name XN, X specializes ET, ET name ETN',
-        build_descr=False):
-        etype = ETYPE_NAME_MAP.get(etype, etype)
-        stype = ETYPE_NAME_MAP.get(stype, stype)
-        schema.eschema(etype)._specialized_type = stype
-        schema.eschema(stype)._specialized_by.append(etype)
-    if has_computed_relations:
-        rset = cnx.execute(
-            'Any X, N, R, D WHERE X is CWComputedRType, X name N, '
-            'X rule R, X description D')
-        for eid, rule_name, rule, description in rset.rows:
-            rtype = ybo.ComputedRelation(name=rule_name, rule=rule, eid=eid,
-                                         description=description)
-            rschema = schema.add_relation_type(rtype)
-            set_perms(rschema, permsidx)
-    # load every relation types
-    for eid, rtype, desc, sym, il, ftc in cnx.execute(
-        'Any X,N,D,S,I,FTC WHERE X is CWRType, X name N, X description D, '
-        'X symmetric S, X inlined I, X fulltext_container FTC', build_descr=False):
-        ertidx[eid] = rtype
-        rschema = schema.add_relation_type(
-            ybo.RelationType(name=rtype, description=desc,
-                             symmetric=bool(sym), inlined=bool(il),
-                             fulltext_container=ftc, eid=eid))
-    # remains to load every relation definitions (ie relations and attributes)
-    cstrsidx = deserialize_rdef_constraints(cnx)
-    pendingrdefs = []
-    # closure to factorize common code of attribute/relation rdef addition
-    def _add_rdef(rdefeid, seid, reid, oeid, **kwargs):
-        rdef = ybo.RelationDefinition(ertidx[seid], ertidx[reid], ertidx[oeid],
-                                      constraints=cstrsidx.get(rdefeid, ()),
-                                      eid=rdefeid, **kwargs)
-        if seid in copiedeids or oeid in copiedeids:
-            # delay addition of this rdef. We'll insert them later if needed. We
-            # have to do this because:
-            #
-            # * on etype renaming, we want relation of the old entity type being
-            #   redirected to the new type during migration
-            #
-            # * in the case of a copy, we've to take care that rdef already
-            #   existing in the schema are not overwritten by a redirected one,
-            #   since we want correct eid on them (redirected rdef will be
-            #   removed in rename_entity_type)
-            pendingrdefs.append(rdef)
-        else:
-            # add_relation_def return a RelationDefinitionSchema if it has been
-            # actually added (can be None on duplicated relation definitions,
-            # e.g. if the relation type is marked as beeing symmetric)
-            rdefs = schema.add_relation_def(rdef)
-            if rdefs is not None:
-                ertidx[rdefeid] = rdefs
-                set_perms(rdefs, permsidx)
-    # Get the type parameters for additional base types.
-    try:
-        extra_props = dict(cnx.execute('Any X, XTP WHERE X is CWAttribute, '
-                                       'X extra_props XTP'))
-    except Exception:
-        cnx.critical('Previous CRITICAL notification about extra_props is not '
-                     'a problem if you are migrating to cubicweb 3.17')
-        extra_props = {} # not yet in the schema (introduced by 3.17 migration)
-
-    # load attributes
-    rql = ('Any X,SE,RT,OE,CARD,ORD,DESC,IDX,FTIDX,I18N,DFLT%(fm)s '
-           'WHERE X is CWAttribute, X relation_type RT, X cardinality CARD,'
-           '      X ordernum ORD, X indexed IDX, X description DESC, '
-           '      X internationalizable I18N, X defaultval DFLT,%(fmsnip)s'
-           '      X fulltextindexed FTIDX, X from_entity SE, X to_entity OE')
-    if has_computed_attributes:
-        rql = rql % {'fm': ',FM', 'fmsnip': 'X formula FM,'}
-    else:
-        rql = rql % {'fm': '', 'fmsnip': ''}
-    for values in cnx.execute(rql, build_descr=False):
-        attrs = dict(zip(
-            ('rdefeid', 'seid', 'reid', 'oeid', 'cardinality',
-             'order', 'description', 'indexed', 'fulltextindexed',
-             'internationalizable', 'default', 'formula'), values))
-        typeparams = extra_props.get(attrs['rdefeid'])
-        attrs.update(json.loads(typeparams.getvalue().decode('ascii')) if typeparams else {})
-        default = attrs['default']
-        if default is not None:
-            if isinstance(default, Binary):
-                # while migrating from 3.17 to 3.18, we still have to
-                # handle String defaults
-                attrs['default'] = default.unzpickle()
-        _add_rdef(**attrs)
-    # load relations
-    for values in cnx.execute(
-        'Any X,SE,RT,OE,CARD,ORD,DESC,C WHERE X is CWRelation, X relation_type RT,'
-        'X cardinality CARD, X ordernum ORD, X description DESC, '
-        'X from_entity SE, X to_entity OE, X composite C', build_descr=False):
-        rdefeid, seid, reid, oeid, card, ord, desc, comp = values
-        _add_rdef(rdefeid, seid, reid, oeid,
-                  cardinality=card, description=desc, order=ord,
-                  composite=comp)
-    for rdef in pendingrdefs:
-        try:
-            rdefs = schema.add_relation_def(rdef)
-        except BadSchemaDefinition:
-            continue
-        if rdefs is not None:
-            set_perms(rdefs, permsidx)
-    unique_togethers = {}
-    rset = cnx.execute(
-    'Any X,E,R WHERE '
-    'X is CWUniqueTogetherConstraint, '
-    'X constraint_of E, X relations R', build_descr=False)
-    for values in rset:
-        uniquecstreid, eeid, releid = values
-        eschema = schema.schema_by_eid(eeid)
-        relations = unique_togethers.setdefault(uniquecstreid, (eschema, []))
-        rel = ertidx[releid]
-        if isinstance(rel, schemamod.RelationDefinitionSchema):
-            # not yet migrated 3.9 database ('relations' target type changed
-            # to CWRType in 3.10)
-            rtype = rel.rtype.type
-        else:
-            rtype = str(rel)
-        relations[1].append(rtype)
-    for eschema, unique_together in unique_togethers.values():
-        eschema._unique_together.append(tuple(sorted(unique_together)))
-    schema.infer_specialization_rules()
-    cnx.commit()
-    schema.finalize()
-    schema.reading_from_database = False
-
-
-def deserialize_ertype_permissions(cnx):
-    """return sect action:groups associations for the given
-    entity or relation schema with its eid, according to schema's
-    permissions stored in the database as [read|add|delete|update]_permission
-    relations between CWEType/CWRType and CWGroup entities
-    """
-    res = {}
-    for action in ('read', 'add', 'update', 'delete'):
-        rql = 'Any E,N WHERE G is CWGroup, G name N, E %s_permission G' % action
-        for eid, gname in cnx.execute(rql, build_descr=False):
-            res.setdefault(eid, {}).setdefault(action, []).append(gname)
-        rql = ('Any E,X,EXPR,V WHERE X is RQLExpression, X expression EXPR, '
-               'E %s_permission X, X mainvars V' % action)
-        for eid, expreid, expr, mainvars in cnx.execute(rql, build_descr=False):
-            # we don't know yet if it's a rql expr for an entity or a relation,
-            # so append a tuple to differentiate from groups and so we'll be
-            # able to instantiate it later
-            res.setdefault(eid, {}).setdefault(action, []).append( (expr, mainvars, expreid) )
-    return res
-
-def deserialize_rdef_constraints(cnx):
-    """return the list of relation definition's constraints as instances"""
-    res = {}
-    for rdefeid, ceid, ct, val in cnx.execute(
-        'Any E, X,TN,V WHERE E constrained_by X, X is CWConstraint, '
-        'X cstrtype T, T name TN, X value V', build_descr=False):
-        cstr = CONSTRAINTS[ct].deserialize(val)
-        cstr.eid = ceid
-        res.setdefault(rdefeid, []).append(cstr)
-    return res
-
-def set_perms(erschema, permsidx):
-    """set permissions on the given erschema according to the permission
-    definition dictionary as built by deserialize_ertype_permissions for a
-    given erschema's eid
-    """
-    # reset erschema permissions here to avoid getting yams default anyway
-    erschema.permissions = dict((action, ()) for action in erschema.ACTIONS)
-    try:
-        thispermsdict = permsidx[erschema.eid]
-    except KeyError:
-        return
-    for action, somethings in thispermsdict.items():
-        erschema.permissions[action] = tuple(
-            isinstance(p, tuple) and erschema.rql_expression(*p) or p
-            for p in somethings)
-
-
-# schema / perms serialization ################################################
-
-def serialize_schema(cnx, schema):
-    """synchronize schema and permissions in the database according to
-    current schema
-    """
-    _title = '-> storing the schema in the database '
-    print(_title, end=' ')
-    execute = cnx.execute
-    eschemas = schema.entities()
-    pb_size = (len(eschemas + schema.relations())
-               + len(CONSTRAINTS)
-               + len([x for x in eschemas if x.specializes()]))
-    if sys.stdout.isatty():
-        pb = ProgressBar(pb_size, title=_title)
-    else:
-        pb = DummyProgressBar()
-    groupmap = group_mapping(cnx, interactive=False)
-    # serialize all entity types, assuring CWEType is serialized first for proper
-    # is / is_instance_of insertion
-    eschemas.remove(schema.eschema('CWEType'))
-    eschemas.insert(0, schema.eschema('CWEType'))
-    for eschema in eschemas:
-        execschemarql(execute, eschema, eschema2rql(eschema, groupmap))
-        pb.update()
-    # serialize constraint types
-    cstrtypemap = {}
-    rql = 'INSERT CWConstraintType X: X name %(ct)s'
-    for cstrtype in CONSTRAINTS:
-        cstrtypemap[cstrtype] = execute(rql, {'ct': text_type(cstrtype)},
-                                        build_descr=False)[0][0]
-        pb.update()
-    # serialize relations
-    for rschema in schema.relations():
-        # skip virtual relations such as eid, has_text and identity
-        if rschema in VIRTUAL_RTYPES:
-            pb.update()
-            continue
-        if rschema.rule:
-            execschemarql(execute, rschema, crschema2rql(rschema, groupmap))
-            pb.update()
-            continue
-        execschemarql(execute, rschema, rschema2rql(rschema, addrdef=False))
-        if rschema.symmetric:
-            rdefs = [rdef for k, rdef in rschema.rdefs.items()
-                     if (rdef.subject, rdef.object) == k]
-        else:
-            rdefs = rschema.rdefs.values()
-        for rdef in rdefs:
-            execschemarql(execute, rdef,
-                          rdef2rql(rdef, cstrtypemap, groupmap))
-        pb.update()
-    # serialize unique_together constraints
-    for eschema in eschemas:
-        if eschema._unique_together:
-            execschemarql(execute, eschema, uniquetogether2rqls(eschema))
-    # serialize yams inheritance relationships
-    for rql, kwargs in specialize2rql(schema):
-        execute(rql, kwargs, build_descr=False)
-        pb.update()
-    print()
-
-
-# high level serialization functions
-
-def execschemarql(execute, schema, rqls):
-    for rql, kwargs in rqls:
-        kwargs['x'] = schema.eid
-        rset = execute(rql, kwargs, build_descr=False)
-        if schema.eid is None:
-            schema.eid = rset[0][0]
-        else:
-            assert rset
-
-def erschema2rql(erschema, groupmap):
-    if isinstance(erschema, schemamod.EntitySchema):
-        return eschema2rql(erschema, groupmap=groupmap)
-    return rschema2rql(erschema, groupmap=groupmap)
-
-def specialize2rql(schema):
-    for eschema in schema.entities():
-        if eschema.final:
-            continue
-        for rql, kwargs in eschemaspecialize2rql(eschema):
-            yield rql, kwargs
-
-# etype serialization
-
-def eschema2rql(eschema, groupmap=None):
-    """return a list of rql insert statements to enter an entity schema
-    in the database as an CWEType entity
-    """
-    relations, values = eschema_relations_values(eschema)
-    # NOTE: 'specializes' relation can't be inserted here since there's no
-    # way to make sure the parent type is inserted before the child type
-    yield 'INSERT CWEType X: %s' % ','.join(relations) , values
-    # entity permissions
-    if groupmap is not None:
-        for rql, args in _erperms2rql(eschema, groupmap):
-            yield rql, args
-
-def eschema_relations_values(eschema):
-    values = _ervalues(eschema)
-    relations = ['X %s %%(%s)s' % (attr, attr) for attr in sorted(values)]
-    return relations, values
-
-def eschemaspecialize2rql(eschema):
-    specialized_type = eschema.specializes()
-    if specialized_type:
-        values = {'x': eschema.eid, 'et': specialized_type.eid}
-        yield 'SET X specializes ET WHERE X eid %(x)s, ET eid %(et)s', values
-
-def uniquetogether2rqls(eschema):
-    rql_args = []
-    # robustness against duplicated CWUniqueTogetherConstraint (pre 3.18)
-    columnset = set()
-    for columns in eschema._unique_together:
-        if columns in columnset:
-            print('schemaserial: skipping duplicate unique together %r %r' %
-                  (eschema.type, columns))
-            continue
-        columnset.add(columns)
-        rql, args = _uniquetogether2rql(eschema, columns)
-        args['name'] = y2sql.unique_index_name(eschema, columns)
-        rql_args.append((rql, args))
-    return rql_args
-
-def _uniquetogether2rql(eschema, unique_together):
-    relations = []
-    restrictions = []
-    substs = {}
-    for i, name in enumerate(unique_together):
-        rschema = eschema.schema.rschema(name)
-        rtype = 'T%d' % i
-        substs[rtype] = text_type(rschema.type)
-        relations.append('C relations %s' % rtype)
-        restrictions.append('%(rtype)s name %%(%(rtype)s)s' % {'rtype': rtype})
-    relations = ', '.join(relations)
-    restrictions = ', '.join(restrictions)
-    rql = ('INSERT CWUniqueTogetherConstraint C: C name %%(name)s, C constraint_of X, %s '
-           'WHERE X eid %%(x)s, %s')
-    return rql % (relations, restrictions), substs
-
-
-def _ervalues(erschema):
-    try:
-        type_ = text_type(erschema.type)
-    except UnicodeDecodeError as e:
-        raise Exception("can't decode %s [was %s]" % (erschema.type, e))
-    try:
-        desc = text_type(erschema.description) or u''
-    except UnicodeDecodeError as e:
-        raise Exception("can't decode %s [was %s]" % (erschema.description, e))
-    return {
-        'name': type_,
-        'final': erschema.final,
-        'description': desc,
-        }
-
-# rtype serialization
-
-def rschema2rql(rschema, cstrtypemap=None, addrdef=True, groupmap=None):
-    """generate rql insert statements to enter a relation schema
-    in the database as an CWRType entity
-    """
-    if rschema.type == 'has_text':
-        return
-    relations, values = rschema_relations_values(rschema)
-    yield 'INSERT CWRType X: %s' % ','.join(relations), values
-    if addrdef:
-        assert cstrtypemap
-        # sort for testing purpose
-        for rdef in sorted(rschema.rdefs.values(),
-                           key=lambda x: (x.subject, x.object)):
-            for rql, values in rdef2rql(rdef, cstrtypemap, groupmap):
-                yield rql, values
-
-def rschema_relations_values(rschema):
-    values = _ervalues(rschema)
-    values['final'] = rschema.final
-    values['symmetric'] = rschema.symmetric
-    values['inlined'] = rschema.inlined
-    if PY2 and isinstance(rschema.fulltext_container, str):
-        values['fulltext_container'] = unicode(rschema.fulltext_container)
-    else:
-        values['fulltext_container'] = rschema.fulltext_container
-    relations = ['X %s %%(%s)s' % (attr, attr) for attr in sorted(values)]
-    return relations, values
-
-def crschema2rql(crschema, groupmap):
-    relations, values = crschema_relations_values(crschema)
-    yield 'INSERT CWComputedRType X: %s' % ','.join(relations), values
-    if groupmap:
-        for rql, args in _erperms2rql(crschema, groupmap):
-            yield rql, args
-
-def crschema_relations_values(crschema):
-    values = _ervalues(crschema)
-    values['rule'] = text_type(crschema.rule)
-    # XXX why oh why?
-    del values['final']
-    relations = ['X %s %%(%s)s' % (attr, attr) for attr in sorted(values)]
-    return relations, values
-
-# rdef serialization
-
-def rdef2rql(rdef, cstrtypemap, groupmap=None):
-    # don't serialize inferred relations
-    if rdef.infered:
-        return
-    relations, values = _rdef_values(rdef)
-    relations.append('X relation_type ER,X from_entity SE,X to_entity OE')
-    values.update({'se': rdef.subject.eid, 'rt': rdef.rtype.eid, 'oe': rdef.object.eid})
-    if rdef.final:
-        etype = 'CWAttribute'
-    else:
-        etype = 'CWRelation'
-    yield 'INSERT %s X: %s WHERE SE eid %%(se)s,ER eid %%(rt)s,OE eid %%(oe)s' % (
-        etype, ','.join(relations), ), values
-    for rql, values in constraints2rql(cstrtypemap, rdef.constraints):
-        yield rql, values
-    # no groupmap means "no security insertion"
-    if groupmap:
-        for rql, args in _erperms2rql(rdef, groupmap):
-            yield rql, args
-
-_IGNORED_PROPS = ['eid', 'constraints', 'uid', 'infered', 'permissions']
-
-def _rdef_values(rdef):
-    amap = {'order': 'ordernum', 'default': 'defaultval'}
-    values = {}
-    extra = {}
-    for prop in rdef.rproperty_defs(rdef.object):
-        if prop in _IGNORED_PROPS:
-            continue
-        value = getattr(rdef, prop)
-        if prop not in KNOWN_RPROPERTIES:
-            extra[prop] = value
-            continue
-        # XXX type cast really necessary?
-        if prop in ('indexed', 'fulltextindexed', 'internationalizable'):
-            value = bool(value)
-        elif prop == 'ordernum':
-            value = int(value)
-        elif PY2 and isinstance(value, str):
-            value = unicode(value)
-        if value is not None and prop == 'default':
-            value = Binary.zpickle(value)
-        values[amap.get(prop, prop)] = value
-    if extra:
-        values['extra_props'] = Binary(json.dumps(extra).encode('ascii'))
-    relations = ['X %s %%(%s)s' % (attr, attr) for attr in sorted(values)]
-    return relations, values
-
-def constraints2rql(cstrtypemap, constraints, rdefeid=None):
-    for constraint in constraints:
-        values = {'ct': cstrtypemap[constraint.type()],
-                  'value': text_type(constraint.serialize()),
-                  'x': rdefeid} # when not specified, will have to be set by the caller
-        yield 'INSERT CWConstraint X: X value %(value)s, X cstrtype CT, EDEF constrained_by X WHERE \
-CT eid %(ct)s, EDEF eid %(x)s', values
-
-
-def _erperms2rql(erschema, groupmap):
-    """return rql insert statements to enter the entity or relation
-    schema's permissions in the database as
-    [read|add|delete|update]_permission relations between CWEType/CWRType
-    and CWGroup entities
-    """
-    for action in erschema.ACTIONS:
-        try:
-            grantedto = erschema.action_permissions(action)
-        except KeyError:
-            # may occurs when modifying persistent schema
-            continue
-        for group_or_rqlexpr in grantedto:
-            if isinstance(group_or_rqlexpr, string_types):
-                # group
-                try:
-                    yield ('SET X %s_permission Y WHERE Y eid %%(g)s, X eid %%(x)s' % action,
-                           {'g': groupmap[group_or_rqlexpr]})
-                except KeyError:
-                    print("WARNING: group %s used in permissions for %s was ignored because it doesn't exist."
-                          " You may want to add it into a precreate.py file" % (group_or_rqlexpr, erschema))
-                    continue
-            else:
-                # rqlexpr
-                rqlexpr = group_or_rqlexpr
-                yield ('INSERT RQLExpression E: E expression %%(e)s, E exprtype %%(t)s, '
-                       'E mainvars %%(v)s, X %s_permission E WHERE X eid %%(x)s' % action,
-                       {'e': text_type(rqlexpr.expression),
-                        'v': text_type(','.join(sorted(rqlexpr.mainvars))),
-                        't': text_type(rqlexpr.__class__.__name__)})
-
-# update functions
-
-def updateeschema2rql(eschema, eid):
-    relations, values = eschema_relations_values(eschema)
-    values['x'] = eid
-    yield 'SET %s WHERE X eid %%(x)s' % ','.join(relations), values
-
-def updaterschema2rql(rschema, eid):
-    if rschema.rule:
-        yield ('SET X rule %(r)s WHERE X eid %(x)s',
-               {'x': eid, 'r': text_type(rschema.rule)})
-    else:
-        relations, values = rschema_relations_values(rschema)
-        values['x'] = eid
-        yield 'SET %s WHERE X eid %%(x)s' % ','.join(relations), values
-
-def updaterdef2rql(rdef, eid):
-    relations, values = _rdef_values(rdef)
-    values['x'] = eid
-    yield 'SET %s WHERE X eid %%(x)s' % ','.join(relations), values