d1e16597846fc15d4388fc0625ce265aec2cd490
hiram
  Tue Jul 2 16:02:00 2019 -0700
adding new list function to show schema for a table with row count refs #23739

diff --git src/hg/hubApi/getData.c src/hg/hubApi/getData.c
index 31dfcb7..347f58c 100644
--- src/hg/hubApi/getData.c
+++ src/hg/hubApi/getData.c
@@ -49,59 +49,30 @@
 return itemCount;
 }	/* static unsigned wigTableDataOutput(struct jsonWrite *jw, ...) */
 
 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)
-/* output column headers for a wiggle data output schema */
-{
-jsonWriteListStart(jw, "columnTypes");
-
-jsonWriteObjectStart(jw, NULL);
-jsonWriteString(jw, "name", "start");
-jsonWriteString(jw, "sqlType", "int");
-jsonWriteString(jw, "jsonType", "number");
-jsonWriteString(jw, "description", "chromStart: 0-based chromosome start position");
-jsonWriteObjectEnd(jw);
-
-jsonWriteObjectStart(jw, NULL);
-jsonWriteString(jw, "name", "end");
-jsonWriteString(jw, "sqlType", "int");
-jsonWriteString(jw, "jsonType", "number");
-jsonWriteString(jw, "description", "chromEnd: 1-based chromosome end position");
-jsonWriteObjectEnd(jw);
-
-jsonWriteObjectStart(jw, NULL);
-jsonWriteString(jw, "name", "value");
-jsonWriteString(jw, "sqlType", "float");
-jsonWriteString(jw, "jsonType", "number");
-jsonWriteString(jw, "description", "numerical data value for this location:start-end");
-jsonWriteObjectEnd(jw);
-
-jsonWriteListEnd(jw);
-}	/* static void wigColumnTypes(struct jsonWrite jw) */
-
 static unsigned sqlQueryJsonOutput(struct sqlConnection *conn,
     struct jsonWrite *jw, char *query, int columnCount, char **columnNames,
 	int *jsonTypes, unsigned itemsDone)
 /* with the SQL query set up, run through those selected items */
 {
 struct sqlResult *sr = sqlGetResult(conn, query);
 char **row = NULL;
 unsigned itemCount = 0;
 while ((itemCount+itemsDone) < maxItemsOutput && (row = sqlNextRow(sr)) != NULL)
     {
     int i = 0;
     if (jsonOutputArrays)
 	{
 	jsonWriteListStart(jw, NULL);
 	for (i = 0; i < columnCount; ++i)
@@ -263,66 +234,35 @@
            hAddBinToQuery(start, end, query);
 	sqlDyStringPrintf(query, "%s='%s' AND %s > %u AND %s < %u ORDER BY %s", chromName, chrom, endName, start, startName, end, startName);
 	}
     }
 
 if (debug)
     jsonWriteString(jw, "select", query->string);
 
 /* continuing, could be wiggle output with no chrom specified */
 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);
+int columnCount = tableColumns(conn, 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);
-	}
+    outputSchema(tdb, jw, columnNames, columnTypes, jsonTypes, hti,
+	columnCount, asColumnCount, columnEl);
     }
 
 unsigned itemsDone = 0;
 
 /* empty chrom, needs to run through all chrom names */
 if (isEmpty(chrom))
     {
     jsonWriteObjectStart(jw, track);	/* begin track data output */
     char fullTableName[256];
     struct chromInfo *ciList = createChromInfoList(NULL, db);
     slSort(ciList, chromInfoCmp);
     struct chromInfo *ci = ciList;
     for ( ; ci && itemsDone < maxItemsOutput; ci = ci->next )
 	{
 	jsonWriteListStart(jw, ci->chrom);	/* starting a chrom output */
@@ -468,53 +408,30 @@
     chromList = bbiChromList(bwf);
     struct bbiChromInfo *bci;
     for (bci = chromList; bci && (itemsDone < maxItemsOutput); bci = bci->next)
 	{
 	itemsDone += wigDataOutput(jw, bwf, bci->name, 0, bci->size);
 	}
 	if (itemsDone >= maxItemsOutput)
 	    reachedMaxItems = TRUE;
     }
     else
 	itemsDone += wigDataOutput(jw, bwf, chrom, start, end);
 
 itemsReturned += itemsDone;
 }
 
-static void bigColumnTypes(struct jsonWrite *jw, struct sqlFieldType *fiList,
-    struct asObject *as)
-/* show the column types from a big file autoSql definitions */
-{
-struct asColumn *columnEl = as->columnList;
-jsonWriteListStart(jw, "columnTypes");
-struct sqlFieldType *fi = fiList;
-for ( ; fi; fi = fi->next, columnEl = columnEl->next)
-    {
-    int jsonType = autoSqlToJsonType(fi->type);
-    jsonWriteObjectStart(jw, NULL);
-    jsonWriteString(jw, "name", fi->name);
-    jsonWriteString(jw, "sqlType", fi->type);
-    jsonWriteString(jw, "jsonType",jsonTypeStrings[jsonType]);
-    if (columnEl && isNotEmpty(columnEl->comment))
-	jsonWriteString(jw, "description", columnEl->comment);
-    else
-	jsonWriteString(jw, "description", "");
-    jsonWriteObjectEnd(jw);
-    }
-jsonWriteListEnd(jw);
-}
-
 static void getHubTrackData(char *hubUrl)
 /* return data from a hub track, optionally just one chrom data,
  *  optionally just one section of that chrom data
  */
 {
 char *genome = cgiOptionalString("genome");
 char *track = cgiOptionalString("track");
 char *chrom = cgiOptionalString("chrom");
 char *start = cgiOptionalString("start");
 char *end = cgiOptionalString("end");
 
 if (isEmpty(genome))
     apiErrAbort(err400, err400Msg, "missing genome=<name> for endpoint '/getData/track'  given hubUrl='%s'", hubUrl);
 if (isEmpty(track))
     apiErrAbort(err400, err400Msg, "missing track=<name> for endpoint '/getData/track'  given hubUrl='%s'", hubUrl);