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]);