5330585af8346d6c94c8e0477463736a51b54877
angie
  Mon Oct 10 15:50:38 2011 -0700
Bug #5591 (dup. GO id's in joining query w/knownGene, kgXref):1. Band-aid: remove successive duplicates from joined output.
It would be better to prevent duplicate queries upstream, but
significantly more work.
2. Got rid of unnecessary duplication of code (joinedTablesTabOut
and joinedTablesTabOutFile) that would have required the same fix
in two places.

diff --git src/hg/hgTables/joining.c src/hg/hgTables/joining.c
index e794c4f..49d7af2 100644
--- src/hg/hgTables/joining.c
+++ src/hg/hgTables/joining.c
@@ -30,88 +30,40 @@
 struct joinedTables
 /* Database query result table that is joinable. */
     {
     struct joinedTables *next;
     struct lm *lm;	/* Local memory structure - used for row allocations. */
     struct joinerDtf *fieldList;	/* Fields user has requested. */
     int fieldCount;	/* Number of fields - calculated at start of load. */
     struct joinerDtf *keyList;	/* List of keys. */
     int keyCount;	/* Number of keys- calculated at start of load. */
     struct joinedRow *rowList;	/* Rows - allocated in lm. */
     int rowCount;	/* Number of rows. */
     int maxRowCount;	/* Max row count allowed (0 means no limit) */
     struct dyString *filter;  /* Filter if any applied. */
     };
 
-static void joinedTablesTabOut(struct joinedTables *joined)
-/* Write out fields. */
-{
-struct joinedRow *jr;
-struct joinerDtf *field;
-int outCount = 0;
-
-/* Print out field names. */
-if (joined->filter)
-    {
-    hPrintf("#filter: %s\n", joined->filter->string);
-    }
-hPrintf("#");
-for (field = joined->fieldList; field != NULL; field = field->next)
-    {
-    hPrintf("%s.%s.%s", field->database, field->table, field->field);
-    if (field->next == NULL)
-        hPrintf("\n");
-    else
-        hPrintf("\t");
-    }
-for (jr = joined->rowList; jr != NULL; jr = jr->next)
-    {
-    int i;
-    if (jr->passedFilter)
-	{
-	for (i=0; i<joined->fieldCount; ++i)
-	    {
-	    struct slName *s;
-	    if (i != 0)
-		hPrintf("\t");
-	    s = jr->fields[i];
-	    if (s == NULL)
-	        hPrintf("n/a");
-	    else if (s->next == NULL)
-	        hPrintf("%s", s->name);
-	    else
-	        {
-		while (s != NULL)
-		    {
-		    hPrintf("%s,", s->name);
-		    s = s->next;
-		    }
-		}
-	    }
-	hPrintf("\n");
-	++outCount;
-	}
-    }
-}
-
 static void joinedTablesTabOutFile(struct joinedTables *joined, FILE *f)
 /* write out fields to file handle */
 {
 struct joinedRow *jr;
 struct joinerDtf *field;
 int outCount = 0;
 
+if (f == NULL)
+    f = stdout;
+
 /* Print out field names. */
 if (joined->filter)
     {
     fprintf(f, "#filter: %s\n", joined->filter->string);
     }
 fprintf(f, "#");
 for (field = joined->fieldList; field != NULL; field = field->next)
     {
     fprintf(f, "%s.%s.%s", field->database, field->table, field->field);
     if (field->next == NULL)
         fprintf(f, "\n");
     else
         fprintf(f, "\t");
     }
 for (jr = joined->rowList; jr != NULL; jr = jr->next)
@@ -119,33 +71,36 @@
     int i;
     if (jr->passedFilter)
 	{
 	for (i=0; i<joined->fieldCount; ++i)
 	    {
 	    struct slName *s;
 	    if (i != 0)
                 fprintf(f, "\t");
 	    s = jr->fields[i];
 	    if (s == NULL)
                 fprintf(f, "n/a");
 	    else if (s->next == NULL)
 	        fprintf(f, "%s", s->name);
 	    else
 	        {
+		char *lastS = NULL;
 		while (s != NULL)
 		    {
+		    if (lastS == NULL || !sameString(lastS, s->name))
 		    fprintf(f, "%s,", s->name);
+		    lastS = s->name;
 		    s = s->next;
 		    }
 		}
 	    }
 	fprintf(f, "\n");
 	++outCount;
 	}
     }
 }
 
 static struct joinedTables *joinedTablesNew(int fieldCount, 
 	int keyCount, int maxRowCount)
 /* Make up new empty joinedTables. */
 {
 struct joinedTables *jt;
@@ -1013,33 +968,30 @@
         makeBamOrderedCommaFieldList(dtfList, dy);
     else if (isVcfTable(dtfList->table))
         makeVcfOrderedCommaFieldList(dtfList, dy);
     else if (isCustomTrack(dtfList->table))
         makeCtOrderedCommaFieldList(dtfList, dy);
     else
 	makeDbOrderedCommaFieldList(conn, dtfList->table, dtfList, dy);
     doTabOutTable(dtfList->database, dtfList->table, f, conn, dy->string);
     hFreeConn(&conn);
     }
 else
     {
     struct joiner *joiner = allJoiner;
     struct joinedTables *joined = joinedTablesCreate(joiner, 
     	primaryDb, primaryTable, dtfList, filterTables, 1000000, getRegions());
-    if (f == NULL)
-        joinedTablesTabOut(joined);
-    else
         joinedTablesTabOutFile(joined, f);
     joinedTablesFree(&joined);
     }
 joinerDtfFreeList(&dtfList);
 joinerDtfFreeList(&filterTables);
 }
 
 
 static struct slName *getBedFieldSlNameList(struct hTableInfo *hti,
 					    char *db, char *table)
 /* Return the bed-compat field list for the given table, as 
  * slName list of "$db.$table.$field". */
 {
 struct slName *snList = NULL, *sn = NULL;
 int fieldCount = 0;