2770a53d1e8e0e5773020965d19c2499439481ca
chmalee
  Tue Feb 7 13:33:08 2023 -0800
Make hubApi return data from multiple tracks at once. Get trackDb tableBrowser setting working correctly in the api

diff --git src/hg/hubApi/list.c src/hg/hubApi/list.c
index 58b5e73..3f62dc1 100644
--- src/hg/hubApi/list.c
+++ src/hg/hubApi/list.c
@@ -290,41 +290,41 @@
         {
         itemCount = bamFileItemCount(bigDataUrl, indexFileOrUrl);
         }
     else if (sameString("vcfTabix", type))
         {
         itemCount = vcfTabixItemCount(bigDataUrl, indexFileOrUrl);
         }
     }
 errCatchEnd(errCatch);
 if (isNotEmpty(errCatch->message->string))
     fprintf(stderr, "%s", errCatch->message->string);
 errCatchFree(&errCatch);
 return itemCount;
 }
 
-static void outputTrackDbVars(struct jsonWrite *jw, struct trackDb *tdb,
+static void outputTrackDbVars(struct jsonWrite *jw, char *db, struct trackDb *tdb,
     long long itemCount)
 /* JSON output the fundamental trackDb variables */
 {
 if (NULL == tdb)	/* might not be any trackDb */
     return;
 
 boolean isContainer = tdbIsComposite(tdb) || tdbIsCompositeView(tdb);
 
 boolean protectedData = FALSE;
-protectedData = protectedTrack(tdb, tdb->track);
+protectedData = protectedTrack(db, tdb, tdb->track);
 jsonWriteString(jw, "shortLabel", tdb->shortLabel);
 jsonWriteString(jw, "type", tdb->type);
 jsonWriteString(jw, "longLabel", tdb->longLabel);
 if (! isContainer && (itemCount > 0))	/* containers do not have items to count and if itemCount == -1 we didn't count */
     jsonWriteNumber(jw, "itemCount", itemCount);
 if (tdb->parent)
     {
     jsonWriteString(jw, "parent", tdb->parent->track);
     if (tdb->parent->parent)
         jsonWriteString(jw, "parentParent", tdb->parent->parent->track);
     }
 if (tdb->settingsHash)
     {
     struct hashEl *hel;
     struct hashCookie hc = hashFirst(tdb->settingsHash);
@@ -376,31 +376,31 @@
 struct trackDb *tdb = obtainTdb(foundGenome, NULL);
 if (NULL == tdb)
     apiErrAbort(err400, err400Msg, "failed to find a track hub definition in genome=%s track=%s for endpoint '/list/schema' given hubUrl=%s'", genome, track, 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/schema'  given hubUrl='%s'", track, genome, hubUrl);
 
 char *bigDataUrl = hReplaceGbdb(trackDbSetting(thisTrack, "bigDataUrl"));
 if (NULL == bigDataUrl)
     apiErrAbort(err400, err400Msg, "failed to find bigDataUrl for specified track=%s in genome=%s for endpoint '/list/schema'  given hubUrl='%s'", track, genome, hubUrl);
 char *indexFileOrUrl = hReplaceGbdb(trackDbSetting(tdb, "bigDataIndex"));
 struct bbiFile *bbi = bigFileOpen(thisTrack->type, bigDataUrl);
 long long itemCount = bbiItemCount(bigDataUrl, thisTrack->type, indexFileOrUrl);
 
-outputTrackDbVars(jw, thisTrack, itemCount);
+outputTrackDbVars(jw, genome, thisTrack, itemCount);
 
 struct asObject *as = bigBedAsOrDefault(bbi);
 if (! as)
     apiErrAbort(err500, err500Msg, "can not find schema definition for bigDataUrl '%s', track=%s genome: '%s' for endpoint '/list/schema' given hubUrl='%s'", bigDataUrl, track, genome, hubUrl);
 struct sqlFieldType *fiList = sqlFieldTypesFromAs(as);
 bigColumnTypes(jw, fiList, as);
 
 apiFinishOutput(0, NULL, jw);
 }	/* static void hubSchemaJsonOutput(FILE *f, char *hubUrl,
 	 *	char *genome, char *track) */
 
 static char *bigDataUrlFromTable(struct sqlConnection *conn, char *table)
 /* perhaps there is a bigDataUrl in a database table */
 {
 char *bigDataUrl = NULL;
@@ -504,80 +504,80 @@
 jsonWriteString(jw, "dataTime", dataTime);
 jsonWriteNumber(jw, "dataTimeStamp", (long long)dataTimeStamp);
 
 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 (! protectedTrack(thisTrack, track))
+    if (! protectedTrack(db, thisTrack, track))
 	{
 	char *indexFileOrUrl = hReplaceGbdb(trackDbSetting(thisTrack, "bigDataIndex"));
 	itemCount = bbiItemCount(bigDataUrl, thisTrack->type, indexFileOrUrl);
 	}
     if (startsWith("bigWig", thisTrack->type))
 	{
 	wigColumnTypes(jw);
 	}
     else
 	{
 	as = bigBedAsOrDefault(bbi);
 	if (! as)
 	    apiErrAbort(err500, err500Msg, "can not find schema definition for bigDataUrl '%s', track=%s genome: '%s' for endpoint '/list/schema'", bigDataUrl, track, db);
 	struct sqlFieldType *fiList = sqlFieldTypesFromAs(as);
 	bigColumnTypes(jw, fiList, as);
 	}
     }
 else
     {
     columnCount = tableColumns(conn, splitTableName, &columnNames, &columnTypes, &jsonTypes);
     as = asForTable(conn, splitTableName, thisTrack);
     if (! as)
 	apiErrAbort(err500, err500Msg, "can not find schema definition for table '%s', track=%s genome: '%s' for endpoint '/list/schema'", splitTableName, track, db);
     columnEl = as->columnList;
     asColumnCount = slCount(columnEl);
 
     /* do not show counts for protected data */
-    if (! protectedTrack(thisTrack, track))
+    if (! protectedTrack(db, thisTrack, track))
 	{
 	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);
 
 
 if (hti && (hti->isSplit || debug))
     jsonWriteBoolean(jw, "splitTable", hti->isSplit);
 
 outputSchema(thisTrack, jw, columnNames, columnTypes, jsonTypes, hti,
   columnCount, asColumnCount, columnEl);
     }
 
-outputTrackDbVars(jw, thisTrack, itemCount);
+outputTrackDbVars(jw, db, 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;
@@ -693,31 +693,31 @@
 char **row;
 while ((row = sqlNextRow(sr)) != NULL)
     {
     itemCount += bbiItemCount(hReplaceGbdb(row[0]), type, NULL);
     }
 sqlFreeResult(&sr);
 return itemCount;
 }
 
 static long long dataItemCount(char *db, struct trackDb *tdb)
 /* determine how many items are in this data set */
 {
 long long itemCount = 0;
 if (trackHasNoData(tdb))	/* container 'tracks' have no data items */
     return itemCount;
-if (protectedTrack(tdb, tdb->track))	/*	private data */
+if (protectedTrack(db, tdb, tdb->track))	/*	private data */
     return itemCount;
 if (sameWord("downloadsOnly", tdb->type))
     return itemCount;
 
 char *bigDataUrl = hReplaceGbdb(trackDbSetting(tdb, "bigDataUrl"));
 if (isNotEmpty(bigDataUrl))
     {
     char *indexFileOrUrl = hReplaceGbdb(trackDbSetting(tdb, "bigDataIndex"));
     itemCount = bbiItemCount(bigDataUrl, tdb->type, indexFileOrUrl);
     }
 else
     {
     /* prepare for getting table row count, find table name */
     /* the trackDb might have a specific table defined */
     char *tableName = trackDbSetting(tdb, "table");
@@ -760,39 +760,39 @@
 
 static void recursiveTrackList(struct jsonWrite *jw, struct trackDb *tdb,
     char *db)
 /* output trackDb tags only for real tracks, not containers,
  * recursive when subtracks exist
  */
 {
 boolean isContainer = trackHasNoData(tdb);
 
 /* do *NOT* print containers when 'trackLeavesOnly' requested */
 if (! (trackLeavesOnly && isContainer) )
     {
 #ifdef NOTNOW
     long long itemCount = 0;
     /* do not show counts for protected data or continers (== no items)*/
-    if (! (isContainer || protectedTrack(tdb, tdb->track)))
+    if (! (isContainer || protectedTrack(db, tdb, tdb->track)))
 	itemCount = dataItemCount(db, tdb);
 #endif
     jsonWriteObjectStart(jw, tdb->track);
     if (tdbIsComposite(tdb))
         jsonWriteString(jw, "compositeContainer", "TRUE");
     if (tdbIsCompositeView(tdb))
         jsonWriteString(jw, "compositeViewContainer", "TRUE");
-    outputTrackDbVars(jw, tdb, -1);
+    outputTrackDbVars(jw, db, tdb, -1);
 
     if (tdb->subtracks)
 	{
 	struct trackDb *el = NULL;
 	for (el = tdb->subtracks; el != NULL; el = el->next )
 	    recursiveTrackList(jw, el, db);
 	}
 
     jsonWriteObjectEnd(jw);
     }
 else if (tdb->subtracks)
     {
     struct trackDb *el = NULL;
     for (el = tdb->subtracks; el != NULL; el = el->next )
 	recursiveTrackList(jw, el, db);