misc/migration/3.21.0_Any.py
author Julien Cristau <julien.cristau@logilab.fr>
Thu, 02 Jul 2015 15:44:49 +0200
changeset 10482 88119421a09c
parent 10448 de5be53e2ea8
child 10483 c8dbb845b465
permissions -rw-r--r--
[migration/3.21] Add missing foreign keys when upgrading Try to delete dangling relations, since there's no point in keeping them. Related to #4846892.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
10482
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
     1
from cubicweb.schema import PURE_VIRTUAL_RTYPES
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
     2
from cubicweb.server.schema2sql import rschema_has_table
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
     3
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
     4
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
     5
def add_foreign_keys():
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
     6
    source = repo.sources_by_uri['system']
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
     7
    if not source.dbhelper.alter_column_support:
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
     8
        return
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
     9
    for rschema in schema.relations():
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    10
        if rschema.inlined:
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    11
            add_foreign_keys_inlined(rschema)
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    12
        elif rschema_has_table(rschema, skip_relations=PURE_VIRTUAL_RTYPES):
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    13
            add_foreign_keys_relation(rschema)
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    14
    for eschema in schema.entities():
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    15
        if eschema.final:
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    16
            continue
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    17
        add_foreign_key_etype(eschema)
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    18
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    19
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    20
def add_foreign_keys_relation(rschema):
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    21
    args = {'r': rschema.type}
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    22
    count = sql('SELECT COUNT(*) FROM %(r)s_relation '
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    23
                'WHERE eid_from NOT IN (SELECT eid FROM entities) '
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    24
                'OR    eid_to   NOT IN (SELECT eid FROM entities)' % args)[0][0]
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    25
    if count:
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    26
        print '%s references %d unknown entities, deleting' % (rschema, count)
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    27
        sql('DELETE FROM %(r)s_relation '
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    28
            'WHERE eid_from NOT IN (SELECT eid FROM entities) '
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    29
            'OR    eid_to   NOT IN (SELECT eid FROM entities)' % args)
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    30
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    31
    # XXX drop if exists?
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    32
    sql('ALTER TABLE %(r)s_relation ADD CONSTRAINT %(r)s_relation_eid_from_fkey '
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    33
        'FOREIGN KEY (eid_from) REFERENCES entities (eid)' % args)
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    34
    sql('ALTER TABLE %(r)s_relation ADD CONSTRAINT %(r)s_relation_eid_to_fkey '
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    35
        'FOREIGN KEY (eid_to) REFERENCES entities (eid)' % args)
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    36
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    37
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    38
def add_foreign_keys_inlined(rschema):
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    39
    for eschema in rschema.subjects():
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    40
        args = {'e': eschema.type, 'r': rschema.type}
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    41
        args['c'] = 'cw_%(e)s_cw_%(r)s_fkey' % args
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    42
        if sql('SELECT COUNT(*) FROM cw_%(e)s WHERE '
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    43
               'cw_%(r)s NOT IN (SELECT eid FROM entities)' % args)[0][0]:
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    44
            if eschema.rdef(rschema).cardinality[0] == '1':
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    45
                assert not '%(e)s.%(r)s references unknown entities, fix manually'
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    46
            print '%(e)s.%(r)s references unknown entities, deleting'
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    47
            sql('UPDATE cw_%(e)s SET cw_%(r)s = NULL WHERE '
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    48
                'cw_%(r)s NOT IN (SELECT eid FROM entities)' % args)
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    49
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    50
        # XXX if exists?
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    51
        #sql('ALTER TABLE cw_%(e)s DROP CONSTRAINT %(c)s' % args)
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    52
        sql('ALTER TABLE cw_%(e)s ADD CONSTRAINT %(c)s '
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    53
            'FOREIGN KEY (cw_%(r)s) references entities(eid)'
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    54
            % args)
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    55
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    56
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    57
def add_foreign_key_etype(eschema):
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    58
    args = {'e': eschema.type}
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    59
    sql('ALTER TABLE cw_%(e)s ADD CONSTRAINT cw_%(e)s_cw_eid_fkey '
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    60
        'FOREIGN KEY (cw_eid) REFERENCES entities (eid)' % args)
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    61
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    62
88119421a09c [migration/3.21] Add missing foreign keys when upgrading
Julien Cristau <julien.cristau@logilab.fr>
parents: 10448
diff changeset
    63
add_foreign_keys()
10208
249126034c0e Add unique index on entities.extid
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    64
249126034c0e Add unique index on entities.extid
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    65
helper = repo.system_source.dbhelper
249126034c0e Add unique index on entities.extid
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    66
sql('DROP INDEX entities_extid_idx')
249126034c0e Add unique index on entities.extid
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    67
sql(helper.sql_create_index('entities', 'extid', True))
10209
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
    68
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
    69
sql('''
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
    70
CREATE TABLE moved_entities (
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
    71
  eid INTEGER PRIMARY KEY NOT NULL,
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
    72
  extid VARCHAR(256) UNIQUE
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
    73
)
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
    74
''')
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
    75
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
    76
moved_entities = sql('SELECT -eid, extid FROM entities WHERE eid < 0')
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
    77
cu = session.cnxset.cu
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
    78
cu.executemany('INSERT INTO moved_entities (eid, extid) VALUES (%s, %s)',
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
    79
               moved_entities)
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
    80
sql('DELETE FROM entities WHERE eid < 0')
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
    81
10208
249126034c0e Add unique index on entities.extid
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    82
commit()
10316
4ce8b8437838 [schemas] make CWEType.final default to False (closes #5049201)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 10209
diff changeset
    83
4ce8b8437838 [schemas] make CWEType.final default to False (closes #5049201)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 10209
diff changeset
    84
sync_schema_props_perms('CWEType')
10371
88577b10b31e [schema] add a unique index on cwuri
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10316
diff changeset
    85
88577b10b31e [schema] add a unique index on cwuri
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10316
diff changeset
    86
sync_schema_props_perms('cwuri')
10448
de5be53e2ea8 [migration] add sql constraints on upgrade
Julien Cristau <julien.cristau@logilab.fr>
parents: 10371
diff changeset
    87
de5be53e2ea8 [migration] add sql constraints on upgrade
Julien Cristau <julien.cristau@logilab.fr>
parents: 10371
diff changeset
    88
from cubicweb.server.schema2sql import check_constraint
de5be53e2ea8 [migration] add sql constraints on upgrade
Julien Cristau <julien.cristau@logilab.fr>
parents: 10371
diff changeset
    89
de5be53e2ea8 [migration] add sql constraints on upgrade
Julien Cristau <julien.cristau@logilab.fr>
parents: 10371
diff changeset
    90
for cwconstraint in rql('Any C WHERE R constrained_by C').entities():
de5be53e2ea8 [migration] add sql constraints on upgrade
Julien Cristau <julien.cristau@logilab.fr>
parents: 10371
diff changeset
    91
    cwrdef = cwconstraint.reverse_constrained_by[0]
de5be53e2ea8 [migration] add sql constraints on upgrade
Julien Cristau <julien.cristau@logilab.fr>
parents: 10371
diff changeset
    92
    rdef = cwrdef.yams_schema()
de5be53e2ea8 [migration] add sql constraints on upgrade
Julien Cristau <julien.cristau@logilab.fr>
parents: 10371
diff changeset
    93
    cstr = rdef.constraint_by_eid(cwconstraint.eid)
de5be53e2ea8 [migration] add sql constraints on upgrade
Julien Cristau <julien.cristau@logilab.fr>
parents: 10371
diff changeset
    94
    if cstr.type() not in ('BoundaryConstraint', 'IntervalBoundConstraint', 'StaticVocabularyConstraint'):
de5be53e2ea8 [migration] add sql constraints on upgrade
Julien Cristau <julien.cristau@logilab.fr>
parents: 10371
diff changeset
    95
        continue
de5be53e2ea8 [migration] add sql constraints on upgrade
Julien Cristau <julien.cristau@logilab.fr>
parents: 10371
diff changeset
    96
    cstrname, check = check_constraint(rdef.subject, rdef.object, rdef.rtype.type,
de5be53e2ea8 [migration] add sql constraints on upgrade
Julien Cristau <julien.cristau@logilab.fr>
parents: 10371
diff changeset
    97
            cstr, helper, prefix='cw_')
de5be53e2ea8 [migration] add sql constraints on upgrade
Julien Cristau <julien.cristau@logilab.fr>
parents: 10371
diff changeset
    98
    sql('ALTER TABLE %s%s ADD CONSTRAINT %s CHECK(%s)' % ('cw_', rdef.subject.type, cstrname, check))
de5be53e2ea8 [migration] add sql constraints on upgrade
Julien Cristau <julien.cristau@logilab.fr>
parents: 10371
diff changeset
    99
commit()