97b43803a09f9085190a3af6bb2b7c63d07016bb
tdreszer
  Mon Aug 22 17:12:52 2011 -0700
Added support for cv terms that are searchable='wildList'.  This type of searching allows comma dilimied lists and '%' wild card.
diff --git src/hg/lib/mdb.c src/hg/lib/mdb.c
index b696ecf..33c99f1 100644
--- src/hg/lib/mdb.c
+++ src/hg/lib/mdb.c
@@ -642,32 +642,32 @@
 
         // Fill in the val(s) from second half of pair
         char *val = NULL;
         if (words[thisWord][0] != '\0' && words[thisWord][0] != '?') // "var=?" or "var=" will query by var name only
             val = cloneString(words[thisWord]);
         if (val != NULL)
             {
             // Strip any single or double quotes first.
             char *end = val + strlen(val) - 1;
             if ((*val == '"'  && *end == '"')
             ||  (*val == '\'' && *end == '\''))
                 {
                 *end = '\0';
                 val++;
                 }
-            // handle comma separated list of vals (if unquoted)
-            if (strchr(val,',') != NULL)
+            // handle comma separated list of vals (if not framed with widcards)
+            if (strchr(val,',') != NULL && (*val != '%' || *(val + strlen(val) - 1) != '%'))
                 {
                 char * aVal = NULL;
                 while((aVal = cloneNextWordByDelimiter(&val,',')) != NULL)
                     {
                     AllocVar(limbVal);
                     limbVal->val = aVal;
                     slAddTail(&rootVar->vals,limbVal);
                     }
                 }
             else
                 {
                 AllocVar(limbVal);
                 limbVal->val = val;
                 rootVar->vals = limbVal;
                 }
@@ -1364,53 +1364,69 @@
 
         if(!hasVal && rootVar->notEqual)
             dyStringPrintf(dy, "NOT EXISTS ");
         else
             dyStringPrintf(dy, "EXISTS ");
 
         dyStringPrintf(dy, "(SELECT T%d.obj FROM %s T%d WHERE T%d.obj = T1.obj AND T%d.var ",tix,table,tix,tix,tix);
 
         if(hasVal && rootVar->notEqual && rootVar->vals == NULL)
             dyStringPrintf(dy, "%s",strchr(rootVar->var,'%')?"NOT ":"!");
 
         dyStringPrintf(dy, "%s '%s'",
             (strchr(rootVar->var,'%')?"LIKE":"="), rootVar->var);
 
         struct mdbLimbVal *limbVal;
-        boolean multiVals = FALSE;
+        boolean multiVals = (rootVar->vals != NULL && rootVar->vals->next != NULL);
+        boolean wilds = FALSE;
+        for(limbVal=rootVar->vals;limbVal!=NULL;limbVal=limbVal->next)
+            {
+            if (strchr(limbVal->val,'%') != NULL)
+                wilds = TRUE;
+            }
         for(limbVal=rootVar->vals;limbVal!=NULL;limbVal=limbVal->next)
             {
             if(limbVal->val == NULL || strlen(limbVal->val) < 1)
                 continue;
 
-            if(!multiVals)
+            if(limbVal==rootVar->vals) // First val
                 {
+                if (wilds && multiVals)
+                    dyStringPrintf(dy, " AND (T%d.val ",tix);
+                else
                 dyStringPrintf(dy, " AND T%d.val ",tix);
-                if(rootVar->notEqual)
-                    dyStringPrintf(dy, "%s",(strchr(limbVal->val,'%') || limbVal->next)?"NOT ":"!");
-                if(limbVal->next == NULL) // only one val
+                }
+            else                      // successive vals
                     {
-                    dyStringPrintf(dy, "%s '%s'",
-                        (strchr(limbVal->val,'%')?"LIKE":"="), sqlEscapeString(limbVal->val));
-                    break;
+                if (wilds && multiVals)
+                    dyStringPrintf(dy, " or T%d.val ",tix);
+                else
+                    dyStringPrintf(dy, ",");
                     }
+
+            if (limbVal==rootVar->vals   // First val
+            ||  (wilds && multiVals))      // and successive if wildcards
+                {
+                if(rootVar->notEqual)
+                    dyStringPrintf(dy, "%s",(strchr(limbVal->val,'%') || limbVal->next)?"NOT ":"!");
+                if (strchr(limbVal->val,'%') != NULL)
+                    dyStringPrintf(dy, "LIKE ");
+                else if (!multiVals || wilds)
+                    dyStringPrintf(dy, "= ");
                 else
                     dyStringPrintf(dy, "IN (");
-                multiVals=TRUE;
                 }
-            else
-                dyStringPrintf(dy, ",");
             dyStringPrintf(dy, "'%s'", sqlEscapeString(limbVal->val));
             }
         if(multiVals)
             dyStringPrintf(dy, ")");
         dyStringPrintf(dy, ")");
         }
     dyStringPrintf(dy, " ORDER BY binary T1.obj, T1.var");  // binary forces case sensitive sort
     verbose(2, "Requesting query:\n\t%s;\n",dyStringContents(dy));
 
     struct mdb *mdb = mdbLoadByQuery(conn, dyStringCannibalize(&dy));
     verbose(3, "rows (vars) returned: %d\n",slCount(mdb));
     struct mdbObj *mdbObjs = mdbObjsLoadFromMemory(&mdb,TRUE);
     verbose(3, "Returned %d object(s) with %d var(s).\n",
         mdbObjCount(mdbObjs,TRUE),mdbObjCount(mdbObjs,FALSE));
     return mdbObjs;
@@ -3078,31 +3094,33 @@
 return mdbObjs;
 }
 
 struct mdbObj *mdbObjRepeatedSearch(struct sqlConnection *conn,struct slPair *varValPairs,boolean tables,boolean files)
 // Search the metaDb table for objs by var,val pairs.  Uses mdbCvSearchMethod() if available.
 // This method will use mdbObjsQueryByVars()
 {
 struct slPair *onePair;
 struct dyString *dyTerms = dyStringNew(256);
 // Build list of terms as "var1=val1 var2=val2a,val2b,val2c var3=%val3%"
 for(onePair = varValPairs; onePair != NULL; onePair = onePair->next)
     {
     if (isEmpty(((char *)(onePair->val)))) // NOTE: All the parens are needed to get the macro to do the right thing
         continue;
     enum cvSearchable searchBy = cvSearchMethod(onePair->name);
-    if (searchBy == cvSearchBySingleSelect || searchBy == cvSearchByMultiSelect)  // multiSelect val will be filled with a comma delimited list
+    if (searchBy == cvSearchByMultiSelect  // multiSelect val will be filled with a comma delimited list
+    || searchBy == cvSearchBySingleSelect
+    || searchBy == cvSearchByWildList)
         {
         if (strchr((char *)onePair->val,' '))
             dyStringPrintf(dyTerms,"%s=\"%s\" ",onePair->name,(char *)onePair->val);
         else
             dyStringPrintf(dyTerms,"%s=%s ",onePair->name,(char *)onePair->val);
         }
     else if (searchBy == cvSearchByFreeText)                                      // If select is by free text then like
         dyStringPrintf(dyTerms,"%s=%%%s%% ",onePair->name,(char *)onePair->val);
     else if (sameWord(onePair->name,MDB_VAR_COMPOSITE))  // special case.  Not directly searchable by UI but indirectly and will show up here.
         dyStringPrintf(dyTerms,"%s=%s ",onePair->name,(char *)onePair->val);
     else if (searchBy == cvSearchByDateRange || searchBy == cvSearchByIntegerRange)
         {
         // TO BE IMPLEMENTED
         }
     }