server/checkintegrity.py
changeset 7040 9b1f9bc74f5d
parent 6931 0af44a38fe41
parent 7036 63386b35ec69
child 7398 26695dd703d8
child 7468 c202aaf71489
--- a/server/checkintegrity.py	Fri Feb 18 17:11:45 2011 +0100
+++ b/server/checkintegrity.py	Mon Mar 07 17:02:15 2011 +0100
@@ -34,6 +34,12 @@
 from cubicweb.server.sqlutils import SQL_PREFIX
 from cubicweb.server.session import security_enabled
 
+def notify_fixed(fix):
+    if fix:
+        print >> sys.stderr, ' [FIXED]'
+    else:
+        print >> sys.stderr
+
 def has_eid(session, sqlcursor, eid, eids):
     """return true if the eid is a valid eid"""
     if eid in eids:
@@ -167,9 +173,7 @@
             print >> sys.stderr, msg % eid,
             if fix:
                 session.system_sql('DELETE FROM appears WHERE uid=%s;' % eid)
-                print >> sys.stderr, ' [FIXED]'
-            else:
-                print >> sys.stderr
+            notify_fixed(fix)
 
 
 def check_entities(schema, session, eids, fix=1):
@@ -183,9 +187,7 @@
             print >> sys.stderr, msg % eid,
             if fix:
                 session.system_sql('DELETE FROM entities WHERE eid=%s;' % eid)
-                print >> sys.stderr, ' [FIXED]'
-            else:
-                print >> sys.stderr
+            notify_fixed(fix)
     print 'Checking entities tables'
     for eschema in schema.entities():
         if eschema.final:
@@ -202,22 +204,19 @@
                 print >> sys.stderr, msg % (eid, eschema.type),
                 if fix:
                     session.system_sql('DELETE FROM %s WHERE %s=%s;' % (table, column, eid))
-                    print >> sys.stderr, ' [FIXED]'
-                else:
-                    print >> sys.stderr
+                notify_fixed(fix)
 
 
 def bad_related_msg(rtype, target, eid, fix):
     msg = '  A relation %s with %s eid %s exists but no such entity in sources'
     print >> sys.stderr, msg % (rtype, target, eid),
-    if fix:
-        print >> sys.stderr, ' [FIXED]'
-    else:
-        print >> sys.stderr
+    notify_fixed(fix)
 
 
 def check_relations(schema, session, eids, fix=1):
-    """check all relations registered in the repo system table"""
+    """check that eids referenced by relations are registered in the repo system
+    table
+    """
     print 'Checking relations'
     for rschema in schema.relations():
         if rschema.final or rschema in PURE_VIRTUAL_RTYPES:
@@ -263,6 +262,54 @@
                     session.system_sql(sql)
 
 
+def check_mandatory_relations(schema, session, eids, fix=1):
+    """check entities missing some mandatory relation"""
+    print 'Checking mandatory relations'
+    for rschema in schema.relations():
+        if rschema.final or rschema in PURE_VIRTUAL_RTYPES:
+            continue
+        smandatory = set()
+        omandatory = set()
+        for rdef in rschema.rdefs.values():
+            if rdef.cardinality[0] in '1+':
+                smandatory.add(rdef.subject)
+            if rdef.cardinality[1] in '1+':
+                omandatory.add(rdef.object)
+        for role, etypes in (('subject', smandatory), ('object', omandatory)):
+            for etype in etypes:
+                if role == 'subject':
+                    rql = 'Any X WHERE NOT X %s Y, X is %s' % (rschema, etype)
+                else:
+                    rql = 'Any X WHERE NOT Y %s X, X is %s' % (rschema, etype)
+                for entity in session.execute(rql).entities():
+                    print >> sys.stderr, '%s #%s is missing mandatory %s relation %s' % (
+                        entity.__regid__, entity.eid, role, rschema)
+                    if fix:
+                        #if entity.cw_describe()['source']['uri'] == 'system': XXX
+                        entity.delete()
+                    notify_fixed(fix)
+
+
+def check_mandatory_attributes(schema, session, eids, fix=1):
+    """check for entities stored in the system source missing some mandatory
+    attribute
+    """
+    print 'Checking mandatory attributes'
+    for rschema in schema.relations():
+        if not rschema.final or rschema in VIRTUAL_RTYPES:
+            continue
+        for rdef in rschema.rdefs.values():
+            if rdef.cardinality[0] in '1+':
+                rql = 'Any X WHERE X %s NULL, X is %s, X cw_source S, S name "system"' % (
+                    rschema, rdef.subject)
+                for entity in session.execute(rql).entities():
+                    print >> sys.stderr, '%s #%s is missing mandatory attribute %s' % (
+                        entity.__regid__, entity.eid, rschema)
+                    if fix:
+                        entity.delete()
+                    notify_fixed(fix)
+
+
 def check_metadata(schema, session, eids, fix=1):
     """check entities has required metadata
 
@@ -285,9 +332,7 @@
                     session.system_sql("UPDATE %s SET %s=%%(v)s WHERE %s=%s ;"
                                        % (table, column, eidcolumn, eid),
                                        {'v': default})
-                    print >> sys.stderr, ' [FIXED]'
-                else:
-                    print >> sys.stderr
+                notify_fixed(fix)
     cursor = session.system_sql('SELECT MIN(%s) FROM %sCWUser;' % (eidcolumn,
                                                                   SQL_PREFIX))
     default_user_eid = cursor.fetchone()[0]
@@ -303,9 +348,7 @@
             if fix:
                 session.system_sql('INSERT INTO %s_relation VALUES (%s, %s) ;'
                                    % (rel, eid, default))
-                print >> sys.stderr, ' [FIXED]'
-            else:
-                print >> sys.stderr
+            notify_fixed(fix)
 
 
 def check(repo, cnx, checks, reindex, fix, withpb=True):