fabf13fff3e3abaf7ef83c69a8c60d0142c288a1
braney
  Fri May 15 12:05:59 2026 -0700
fix two remaining quickLift issues on UCSC RefSeq item detail page: CCDS link routes to source assembly (with coords lifted back) so the ccdsGene handler doesn't try to open the hub-virtual db, and Get Genomic Sequence Near Gene now reads sequence from the destination assembly at the lifted exon coordinates refs #36125

diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c
index 81103698c92..2cf3b71f6cc 100644
--- src/hg/hgc/hgc.c
+++ src/hg/hgc/hgc.c
@@ -10248,47 +10248,60 @@
     itemCount = getSeqForBigGene(tdb, geneName);
     }
 else
     {
     if (isHubTrack(table))
         tdb = hubConnectAddHubForTrackAndFindTdb( database, table, NULL, trackHash);
     else
         tdb = hashFindVal(trackHash, table);
     char *bigDataUrl = trackDbSetting(tdb, "bigDataUrl");
     if (bigDataUrl)
         {
         itemCount = getSeqForBigGene(tdb, geneName);
         }
     else
         {
-        char constraints[256];
-        sqlSafef(constraints, sizeof(constraints), "name = '%s'", geneName);
-        char *db = database;
         char *liftDb = cloneString(trackDbSetting(tdb, "quickLiftDb"));
-        // When quickLifted, the genePred table lives in the source assembly,
-        // and the click's seqName/winStart/winEnd are in destination coords;
-        // lift them back to source coords so hgSeqItemsInRange finds rows.
-        char *querySeq = seqName;
-        int queryStart = winStart, queryEnd = winEnd;
         if (liftDb != NULL)
             {
-            db = liftDb;
-            quickLiftLiftPos(trackHubSkipHubName(database), liftDb,
-                             seqName, winStart, winEnd,
-                             &querySeq, &queryStart, &queryEnd);
+            // Load the genePred from the source assembly and lift it to
+            // destination coords, so hgSeqBed reads sequence from the
+            // destination assembly at the lifted exon coordinates.
+            struct genePred *gpList = getGenePredForPosition(table, geneName);
+            struct bed *bedList = NULL;
+            struct genePred *gp;
+            for (gp = gpList; gp != NULL; gp = gp->next)
+                slAddHead(&bedList, bedFromGenePred(gp));
+            slReverse(&bedList);
+            char rootName[HDB_MAX_TABLE_STRING];
+            char parsedChrom[HDB_MAX_CHROM_STRING];
+            char *bareTable = trackHubSkipHubName(table);
+            hParseTableName(liftDb, bareTable, rootName, parsedChrom);
+            struct hTableInfo *hti = hFindTableInfo(liftDb, NULL, rootName);
+            if (hti == NULL)
+                webAbort("Error", "Could not find table info for table %s (%s)",
+                         rootName, table);
+            itemCount = hgSeqBed(database, hti, bedList);
+            bedFreeList(&bedList);
+            genePredFreeList(&gpList);
+            }
+        else
+            {
+            char constraints[256];
+            sqlSafef(constraints, sizeof(constraints), "name = '%s'", geneName);
+            itemCount = hgSeqItemsInRange(database, table, seqName, winStart, winEnd, constraints);
             }
-        itemCount = hgSeqItemsInRange(db, trackHubSkipHubName(table), querySeq, queryStart, queryEnd, constraints);
         }
     }
 if (itemCount == 0)
     printf("\n# No results returned from query.\n\n");
 puts("</PRE>");
 }
 
 void htcTrackHtml(struct trackDb *tdb)
 /* Handle click to display track html */
 {
 cartWebStart(cart, database, "%s", tdb->shortLabel);
 printTrackHtml(tdb);
 }
 
 void doViralProt(struct trackDb *tdb, char *geneName)
@@ -10824,31 +10837,31 @@
     struct sqlResult *sr = NULL;
     char **row;
     sqlSafef(query, sizeof(query), "select biotype, extGeneId from %s where %s",
           tdb->table, condStr);
     sr = sqlGetResult(conn, query);
     if ((row = sqlNextRow(sr)) != NULL)
         {
         printf("<B>Gene Type:</B> %s<BR>\n", row[0]);
         printf("<B>External Gene ID:</B> %s<BR>\n", row[1]);
         }
     sqlFreeResult(&sr);
     }
 else
     {
     /* print CCDS if this is not a non-coding gene */
-    printCcdsForSrcDb(conn, item);
+    printCcdsForSrcDb(conn, tdb, item);
     printf("<BR>\n");
     }
 
 if (hTableExists(database, "ensInfo"))
     {
     struct sqlResult *sr;
     char query[256], **row;
     struct ensInfo *info = NULL;
 
     sqlSafef(query, sizeof(query),
           "select * from ensInfo where name = '%s'", item);
     sr = sqlGetResult(conn, query);
     while ((row = sqlNextRow(sr)) != NULL)
         {
         info = ensInfoLoad(row);
@@ -13120,31 +13133,31 @@
 char *org = sqlQuickString(conn, query);
 if (org == NULL)
     org = cloneString("unknown");
 printf("<B>Organism:</B> %s<BR>", org);
 char *xenoDb = hDbForSciName(org);
 if ((xenoDb != NULL) && hDbIsActive(xenoDb) && hTableExists(xenoDb, "refSeqAli"))
     {
     printf("<B>UCSC browser: </B> \n");
     linkToOtherBrowserSearch(xenoDb, rl->mrnaAcc);
     printf("%s on %s (%s)</B> \n", rl->mrnaAcc, hOrganism(xenoDb), xenoDb);
     printf("</A><BR>");
     }
 freeMem(org);
 }
 
-void prRefGeneInfo(struct sqlConnection *conn, char *rnaName,
+void prRefGeneInfo(struct sqlConnection *conn, struct trackDb *tdb, char *rnaName,
                    char *sqlRnaName, struct refLink *rl, boolean isXeno)
 /* print basic details information and links for a RefGene */
 {
 struct sqlResult *sr;
 char **row;
 char query[256];
 // For quickLifted tracks the conn is on the source assembly, while the
 // `database` global is the destination (possibly hub_NNN_<db>, which is
 // not a real MySQL db).  Use the conn's db for hTableExists/startsWith
 // checks so we don't abort on "Unknown database".
 char *srcDb = sqlGetDatabase(conn);
 int ver = gbCdnaGetVersion(conn, rl->mrnaAcc);
 char *cdsCmpl = NULL;
 
 printf("<td valign=top nowrap>\n");
@@ -13173,31 +13186,31 @@
     if (stat != NULL)
 	printf("&nbsp;&nbsp; <B>Status: </B>%s", stat);
     }
 puts("<BR>");
 char *desc = gbCdnaGetDescription(conn, rl->mrnaAcc);
 if (desc != NULL)
     {
     printf("<B>Description:</B> ");
     htmlTextOut(desc);
     printf("<BR>\n");
     }
 
 if (isXeno)
     prRefGeneXenoInfo(conn, rl);
 else
-    printCcdsForSrcDb(conn, rl->mrnaAcc);
+    printCcdsForSrcDb(conn, tdb, rl->mrnaAcc);
 
 cdsCmpl = getRefSeqCdsCompleteness(conn, sqlRnaName);
 if (cdsCmpl != NULL)
     {
     printf("<B>CDS:</B> %s<BR>", cdsCmpl);
     }
 if (rl->omimId != 0)
     {
     printf("<B>OMIM:</B> <A HREF=\"");
     printEntrezOMIMUrl(stdout, rl->omimId);
     printf("\" TARGET=_blank>%d</A><BR>\n", rl->omimId);
     }
 if (rl->locusLinkId != 0)
     {
     printf("<B>Entrez Gene:</B> ");
@@ -13280,61 +13293,61 @@
 	}
     sqlFreeResult(&sr);
     }
 if (startsWith("hg", srcDb))
     {
     printf("\n");
     printf("<B>AceView:</B> ");
     printf("<A HREF = \"https://www.ncbi.nlm.nih.gov/IEB/Research/Acembly/av.cgi?db=human&l=%s\" TARGET=_blank>",
 	   rl->name);
     printf("%s</A><BR>\n", rl->name);
     }
 prGRShortRefGene(conn, rl->name);
 
 }
 
-void prKnownGeneInfo(struct sqlConnection *conn, char *rnaName,
+void prKnownGeneInfo(struct sqlConnection *conn, struct trackDb *tdb, char *rnaName,
                    char *sqlRnaName, struct refLink *rl)
 /* print basic details information and links for a Known Gene */
 {
 struct sqlResult *sr;
 char **row;
 char query[256];
 int ver = gbCdnaGetVersion(conn, rl->mrnaAcc);
 char *cdsCmpl = NULL;
 
 printf("<td valign=top nowrap>\n");
 
 printf("<H2>Known Gene %s</H2>\n", rl->name);
 printf("<B>KnownGene:</B> <A HREF=\"");
 printEntrezNucleotideUrl(stdout, rl->mrnaAcc);
 if (ver > 0)
     printf("\" TARGET=_blank>%s.%d</A>", rl->mrnaAcc, ver);
 else
     printf("\" TARGET=_blank>%s</A>", rl->mrnaAcc);
 fflush(stdout);
 
 puts("<BR>");
 char *desc = gbCdnaGetDescription(conn, rl->mrnaAcc);
 if (desc != NULL)
     {
     printf("<B>Description:</B> ");
     htmlTextOut(desc);
     printf("<BR>\n");
     }
 
-printCcdsForSrcDb(conn, rl->mrnaAcc);
+printCcdsForSrcDb(conn, tdb, rl->mrnaAcc);
 
 cdsCmpl = getRefSeqCdsCompleteness(conn, sqlRnaName);
 if (cdsCmpl != NULL)
     {
     printf("<B>CDS:</B> %s<BR>", cdsCmpl);
     }
 if (rl->omimId != 0)
     {
     printf("<B>OMIM:</B> <A HREF=\"");
     printEntrezOMIMUrl(stdout, rl->omimId);
     printf("\" TARGET=_blank>%d</A><BR>\n", rl->omimId);
     }
 if (rl->locusLinkId != 0)
     {
     printf("<B>Entrez Gene:</B> ");
@@ -13398,31 +13411,31 @@
         errAbort("Couldn't find %s in %s table - this accession may no longer be available.",
                  rnaName, refLinkTable);
     rl = refLinkLoad(row);
     sqlFreeResult(&sr);
     }
 else
     {
     rlR.name    = strdup(kgId);
     rlR.mrnaAcc = strdup(kgId);
     rlR.locusLinkId = 0;
     rl = &rlR;
     }
 
 cartWebStart(cart, database, "Known Gene");
 printf("<table border=0>\n<tr>\n");
-prKnownGeneInfo(conn, rnaName, sqlRnaName, rl);
+prKnownGeneInfo(conn, tdb, rnaName, sqlRnaName, rl);
 
 printf("</tr>\n</table>\n");
 
 /* optional summary text */
 summary = getRefSeqSummary(conn, kgId);
 if (summary != NULL)
     {
     htmlHorizontalLine();
     printf("<H3>Summary of %s</H3>\n", kgId);
     printf("<P>%s</P>\n", summary);
     freeMem(summary);
     }
 htmlHorizontalLine();
 
 /* print alignments that track was based on */
@@ -13489,31 +13502,31 @@
 else
     {
     sqlSafef(query, sizeof(query), "select * from %s r, %s g where mrnaAcc = '%s' and r.mrnaAcc=g.acc and g.version='%s'", refLinkTable,gbCdnaInfoTable, sqlRnaName, version);
     sr = sqlGetResult(conn, query);
     if ((row = sqlNextRow(sr)) == NULL)
 	{
 	sqlFreeResult(&sr);
 	return NULL;
 	}
     rl = refLinkLoad(row);
     sqlFreeResult(&sr);
     }
 
 /* print the first section with info  */
 printf("<table border=0>\n<tr>\n");
-prRefGeneInfo(conn, rnaName, sqlRnaName, rl, isXeno);
+prRefGeneInfo(conn, tdb, rnaName, sqlRnaName, rl, isXeno);
 addGeneExtra(rl->name);  /* adds columns if extra info is available */
 
 printf("</tr>\n</table>\n");
 
 /* optional summary text */
 summary = getRefSeqSummary(conn, sqlRnaName);
 if (summary != NULL)
     {
     htmlHorizontalLine();
     printf("<H3>Summary of %s</H3>\n", rl->name);
     printf("<P>%s</P>\n", summary);
     freeMem(summary);
     }
 htmlHorizontalLine();