f587148862bf76eb764a550db5d52b00318679fc
angie
  Wed May 29 10:28:10 2019 -0700
Report item counts correctly for big* types whose files are specified in db tables instead of bigDataUrl settings.  refs #18869, #23521

diff --git src/hg/hubApi/list.c src/hg/hubApi/list.c
index 1db5129..e41e290 100644
--- src/hg/hubApi/list.c
+++ src/hg/hubApi/list.c
@@ -342,76 +342,105 @@
     {
     if (allowedBigBedType(type))
         {
         struct bbiFile *bbi = NULL;
         bbi = bigBedFileOpen(bigDataUrl);
         itemCount = bigBedItemCount(bbi);
         bbiFileClose(&bbi);
         }
     else if (startsWithWord("bigWig", type))
         {
         struct bbiFile *bwf = bigWigFileOpen(bigDataUrl);
         struct bbiSummaryElement sum = bbiTotalSummary(bwf);
         itemCount = sum.validCount;
         bbiFileClose(&bwf);
         }
+    // NOTE: htslib does not appear to have a function to extract a count from BAI or TBI (tabix)
+    // indexes.  One could probably be added by adding code similar to samtools' idxstats subcommand,
+    // But in the meantime, this is not supported for types vcfTabix and bam.
     }
 errCatchEnd(errCatch);
 errCatchFree(&errCatch);
 return itemCount;
 }
 
+static long long bbiTableItemCount(struct sqlConnection *conn, char *type, char *tableName)
+/* Given a tableName that has a fileName column pointing to big*, bam or vcfTabix files, return the
+ * total itemCount from all rows (BAM and VCF tables may have one row per chrom). */
+{
+long long itemCount = 0;
+char query[2048];
+sqlSafef(query, sizeof query, "select fileName from %s", tableName);
+struct sqlResult *sr = sqlGetResult(conn, query);
+char **row;
+while ((row = sqlNextRow(sr)) != NULL)
+    {
+    itemCount += bbiItemCount(row[0], type);
+    }
+sqlFreeResult(&sr);
+return itemCount;
+}
+
 static long long dataItemCount(char *db, struct trackDb *tdb)
 /* determine how many items are in this data set */
 {
 boolean isContainer = tdbIsComposite(tdb) || tdbIsCompositeView(tdb);
 if (trackDbSetting(tdb, "container"))
     isContainer = TRUE;
 long long itemCount = 0;
 if (isContainer)	/* containers have no data items */
     return itemCount;
 if (sameWord("downloadsOnly", tdb->type))
     return itemCount;
 
 char *bigDataUrl = trackDbSetting(tdb, "bigDataUrl");
 if (isNotEmpty(bigDataUrl))
     itemCount = bbiItemCount(bigDataUrl, tdb->type);
 else
     {
     /* prepare for getting table row count, find table name */
     /* the trackDb might have a specific table defined */
     char *tableName = trackDbSetting(tdb, "table");
     if (isEmpty(tableName))
 	tableName = trackDbSetting(tdb, "track");
     if (isNotEmpty(tableName))
 	{
 	struct sqlConnection *conn = hAllocConnMaybe(db);
 	if (conn)
 	    {
+            if ((startsWith("big", tdb->type) ||
+                 sameString("vcfTabix", tdb->type) || sameString("bam", tdb->type)) &&
+                sqlColumnExists(conn, tableName, "fileName"))
+                {
+                itemCount = bbiTableItemCount(conn, tdb->type, tableName);
+                }
+            else
+                {
                 /* punting on split tables, return zero */
                 struct hTableInfo *hti =
                     hFindTableInfoWithConn(conn, NULL, tableName);
                 if (hti && hti->isSplit)
                     {
                     itemCount = 0;
                     }
                 else
                     {
                     char query[2048];
                     sqlSafef(query, sizeof(query), "select count(*) from %s", tableName);
                     itemCount = sqlQuickNum(conn, query);
                     }
+                }
             hFreeConn(&conn);
 	    }
 	}
     }
 return itemCount;
 }
 
 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 = tdbIsComposite(tdb) || tdbIsCompositeView(tdb);