840cb1f540fd01d0728d0313bcafebe95b2bd6ca
hiram
  Fri Apr 19 10:11:42 2019 -0700
complete wiggle table output for all options refs #18869

diff --git src/hg/hubApi/getData.c src/hg/hubApi/getData.c
index d4940ef..a6dd07f 100644
--- src/hg/hubApi/getData.c
+++ src/hg/hubApi/getData.c
@@ -1,56 +1,58 @@
 /* manage endpoint /getData/ functions */
 
 #include "dataApi.h"
 
-static void wigTableDataOutput(struct jsonWrite *jw, char *database, char *table, char *chrom, int start, int end)
+static unsigned wigTableDataOutput(struct jsonWrite *jw, char *database,
+	char *table, char *chrom, int start, int end, unsigned itemsDone)
 /* output wiggle data from the given table and specified chrom:start-end */
 {
 struct wiggleDataStream *wds = wiggleDataStreamNew();
 wds->setMaxOutput(wds, maxItemsOutput);
 wds->setChromConstraint(wds, chrom);
 wds->setPositionConstraint(wds, start, end);
 int operations = wigFetchAscii;
 long long valuesMatched = wds->getData(wds, database, table, operations);
 jsonWriteNumber(jw, "valuesMatched", valuesMatched);
 struct wigAsciiData *el;
 jsonWriteListStart(jw, chrom);
 unsigned itemCount = 0;
-for (el = wds->ascii; itemCount < maxItemsOutput && el; el = el->next)
+for (el = wds->ascii; (itemCount + itemsDone) < maxItemsOutput && el; el = el->next)
     {
     int s = el->data->chromStart;
     int e = s + el->span;
     double val = el->data->value;
     if (jsonOutputArrays)
 	{
 	jsonWriteListStart(jw, NULL);
 	jsonWriteNumber(jw, NULL, (long long)s);
 	jsonWriteNumber(jw, NULL, (long long)e);
 	jsonWriteDouble(jw, NULL, val);
 	jsonWriteListEnd(jw);
 	}
     else
 	{
 	jsonWriteObjectStart(jw, NULL);
 	jsonWriteNumber(jw, "start", (long long)s);
 	jsonWriteNumber(jw, "end", (long long)e);
 	jsonWriteDouble(jw, "value", val);
 	jsonWriteObjectEnd(jw);
 	}
     ++itemCount;
     }
 jsonWriteListEnd(jw);
+return itemCount;
 }
 
 static void jsonDatumOut(struct jsonWrite *jw, char *name, char *val,
     int jsonType)
 /* output a json item, determine type, appropriate output, name can be NULL */
 {
 if (JSON_DOUBLE == jsonType)
     jsonWriteDouble(jw, name, sqlDouble(val));
 else if (JSON_NUMBER == jsonType)
     jsonWriteNumber(jw, name, sqlLongLong(val));
 else
     jsonWriteString(jw, name, val);
 }
 
 static void wigColumnTypes(struct jsonWrite *jw)
@@ -212,120 +214,148 @@
     {
     /* this setup here is for the case of non-split tables, will later
      * determine if split, and then will go through each chrom
      */
     sqlDyStringPrintf(query, "select * from %s", splitSqlTable);
     }
 else if (0 == (start + end))	/* have chrom, no start,end == full chr */
     {
     if (! sqlColumnExists(conn, splitSqlTable, chromName))
 	apiErrAbort(err400, err400Msg, "track '%s' is not a position track, request track without chrom specification, genome: '%s'", track, db);
 
     jsonWriteString(jw, "chrom", chrom);
     struct chromInfo *ci = hGetChromInfo(db, chrom);
     jsonWriteNumber(jw, "start", (long long)0);
     jsonWriteNumber(jw, "end", (long long)ci->size);
+    if (startsWith("wig", tdb->type))
+	{
+	if (jsonOutputArrays || debug)
+	    wigColumnTypes(jw);
+        wigTableDataOutput(jw, db, splitSqlTable, chrom, 0, ci->size, 0);
+        return;	/* DONE */
+	}
+    else
+	{
 	sqlDyStringPrintf(query, "select * from %s where %s='%s'", splitSqlTable, chromName, chrom);
 	}
+    }
 else	/* fully specified chrom:start-end */
     {
     jsonWriteString(jw, "chrom", chrom);
     jsonWriteNumber(jw, "start", (long long)start);
     jsonWriteNumber(jw, "end", (long long)end);
-    if (jsonOutputArrays || debug)
-	wigColumnTypes(jw);
     if (startsWith("wig", tdb->type))
 	{
-        wigTableDataOutput(jw, db, splitSqlTable, chrom, start, end);
+	if (jsonOutputArrays || debug)
+	    wigColumnTypes(jw);
+        wigTableDataOutput(jw, db, splitSqlTable, chrom, start, end, 0);
         return;	/* DONE */
 	}
     else
 	{
 	sqlDyStringPrintf(query, "select * from %s where ", splitSqlTable);
         hAddBinToQuery(start, end, query);
 	sqlDyStringPrintf(query, "%s='%s' AND %s > %u AND %s < %u", chromName, chrom, endName, start, startName, end);
 	}
     }
 
 if (debug)
     jsonWriteString(jw, "select", query->string);
 
 /* continuing, not a wiggle output */
 char **columnNames = NULL;
 char **columnTypes = NULL;
 int *jsonTypes = NULL;
 struct asObject *as = asForTable(conn, splitSqlTable, tdb);
 struct asColumn *columnEl = as->columnList;
 int asColumnCount = slCount(columnEl);
 int columnCount = tableColumns(conn, jw, splitSqlTable, &columnNames, &columnTypes, &jsonTypes);
 if (jsonOutputArrays || debug)
     {
+    if (startsWith("wig", tdb->type))
+	{
+	    wigColumnTypes(jw);
+	}
+    else
+	{
 	jsonWriteListStart(jw, "columnTypes");
 	int i = 0;
 	for (i = 0; i < columnCount; ++i)
 	    {
 	    jsonWriteObjectStart(jw, NULL);
 	    jsonWriteString(jw, "name", columnNames[i]);
 	    jsonWriteString(jw, "sqlType", columnTypes[i]);
 	    jsonWriteString(jw, "jsonType", jsonTypeStrings[jsonTypes[i]]);
 	    if ((0 == i) && (hti && hti->hasBin))
 		jsonWriteString(jw, "description", "Indexing field to speed chromosome range queries");
 	    else if (columnEl && isNotEmpty(columnEl->comment))
 		jsonWriteString(jw, "description", columnEl->comment);
 	    else
 		jsonWriteString(jw, "description", "");
 
 	    /* perhaps move the comment pointer forward */
 	    if (columnEl)
 		{
 		if (asColumnCount == columnCount)
 		    columnEl = columnEl->next;
 		else if (! ((0 == i) && (hti && hti->hasBin)))
 		    columnEl = columnEl->next;
 		}
 	    jsonWriteObjectEnd(jw);
 	}
 	jsonWriteListEnd(jw);
 	}
+    }
+
+/* data output list starting */
 jsonWriteListStart(jw, track);
 
 unsigned itemsDone = 0;
 
-/* empty chrom and isSplit, needs to run through all chrom names */
-if ((hti && hti->isSplit) && isEmpty(chrom))
+/* empty chrom, needs to run through all chrom names */
+if (isEmpty(chrom))
     {
+    char fullTableName[256];
     struct chromInfo *ciList = createChromInfoList(NULL, db);
     slSort(ciList, chromInfoCmp);
     struct chromInfo *el = ciList;
-    char fullTableName[256];
     for ( ; itemsDone < maxItemsOutput && el != NULL; el = el->next )
 	{
 	freeDyString(&query);
 	query = dyStringNew(64);
+	if (hti && hti->isSplit) /* when split, make up split chr name */
+	    {
 	    safef(fullTableName, sizeof(fullTableName), "%s_%s", el->chrom, hti->rootName);
 	    sqlDyStringPrintf(query, "select * from %s", fullTableName);
-	itemsDone += sqlQueryJsonOutput(conn, jw, query->string, columnCount,
-	    columnNames, jsonTypes, itemsDone);
+	    }
+	else
+	    sqlDyStringPrintf(query, "select * from %s", splitSqlTable);
+	if (startsWith("wig", tdb->type))
+            itemsDone += wigTableDataOutput(jw, db, splitSqlTable, chrom,
+		start, end, itemsDone);
+	else
+	    itemsDone += sqlQueryJsonOutput(conn, jw, query->string,
+		columnCount, columnNames, jsonTypes, itemsDone);
 	}
     }
 else
     {
     itemsDone += sqlQueryJsonOutput(conn, jw, query->string, columnCount,
 	columnNames, jsonTypes, itemsDone);
     }
 freeDyString(&query);
-jsonWriteListEnd(jw);
+jsonWriteListEnd(jw);	/* data output list end */
 }	/*  static void tableDataOutput(char *db, struct trackDb *tdb, ... ) */
 
 static boolean typedBig9Plus(struct trackDb *tdb)
 /* check if track type is 'bed 9+ ...' to determine itemRgb for big* types */
 {
 if (isNotEmpty(tdb->type) && (allowedBigBedType(tdb->type)))
     {
     char *words[8];
     int wordCount;
     wordCount = chopLine(cloneString(tdb->type), words);
     if ( (wordCount > 1) && startsWith("bigBed", words[0]))
 	{
 	if (isAllDigits(words[1]))
 	   if (8 < sqlUnsigned(words[1]))
 		return TRUE;