Fix two crashes in db-check (closes #3024964) stable
authorDenis Laxalde <denis.laxalde@logilab.fr>
Thu, 18 Jul 2013 12:36:56 +0200
branchstable
changeset 9171 be9596750678
parent 9170 e6fe77dbcfdf
child 9172 57edd7e51496
Fix two crashes in db-check (closes #3024964) Also improves various debugging messages.
server/checkintegrity.py
server/repository.py
--- a/server/checkintegrity.py	Mon Jul 22 11:09:28 2013 +0200
+++ b/server/checkintegrity.py	Thu Jul 18 12:36:56 2013 +0200
@@ -57,6 +57,9 @@
             pass
         eids[eid] = False
         return False
+    if etype not in session.vreg.schema:
+        eids[eid] = False
+        return False
     sqlcursor.execute('SELECT * FROM %s%s WHERE %seid=%s' % (SQL_PREFIX, etype,
                                                              SQL_PREFIX, eid))
     result = sqlcursor.fetchall()
@@ -179,12 +182,12 @@
     """check all entities registered in the repo system table"""
     print 'Checking entities system table'
     # system table but no source
-    msg = '  Entity with eid %s exists in the system table but in no source (autofix will delete the entity)'
-    cursor = session.system_sql('SELECT eid FROM entities;')
+    msg = '  Entity %s with eid %s exists in the system table but in no source (autofix will delete the entity)'
+    cursor = session.system_sql('SELECT eid,type FROM entities;')
     for row in cursor.fetchall():
-        eid = row[0]
+        eid, etype = row
         if not has_eid(session, cursor, eid, eids):
-            sys.stderr.write(msg % eid)
+            sys.stderr.write(msg % (etype, eid))
             if fix:
                 session.system_sql('DELETE FROM entities WHERE eid=%s;' % eid)
             notify_fixed(fix)
@@ -258,6 +261,12 @@
     sys.stderr.write(msg % (rtype, target, eid))
     notify_fixed(fix)
 
+def bad_inlined_msg(rtype, parent_eid, eid, fix):
+    msg = ('  An inlined relation %s from %s to %s exists but the latter '
+           'entity does not exist')
+    sys.stderr.write(msg % (rtype, parent_eid, eid))
+    notify_fixed(fix)
+
 
 def check_relations(schema, session, eids, fix=1):
     """check that eids referenced by relations are registered in the repo system
@@ -271,13 +280,13 @@
             for subjtype in rschema.subjects():
                 table = SQL_PREFIX + str(subjtype)
                 column = SQL_PREFIX +  str(rschema)
-                sql = 'SELECT %s FROM %s WHERE %s IS NOT NULL;' % (
+                sql = 'SELECT cw_eid,%s FROM %s WHERE %s IS NOT NULL;' % (
                     column, table, column)
                 cursor = session.system_sql(sql)
                 for row in cursor.fetchall():
-                    eid = row[0]
+                    parent_eid, eid = row
                     if not has_eid(session, cursor, eid, eids):
-                        bad_related_msg(rschema, 'object', eid, fix)
+                        bad_inlined_msg(rschema, parent_eid, eid, fix)
                         if fix:
                             sql = 'UPDATE %s SET %s=NULL WHERE %s=%s;' % (
                                 table, column, column, eid)
@@ -366,6 +375,13 @@
     eidcolumn = SQL_PREFIX + 'eid'
     msg = '  %s with eid %s has no %s (autofix will set it to now)'
     for etype, in cursor.fetchall():
+        if etype not in session.vreg.schema:
+            sys.stderr.write('entities table references unknown type %s\n' %
+                             etype)
+            if fix:
+                session.system_sql("DELETE FROM entities WHERE type = %(type)s",
+                                   {'type': etype})
+            continue
         table = SQL_PREFIX + etype
         for rel, default in ( ('creation_date', datetime.now()),
                               ('modification_date', datetime.now()), ):
--- a/server/repository.py	Mon Jul 22 11:09:28 2013 +0200
+++ b/server/repository.py	Thu Jul 18 12:36:56 2013 +0200
@@ -352,9 +352,8 @@
             except Exception as ex:
                 import traceback
                 traceback.print_exc()
-                raise Exception('Is the database initialised ? (cause: %s)' %
-                                (ex.args and ex.args[0].strip() or 'unknown')), \
-                                None, sys.exc_info()[-1]
+                raise (Exception('Is the database initialised ? (cause: %s)' % ex),
+                       None, sys.exc_info()[-1])
         return appschema
 
     def _prepare_startup(self):