da4634bf1f2792c8742b4b8a28927ef82c65cea7 tdreszer Wed Mar 30 12:43:36 2011 -0700 Cleaned up fileSortOrderGet's discovery of sortable vars to use cv.ra searchable with a couple of exceptions diff --git src/hg/lib/mdb.c src/hg/lib/mdb.c index dcd50a3..2cee692 100644 --- src/hg/lib/mdb.c +++ src/hg/lib/mdb.c @@ -1761,46 +1761,47 @@ return FALSE; } boolean mdbObjsContainAltleastOneMatchingVar(struct mdbObj *mdbObjs, char *var, char *val) // Returns TRUE if any object in set contains var { struct mdbObj *mdbObj = mdbObjs; for(;mdbObj!=NULL; mdbObj=mdbObj->next) { if(mdbObjContains(mdbObj, var, val)) return TRUE; } return FALSE; } +#define MDB_COMMON_VARS_OBJ_SEARCH_LIMIT 10 struct mdbObj *mdbObjsCommonVars(struct mdbObj *mdbObjs) // Returns a new mdbObj with all vars that are contained in every obj passed in. // Note that the returnd mdbObj has a meaningles obj name and vals. { if (mdbObjs == NULL || mdbObjs->vars == NULL) return NULL; struct mdbObj *mdbObj = mdbObjs; struct mdbObj *commonVars = mdbObjClone(mdbObj); // Clone the first obj then prune it commonVars->next = NULL; mdbObj=mdbObj->next; // No need to include first obj in search if (mdbObj != NULL) { int count = 1; // NOTE: This should not loop through all, as the list could be huge. Just compare the first 10 for now struct dyString *dyPruneVars = dyStringNew(512); - for(;mdbObj != NULL && count < 10;mdbObj=mdbObj->next, count++) + for(;mdbObj != NULL && count < MDB_COMMON_VARS_OBJ_SEARCH_LIMIT;mdbObj=mdbObj->next, count++) { struct mdbVar *mdbVar = commonVars->vars; // Will walk through the first obj's vars for(; mdbVar != NULL; mdbVar = mdbVar->next ) { if (mdbObjsContainAtleastOne(mdbObj, mdbVar->var) == FALSE) dyStringPrintf(dyPruneVars,"%s ",mdbVar->var); // var not found so add to prune list } if (dyStringLen(dyPruneVars) > 0) { mdbObjRemoveVars(commonVars,dyStringContents(dyPruneVars)); dyStringClear(dyPruneVars); } } dyStringFree(&dyPruneVars); } @@ -2078,55 +2079,75 @@ struct hash *varHash = el->val; if (SETTING_IS_ON(hashFindVal(varHash, CV_TOT_HIDDEN))) { assert(cvSearchMethod(el->name) == cvNotSearchable); // Good idea to assert but cv.ra is a user updatable file dyStringPrintf(dyRemoveVars,"%s ",el->name); } } hashElFreeList(&elList); if (dyStringLen(dyRemoveVars)) mdbObjRemoveVars(mdbObjs, dyStringContents(dyRemoveVars)); dyStringFree(&dyRemoveVars); } -char *mdbRemoveCommonVar(struct mdbObj *mdbList, char *var) -// Removes var from set of mdbObjs but only if all that have it have a commmon val -// Returns the val if removed, else NULL +boolean mdbObjsHasCommonVar(struct mdbObj *mdbList, char *var, boolean missingOk) +// Returns TRUE if all mbObjs passed in have the var with the same value { char *val = NULL; struct mdbObj *mdb = NULL; for(mdb = mdbList; mdb; mdb=mdb->next) { char *thisVal = mdbObjFindValue(mdb,var); - if (thisVal == NULL) // If var isn't found in some, that is okay + if (thisVal == NULL) + { + if (missingOk) continue; + else + return FALSE; + } if (val == NULL) val = thisVal; else if(differentWord(val,thisVal)) - return NULL; + return FALSE; + } +return TRUE; } -if (val) +char *mdbRemoveCommonVar(struct mdbObj *mdbList, char *var) +// Removes var from set of mdbObjs but only if all that have it have a commmon val +// Returns the val if removed, else NULL { - val = cloneString(val); - for(mdb = mdbList;mdb;mdb=mdb->next) +if (mdbObjsHasCommonVar(mdbList,var,TRUE)) // If var isn't found in some, that is okay + { + char *val = NULL; + struct mdbObj *mdb = mdbList; + for( ; mdb; mdb=mdb->next) + { + if (val == NULL) + { + char *thisVal = mdbObjFindValue(mdb,var); + if (thisVal != NULL) + val = cloneString(thisVal); + } mdbObjRemoveVars(mdb,var); } return val; } +return NULL; +} boolean mdbObjSetVar(struct mdbObj *mdbObj, char *var,char *val) // Sets the string value to a single var into an obj, preparing for DB update. // returns TRUE if updated, FALSE if added { assert(mdbObj != NULL && var != NULL && val != NULL); struct mdbVar *mdbVar = mdbObjFind(mdbObj, var); if (mdbVar != NULL) { if (mdbVar->val != NULL) freeMem(mdbVar->val); mdbVar->val = cloneString(val); if (mdbObj->varHash != NULL) hashReplace(mdbObj->varHash, mdbVar->var, mdbVar); // pointer to struct to resolve type return TRUE; @@ -3116,32 +3137,30 @@ // 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 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 - // Requires new mdbObjSearch API and more than one (char *)onePair->val - warn("mdb search by date or number is not yet implemented."); } } // Be sure to include table or file in selections if (tables) dyStringPrintf(dyTerms,"%s=%s ",MDB_OBJ_TYPE,MDB_OBJ_TYPE_TABLE); if (files) dyStringPrintf(dyTerms,"%s=? ",MDB_VAR_FILENAME); // Build the mdbByVals struct and then select all mdbObjs in one query struct mdbObj *mdbObjs = mdbObjsQueryByVarVals(conn,dyStringContents(dyTerms)); dyStringFree(&dyTerms); return mdbObjs; } struct slName *mdbObjNameSearch(struct sqlConnection *conn, char *var, char *val, char *op, int limit, boolean tables, boolean files)