c6ce277e36a537437a04146c8fa7adebb40428ff chmalee Wed May 15 12:10:42 2024 -0700 Libify some searching code so checkHgFindSpec can use it. Make checkHgFindSpec use the same code path as hgSearch so it can correctly test the search correctly, refs #33731 diff --git src/hg/hubApi/search.c src/hg/hubApi/search.c index 3258ac2..a0695fa 100644 --- src/hg/hubApi/search.c +++ src/hg/hubApi/search.c @@ -1,155 +1,91 @@ #include "dataApi.h" #include "hgFind.h" #include "cartTrackDb.h" #include "cartJson.h" -static struct trackDb *addSupers(struct trackDb *trackList) -/* Insert supertracks into the hierarchy. */ -{ -struct trackDb *newList = NULL; -struct trackDb *tdb, *nextTdb; -struct hash *superHash = newHash(5); - -for(tdb = trackList; tdb; tdb = nextTdb) - { - nextTdb = tdb->next; - if (tdb->parent) - { - // part of a super track - if (hashLookup(superHash, tdb->parent->track) == NULL) - { - hashStore(superHash, tdb->parent->track); - - slAddHead(&newList, tdb->parent); - } - slAddTail(&tdb->parent->subtracks, tdb); - } - else - slAddHead(&newList, tdb); - } -slReverse(&newList); -return newList; -} - -static void hashTdbNames(struct trackDb *tdb, struct hash *trackHash) -/* Store the track names for lookup, except for knownGene which gets its own special - * category in the UI */ -{ -struct trackDb *tmp; -for (tmp = tdb; tmp != NULL; tmp = tmp->next) - { - if (tmp->subtracks) - hashTdbNames(tmp->subtracks, trackHash); - if (!sameString(tmp->table, tmp->track)) - hashAdd(trackHash, tmp->track, tmp); - hashAdd(trackHash, tmp->table, tmp); - } -} - -void hashTracksAndGroups(struct cart *cart, char *db) -/* get the list of tracks available for this assembly. Note that this implicitly - * makes connected hubs show up in the trackList struct, which means we get item - * search for connected hubs for free */ -{ -static struct trackDb *tdbList = NULL; -static struct grp *grpList = NULL; -if (tdbList != NULL && grpList != NULL) - return; - -// hgFindTrackHash/hgFindGroupHash are globals from hgFind.h -if (!hgFindTrackHash) - hgFindTrackHash = hashNew(0); -if (!hgFindGroupHash) - hgFindGroupHash = hashNew(0); -cartTrackDbInit(cart, &tdbList, &grpList, FALSE); -if (!tdbList) - errAbort("Error getting tracks for %s", db); -struct trackDb *superList = addSupers(tdbList); -tdbList = superList; -hashTdbNames(superList, hgFindTrackHash); -struct grp *g; -for (g = grpList; g != NULL; g = g->next) - if (!sameString(g->name, "allTracks") && !sameString(g->name, "allTables")) - hashStore(hgFindGroupHash, g->name); -} +/* Caches used by hgFind.c */ +extern struct trackDb *hgFindTdbList; +extern struct grp *hgFindGrpList; +extern struct hash *hgFindGroupHash; +extern struct hash *hgFindTrackHash; struct searchCategory *makeCategsFromString(char *categoriesString, char *db, struct cart *bogusCart) /* Turn a ';' separated string of table names into a list of searchCategory */ { struct searchCategory *ret = NULL, *category = NULL; int maxCategs = 1024; char *chopped[maxCategs]; int numCategs = chopString(categoriesString, ",", chopped, maxCategs); int i; for (i = 0; i < numCategs; i++) { char *categName = chopped[i]; if (!sameString(categName, "allTracks")) category = makeCategory(bogusCart, categName, NULL, db, hgFindGroupHash); else { struct hashEl *hel, *helList = hashElListHash(hgFindTrackHash); for (hel = helList; hel != NULL; hel = hel->next) { struct trackDb *tdb = hel->val; if (!sameString(tdb->track, "knownGene") && !sameString(tdb->table, "knownGene")) slAddHead(&category, makeCategory(bogusCart, tdb->track, NULL, db, hgFindGroupHash)); } // the hgFindTrackHash can contain both a composite track (where makeCategory would make // categories for each of the subtracks, and a subtrack, where makeCategory just makes a // single category, which means our final list can contain duplicate categories, so do a // uniqify here so we only have one category for each category slUniqify(&category, cmpCategories, searchCategoryFree); } if (category != NULL) { if (ret) slCat(&ret, category); else ret = category; } } return ret; } void getSearchResults(char *searchTerm, char *db, char *hubUrl, char *categories) /* Output search results for db, potentially limited by categories */ { initGenbankTableNames(db); struct cart *bogusCart = cartOfNothing(); cartAddString(bogusCart, "db", db); hashTracksAndGroups(bogusCart, db); struct jsonWrite *jw = apiStartOutput(); struct searchCategory *searchCategoryList = NULL; if (isNotEmpty(categories)) searchCategoryList = makeCategsFromString(categories, db, bogusCart); else searchCategoryList = getAllCategories(bogusCart, db, hgFindGroupHash); struct hgPositions *hgp = NULL; jsonWriteString(jw, "genome", db); hgp = hgPositionsFind(db, searchTerm, "", "searchExample", bogusCart, FALSE, measureTiming, searchCategoryList); if (hgp) hgPositionsJson(jw, db, hgp, NULL); apiFinishOutput(0, NULL, jw); } void apiSearch(char *words[MAX_PATH_INFO]) /* 'search' function */ { char *hubUrl = cgiOptionalString("hubUrl"); char *extraArgs = verifyLegalArgs(argSearch); if (extraArgs) apiErrAbort(err400, err400Msg, "extraneous arguments found for function /search'%s'", extraArgs); // verify required genome and searchTerm parameters exist char *db = cgiOptionalString("genome"); if (isEmpty(db)) apiErrAbort(err400, err400Msg, "missing URL variable genome=<ucscDb> name for endpoint '/search/"); char *searchTerm = cgiOptionalString(argSearchTerm); if (isEmpty(searchTerm)) apiErrAbort(err400, err400Msg, "missing URL variable %s=<search query> for endpoint '/search/", argSearchTerm); char *categories = cgiOptionalString(argCategories); getSearchResults(searchTerm, db, hubUrl, categories); }