8ce7da98082db69f86314bf79d8f69978e008455
angie
  Fri Apr 28 16:43:36 2017 -0700
hgVai was crashing when there was a new snpNNN table in the database but not yet in trackDb.  Now make sure to use the latest SNPs track not just the latest table.  refs #19272

diff --git src/hg/hgVai/hgVai.c src/hg/hgVai/hgVai.c
index 868a394..24d4ac0 100644
--- src/hg/hgVai/hgVai.c
+++ src/hg/hgVai/hgVai.c
@@ -482,31 +482,33 @@
     printf("If you have more than one custom track or hub track in "
            PGSNP_OR_VCF " format, please select the one you wish to annotate:<BR>\n");
     }
 printf("<B>variants: </B>");
 printf("<SELECT ID='hgva_variantTrack' NAME='hgva_variantTrack'>\n");
 jsOnEventById("change", "hgva_variantTrack", "hgva.changeVariantSource();");
 char *selected = cartUsualString(cart, "hgva_variantTrack", "");
 struct slRef *ref;
 for (ref = varTrackList;  ref != NULL;  ref = ref->next)
     {
     struct trackDb *tdb = ref->val;
     printOption(tdb->track, selected, tdb->longLabel);
     }
 printOption(hgvaSampleVariants, selected, hgvaSampleVariantsLabel);
 printOption(hgvaUseHgvs, selected, hgvaHgvsLabel);
-boolean hasSnps = (hFindLatestSnpTable(database, NULL) != NULL);
+struct trackDb *snpTdb = hFindLatestSnpTrack(database, NULL, &fullTrackList);
+// We can convert rsIds from snpNNN tables (but not ancient "snp" - no refUCSC column) into VCF
+boolean hasSnps = (snpTdb != NULL && differentString(snpTdb->table, "snp"));
 if (hasSnps)
     printOption(hgvaUseVariantIds, selected, hgvaVariantIdsLabel);
 printf("</SELECT><BR>\n");
 
 printf("<div id='"hgvaHgvsPasteContainer"'%s>\n",
        differentString(selected, hgvaUseHgvs) ? " style='display: none;'" : "");
 printf("Enter HGVS terms: one term per line; blank lines and comment lines beginning with '#' "
        "are ignored.<BR>\n");
 char *oldPasted = cartUsualString(cart, hgvaHgvs, "");
 cgiMakeTextArea(hgvaHgvs, oldPasted, 10, 70);
 puts("</div>");
 
 if (hasSnps)
     {
     printf("<div id='"hgvaVariantPasteContainer"'%s>\n",
@@ -713,68 +715,63 @@
 	printDbNsfpSource(table->name, HDIV);
 	printDbNsfpSource(table->name, HVAR);
 	}
     else
 	printDbNsfpSource(table->name, 0);
     }
 jsEndContainer();
 puts("<BR>");
 endCollapsibleSection();
 }
 
 boolean findSnpBed4(char *suffix, char **retFileName, struct trackDb **retTdb)
 /* If we can find the latest snpNNNsuffix table, or better yet a bigBed file for it (faster),
  * set the appropriate ret* and return TRUE, otherwise return FALSE. */
 {
-char *table = hFindLatestSnpTable(database, suffix);
-if (table == NULL)
+struct trackDb *tdb = hFindLatestSnpTrack(database, suffix, &fullTrackList);
+if (tdb == NULL)
     return FALSE;
 boolean foundIt = FALSE;
 // Do we happen to have a bigBed version?  Better yet, bed4 only for current uses:
 char origFileName[HDB_MAX_PATH_STRING];
-safef(origFileName, sizeof(origFileName), "/gbdb/%s/vai/%s.bed4.bb", database, table);
+safef(origFileName, sizeof(origFileName), "/gbdb/%s/vai/%s.bed4.bb", database, tdb->table);
 char* fileName = hReplaceGbdb(origFileName);
 if (fileExists(fileName))
     {
     if (retFileName != NULL)
 	*retFileName = fileName;
     foundIt = TRUE;
     }
 else
     {
     // Not bed4; try just .bb:
     freez(&fileName);
-    safef(origFileName, sizeof(origFileName), "/gbdb/%s/vai/%s.bb", database, table);
+    safef(origFileName, sizeof(origFileName), "/gbdb/%s/vai/%s.bb", database, tdb->table);
     fileName = hReplaceGbdb(origFileName);
     if (fileExists(fileName))
 	{
 	if (retFileName != NULL)
 	    *retFileName = fileName;
 	foundIt = TRUE;
 	}
     }
-if (foundIt && retTdb == NULL)
-    return TRUE;
-struct trackDb *tdb = tdbForTrack(database, table, &fullTrackList);
-if (tdb != NULL)
-    {
-    if (retTdb != NULL)
+if (retTdb == NULL)
+    return foundIt;
+else
     *retTdb = tdb;
 return TRUE;
 }
-return foundIt;
-}
 
 void selectDbSnp(boolean gotSnp)
 /* Offer to include rsID (and other fields, or leave that for advanced output??) if available */
 {
 if (!gotSnp)
     return;
 startCollapsibleSection("dbSnp", "Known variation", TRUE);
 cartMakeCheckBox(cart, "hgva_rsId", TRUE);
 printf("Include <A HREF='http://www.ncbi.nlm.nih.gov/projects/SNP/' TARGET=_BLANK>dbSNP</A> "
        "rs# ID if one exists<BR>\n");
 puts("<BR>");
 endCollapsibleSection();
 }
 
 #define GENCODE_PREFIX "wgEncodeGencode"
@@ -2181,38 +2178,38 @@
     dyStringPrintf(dy, "'%s'", el->name);
     }
 return dyStringCannibalize(&dy);
 }
 
 //#*** Variant ID-matching should be metadata-driven too.  termRegex -> data source.
 static const char *rsIdRegex = "^rs[0-9]+$";
 
 static void rsIdsToVcfRecords(struct annoAssembly *assembly, struct slName *rsIds,
 			      struct vcfFile *vcff, struct vcfRecord **pRecList,
 			      struct slName **pCommentList)
 /* If possible, look up coordinates and alleles of dbSNP rs IDs. */
 {
 if (rsIds == NULL)
     return;
-char *table = hFindLatestSnpTable(database, NULL);
-if (table == NULL)
+struct trackDb *tdb = hFindLatestSnpTrack(database, NULL, &fullTrackList);
+if (tdb == NULL)
     return;
 struct sqlConnection *conn = hAllocConn(assembly->name);
 // Build a 'name in (...)' query, and build a hash of IDs so we can test whether all were found
 struct dyString *dq = sqlDyStringCreate("select chrom, chromStart, chromEnd, name, strand, "
 					"refUCSC, observed from %s where name in (",
-					table);
+					tdb->table);
 struct hash *idHash = hashNew(0);
 struct slName *id;
 for (id = rsIds;  id != NULL;  id = id->next)
     {
     tolowers(id->name);
     dyStringPrintf(dq, "%s'%s'", (id != rsIds ? "," : ""), id->name);
     hashStoreName(idHash, id->name);
     }
 dyStringAppend(dq, ");");
 struct sqlResult *sr = sqlGetResult(conn, dq->string);
 // Construct a minimal VCF row to make a vcfRecord for each variant.
 char *vcfRow[9];
 vcfRow[5] = vcfRow[6] = vcfRow[7] = "."; // placeholder for qual, filter, info
 // It would be cool to someday add snpNNN's exceptions column to the filter or info.
 struct dyString *dyAltAlStr = dyStringNew(0);