misc/migration/3.18.0_Any.py
changeset 9375 8e88576787c3
parent 9370 15c695d8d865
child 9395 96dba2efd16d
equal deleted inserted replaced
9374:1236d9058ad3 9375:8e88576787c3
       
     1 driver = config.sources()['system']['db-driver']
       
     2 if not (driver == 'postgres' or driver.startswith('sqlserver')):
       
     3     import sys
       
     4     print >>sys.stderr, 'This migration is not supported for backends other than sqlserver or postgres (yet).'
       
     5     sys.exit(1)
       
     6 
     1 sync_schema_props_perms('defaultval')
     7 sync_schema_props_perms('defaultval')
     2 
     8 
     3 def convert_defaultval(cwattr, default):
     9 def convert_defaultval(cwattr, default):
     4     from decimal import Decimal
    10     from decimal import Decimal
     5     import yams
    11     import yams
    29         assert atype == 'String', atype
    35         assert atype == 'String', atype
    30         default = unicode(default)
    36         default = unicode(default)
    31     return Binary.zpickle(default)
    37     return Binary.zpickle(default)
    32 
    38 
    33 dbh = repo.system_source.dbhelper
    39 dbh = repo.system_source.dbhelper
    34 driver = config.sources()['system']['db-driver']
       
    35 
    40 
    36 if driver == 'postgres' or driver.startswith('sqlserver'):
       
    37 
    41 
    38     sql('ALTER TABLE cw_cwattribute ADD new_defaultval %s' % dbh.TYPE_MAPPING['Bytes'])
    42 sql('ALTER TABLE cw_cwattribute ADD new_defaultval %s' % dbh.TYPE_MAPPING['Bytes'])
    39 
    43 
    40     for cwattr in rql('CWAttribute X').entities():
    44 for cwattr in rql('CWAttribute X').entities():
    41         olddefault = cwattr.defaultval
    45     olddefault = cwattr.defaultval
    42         if olddefault is not None:
    46     if olddefault is not None:
    43             req = "UPDATE cw_cwattribute SET new_defaultval = %(val)s WHERE cw_eid = %(eid)s"
    47         req = "UPDATE cw_cwattribute SET new_defaultval = %(val)s WHERE cw_eid = %(eid)s"
    44             args = {'val': dbh.binary_value(convert_defaultval(cwattr, olddefault).getvalue()), 'eid': cwattr.eid}
    48         args = {'val': dbh.binary_value(convert_defaultval(cwattr, olddefault).getvalue()), 'eid': cwattr.eid}
    45             sql(req, args, ask_confirm=False)
       
    46 
       
    47     sql('ALTER TABLE cw_cwattribute DROP COLUMN cw_defaultval')
       
    48     if config.sources()['system']['db-driver'] == 'postgres':
       
    49         sql('ALTER TABLE cw_cwattribute RENAME COLUMN new_defaultval TO cw_defaultval')
       
    50     else:
       
    51         sql("sp_rename 'cw_cwattribute.new_defaultval', 'cw_defaultval', 'COLUMN'")
       
    52 
       
    53 elif driver == 'sqlite':
       
    54 
       
    55     import re
       
    56     create = sql("SELECT sql FROM sqlite_master WHERE name = 'cw_CWAttribute'")[0][0]
       
    57     create = re.sub('cw_defaultval varchar[^,]*,', 'cw_defaultval bytea,', create, re.I)
       
    58     create = re.sub('cw_CWAttribute', 'tmp_cw_CWAttribute', create, re.I)
       
    59     sql(create)
       
    60     sql("INSERT INTO tmp_cw_CWAttribute SELECT * FROM cw_CWAttribute")
       
    61     for cwattr in rql('CWAttribute X').entities():
       
    62         olddefault = cwattr.defaultval
       
    63         if olddefault is None:
       
    64             continue
       
    65         req = "UPDATE tmp_cw_CWAttribute SET cw_defaultval = %(val)s WHERE cw_eid = %(eid)s"
       
    66         args = {'val': dbh.binary_value(convert_defaultval(cwattr, olddefault).getvalue()),
       
    67                 'eid': cwattr.eid}
       
    68         sql(req, args, ask_confirm=False)
    49         sql(req, args, ask_confirm=False)
    69 
    50 
    70     sql('DROP TABLE cw_CWAttribute')
    51 sql('ALTER TABLE cw_cwattribute DROP COLUMN cw_defaultval')
    71     sql('ALTER TABLE tmp_cw_CWAttribute RENAME TO cw_CWAttribute')
    52 if driver == 'postgres':
       
    53     sql('ALTER TABLE cw_cwattribute RENAME COLUMN new_defaultval TO cw_defaultval')
       
    54 else: # sqlserver
       
    55     sql("sp_rename 'cw_cwattribute.new_defaultval', 'cw_defaultval', 'COLUMN'")
    72 
    56 
    73 else:
       
    74     assert False, 'upgrade not supported on this database backend'
       
    75 
    57 
    76 # Set object type to "Bytes" for CWAttribute's "defaultval" attribute
    58 # Set object type to "Bytes" for CWAttribute's "defaultval" attribute
    77 rql('SET X to_entity B WHERE X is CWAttribute, X from_entity Y, Y name "CWAttribute", '
    59 rql('SET X to_entity B WHERE X is CWAttribute, X from_entity Y, Y name "CWAttribute", '
    78     'X relation_type Z, Z name "defaultval", B name "Bytes"')
    60     'X relation_type Z, Z name "defaultval", B name "Bytes"')
    79 
    61 
    80 from yams import buildobjs as ybo
    62 from yams import buildobjs as ybo
    81 schema.add_relation_def(ybo.RelationDefinition('CWAttribute', 'defaultval', 'Bytes'))
    63 schema.add_relation_def(ybo.RelationDefinition('CWAttribute', 'defaultval', 'Bytes'))
    82 schema.del_relation_def('CWAttribute', 'defaultval', 'String')
    64 schema.del_relation_def('CWAttribute', 'defaultval', 'String')
    83 
    65 
    84 commit()
    66 commit()
    85 
       
    86 
    67 
    87 for rschema in schema.relations():
    68 for rschema in schema.relations():
    88     if rschema.symmetric:
    69     if rschema.symmetric:
    89         subjects = set(repr(e.type) for e in rschema.subjects())
    70         subjects = set(repr(e.type) for e in rschema.subjects())
    90         objects = set(repr(e.type) for e in rschema.objects())
    71         objects = set(repr(e.type) for e in rschema.objects())
    98             print 'deleting broken relations %s for eids %s' % (rschema.type, martians)
    79             print 'deleting broken relations %s for eids %s' % (rschema.type, martians)
    99             sql('DELETE FROM %s_relation WHERE eid_from IN (%s) OR eid_to IN (%s)' % (rschema.type, martians, martians))
    80             sql('DELETE FROM %s_relation WHERE eid_from IN (%s) OR eid_to IN (%s)' % (rschema.type, martians, martians))
   100         with session.deny_all_hooks_but():
    81         with session.deny_all_hooks_but():
   101             rql('SET X %(r)s Y WHERE Y %(r)s X, NOT X %(r)s Y' % {'r': rschema.type})
    82             rql('SET X %(r)s Y WHERE Y %(r)s X, NOT X %(r)s Y' % {'r': rschema.type})
   102     commit()
    83     commit()
       
    84 
       
    85 
       
    86 # multi columns unique constraints regeneration
       
    87 from cubicweb.server import schemaserial
       
    88 
       
    89 # syncschema hooks would try to remove indices but
       
    90 # 1) we already do that below
       
    91 # 2) the hook expects the CWUniqueTogetherConstraint.name attribute that hasn't
       
    92 #    yet been added
       
    93 with session.allow_all_hooks_but('syncschema'):
       
    94     rql('DELETE CWUniqueTogetherConstraint C')
       
    95 commit()
       
    96 
       
    97 add_attribute('CWUniqueTogetherConstraint', 'name')
       
    98 
       
    99 # low-level wipe code for postgres & sqlserver, plain sql ...
       
   100 if driver == 'postgres':
       
   101     for indexname, in sql('select indexname from pg_indexes'):
       
   102         if indexname.startswith('unique_'):
       
   103             print 'dropping index', indexname
       
   104             sql('DROP INDEX %s' % indexname)
       
   105     commit()
       
   106 elif driver.startswith('sqlserver'):
       
   107     for viewname, in sql('select name from sys.views'):
       
   108         if viewname.startswith('utv_'):
       
   109             print 'dropping view (index should be cascade-deleted)', viewname
       
   110             sql('DROP VIEW %s' % viewname)
       
   111     commit()
       
   112 
       
   113 # recreate the constraints, hook will lead to low-level recreation
       
   114 for eschema in sorted(schema.entities()):
       
   115     if eschema._unique_together:
       
   116         rql_args = schemaserial.uniquetogether2rqls(eschema)
       
   117         for rql, args in rql_args:
       
   118             args['x'] = eschema.eid
       
   119             session.execute(rql, args)
       
   120         commit()