76367141415738bfc83da601aeeeaf05d1eee04f
chmalee
  Fri Jul 22 11:43:03 2022 -0700
When searching a bigBed track, search first the trix index if present, and then search on any bigBed indexes. Uniqify the results. Restores behaviour changed by my previous commit while still removing duplicates, refs #29685

diff --git src/hg/lib/bigBedFind.c src/hg/lib/bigBedFind.c
index e3c5862..61e3ef1 100644
--- src/hg/lib/bigBedFind.c
+++ src/hg/lib/bigBedFind.c
@@ -114,30 +114,48 @@
 for ( ; tsList != NULL; tsList = tsList->next)
     {
     struct slName *oneIndex = indices;
     for (; oneIndex; oneIndex = oneIndex->next)
 	{
 	struct hgPos *posList2 = getPosFromBigBed(cart, tdb, bbi, oneIndex->name,
                                                   tsList->itemId, description, hfs);
 
 	posList = slCat(posList, posList2);
 	}
     }
 
 return posList;
 }
 
+int posListCompare(const void *va, const void *vb)
+/* Compare to sort based on name and then position. */
+{
+const struct hgPos *a = *((struct hgPos **)va);
+const struct hgPos *b = *((struct hgPos **)vb);
+int diff = strcmp(a->name, b->name);
+if (diff == 0)
+    {
+    diff = strcmp(a->chrom, b->chrom);
+    if (diff == 0)
+        {
+        diff = a->chromStart - b->chromStart;
+        if (diff == 0)
+            diff = a->chromEnd - b->chromEnd;
+        }
+    }
+return diff;
+}
 
 boolean findBigBedPosInTdbList(struct cart *cart, char *db, struct trackDb *tdbList, char *term, struct hgPositions *hgp, struct hgFindSpec *hfs)
 /* Given a list of trackDb entries, check each of them for a searchIndex */
 {
 char *description = NULL;
 if (hfs)
     {
     char buf[2048];
     if (isNotEmpty(hfs->searchDescription))
         truncatef(buf, sizeof(buf), "%s", hfs->searchDescription);
     else
         safef(buf, sizeof(buf), "%s", hfs->searchTable);
     description = cloneString(buf);
     }
 struct trackDb *tdb;
@@ -204,41 +222,39 @@
     // if there is a trix file, use it to search for the term
     if (trixFile != NULL)
 	{
         struct errCatch *errCatch = errCatchNew();
         if (errCatchStart(errCatch))
             {
             posList1 = doTrixSearch(cart, tdb, hReplaceGbdb(trixFile), indexList, bbi, term,
                                     NULL, hfs);
             }
         errCatchEnd(errCatch);
         if (errCatch->gotError)
             warn("trix search failure for %s: %s", tdb->table, dyStringContents(errCatch->message));
         errCatchFree(&errCatch);
 	}
 
-    // if no trix file or we didn't find anything from a trix search
-    if (!posList1)
-        {
     // now search for the raw id's
     struct slName *oneIndex=indexList;
     for (; oneIndex; oneIndex = oneIndex->next)
         {
         posList2 = getPosFromBigBed(cart, tdb, bbi, oneIndex->name, term, NULL, hfs);
         posList1 = slCat(posList1, posList2);
         }
-        }
+    // the trix search and the id search may have found the same item so uniqify:
+    slUniqify(&posList1, posListCompare, hgPosFree);
 
     if (posList1 != NULL)
 	{
 	struct hgPosTable *table;
 
 	found = TRUE;
 	AllocVar(table);
 	slAddHead(&hgp->tableList, table);
 	table->description = cloneString(description ? description : tdb->longLabel);
 	table->name = cloneString(tdb->table);
 
 	table->posList = posList1;
 	}
     bigBedFileClose(&bbi);
     }