Index: src/hg/utils/tdbQuery/tdbQuery.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/utils/tdbQuery/tdbQuery.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -b -B -U 4 -r1.25 -r1.26
--- src/hg/utils/tdbQuery/tdbQuery.c	10 Dec 2009 07:13:56 -0000	1.25
+++ src/hg/utils/tdbQuery/tdbQuery.c	4 Jan 2010 19:12:40 -0000	1.26
@@ -20,8 +20,11 @@
 static boolean clStrict = FALSE;	/* If set only return tracks with actual tables. */
 static boolean clAlpha = FALSE;		/* If set include release alphas, exclude release beta. */
 static boolean clNoBlank = FALSE;	/* If set suppress blank lines in output. */
 static char *clRewrite = NULL;		/* Rewrite to given directory. */
+static boolean clNoCompSub = FALSE;	/* If set don't do subtrack inheritence of fields. */
+
+boolean uglyOne;
 
 void usage()
 /* Explain usage and exit. */
 {
@@ -50,12 +53,11 @@
 "Check that trackDb is internally consistent.  Prints diagnostic output to stderr and aborts if \n"
 "there's problems.\n"
 "   -strict\n"
 "Mimic -strict option on hgTrackDb. Suppresses tracks where corresponding table does not exist.\n"
-"   -alpha\n"
-"Do checking on release alpha (and not release beta) tracks\n"
-"   -noBlank\n"
-"Don't print out blank lines separating records"
+"   -alpha Do checking on release alpha (and not release beta) tracks\n"
+"   -noBlank  Don't print out blank lines separating records"
+"   -noCompSub Subtracks don't inherit fields from parents\n"
 );
 }
 
 
@@ -65,8 +67,9 @@
    {"strict", OPTION_BOOLEAN},
    {"alpha", OPTION_BOOLEAN},
    {"noBlank", OPTION_BOOLEAN},
    {"rewrite", OPTION_STRING},
+   {"noCompSub", OPTION_BOOLEAN},
    {NULL, 0},
 };
 
 #define glKeyField "track"	 /* The field that has the record ID */
@@ -567,8 +570,10 @@
 /* Find parent record if possible.  This is a bit complicated by wanting to
  * match parents and children from the same release if possible.  Our
  * strategy is to just ignore records from the wrond release. */
 {
+if (clNoCompSub)
+    return NULL;
 struct tdbField *parentField = tdbRecordField(rec, parentFieldName);
 if (parentField == NULL)
     return NULL;
 char *parentLine = parentField->val;
@@ -745,8 +750,10 @@
 			    break;
 		    }
 		}
 	    }
+	if (!clNoCompSub)
+	    {
 	if (view != NULL)
 	    {
 	    struct slPair *setting;
 	    for (setting = view->val; setting != NULL; setting = setting->next)
@@ -766,13 +773,15 @@
 	    {
 	    verbose(3, "view %s not in parent settingsByView of %s\n", viewName, rec->key);
 	    }
 	}
+	}
 
     /* Then inherit from parents. */
     struct tdbRecord *parent;
     for (parent = rec->parent; parent != NULL; parent = parent->parent)
 	{
+	if (!clNoCompSub)
 	mergeParentRecord(rec, parent, lm);
 	}
     }
 }
@@ -859,18 +868,28 @@
     }
 return FALSE;
 }
 
-static struct tdbRecord *closestParentInFile(struct slRef *allParentRefs, 
-	struct tdbFilePos *childPos)
-/* Find parent that comes closest to (but before) childPos. */
+static int countAncestors(struct tdbRecord *r)
+/* Return 0 if has no parent, 1 if has a parent, 2 if it has a grandparent, etc. */
 {
-struct slRef *parentRef;
-struct tdbRecord *closestParent = NULL;
+int count = 0;
+struct tdbRecord *p;
+for (p = r->parent; p != NULL; p = p->parent)
+    count += 1;
+return count;
+}
+
+static struct tdbRecord *closestTdbAboveLevel(struct tdbRecord *tdbList, 
+	struct tdbFilePos *childPos, int parentDepth)
+/* Find parent at given depth that comes closest to (but before) childPos. */
+{
+struct tdbRecord *parent, *closestParent = NULL;
 int closestDistance = BIGNUM;
-for (parentRef = allParentRefs; parentRef != NULL; parentRef = parentRef->next)
+for (parent = tdbList; parent != NULL; parent = parent->next)
+    {
+    if (countAncestors(parent) <= parentDepth)
     {
-    struct tdbRecord *parent = parentRef->val;
     struct tdbFilePos *pos;
     for (pos = parent->posList; pos != NULL; pos = pos->next)
         {
 	if (sameString(pos->fileName, childPos->fileName))
@@ -886,16 +905,19 @@
 		}
 	    }
 	}
     }
+    }
 return closestParent;
 }
 
-static void checkChildUnderNearestParent(struct slRef *allParentRefs,
-	struct tdbRecord *parent, struct tdbRecord *child)
+static void checkChildUnderNearestParent(struct tdbRecord *recordList, struct tdbRecord *child)
 /* Make sure that parent record occurs before child, and that indeed it is the
  * closest parent before the child. */
 {
+struct tdbRecord *parent = child->parent;
+int parentDepth = countAncestors(parent);
+
 /* We do the check for each file the child is in */
 struct tdbFilePos *childFp, *parentFp;
 for (childFp = child->posList; childFp != NULL; childFp = childFp->next)
     {
@@ -908,9 +930,10 @@
 	        errAbort("Child before parent in %s\n"
 		         "Child (%s) at line %d, parent (%s) at line %d",
 			 childFp->fileName, child->key, childFp->startLineIx, 
 			 parent->key, parentFp->startLineIx);
-	    struct tdbRecord *closestParent = closestParentInFile(allParentRefs, childFp);
+	    struct tdbRecord *closestParent = closestTdbAboveLevel(recordList, childFp, 
+	    	parentDepth);
 	    assert(closestParent != NULL);
 	    if (closestParent != parent)
 	        errAbort("%s comes between parent (%s) and child (%s) in %s\n"
 		         "Parent at line %d, child at line %d.",
@@ -951,21 +974,13 @@
 	    }
 	}
     }
 
-/* Create parent list, which we'll use for various child/parent checks. */
-struct slRef *parentRefList = NULL;
-for (record = recordList; record != NULL; record = record->next)
-    {
-    if (record->children != NULL)
-        refAdd(&parentRefList, record);
-    }
-
 /* Additional child/parent checks. */
 for (record = recordList; record != NULL; record = record->next)
     {
     if (record->parent != NULL)
-        checkChildUnderNearestParent(parentRefList, record->parent, record);
+        checkChildUnderNearestParent(recordList, record);
     }
 }
 
 void tdbQuery(char *sql)
@@ -1274,8 +1289,9 @@
 clStrict = optionExists("strict");
 clAlpha = optionExists("alpha");
 clNoBlank = optionExists("noBlank");
 clRewrite = optionVal("rewrite", clRewrite);
+clNoCompSub = optionExists("noCompSub");
 if (clRewrite)
     {
     doRewrite(clRewrite, clRoot, "trackDb.ra", "visibility.ra", "priority.ra");
     }

