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 } }