misc/migration/bootstrapmigration_repository.py
changeset 10270 1ae64186af94
parent 10058 d47c318f95b2
child 10272 3231fd2fa7a5
equal deleted inserted replaced
10269:d5e298df98d1 10270:1ae64186af94
    47     cursor.execute(dbh.sql_drop_sequence('entities_id_seq'))
    47     cursor.execute(dbh.sql_drop_sequence('entities_id_seq'))
    48     cursor.execute(dbh.sql_create_numrange('entities_id_seq'))
    48     cursor.execute(dbh.sql_create_numrange('entities_id_seq'))
    49     cursor.execute(dbh.sql_restart_numrange('entities_id_seq', initial_value=lasteid))
    49     cursor.execute(dbh.sql_restart_numrange('entities_id_seq', initial_value=lasteid))
    50     session.commit()
    50     session.commit()
    51 
    51 
       
    52 if applcubicwebversion <= (3, 13, 0) and cubicwebversion >= (3, 13, 1):
       
    53     sql('ALTER TABLE entities ADD asource VARCHAR(64)')
       
    54     sql('UPDATE entities SET asource=cw_name  '
       
    55         'FROM cw_CWSource, cw_source_relation '
       
    56         'WHERE entities.eid=cw_source_relation.eid_from AND cw_source_relation.eid_to=cw_CWSource.cw_eid')
       
    57     commit()
       
    58 
       
    59 if applcubicwebversion <= (3, 14, 4) and cubicwebversion >= (3, 14, 4):
       
    60     from yams import schema2sql as y2sql
       
    61     dbhelper = repo.system_source.dbhelper
       
    62     rdefdef = schema['CWSource'].rdef('name')
       
    63     attrtype = y2sql.type_from_constraints(dbhelper, rdefdef.object, rdefdef.constraints).split()[0]
       
    64     cursor = session.cnxset.cu
       
    65     sql('UPDATE entities SET asource = source WHERE asource is NULL')
       
    66     dbhelper.change_col_type(cursor, 'entities', 'asource', attrtype, False)
       
    67     dbhelper.change_col_type(cursor, 'entities', 'source', attrtype, False)
       
    68 
       
    69     # we now have a functional asource column, start using the normal eid_type_source method
       
    70     if repo.system_source.eid_type_source == repo.system_source.eid_type_source_pre_131:
       
    71         del repo.system_source.eid_type_source
       
    72 
    52 if applcubicwebversion < (3, 19, 0) and cubicwebversion >= (3, 19, 0):
    73 if applcubicwebversion < (3, 19, 0) and cubicwebversion >= (3, 19, 0):
    53     try: 
    74     try: 
    54         # need explicit drop of the indexes on some database systems (sqlserver)
    75         # need explicit drop of the indexes on some database systems (sqlserver)
    55         sql(repo.system_source.dbhelper.sql_drop_index('entities', 'mtime'))
    76         sql(repo.system_source.dbhelper.sql_drop_index('entities', 'mtime'))
    56         sql('ALTER TABLE "entities" DROP COLUMN "mtime"')
    77         sql('ALTER TABLE "entities" DROP COLUMN "mtime"')
    60         print "'entities' table of the database has probably been already updated"
    81         print "'entities' table of the database has probably been already updated"
    61 
    82 
    62     commit()
    83     commit()
    63 
    84 
    64     replace_eid_sequence_with_eid_numrange(session)
    85     replace_eid_sequence_with_eid_numrange(session)
       
    86 
       
    87 if schema['TZDatetime'].eid is None:
       
    88     add_entity_type('TZDatetime', auto=False)
       
    89 if schema['TZTime'].eid is None:
       
    90     add_entity_type('TZTime', auto=False)
       
    91 
       
    92 if applcubicwebversion < (3, 18, 0) and cubicwebversion >= (3, 18, 0):
       
    93     driver = config.system_source_config['db-driver']
       
    94     if not (driver == 'postgres' or driver.startswith('sqlserver')):
       
    95         import sys
       
    96         print >>sys.stderr, 'This migration is not supported for backends other than sqlserver or postgres (yet).'
       
    97         sys.exit(1)
       
    98 
       
    99     add_relation_definition('CWAttribute', 'add_permission', 'CWGroup')
       
   100     add_relation_definition('CWAttribute', 'add_permission', 'RQLExpression')
       
   101 
       
   102     # a bad defaultval in 3.13.8 schema was fixed in 3.13.9, but the migration was missed
       
   103     rql('SET ATTR defaultval NULL WHERE ATTR from_entity E, E name "CWSource", ATTR relation_type T, T name "in_synchronization"')
       
   104 
       
   105     # the migration gets confused when we change rdefs out from under it.  So
       
   106     # explicitly remove this size constraint so it doesn't stick around and break
       
   107     # things later.
       
   108     rdefeid = schema['defaultval'].rdefs.values()[0].eid
       
   109     rql('DELETE CWConstraint C WHERE C cstrtype T, T name "SizeConstraint", R constrained_by C, R eid %(eid)s', {'eid': rdefeid})
       
   110 
       
   111     sync_schema_props_perms('defaultval')
       
   112 
       
   113     def convert_defaultval(cwattr, default):
       
   114         from decimal import Decimal
       
   115         import yams
       
   116         from cubicweb import Binary
       
   117         if default is None:
       
   118             return
       
   119         if isinstance(default, Binary):
       
   120             # partially migrated instance, try to be idempotent
       
   121             return default
       
   122         atype = cwattr.to_entity[0].name
       
   123         if atype == 'Boolean':
       
   124             # boolean attributes with default=False were stored as ''
       
   125             assert default in ('True', 'False', ''), repr(default)
       
   126             default = default == 'True'
       
   127         elif atype in ('Int', 'BigInt'):
       
   128             default = int(default)
       
   129         elif atype == 'Float':
       
   130             default = float(default)
       
   131         elif atype == 'Decimal':
       
   132             default = Decimal(default)
       
   133         elif atype in ('Date', 'Datetime', 'TZDatetime', 'Time'):
       
   134             try:
       
   135                 # handle NOW and TODAY, keep them stored as strings
       
   136                 yams.KEYWORD_MAP[atype][default.upper()]
       
   137                 default = default.upper()
       
   138             except KeyError:
       
   139                 # otherwise get an actual date or datetime
       
   140                 default = yams.DATE_FACTORY_MAP[atype](default)
       
   141         else:
       
   142             assert atype == 'String', atype
       
   143             default = unicode(default)
       
   144         return Binary.zpickle(default)
       
   145 
       
   146     dbh = repo.system_source.dbhelper
       
   147 
       
   148 
       
   149     sql('ALTER TABLE cw_cwattribute ADD new_defaultval %s' % dbh.TYPE_MAPPING['Bytes'])
       
   150 
       
   151     for cwattr in rql('CWAttribute X').entities():
       
   152         olddefault = cwattr.defaultval
       
   153         if olddefault is not None:
       
   154             req = "UPDATE cw_cwattribute SET new_defaultval = %(val)s WHERE cw_eid = %(eid)s"
       
   155             args = {'val': dbh.binary_value(convert_defaultval(cwattr, olddefault).getvalue()), 'eid': cwattr.eid}
       
   156             sql(req, args, ask_confirm=False)
       
   157 
       
   158     sql('ALTER TABLE cw_cwattribute DROP COLUMN cw_defaultval')
       
   159     if driver == 'postgres':
       
   160         sql('ALTER TABLE cw_cwattribute RENAME COLUMN new_defaultval TO cw_defaultval')
       
   161     else: # sqlserver
       
   162         sql("sp_rename 'cw_cwattribute.new_defaultval', 'cw_defaultval', 'COLUMN'")
       
   163 
       
   164 
       
   165     # Set object type to "Bytes" for CWAttribute's "defaultval" attribute
       
   166     rql('SET X to_entity B WHERE X is CWAttribute, X from_entity Y, Y name "CWAttribute", '
       
   167         'X relation_type Z, Z name "defaultval", B name "Bytes", NOT X to_entity B')
       
   168 
       
   169     oldrdef = schema['CWAttribute'].rdef('defaultval')
       
   170     import yams.buildobjs as ybo
       
   171     newrdef = ybo.RelationDefinition('CWAttribute', 'defaultval', 'Bytes')
       
   172     newrdef.eid = oldrdef.eid
       
   173     schema.add_relation_def(newrdef)
       
   174     schema.del_relation_def('CWAttribute', 'defaultval', 'String')
       
   175 
       
   176     commit()
       
   177 
       
   178     sync_schema_props_perms('defaultval')
       
   179 
       
   180     for rschema in schema.relations():
       
   181         if rschema.symmetric:
       
   182             subjects = set(repr(e.type) for e in rschema.subjects())
       
   183             objects = set(repr(e.type) for e in rschema.objects())
       
   184             assert subjects == objects
       
   185             martians = set(str(eid) for eid, in sql('SELECT eid_to FROM %s_relation, entities WHERE eid_to = eid AND type NOT IN (%s)' %
       
   186                                                (rschema.type, ','.join(subjects))))
       
   187             martians |= set(str(eid) for eid, in sql('SELECT eid_from FROM %s_relation, entities WHERE eid_from = eid AND type NOT IN (%s)' %
       
   188                                                 (rschema.type, ','.join(subjects))))
       
   189             if martians:
       
   190                 martians = ','.join(martians)
       
   191                 print 'deleting broken relations %s for eids %s' % (rschema.type, martians)
       
   192                 sql('DELETE FROM %s_relation WHERE eid_from IN (%s) OR eid_to IN (%s)' % (rschema.type, martians, martians))
       
   193             with session.deny_all_hooks_but():
       
   194                 rql('SET X %(r)s Y WHERE Y %(r)s X, NOT X %(r)s Y' % {'r': rschema.type})
       
   195             commit()
       
   196 
       
   197 
       
   198     # multi columns unique constraints regeneration
       
   199     from cubicweb.server import schemaserial
       
   200 
       
   201     # syncschema hooks would try to remove indices but
       
   202     # 1) we already do that below
       
   203     # 2) the hook expects the CWUniqueTogetherConstraint.name attribute that hasn't
       
   204     #    yet been added
       
   205     with session.allow_all_hooks_but('syncschema'):
       
   206         rql('DELETE CWUniqueTogetherConstraint C')
       
   207     commit()
       
   208     add_attribute('CWUniqueTogetherConstraint', 'name')
       
   209 
       
   210     # low-level wipe code for postgres & sqlserver, plain sql ...
       
   211     if driver == 'postgres':
       
   212         for indexname, in sql('select indexname from pg_indexes'):
       
   213             if indexname.startswith('unique_'):
       
   214                 print 'dropping index', indexname
       
   215                 sql('DROP INDEX %s' % indexname)
       
   216         commit()
       
   217     elif driver.startswith('sqlserver'):
       
   218         for viewname, in sql('select name from sys.views'):
       
   219             if viewname.startswith('utv_'):
       
   220                 print 'dropping view (index should be cascade-deleted)', viewname
       
   221                 sql('DROP VIEW %s' % viewname)
       
   222         commit()
       
   223 
       
   224     # recreate the constraints, hook will lead to low-level recreation
       
   225     for eschema in sorted(schema.entities()):
       
   226         if eschema._unique_together:
       
   227             print 'recreate unique indexes for', eschema
       
   228             rql_args = schemaserial.uniquetogether2rqls(eschema)
       
   229             for rql, args in rql_args:
       
   230                 args['x'] = eschema.eid
       
   231                 session.execute(rql, args)
       
   232     commit()
       
   233 
       
   234     # all attributes perms have to be refreshed ...
       
   235     for rschema in sorted(schema.relations()):
       
   236         if rschema.final:
       
   237             if rschema.type in fsschema:
       
   238                 print 'sync perms for', rschema.type
       
   239                 sync_schema_props_perms(rschema.type, syncprops=False, ask_confirm=False, commit=False)
       
   240             else:
       
   241                 print 'WARNING: attribute %s missing from fs schema' % rschema.type
       
   242     commit()
    65 
   243 
    66 if applcubicwebversion < (3, 17, 0) and cubicwebversion >= (3, 17, 0):
   244 if applcubicwebversion < (3, 17, 0) and cubicwebversion >= (3, 17, 0):
    67     try:
   245     try:
    68         add_cube('sioc', update_database=False)
   246         add_cube('sioc', update_database=False)
    69     except ConfigurationError:
   247     except ConfigurationError:
    81     except ConfigurationError:
   259     except ConfigurationError:
    82         if not confirm('In cubicweb 3.17 geocoding views have been moved to the geocoding '
   260         if not confirm('In cubicweb 3.17 geocoding views have been moved to the geocoding '
    83                        'cube, which is not installed.  Continue anyway?'):
   261                        'cube, which is not installed.  Continue anyway?'):
    84             raise
   262             raise
    85 
   263 
    86 if applcubicwebversion <= (3, 13, 0) and cubicwebversion >= (3, 13, 1):
       
    87     sql('ALTER TABLE entities ADD asource VARCHAR(64)')
       
    88     sql('UPDATE entities SET asource=cw_name  '
       
    89         'FROM cw_CWSource, cw_source_relation '
       
    90         'WHERE entities.eid=cw_source_relation.eid_from AND cw_source_relation.eid_to=cw_CWSource.cw_eid')
       
    91     commit()
       
    92 
       
    93 if schema['TZDatetime'].eid is None:
       
    94     add_entity_type('TZDatetime', auto=False)
       
    95 if schema['TZTime'].eid is None:
       
    96     add_entity_type('TZTime', auto=False)
       
    97 
       
    98 
   264 
    99 if applcubicwebversion <= (3, 14, 0) and cubicwebversion >= (3, 14, 0):
   265 if applcubicwebversion <= (3, 14, 0) and cubicwebversion >= (3, 14, 0):
   100     if 'require_permission' in schema and not 'localperms'in repo.config.cubes():
   266     if 'require_permission' in schema and not 'localperms'in repo.config.cubes():
   101         from cubicweb import ExecutionError
   267         from cubicweb import ExecutionError
   102         try:
   268         try:
   103             add_cube('localperms', update_database=False)
   269             add_cube('localperms', update_database=False)
   104         except ConfigurationError:
   270         except ConfigurationError:
   105             raise ExecutionError('In cubicweb 3.14, CWPermission and related stuff '
   271             raise ExecutionError('In cubicweb 3.14, CWPermission and related stuff '
   106                                  'has been moved to cube localperms. Install it first.')
   272                                  'has been moved to cube localperms. Install it first.')
   107 
   273 
       
   274 
   108 if applcubicwebversion == (3, 6, 0) and cubicwebversion >= (3, 6, 0):
   275 if applcubicwebversion == (3, 6, 0) and cubicwebversion >= (3, 6, 0):
   109     CSTRMAP = dict(rql('Any T, X WHERE X is CWConstraintType, X name T',
   276     CSTRMAP = dict(rql('Any T, X WHERE X is CWConstraintType, X name T',
   110                        ask_confirm=False))
   277                        ask_confirm=False))
   111     _add_relation_definition_no_perms('CWAttribute', 'update_permission', 'CWGroup')
   278     _add_relation_definition_no_perms('CWAttribute', 'update_permission', 'CWGroup')
   112     _add_relation_definition_no_perms('CWAttribute', 'update_permission', 'RQLExpression')
   279     _add_relation_definition_no_perms('CWAttribute', 'update_permission', 'RQLExpression')
   113     rql('SET X update_permission Y WHERE X is CWAttribute, X add_permission Y')
   280     rql('SET X update_permission Y WHERE X is CWAttribute, X add_permission Y')
   114     drop_relation_definition('CWAttribute', 'add_permission', 'CWGroup')
       
   115     drop_relation_definition('CWAttribute', 'add_permission', 'RQLExpression')
       
   116     drop_relation_definition('CWAttribute', 'delete_permission', 'CWGroup')
   281     drop_relation_definition('CWAttribute', 'delete_permission', 'CWGroup')
   117     drop_relation_definition('CWAttribute', 'delete_permission', 'RQLExpression')
   282     drop_relation_definition('CWAttribute', 'delete_permission', 'RQLExpression')
   118 
   283 
   119 elif applcubicwebversion < (3, 6, 0) and cubicwebversion >= (3, 6, 0):
   284 elif applcubicwebversion < (3, 6, 0) and cubicwebversion >= (3, 6, 0):
   120     CSTRMAP = dict(rql('Any T, X WHERE X is CWConstraintType, X name T',
   285     CSTRMAP = dict(rql('Any T, X WHERE X is CWConstraintType, X name T',