server/checkintegrity.py
changeset 7965 d45c0eb39e72
parent 7896 4c954e1e73ef
child 8447 4fb20c09017a
equal deleted inserted replaced
7964:4ea2abc83dce 7965:d45c0eb39e72
   162 
   162 
   163 
   163 
   164 def check_text_index(schema, session, eids, fix=1):
   164 def check_text_index(schema, session, eids, fix=1):
   165     """check all entities registered in the text index"""
   165     """check all entities registered in the text index"""
   166     print 'Checking text index'
   166     print 'Checking text index'
       
   167     msg = '  Entity with eid %s exists in the text index but in no source (autofix will remove from text index)'
   167     cursor = session.system_sql('SELECT uid FROM appears;')
   168     cursor = session.system_sql('SELECT uid FROM appears;')
   168     for row in cursor.fetchall():
   169     for row in cursor.fetchall():
   169         eid = row[0]
   170         eid = row[0]
   170         if not has_eid(session, cursor, eid, eids):
   171         if not has_eid(session, cursor, eid, eids):
   171             msg = '  Entity with eid %s exists in the text index but in no source\n'
       
   172             sys.stderr.write(msg % eid)
   172             sys.stderr.write(msg % eid)
   173             if fix:
   173             if fix:
   174                 session.system_sql('DELETE FROM appears WHERE uid=%s;' % eid)
   174                 session.system_sql('DELETE FROM appears WHERE uid=%s;' % eid)
   175             notify_fixed(fix)
   175             notify_fixed(fix)
   176 
   176 
   177 
   177 
   178 def check_entities(schema, session, eids, fix=1):
   178 def check_entities(schema, session, eids, fix=1):
   179     """check all entities registered in the repo system table"""
   179     """check all entities registered in the repo system table"""
   180     print 'Checking entities system table'
   180     print 'Checking entities system table'
       
   181     # system table but no source
       
   182     msg = '  Entity with eid %s exists in the system table but in no source (autofix will delete the entity)'
   181     cursor = session.system_sql('SELECT eid FROM entities;')
   183     cursor = session.system_sql('SELECT eid FROM entities;')
   182     for row in cursor.fetchall():
   184     for row in cursor.fetchall():
   183         eid = row[0]
   185         eid = row[0]
   184         if not has_eid(session, cursor, eid, eids):
   186         if not has_eid(session, cursor, eid, eids):
   185             msg = '  Entity with eid %s exists in the system table but in no source\n'
       
   186             sys.stderr.write(msg % eid)
   187             sys.stderr.write(msg % eid)
   187             if fix:
   188             if fix:
   188                 session.system_sql('DELETE FROM entities WHERE eid=%s;' % eid)
   189                 session.system_sql('DELETE FROM entities WHERE eid=%s;' % eid)
   189             notify_fixed(fix)
   190             notify_fixed(fix)
   190     session.system_sql('INSERT INTO cw_source_relation (eid_from, eid_to) '
   191     # source in entities, but no relation cw_source
   191                        'SELECT e.eid, s.cw_eid FROM entities as e, cw_CWSource as s '
   192     applcwversion = session.repo.get_versions().get('cubicweb')
   192                        'WHERE s.cw_name=e.asource AND NOT EXISTS(SELECT 1 FROM cw_source_relation as cs '
   193     if applcwversion >= (3,13,1): # entities.asource appeared in 3.13.1
   193                        '  WHERE cs.eid_from=e.eid AND cs.eid_to=s.cw_eid)')
   194         cursor = session.system_sql('SELECT e.eid FROM entities as e, cw_CWSource as s '
   194     session.system_sql('INSERT INTO is_relation (eid_from, eid_to) '
   195                                     'WHERE s.cw_name=e.asource AND '
   195                        'SELECT e.eid, s.cw_eid FROM entities as e, cw_CWEType as s '
   196                                     'NOT EXISTS(SELECT 1 FROM cw_source_relation as cs '
   196                        'WHERE s.cw_name=e.type AND NOT EXISTS(SELECT 1 FROM is_relation as cs '
   197                                     '  WHERE cs.eid_from=e.eid AND cs.eid_to=s.cw_eid) '
   197                        '  WHERE cs.eid_from=e.eid AND cs.eid_to=s.cw_eid)')
   198                                     'ORDER BY e.eid')
   198     session.system_sql('INSERT INTO is_instance_of_relation (eid_from, eid_to) '
   199         msg = ('  Entity with eid %s refers to source in entities table, '
   199                        'SELECT e.eid, s.cw_eid FROM entities as e, cw_CWEType as s '
   200                'but is missing relation cw_source (autofix will create the relation)\n')
   200                        'WHERE s.cw_name=e.type AND NOT EXISTS(SELECT 1 FROM is_instance_of_relation as cs '
   201         for row in cursor.fetchall():
   201                        '  WHERE cs.eid_from=e.eid AND cs.eid_to=s.cw_eid)')
   202             sys.stderr.write(msg % row[0])
       
   203         if fix:
       
   204             session.system_sql('INSERT INTO cw_source_relation (eid_from, eid_to) '
       
   205                                'SELECT e.eid, s.cw_eid FROM entities as e, cw_CWSource as s '
       
   206                                'WHERE s.cw_name=e.asource AND NOT EXISTS(SELECT 1 FROM cw_source_relation as cs '
       
   207                                '  WHERE cs.eid_from=e.eid AND cs.eid_to=s.cw_eid)')
       
   208             notify_fixed(True)
       
   209     # inconsistencies for 'is'
       
   210     msg = '  %s #%s is missing relation "is" (autofix will create the relation)\n'
       
   211     cursor = session.system_sql('SELECT e.type, e.eid FROM entities as e, cw_CWEType as s '
       
   212                                 'WHERE s.cw_name=e.type AND NOT EXISTS(SELECT 1 FROM is_relation as cs '
       
   213                                 '  WHERE cs.eid_from=e.eid AND cs.eid_to=s.cw_eid) '
       
   214                                 'ORDER BY e.eid')
       
   215     for row in cursor.fetchall():
       
   216         sys.stderr.write(msg % row)
       
   217     if fix:
       
   218         session.system_sql('INSERT INTO is_relation (eid_from, eid_to) '
       
   219                            'SELECT e.eid, s.cw_eid FROM entities as e, cw_CWEType as s '
       
   220                            'WHERE s.cw_name=e.type AND NOT EXISTS(SELECT 1 FROM is_relation as cs '
       
   221                            '  WHERE cs.eid_from=e.eid AND cs.eid_to=s.cw_eid)')
       
   222         notify_fixed(True)
       
   223     # inconsistencies for 'is_instance_of'
       
   224     msg = '  %s #%s is missing relation "is_instance_of" (autofix will create the relation)\n'
       
   225     cursor = session.system_sql('SELECT e.type, e.eid FROM entities as e, cw_CWEType as s '
       
   226                                 'WHERE s.cw_name=e.type AND NOT EXISTS(SELECT 1 FROM is_instance_of_relation as cs '
       
   227                                 '  WHERE cs.eid_from=e.eid AND cs.eid_to=s.cw_eid) '
       
   228                                 'ORDER BY e.eid')
       
   229     for row in cursor.fetchall():
       
   230         sys.stderr.write(msg % row)
       
   231     if fix:
       
   232         session.system_sql('INSERT INTO is_instance_of_relation (eid_from, eid_to) '
       
   233                            'SELECT e.eid, s.cw_eid FROM entities as e, cw_CWEType as s '
       
   234                            'WHERE s.cw_name=e.type AND NOT EXISTS(SELECT 1 FROM is_instance_of_relation as cs '
       
   235                            '  WHERE cs.eid_from=e.eid AND cs.eid_to=s.cw_eid)')
       
   236         notify_fixed(True)
   202     print 'Checking entities tables'
   237     print 'Checking entities tables'
       
   238     msg = '  Entity with eid %s exists in the %s table but not in the system table (autofix will delete the entity)'
   203     for eschema in schema.entities():
   239     for eschema in schema.entities():
   204         if eschema.final:
   240         if eschema.final:
   205             continue
   241             continue
   206         table = SQL_PREFIX + eschema.type
   242         table = SQL_PREFIX + eschema.type
   207         column = SQL_PREFIX +  'eid'
   243         column = SQL_PREFIX +  'eid'
   209         for row in cursor.fetchall():
   245         for row in cursor.fetchall():
   210             eid = row[0]
   246             eid = row[0]
   211             # eids is full since we have fetched everything from the entities table,
   247             # eids is full since we have fetched everything from the entities table,
   212             # no need to call has_eid
   248             # no need to call has_eid
   213             if not eid in eids or not eids[eid]:
   249             if not eid in eids or not eids[eid]:
   214                 msg = '  Entity with eid %s exists in the %s table but not in the system table'
       
   215                 sys.stderr.write(msg % (eid, eschema.type))
   250                 sys.stderr.write(msg % (eid, eschema.type))
   216                 if fix:
   251                 if fix:
   217                     session.system_sql('DELETE FROM %s WHERE %s=%s;' % (table, column, eid))
   252                     session.system_sql('DELETE FROM %s WHERE %s=%s;' % (table, column, eid))
   218                 notify_fixed(fix)
   253                 notify_fixed(fix)
   219 
   254 
   228     """check that eids referenced by relations are registered in the repo system
   263     """check that eids referenced by relations are registered in the repo system
   229     table
   264     table
   230     """
   265     """
   231     print 'Checking relations'
   266     print 'Checking relations'
   232     for rschema in schema.relations():
   267     for rschema in schema.relations():
   233         if rschema.final or rschema in PURE_VIRTUAL_RTYPES:
   268         if rschema.final or rschema.type in PURE_VIRTUAL_RTYPES:
   234             continue
   269             continue
   235         if rschema.inlined:
   270         if rschema.inlined:
   236             for subjtype in rschema.subjects():
   271             for subjtype in rschema.subjects():
   237                 table = SQL_PREFIX + str(subjtype)
   272                 table = SQL_PREFIX + str(subjtype)
   238                 column = SQL_PREFIX +  str(rschema)
   273                 column = SQL_PREFIX +  str(rschema)
   274 
   309 
   275 
   310 
   276 def check_mandatory_relations(schema, session, eids, fix=1):
   311 def check_mandatory_relations(schema, session, eids, fix=1):
   277     """check entities missing some mandatory relation"""
   312     """check entities missing some mandatory relation"""
   278     print 'Checking mandatory relations'
   313     print 'Checking mandatory relations'
       
   314     msg = '%s #%s is missing mandatory %s relation %s (autofix will delete the entity)'
   279     for rschema in schema.relations():
   315     for rschema in schema.relations():
   280         if rschema.final or rschema in PURE_VIRTUAL_RTYPES:
   316         if rschema.final or rschema.type in PURE_VIRTUAL_RTYPES:
   281             continue
   317             continue
   282         smandatory = set()
   318         smandatory = set()
   283         omandatory = set()
   319         omandatory = set()
   284         for rdef in rschema.rdefs.values():
   320         for rdef in rschema.rdefs.values():
   285             if rdef.cardinality[0] in '1+':
   321             if rdef.cardinality[0] in '1+':
   291                 if role == 'subject':
   327                 if role == 'subject':
   292                     rql = 'Any X WHERE NOT X %s Y, X is %s' % (rschema, etype)
   328                     rql = 'Any X WHERE NOT X %s Y, X is %s' % (rschema, etype)
   293                 else:
   329                 else:
   294                     rql = 'Any X WHERE NOT Y %s X, X is %s' % (rschema, etype)
   330                     rql = 'Any X WHERE NOT Y %s X, X is %s' % (rschema, etype)
   295                 for entity in session.execute(rql).entities():
   331                 for entity in session.execute(rql).entities():
   296                     sys.stderr.write('%s #%s is missing mandatory %s relation %s' % (
   332                     sys.stderr.write(msg % (entity.__regid__, entity.eid, role, rschema))
   297                             entity.__regid__, entity.eid, role, rschema))
       
   298                     if fix:
   333                     if fix:
   299                         #if entity.cw_describe()['source']['uri'] == 'system': XXX
   334                         #if entity.cw_describe()['source']['uri'] == 'system': XXX
   300                         entity.cw_delete()
   335                         entity.cw_delete() # XXX this is BRUTAL!
   301                     notify_fixed(fix)
   336                     notify_fixed(fix)
   302 
   337 
   303 
   338 
   304 def check_mandatory_attributes(schema, session, eids, fix=1):
   339 def check_mandatory_attributes(schema, session, eids, fix=1):
   305     """check for entities stored in the system source missing some mandatory
   340     """check for entities stored in the system source missing some mandatory
   306     attribute
   341     attribute
   307     """
   342     """
   308     print 'Checking mandatory attributes'
   343     print 'Checking mandatory attributes'
       
   344     msg = '%s #%s is missing mandatory attribute %s (autofix will delete the entity)'
   309     for rschema in schema.relations():
   345     for rschema in schema.relations():
   310         if not rschema.final or rschema in VIRTUAL_RTYPES:
   346         if not rschema.final or rschema in VIRTUAL_RTYPES:
   311             continue
   347             continue
   312         for rdef in rschema.rdefs.values():
   348         for rdef in rschema.rdefs.values():
   313             if rdef.cardinality[0] in '1+':
   349             if rdef.cardinality[0] in '1+':
   314                 rql = 'Any X WHERE X %s NULL, X is %s, X cw_source S, S name "system"' % (
   350                 rql = 'Any X WHERE X %s NULL, X is %s, X cw_source S, S name "system"' % (
   315                     rschema, rdef.subject)
   351                     rschema, rdef.subject)
   316                 for entity in session.execute(rql).entities():
   352                 for entity in session.execute(rql).entities():
   317                     sys.stderr.write('%s #%s is missing mandatory attribute %s' % (
   353                     sys.stderr.write(msg % (entity.__regid__, entity.eid, rschema))
   318                             entity.__regid__, entity.eid, rschema))
       
   319                     if fix:
   354                     if fix:
   320                         entity.cw_delete()
   355                         entity.cw_delete()
   321                     notify_fixed(fix)
   356                     notify_fixed(fix)
   322 
   357 
   323 
   358 
   327     FIXME: rewrite using RQL queries ?
   362     FIXME: rewrite using RQL queries ?
   328     """
   363     """
   329     print 'Checking metadata'
   364     print 'Checking metadata'
   330     cursor = session.system_sql("SELECT DISTINCT type FROM entities;")
   365     cursor = session.system_sql("SELECT DISTINCT type FROM entities;")
   331     eidcolumn = SQL_PREFIX + 'eid'
   366     eidcolumn = SQL_PREFIX + 'eid'
       
   367     msg = '  %s with eid %s has no %s (autofix will set it to now)'
   332     for etype, in cursor.fetchall():
   368     for etype, in cursor.fetchall():
   333         table = SQL_PREFIX + etype
   369         table = SQL_PREFIX + etype
   334         for rel, default in ( ('creation_date', datetime.now()),
   370         for rel, default in ( ('creation_date', datetime.now()),
   335                               ('modification_date', datetime.now()), ):
   371                               ('modification_date', datetime.now()), ):
   336             column = SQL_PREFIX + rel
   372             column = SQL_PREFIX + rel
   337             cursor = session.system_sql("SELECT %s FROM %s WHERE %s is NULL"
   373             cursor = session.system_sql("SELECT %s FROM %s WHERE %s is NULL"
   338                                         % (eidcolumn, table, column))
   374                                         % (eidcolumn, table, column))
   339             for eid, in cursor.fetchall():
   375             for eid, in cursor.fetchall():
   340                 msg = '  %s with eid %s has no %s'
       
   341                 sys.stderr.write(msg % (etype, eid, rel))
   376                 sys.stderr.write(msg % (etype, eid, rel))
   342                 if fix:
   377                 if fix:
   343                     session.system_sql("UPDATE %s SET %s=%%(v)s WHERE %s=%s ;"
   378                     session.system_sql("UPDATE %s SET %s=%%(v)s WHERE %s=%s ;"
   344                                        % (table, column, eidcolumn, eid),
   379                                        % (table, column, eidcolumn, eid),
   345                                        {'v': default})
   380                                        {'v': default})