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