from__future__importprint_functionfromcubicweb.schemaimportPURE_VIRTUAL_RTYPESfromcubicweb.server.schema2sqlimportrschema_has_tabledefadd_foreign_keys():source=repo.system_sourceifnotsource.dbhelper.alter_column_support:returnforrschemainschema.relations():ifrschema.inlined:add_foreign_keys_inlined(rschema)elifrschema_has_table(rschema,skip_relations=PURE_VIRTUAL_RTYPES):add_foreign_keys_relation(rschema)foreschemainschema.entities():ifeschema.final:continueadd_foreign_key_etype(eschema)defadd_foreign_keys_relation(rschema):args={'r':rschema.type}count=sql('SELECT COUNT(*) FROM ('' SELECT eid_from FROM %(r)s_relation'' UNION'' SELECT eid_to FROM %(r)s_relation'' EXCEPT'' SELECT eid FROM entities) AS eids'%args,ask_confirm=False)[0][0]ifcount:print('%s references %d unknown entities, deleting'%(rschema,count))sql('DELETE FROM %(r)s_relation ''WHERE eid_from IN (SELECT eid_from FROM %(r)s_relation EXCEPT SELECT eid FROM entities)'%args)sql('DELETE FROM %(r)s_relation ''WHERE eid_to IN (SELECT eid_to FROM %(r)s_relation EXCEPT SELECT eid FROM entities)'%args)args['from_fk']='%(r)s_relation_eid_from_fkey'%argsargs['to_fk']='%(r)s_relation_eid_to_fkey'%argsargs['table']='%(r)s_relation'%argsifrepo.system_source.dbdriver=='postgres':sql('ALTER TABLE %(table)s DROP CONSTRAINT IF EXISTS %(from_fk)s'%args,ask_confirm=False)sql('ALTER TABLE %(table)s DROP CONSTRAINT IF EXISTS %(to_fk)s'%args,ask_confirm=False)elifrepo.system_source.dbdriver.startswith('sqlserver'):sql("IF OBJECT_ID('%(from_fk)s', 'F') IS NOT NULL ""ALTER TABLE %(table)s DROP CONSTRAINT %(from_fk)s"%args,ask_confirm=False)sql("IF OBJECT_ID('%(to_fk)s', 'F') IS NOT NULL ""ALTER TABLE %(table)s DROP CONSTRAINT %(to_fk)s"%args,ask_confirm=False)sql('ALTER TABLE %(table)s ADD CONSTRAINT %(from_fk)s ''FOREIGN KEY (eid_from) REFERENCES entities (eid)'%args,ask_confirm=False)sql('ALTER TABLE %(table)s ADD CONSTRAINT %(to_fk)s ''FOREIGN KEY (eid_to) REFERENCES entities (eid)'%args,ask_confirm=False)defadd_foreign_keys_inlined(rschema):foreschemainrschema.subjects():args={'e':eschema.type,'r':rschema.type}args['c']='cw_%(e)s_cw_%(r)s_fkey'%argsifeschema.rdef(rschema).cardinality[0]=='1':broken_eids=sql('SELECT cw_eid FROM cw_%(e)s WHERE cw_%(r)s IS NULL'%args,ask_confirm=False)ifbroken_eids:print('Required relation %(e)s.%(r)s missing'%args)args['eids']=', '.join(str(eid)foreid,inbroken_eids)rql('DELETE %(e)s X WHERE X eid IN (%(eids)s)'%args)broken_eids=sql('SELECT cw_eid FROM cw_%(e)s WHERE cw_%(r)s IN (SELECT cw_%(r)s FROM cw_%(e)s ''EXCEPT SELECT eid FROM entities)'%args,ask_confirm=False)ifbroken_eids:print('Required relation %(e)s.%(r)s references unknown objects, deleting subject entities'%args)args['eids']=', '.join(str(eid)foreid,inbroken_eids)rql('DELETE %(e)s X WHERE X eid IN (%(eids)s)'%args)else:ifsql('SELECT COUNT(*) FROM ('' SELECT cw_%(r)s FROM cw_%(e)s WHERE cw_%(r)s IS NOT NULL'' EXCEPT'' SELECT eid FROM entities) AS eids'%args,ask_confirm=False)[0][0]:print('%(e)s.%(r)s references unknown entities, deleting relation'%args)sql('UPDATE cw_%(e)s SET cw_%(r)s = NULL WHERE cw_%(r)s IS NOT NULL AND cw_%(r)s IN ''(SELECT cw_%(r)s FROM cw_%(e)s EXCEPT SELECT eid FROM entities)'%args)ifrepo.system_source.dbdriver=='postgres':sql('ALTER TABLE cw_%(e)s DROP CONSTRAINT IF EXISTS %(c)s'%args,ask_confirm=False)elifrepo.system_source.dbdriver.startswith('sqlserver'):sql("IF OBJECT_ID('%(c)s', 'F') IS NOT NULL ""ALTER TABLE cw_%(e)s DROP CONSTRAINT %(c)s"%args,ask_confirm=False)sql('ALTER TABLE cw_%(e)s ADD CONSTRAINT %(c)s ''FOREIGN KEY (cw_%(r)s) references entities(eid)'%args,ask_confirm=False)defadd_foreign_key_etype(eschema):args={'e':eschema.type}ifsql('SELECT COUNT(*) FROM ('' SELECT cw_eid FROM cw_%(e)s'' EXCEPT'' SELECT eid FROM entities) AS eids'%args,ask_confirm=False)[0][0]:print('%(e)s has nonexistent entities, deleting'%args)sql('DELETE FROM cw_%(e)s WHERE cw_eid IN ''(SELECT cw_eid FROM cw_%(e)s EXCEPT SELECT eid FROM entities)'%args)args['c']='cw_%(e)s_cw_eid_fkey'%argsifrepo.system_source.dbdriver=='postgres':sql('ALTER TABLE cw_%(e)s DROP CONSTRAINT IF EXISTS %(c)s'%args,ask_confirm=False)elifrepo.system_source.dbdriver.startswith('sqlserver'):sql("IF OBJECT_ID('%(c)s', 'F') IS NOT NULL ""ALTER TABLE cw_%(e)s DROP CONSTRAINT %(c)s"%args,ask_confirm=False)sql('ALTER TABLE cw_%(e)s ADD CONSTRAINT %(c)s ''FOREIGN KEY (cw_eid) REFERENCES entities (eid)'%args,ask_confirm=False)add_foreign_keys()cu=session.cnxset.cuhelper=repo.system_source.dbhelperhelper.drop_index(cu,'entities','extid',False)# don't use create_index because it doesn't work for columns that may be NULL# on sqlserverforqueryinhelper.sqls_create_multicol_unique_index('entities',['extid']):cu.execute(query)if'moved_entities'notinhelper.list_tables(cu):sql(''' CREATE TABLE moved_entities ( eid INTEGER PRIMARY KEY NOT NULL, extid VARCHAR(256) UNIQUE ) ''')moved_entities=sql('SELECT -eid, extid FROM entities WHERE eid < 0',ask_confirm=False)ifmoved_entities:cu.executemany('INSERT INTO moved_entities (eid, extid) VALUES (%s, %s)',moved_entities)sql('DELETE FROM entities WHERE eid < 0')commit()sync_schema_props_perms('CWEType')sync_schema_props_perms('cwuri')fromcubicweb.server.schema2sqlimportcheck_constraintforcwconstraintinrql('Any C WHERE R constrained_by C').entities():cwrdef=cwconstraint.reverse_constrained_by[0]rdef=cwrdef.yams_schema()cstr=rdef.constraint_by_eid(cwconstraint.eid)ifcstr.type()notin('BoundaryConstraint','IntervalBoundConstraint','StaticVocabularyConstraint'):continuecstrname,check=check_constraint(rdef.subject,rdef.object,rdef.rtype.type,cstr,helper,prefix='cw_')args={'e':rdef.subject.type,'c':cstrname,'v':check}ifrepo.system_source.dbdriver=='postgres':sql('ALTER TABLE cw_%(e)s DROP CONSTRAINT IF EXISTS %(c)s'%args)elifrepo.system_source.dbdriver.startswith('sqlserver'):sql("IF OBJECT_ID('%(c)s', 'C') IS NOT NULL ""ALTER TABLE cw_%(e)s DROP CONSTRAINT %(c)s"%args)sql('ALTER TABLE cw_%(e)s ADD CONSTRAINT %(c)s CHECK(%(v)s)'%args)commit()