e7264355c83a0d0875b372b7ad26162adb363f6c
chmalee
  Tue May 12 13:20:28 2026 -0700
myVariants v1 follow-ups: CT edit gate, anon-user button gate, hgc duplicate link, item-name synthesis from ref/alt or HGVS, refs #33808

diff --git src/hg/lib/myVariants.c src/hg/lib/myVariants.c
index aa6ee4fe96e..3a037263ab5 100644
--- src/hg/lib/myVariants.c
+++ src/hg/lib/myVariants.c
@@ -41,52 +41,71 @@
 struct sqlResult *sr;
 char **row;
 sr = sqlGetResult(conn, query);
 while ((row = sqlNextRow(sr)) != NULL)
     {
     el = myVariantsLoad(row);
     slAddHead(&list, el);
     }
 slReverse(&list);
 sqlFreeResult(&sr);
 return list;
 }
 
 void myVariantsSaveToDb(struct sqlConnection *conn, struct myVariants *el, char *tableName, int updateSize)
 /* Save myVariants as a row to the table specified by tableName.
- * Uses explicit column names so custom fields in el->customFields are included. */
+ * Uses explicit column names so custom fields in el->customFields are included.
+ * If el->name is NULL or empty, fills it in post-INSERT as "Variant N" using
+ * the row's auto-increment id; sqlLastAutoId wraps MariaDB's mysql_insert_id,
+ * which is per-connection and unaffected by concurrent INSERTs on other
+ * connections. */
 {
 struct dyString *update = dyStringNew(updateSize);
 sqlDyStringPrintf(update, "insert into %s (bin,chrom,chromStart,chromEnd,name,score,strand,thickStart,thickEnd,itemRgb,description,db,ref,alt,project,mouseover", tableName);
 
 /* Append custom field column names */
 struct slPair *cf;
 for (cf = el->customFields; cf != NULL; cf = cf->next)
     sqlDyStringPrintf(update, ",%s", cf->name);
 
+char *insertName = isEmpty(el->name) ? "" : el->name;
 sqlDyStringPrintf(update, ") values (%u,'%s',%u,%u,'%s',%u,'%s',%u,%u,%u,'%s','%s','%s','%s','%s','%s'",
-    el->bin, el->chrom, el->chromStart, el->chromEnd, el->name, el->score, el->strand,
+    el->bin, el->chrom, el->chromStart, el->chromEnd, insertName, el->score, el->strand,
     el->thickStart, el->thickEnd, el->itemRgb, el->description, el->db, el->ref, el->alt,
     el->project, el->mouseover);
 
 /* Append custom field values */
 for (cf = el->customFields; cf != NULL; cf = cf->next)
     sqlDyStringPrintf(update, ",'%s'", (char *)cf->val);
 
 sqlDyStringPrintf(update, ")");
 sqlUpdate(conn, update->string);
 dyStringFree(&update);
+
+if (isEmpty(el->name))
+    {
+    unsigned int newId = sqlLastAutoId(conn);
+    struct dyString *nameUpdate = sqlDyStringCreate(
+        "update %s set name = 'Variant %u' where id = %u",
+        tableName, newId, newId);
+    sqlUpdate(conn, dyStringCannibalize(&nameUpdate));
+    el->id = newId;
+    freez(&el->name);
+    struct dyString *dy = dyStringNew(0);
+    dyStringPrintf(dy, "Variant %u", newId);
+    el->name = dyStringCannibalize(&dy);
+    }
 }
 
 struct myVariants *myVariantsLoad(char **row)
 /* Load a myVariants from row fetched with select * from myVariants from database. Dispose of this with myVariantsFree(). */
 {
 struct myVariants *ret;
 AllocVar(ret);
 ret->bin = sqlUnsigned(row[0]);
 ret->chrom = cloneString(row[1]);
 ret->chromStart = sqlUnsigned(row[2]);
 ret->chromEnd = sqlUnsigned(row[3]);
 ret->name = cloneString(row[4]);
 ret->score = sqlUnsigned(row[5]);
 safecpy(ret->strand, sizeof(ret->strand), row[6]);
 ret->thickStart = sqlUnsigned(row[7]);