ab553b2a1e248cdc8108d39f5e2a8d859216f15b
hiram
  Tue Sep 17 14:21:12 2019 -0700
fix list chromosomes function for bigDataUrl tracks on database genomes refs #23589

diff --git src/hg/hubApi/list.c src/hg/hubApi/list.c
index 2f588b1..a5b1047 100644
--- src/hg/hubApi/list.c
+++ src/hg/hubApi/list.c
@@ -102,30 +102,47 @@
 char **columnNames = NULL;
 char **columnTypes = NULL;
 int *jsonTypes = NULL;
 int columnCount = tableColumns(conn, "dbDb", &columnNames, &columnTypes,
     &jsonTypes);
 jsonWriteObjectStart(jw, "ucscGenomes");
 for ( el=dbList; el != NULL; el = el->next )
     {
     dbDbJsonData(jw, el, columnCount, columnNames);
     }
 jsonWriteObjectEnd(jw);
 apiFinishOutput(0, NULL, jw);
 hDisconnectCentral(&conn);
 }
 
+static void bigFileChromInfoOutput(struct jsonWrite *jw,
+    struct trackDb *thisTrack, char *bigDataUrl)
+/* output the chromosome list for the bigDataUrl file */
+{
+struct bbiFile *bbi = bigFileOpen(thisTrack->type, bigDataUrl);
+struct bbiChromInfo *chrList = bbiChromList(bbi);
+slSort(chrList, chromInfoCmp);
+struct bbiChromInfo *el = chrList;
+jsonWriteNumber(jw, "chromCount", (long long)slCount(chrList));
+jsonWriteObjectStart(jw, "chromosomes");
+for ( ; el; el = el->next )
+    {
+    jsonWriteNumber(jw, el->name, (long long)el->size);
+    }
+jsonWriteObjectEnd(jw);	/* chromosomes */
+}
+
 static void hubChromInfoJsonOutput(FILE *f, char *hubUrl, char *genome)
 /* for given hubUrl list the chromosomes in the sequence for specified genome
  */
 {
 struct trackHub *hub = errCatchTrackHubOpen(hubUrl);
 struct trackHubGenome *ge = NULL;
 char *track = cgiOptionalString("track");
 
 if (isEmpty(genome))
     apiErrAbort(err400, err400Msg, "must specify a 'genome=name' with hubUrl for endpoint: /list/chromosomes?hubUrl=%s;genome=<empty>", hubUrl);
 
 struct trackHubGenome *foundGenome = NULL;
 
 for (ge = hub->genomeList; ge; ge = ge->next)
     {
@@ -142,41 +159,31 @@
 struct jsonWrite *jw = apiStartOutput();
 jsonWriteString(jw, "hubUrl", hubUrl);
 jsonWriteString(jw, "genome", genome);
 if (isNotEmpty(track))
     {
     jsonWriteString(jw, "track", track);
     struct trackDb *tdb = obtainTdb(foundGenome, NULL);
     if (NULL == tdb)
 	apiErrAbort(err400, err400Msg, "failed to find a track hub definition in genome=%s for endpoint '/list/chromosomes' given hubUrl=%s'", genome, hubUrl);
 
     struct trackDb *thisTrack = findTrackDb(track, tdb);
     if (NULL == thisTrack)
 	apiErrAbort(err400, err400Msg, "failed to find specified track=%s in genome=%s for endpoint '/list/chromosomes'  given hubUrl='%s'", track, genome, hubUrl);
 
     char *bigDataUrl = trackDbSetting(thisTrack, "bigDataUrl");
-    struct bbiFile *bbi = bigFileOpen(thisTrack->type, bigDataUrl);
-    struct bbiChromInfo *chrList = bbiChromList(bbi);
-    slSort(chrList, chromInfoCmp);
-    struct bbiChromInfo *el = chrList;
-    jsonWriteNumber(jw, "chromCount", (long long)slCount(chrList));
-    jsonWriteObjectStart(jw, "chromosomes");
-    for ( ; el; el = el->next )
-	{
-	jsonWriteNumber(jw, el->name, (long long)el->size);
-	}
-    jsonWriteObjectEnd(jw);	/* chromosomes */
+    bigFileChromInfoOutput(jw, thisTrack, bigDataUrl);
     }
 else
     {
     struct chromInfo *ci = NULL;
     /* might be a track hub on a UCSC database */
     if (isEmpty(foundGenome->twoBitPath))
 	{
 	struct sqlConnection *conn = hAllocConnMaybe(foundGenome->trackHub->defaultDb);
 	if (NULL == conn)
 	    apiErrAbort(err400, err400Msg, "can not find 'genome=%s' for endpoint '/list/chromosomes", foundGenome->trackHub->defaultDb);
 	else
 	    hFreeConn(&conn);
 	ci = createChromInfoList(NULL, foundGenome->trackHub->defaultDb);
 	}
     else
@@ -233,40 +240,42 @@
 /* check if table name needs to be modified */
 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);	/* return to caller */
     }
 else
     {
     *splitTableName = sqlTableName;	/* return to caller */
     }
 
+if (! sqlTableExists(conn, sqlTableName))
+    returnChrom = NULL;
 /* may need to extend this in the future for other track types */
-if (sqlColumnExists(conn, sqlTableName, "chrom"))	/* standard bed tables */
+else if (sqlColumnExists(conn, sqlTableName, "chrom"))	/* standard bed tables */
     returnChrom = cloneString("chrom");
 else if (sqlColumnExists(conn, sqlTableName, "tName"))	/* track type psl */
     returnChrom = cloneString("tName");
 else if (sqlColumnExists(conn, sqlTableName, "genoName"))	/* track type rmsk */
     returnChrom = cloneString("genoName");
 
 return returnChrom;
-}
+}	/*	static char *validChromName() */
 
 static long long bbiItemCount(char *bigDataUrl, char *type, char *indexFileOrUrl)
 /* check the bigDataUrl to see what the itemCount is there */
 {
 long long itemCount = 0;
 struct errCatch *errCatch = errCatchNew();
 if (errCatchStart(errCatch))
     {
     if (allowedBigBedType(type))
         {
         struct bbiFile *bbi = NULL;
         bbi = bigBedFileOpen(bigDataUrl);
         itemCount = bigBedItemCount(bbi);
         bbiFileClose(&bbi);
         }
@@ -532,37 +541,49 @@
 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");
+char *bigDataUrl = NULL;
+struct trackDb *thisTrack = NULL;
 struct sqlConnection *conn = hAllocConnMaybe(db);
 if (NULL == conn)
     apiErrAbort(err400, err400Msg, "can not find 'genome=%s' for endpoint '/list/chromosomes", db);
 
 if (table)
     chromName = validChromName(conn, db, table, &splitSqlTable, &tableInfo);
 
+/* given track can't find a chromName, maybe it is a bigDataUrl */
+if (table && ! chromName)
+    {
+    /* 'track' name in trackDb usually refers to a SQL 'table' */
+    struct trackDb *tdb = obtainTdb(NULL, db);
+    thisTrack = findTrackDb(table,tdb);
+    /* might have a bigDataUrl */
+    bigDataUrl = trackDbSetting(thisTrack, "bigDataUrl");
+    }
+
 /* in trackDb language: track == table */
 /* punting on split tables, just return chromInfo */
 if (table && chromName && ! (tableInfo && tableInfo->isSplit) )
     {
     if (! sqlTableExists(conn, splitSqlTable))
 	apiErrAbort(err400, err400Msg, "can not find specified 'track=%s' for endpoint: /list/chromosomes?genome=%s;track=%s", table, db, table);
 
     if (sqlColumnExists(conn, splitSqlTable, chromName))
 	{
 	char *dataTime = sqlTableUpdate(conn, splitSqlTable);
 	time_t dataTimeStamp = sqlDateToUnixTime(dataTime);
 	replaceChar(dataTime, ' ', 'T');	/* ISO 8601 */
         struct jsonWrite *jw = apiStartOutput();
 	jsonWriteString(jw, "genome", db);
 	jsonWriteString(jw, "track", table);
@@ -581,30 +602,39 @@
     	}
 	sqlFreeResult(&sr);
         slPairIntSort(&list);
         slReverse(&list);
         jsonWriteNumber(jw, "chromCount", (long long)slCount(list));
 	jsonWriteObjectStart(jw, "chromosomes");
         struct slPair *el = list;
         for ( ; el != NULL; el = el->next )
             jsonWriteNumber(jw, el->name, (long long)ptToInt(el->val));
 	jsonWriteObjectEnd(jw);	/* chromosomes */
 	apiFinishOutput(0, NULL, jw);
 	}
     else
 	apiErrAbort(err400, err400Msg, "track '%s' is not a position track, request table without chrom specification, genome: '%s'", table, db);
     }
+else if (bigDataUrl)
+    {
+    struct jsonWrite *jw = apiStartOutput();
+    jsonWriteString(jw, "genome", db);
+    jsonWriteString(jw, "track", table);
+    jsonWriteString(jw, "bigDataUrl", bigDataUrl);
+    bigFileChromInfoOutput(jw, thisTrack, bigDataUrl);
+    apiFinishOutput(0, NULL, jw);
+    }
 else if (table && !chromName)	/* only allowing position tables at this time */
 	apiErrAbort(err400, err400Msg, "track '%s' is not a position track, request table without chrom specification, genome: '%s'", table, db);
 else
     {
     char *dataTime = sqlTableUpdate(conn, "chromInfo");
     time_t dataTimeStamp = sqlDateToUnixTime(dataTime);
     replaceChar(dataTime, ' ', 'T');	/* ISO 8601 */
     struct chromInfo *ciList = createChromInfoList(NULL, db);
     slSort(ciList, chromInfoCmp);
     struct chromInfo *el = ciList;
     struct jsonWrite *jw = apiStartOutput();
     jsonWriteString(jw, "genome", db);
     jsonWriteString(jw, "dataTime", dataTime);
     if (tableInfo && tableInfo->isSplit)	/* the split table punt */
 	jsonWriteString(jw, "track", table);