454f6d047a6d35baa30335cbe939c41b6df3865f hiram Mon Feb 5 12:24:56 2024 -0800 now honoring allowAll in single word searches refs #32897 diff --git src/hg/hubApi/findGenome.c src/hg/hubApi/findGenome.c index fc5d195..6152923 100644 --- src/hg/hubApi/findGenome.c +++ src/hg/hubApi/findGenome.c @@ -8,30 +8,31 @@ #include "asmAlias.h" #include "asmSummary.h" struct combinedSummary /* may have information from any of: asmSummary, genark or dbDb */ { struct combinedSummary *next; /* Next in singly linked list */ struct asmSummary *summary; /* from asmSummary table */ struct genark *genArk; /* from genark table */ struct dbDb *dbDb; /* from dbDb table */ }; /* will be initialized as this function begins */ static char *genarkTable = NULL; static boolean statsOnly = FALSE; +static boolean allowAll = FALSE; /* default only show existing browsers*/ static void startGenomes(struct jsonWrite *jw) /* begin the list output */ { if (jsonOutputArrays) jsonWriteListStart(jw, "genomes"); else jsonWriteObjectStart(jw, "genomes"); } static void endGenomes(struct jsonWrite *jw) /* end the list output */ { if (jsonOutputArrays) jsonWriteListEnd(jw); @@ -197,72 +198,100 @@ cs->genArk = NULL; cs->dbDb = NULL; char query[4096]; sqlSafef(query, sizeof(query), "SELECT * FROM %s WHERE gcAccession = \"%s\"", genarkTable, el->assemblyAccession); struct genark *gA = genarkLoadByQuery(conn, query); if (gA) cs->genArk = gA; slAddHead(&comboSumary, cs); } } if (comboSumary) slReverse(&comboSumary); return comboSumary; } +static struct asmSummary *checkAsmSummary(struct sqlConnection *conn, char *oneAccession) +/* check the asmSummary table for the single accession LIKE */ +{ +char query[4096]; +sqlSafef(query, sizeof(query), "SELECT * FROM asmSummary WHERE assemblyAccession LIKE \"%s%%\"", oneAccession); +struct asmSummary *list = asmSummaryLoadByQuery(conn, query); +return list; +} + static int singleWordSearch(struct sqlConnection *conn, char *searchWord, struct jsonWrite *jw) /* conn is a connection to hgcentral, searching for one word, * might be a UCSC database or a GenArk hub accession, or just some word. */ { /* the input word might be a database alias * asmAliasFind returns the searchWord if no alias found */ char *perhapsAlias = asmAliasFind(searchWord); int itemCount = 0; if (startsWith("GC", perhapsAlias)) { + struct asmSummary *asmSumFound = NULL; + struct hash *asmSummaryHash = NULL; + asmSumFound = checkAsmSummary(conn, perhapsAlias); + verbose(0, "# found %d items\n", slCount(asmSumFound)); + if (asmSumFound) + { + struct asmSummary *el; + asmSummaryHash = newHash(0); + for (el = asmSumFound; el != NULL; el = el->next) + hashAdd(asmSummaryHash, el->assemblyAccession, (void *)el); + } char query[4096]; sqlSafef(query, sizeof(query), "SELECT * FROM %s WHERE gcAccession LIKE \"%s%%\"", genarkTable, perhapsAlias); struct sqlResult *sr = sqlGetResult(conn, query); char **row; - struct genark *genArkList = NULL; + struct combinedSummary *comboOutput = NULL; while ((row = sqlNextRow(sr)) != NULL) { struct genark *genome = genarkLoad(row); - slAddHead(&genArkList, genome); + struct combinedSummary *cs = NULL; + AllocVar(cs); + cs->genArk = genome; + cs->dbDb = NULL; + if (asmSummaryHash) + { + cs->summary = hashFindVal(asmSummaryHash, genome->gcAccession); + if (cs->summary) + hashRemove(asmSummaryHash, genome->gcAccession); + } + slAddHead(&comboOutput, cs); } sqlFreeResult(&sr); - slReverse(&genArkList); - struct combinedSummary *comboOutput = NULL; - struct genark *el = NULL; - for (el = genArkList; el != NULL; el = el->next) + if (allowAll && asmSummaryHash) + { + /* check if all asmSummaryHash has been used up */ + struct hashCookie cookie = hashFirst(asmSummaryHash); + struct hashEl *hel; + while ((hel = hashNext(&cookie)) != NULL) { struct combinedSummary *cs = NULL; AllocVar(cs); - cs->summary = NULL; - cs->genArk = el; + cs->genArk = NULL; cs->dbDb = NULL; - char asmSumQuery[4096]; - sqlSafef(asmSumQuery, sizeof(asmSumQuery), "SELECT * FROM asmSummary WHERE assemblyAccession = \"%s\"", el->gcAccession); - struct asmSummary *as = asmSummaryLoadByQuery(conn, asmSumQuery); - if (as) - cs->summary = as; + cs->summary = hel->val; slAddHead(&comboOutput, cs); } + } if (comboOutput) { slReverse(&comboOutput); itemCount = outputCombo(jw, comboOutput); } } /* if (startsWith("GC", perhapsAlias)) */ else { /* not a GC genArk name, perhaps a UCSC database */ if (hDbIsActive(perhapsAlias)) { struct combinedSummary *comboOutput = NULL; AllocVar(comboOutput); comboOutput->summary = NULL; comboOutput->genArk = NULL; /* TBD need to get an equivalent GC accession name for UCSC database */ @@ -354,39 +383,50 @@ char *inputSearchString = cloneString(searchString); char *extraArgs = verifyLegalArgs(argFindGenome); genarkTable = genarkTableName(); if (extraArgs) apiErrAbort(err400, err400Msg, "extraneous arguments found for function /findGenome'%s'", extraArgs); boolean asmSummaryExists = hTableExists("hgcentraltest", "asmSummary"); if (!asmSummaryExists) apiErrAbort(err400, err400Msg, "table hgcentraltest.asmSummary does not exist for /findGenome"); boolean genArkExists = hTableExists("hgcentraltest", genarkTable); if (!genArkExists) apiErrAbort(err400, err400Msg, "table hgcentraltest.%s does not exist for /findGenome", genarkTable); -char *statsOnlyArg = cgiOptionalString("statsOnly"); -if (isNotEmpty(statsOnlyArg)) +char *allowAllString = cgiOptionalString(argAllowAll); +if (isNotEmpty(allowAllString)) + { + if (sameString("1", allowAllString)) + allowAll = TRUE; + else if (sameString("0", allowAllString)) + allowAll = FALSE; + else + apiErrAbort(err400, err400Msg, "unrecognized '%s=%s' argument, can only be =1 or =0", argAllowAll, allowAllString); + } + +char *statsOnlyString = cgiOptionalString(argStatsOnly); +if (isNotEmpty(statsOnlyString)) { - if (sameString("1", statsOnlyArg)) + if (sameString("1", statsOnlyString)) statsOnly = TRUE; - else if (sameString("0", statsOnlyArg)) + else if (sameString("0", statsOnlyString)) statsOnly = FALSE; else - apiErrAbort(err400, err400Msg, "unrecognized 'statsOnly=%s' argument, can only be =1 or =0", statsOnlyArg); + apiErrAbort(err400, err400Msg, "unrecognized '%s=%s' argument, can only be =1 or =0", argStatsOnly, statsOnlyString); } struct sqlConnection *conn = hConnectCentral(); if (!sqlTableExists(conn, genarkTable)) apiErrAbort(err500, err500Msg, "missing central.genark table in function /findGenome'%s'", extraArgs); int wordCount = 0; if (! statsOnly) { /* verify number of words in search string is legal */ wordCount = chopByWhite(searchString, NULL, 0); if (wordCount < 1) @@ -396,30 +436,32 @@ } genarkTable = genarkTableName(); struct jsonWrite *jw = apiStartOutput(); if (statsOnly) { doStatsOnly(conn, jw); elapsedTime(jw); apiFinishOutput(0, NULL, jw); hDisconnectCentral(&conn); return; } jsonWriteString(jw, argGenomeSearchTerm, searchString); +if (allowAll) + jsonWriteBoolean(jw, argAllowAll, allowAll); int itemCount = 0; /* save the search string before it is chopped */ char *pristineSearchString = cloneString(searchString); char **words; AllocArray(words, wordCount); (void) chopByWhite(searchString, words, wordCount); if (1 == wordCount) { itemCount = singleWordSearch(conn, words[0], jw); if (itemCount) jsonWriteNumber(jw, "itemCount", itemCount); else verbose(0, "# DBG need to search this word %s somewhere else\n", words[0]);