a3801c8acc3bee5d65e260dcd842d615be11b3a6
hiram
  Wed Sep 4 10:18:46 2019 -0700
list schema needs to handle big* files correctly refs #23589

diff --git src/hg/hubApi/list.c src/hg/hubApi/list.c
index f3e51cb..2f588b1 100644
--- src/hg/hubApi/list.c
+++ src/hg/hubApi/list.c
@@ -395,100 +395,153 @@
 struct sqlConnection *conn = hAllocConnMaybe(db);
 if (NULL == conn)
     apiErrAbort(err400, err400Msg, "can not find 'genome=%s' for endpoint '/list/schema", db);
 
 struct trackDb *tdb = obtainTdb(NULL, db);
 struct trackDb *thisTrack = findTrackDb(track, tdb);
 if (NULL == thisTrack)	/* OK to work with tables without trackDb definitions */
     {
     if (! sqlTableExists(conn, track))
 	apiErrAbort(err400, err400Msg, "failed to find specified track=%s in genome=%s for endpoint '/list/schema'", track, db);
     }
 
 if (trackHasNoData(thisTrack))
     apiErrAbort(err400, err400Msg, "container track '%s' does not contain data, use the children of this container for data access", track);
 
+/* might be a table that points to a big* file
+ * or is just a bigDataUrl without any table
+ */
+char *bigDataUrl = trackDbSetting(thisTrack, "bigDataUrl");
+
 char *sqlTableName = cloneString(track);
 /* the trackDb might have a specific table defined instead */
 char *tableName = trackDbSetting(thisTrack, "table");
 if (isNotEmpty(tableName))
     {
     freeMem(sqlTableName);
     sqlTableName = cloneString(tableName);
     }
 
 /* this function knows how to deal with split chromosomes, the NULL
  * here for the chrom name means to use the first chrom name in chromInfo
  */
 struct hTableInfo *hti = hFindTableInfoWithConn(conn, NULL, sqlTableName);
 /* check if table name needs to be modified */
 char *splitTableName = NULL;
 if (hti && hti->isSplit)
     {
     char *defaultChrom = hDefaultChrom(db);
     char fullTableName[256];
     safef(fullTableName, sizeof(fullTableName), "%s_%s", defaultChrom, hti->rootName);
     freeMem(sqlTableName);
     sqlTableName = cloneString(fullTableName);
     splitTableName = cloneString(fullTableName);
     }
 else
     {
     splitTableName = sqlTableName;
     }
 
-char **columnNames = NULL;
-char **columnTypes = NULL;
-int *jsonTypes = NULL;
-int columnCount = tableColumns(conn, splitTableName, &columnNames, &columnTypes, &jsonTypes);
-struct asObject *as = asForTable(conn, splitTableName, thisTrack);
-struct asColumn *columnEl = as->columnList;
-int asColumnCount = slCount(columnEl);
+struct bbiFile *bbi = NULL;
+if (thisTrack && startsWith("big", thisTrack->type))
+    {
+    if (bigDataUrl)
+	bbi = bigFileOpen(thisTrack->type, bigDataUrl);
+    else
+	{
+	char query[4096];
+	char quickReturn[2048];
+	sqlSafef(query, sizeof(query), "select fileName from %s", splitTableName);
+	if (sqlQuickQuery(conn, query, quickReturn, sizeof(quickReturn)))
+	    {
+	    bigDataUrl = hReplaceGbdb(cloneString(quickReturn));
+	    bbi = bigFileOpen(thisTrack->type, bigDataUrl);
+	    }
+	}
+    if (NULL == bbi)
+	apiErrAbort(err400, err400Msg, "failed to find bigDataUrl=%s for track=%s in database=%s for endpoint '/getData/schema'", bigDataUrl, track, db);
+    }
 
 char *dataTime = sqlTableUpdate(conn, splitTableName);
 
 time_t dataTimeStamp = sqlDateToUnixTime(dataTime);
 replaceChar(dataTime, ' ', 'T');	/* ISO 8601 */
 struct jsonWrite *jw = apiStartOutput();
 jsonWriteString(jw, "genome", db);
 jsonWriteString(jw, "track", track);
 jsonWriteString(jw, "dataTime", dataTime);
 jsonWriteNumber(jw, "dataTimeStamp", (long long)dataTimeStamp);
 freeMem(dataTime);
 
+char **columnNames = NULL;
+char **columnTypes = NULL;
+int *jsonTypes = NULL;
+int columnCount = 0;
+struct asObject *as = NULL;
+struct asColumn *columnEl = NULL;
+int asColumnCount = 0;
 long long itemCount = 0;
+
+if (bbi)
+    {
+    /* do not show itemCount for protected data */
+    if (! trackDbSetting(thisTrack, "tableBrowser"))
+	{
+	char *indexFileOrUrl = hReplaceGbdb(trackDbSetting(thisTrack, "bigDataIndex"));
+	itemCount = bbiItemCount(bigDataUrl, thisTrack->type, indexFileOrUrl);
+	}
+    if (startsWith("bigWig", thisTrack->type))
+	{
+	wigColumnTypes(jw);
+	}
+    else
+	{
+	as = bigBedAsOrDefault(bbi);
+	struct sqlFieldType *fiList = sqlFieldTypesFromAs(as);
+	bigColumnTypes(jw, fiList, as);
+	}
+    }
+else
+    {
+    columnCount = tableColumns(conn, splitTableName, &columnNames, &columnTypes, &jsonTypes);
+    as = asForTable(conn, splitTableName, thisTrack);
+    columnEl = as->columnList;
+    asColumnCount = slCount(columnEl);
+
     /* do not show counts for protected data */
     if (! trackDbSetting(thisTrack, "tableBrowser"))
 	{
 	char query[2048];
 	sqlSafef(query, sizeof(query), "select count(*) from %s", splitTableName);
 	if (hti && hti->isSplit)	/* punting on split table item count */
 	    itemCount = 0;
 	else
 	    {
 	    itemCount = sqlQuickNum(conn, query);
 	    }
 	}
 hFreeConn(&conn);
 
-outputTrackDbVars(jw, thisTrack, itemCount);
 
 if (hti && (hti->isSplit || debug))
     jsonWriteBoolean(jw, "splitTable", hti->isSplit);
 
 outputSchema(thisTrack, jw, columnNames, columnTypes, jsonTypes, hti,
   columnCount, asColumnCount, columnEl);
+    }
+
+outputTrackDbVars(jw, thisTrack, itemCount);
 
 apiFinishOutput(0, NULL, jw);
 
 }	/*	static void schemaJsonOutput(FILE *f, char *db, char *track) */
 
 static void chromInfoJsonOutput(FILE *f, char *db)
 /* for given db, if there is a track, list the chromosomes in that track,
  * for no track, simply list the chromosomes in the sequence
  */
 {
 char *splitSqlTable = NULL;
 struct hTableInfo *tableInfo = NULL;
 char *chromName = NULL;
 char *table = cgiOptionalString("track");
 struct sqlConnection *conn = hAllocConnMaybe(db);