15746316e92290a4aee220a757cb35293176d6e8
max
  Tue Feb 7 05:29:10 2023 -0800
adding file download links directly to the table browser "schema / data format" button, refs #30491

diff --git src/hg/hgTables/schema.c src/hg/hgTables/schema.c
index c441c7e..597e92b 100644
--- src/hg/hgTables/schema.c
+++ src/hg/hgTables/schema.c
@@ -343,66 +343,91 @@
 	{
 	// H2 (as in "<H2>Description</H2>") has a big top margin, which adds to
 	// the 10px start-of-web-section <tr> (except for IE < 8, above).
 	// Tim's trick for moving the text back up in this case, to look like more
 	// like details pages in which HR's bottom margin melts into H2's top margin:
 	char *s = skipLeadingSpaces(tdb->html);
 	if (startsWith("<H2>", s) || startsWith("<h2>", s))
 	    printf("<div style='position:relative; top:-1.2em; margin-bottom:0em;'>%s\n</div>",
 		   tdb->html);
 	else
 	    puts(tdb->html);
 	}
     }
 }
 
+static void addNotesForBbiTables(struct trackDb *tdb, struct sqlConnection *conn)
+/* single-row BBI file pointer tables are confusing, help the users a little here */
+{
+if (tdb != NULL)
+    {
+    boolean isBig = printTypeHelpDesc(tdb->type);
+
+    if (isBig)
+        {
+        char *fileName = trackDbSetting(tdb, "bigDataUrl");
+        if (!fileName) 
+            {
+            char query[1024];
+            sqlSafef(query, sizeof query, "SELECT fileName from %s", tdb->table);
+            char *bbiPath = sqlQuickString(conn, query);
+            printf("The MySQL table contains only a single row with a pointer to the file.<BR>");
+            printf("You can download the binary file from our "
+                    "<a href=\"https://hgdownload.soe.ucsc.edu%s\">Download server</a>.<BR>", bbiPath);
+            }
+        }
+    }
+}
 
 static void showSchemaDb(char *db, struct trackDb *tdb, char *table)
 /* Show schema to open html page. */
 {
 struct trackDb *tdbForConn = tdb ? tdb : curTrack;
 struct sqlConnection *conn;
 if (tdbForConn == NULL)
     conn = hAllocConn(db);
 else
     conn = hAllocConnTrack(db, tdbForConn);
 struct joiner *joiner = allJoiner;
 struct joinerPair *jpList, *jp;
 struct asObject *asObj = asForTable(conn, table);
 char *splitTable = chromTable(conn, table);
 hPrintf("<B>Database:</B> %s", db);
 hPrintf("&nbsp;&nbsp;&nbsp;&nbsp;<B>Primary Table:</B> %s", table);
 if (!sameString(splitTable, table))
     hPrintf(" (%s)", splitTable);
 hPrintf("&nbsp;&nbsp;&nbsp;&nbsp;<B>Row Count: </B>  ");
 printLongWithCommas(stdout, sqlTableSize(conn, splitTable));
 char *date = firstWordInLine(sqlTableUpdate(conn, splitTable));
 if (date != NULL)
     printf("&nbsp&nbsp<B> Data last updated:&nbsp;</B>%s<BR>\n", date);
 if (asObj != NULL)
     hPrintf("<B>Format description:</B> %s<BR>", asObj->comment);
+
 if (cartTrackDbIsNoGenome(db, table))
     hPrintf(" Note: genome-wide queries are not available for this table.");
-describeFields(db, splitTable, asObj, conn);
-if (tdbForConn != NULL)
+else
     {
-    char *type = tdbForConn->type;
-    if (startsWithWord("bigWig", type))
-	printf("<BR>This table points to a file in "
-	       "<A HREF=\"/goldenPath/help/bigWig.html\" TARGET=_BLANK>"
-	       "BigWig</A> format.<BR>\n");
+    hPrintf("<B>On download server: </B>");
+    hPrintf("<A HREF='https://hgdownload.soe.ucsc.edu/goldenPath/%s/database/'>MariaDB table dump directory</A><BR>", db);
     }
+
+describeFields(db, splitTable, asObj, conn);
+
+struct trackDb *childTdb = tdbForTrack(db, table, NULL);
+addNotesForBbiTables(childTdb, conn);
+
 jpList = joinerRelate(joiner, db, table, NULL);
 
 /* sort and unique list */
 slUniqify(&jpList, joinerPairCmpOnAandB, joinerPairFree);
 
 if (jpList != NULL)
     {
     webNewSection("Connected Tables and Joining Fields");
     for (jp = jpList; jp != NULL; jp = jp->next)
 	{
 	if (cartTrackDbIsAccessDenied(jp->b->database, jp->b->table))
 	    continue;
 	struct joinerSet *js = jp->identifier;
 	boolean aViaIndex, bViaIndex;
 	hPrintSpaces(6);