e260a83c1023f097f5fb1f3c0a8b3d464c536c3c braney Wed Sep 25 20:52:50 2019 -0700 support <columnName>.Filter* format for trackDb filtering variables diff --git src/hg/lib/hui.c src/hg/lib/hui.c index c00d0e2..09ca6aa 100644 --- src/hg/lib/hui.c +++ src/hg/lib/hui.c @@ -3620,47 +3620,60 @@ if (val == filterBy->slValues) // First one filterBy->valueAndLabel = TRUE; if (filterBy->valueAndLabel == FALSE) errAbort("filterBy values either all have labels (as value|label) " "or none do."); *chipper++ = 0; // The label is found inside filters->svValues as the next string strSwapChar(chipper,'_',' '); // Title does not have underscores } else if (filterBy->valueAndLabel) errAbort("filterBy values either all have labels in form of value|label " "or none do."); } } } +char *extractFieldName(char *cartVariable, char *filterType) +/* Extract field name from a filter cart variable. Variables can either be + * <columnName>Filter* or <columnName>.Filter* */ +{ +char *field = cloneString(cartVariable); +int ix = strlen(field) - strlen(filterType); +assert(ix > 1); +field[ix] = '\0'; +if (field[ix - 1] == '.') + field[ix - 1] = '\0'; + +return field; +} + filterBy_t *buildFilterBy(struct trackDb *tdb, struct cart *cart, struct asObject *as, char *filterName, char *name) /* Build a filterBy_t structure from a <column>FilterValues statement. */ { char *setting = trackDbSetting(tdb, filterName); char *value = cartUsualStringClosestToHome(cart, tdb, FALSE, filterName, setting); -char *field = cloneString(filterName); -int ix = strlen(field) - strlen(FILTER_VALUES_NAME); -assert(ix > 0); -field[ix] = '\0'; +char *field = extractFieldName(filterName, FILTER_VALUES_NAME); filterBy_t *filterBy; AllocVar(filterBy); filterBy->column = field; filterBy->title = field; /// title should come from AS file, or trackDb variable struct asColumn *asCol = asColumnFind(as, field); if (asCol != NULL) filterBy->title = asCol->comment; +else + errAbort("Building filter on field %s which is not in AS file.", field); filterBy->useIndex = FALSE; filterBy->slValues = slNameListFromCommaEscaped(value); chopUpValues(filterBy); if (cart != NULL) { char suffix[256]; safef(suffix, sizeof(suffix), "%s.%s", "filterBy", filterBy->column); boolean parentLevel = isNameAtParentLevel(tdb,tdb->track); if (cartLookUpVariableClosestToHome(cart,tdb,parentLevel,suffix,&(filterBy->htmlName))) { filterBy->slChoices = cartOptionalSlNameList(cart,filterBy->htmlName); freeMem(filterBy->htmlName); } } @@ -5872,56 +5885,55 @@ if (!isHubTrack(db)) conn = hAllocConnTrack(db, tdb); struct asObject *as = asForTdb(conn, tdb); hFreeConn(&conn); #endif///ndef EXTRA_FIELDS_SUPPORT while ((filter = slPopHead(&filterSettings)) != NULL) { if (differentString(filter->name,NO_SCORE_FILTER)) { // Determine floating point or integer char *setting = trackDbSetting(tdb, filter->name); boolean isFloat = (strchr(setting,'.') != NULL); char *scoreName = cloneString(filter->name); - char *field = filter->name; // No need to clone: will be thrown away at end of cycle - int ix = strlen(field) - strlen(FILTER_NUMBER_NAME); - assert(ix > 0); - field[ix] = '\0'; + char *field = extractFieldName(filter->name, FILTER_NUMBER_NAME); #ifdef EXTRA_FIELDS_SUPPORT if (extras != NULL) { struct extraField *extra = extraFieldsFind(extras, field); if (extra != NULL) { // Found label so replace field field = extra->label; if (!isFloat) isFloat = (extra->type == ftFloat); } } #else///ifndef EXTRA_FIELDS_SUPPORT if (as != NULL) { struct asColumn *asCol = asColumnFind(as, field); if (asCol != NULL) { // Found label so replace field field = asCol->comment; if (!isFloat) isFloat = asTypesIsFloating(asCol->lowType->type); } + else + errAbort("Building filter on field %s which is not in AS file.", field); } #endif///ndef EXTRA_FIELDS_SUPPORT // FIXME: Label munging should be localized to showScoreFilter() // when that function is simplified char varName[256]; char label[128]; safef(varName, sizeof(varName), "%s%s", scoreName, _BY_RANGE); boolean filterByRange = trackDbSettingClosestToHomeOn(tdb, varName); safef(label, sizeof(label),"%s%s", filterByRange ? "": "Minimum ", field); showScoreFilter(cart,tdb,opened,boxed,parentLevel,name,title,label,scoreName,isFloat); freeMem(scoreName); count++; } slNameFree(&filter); @@ -5972,38 +5984,42 @@ return TRUE; } if (!blocked) // scoreFilter is implicit unless NO_SCORE_FILTER return TRUE; return FALSE; } void textFiltersShowAll(char *db, struct cart *cart, struct trackDb *tdb) /* Show all the text filters for this track. */ { struct slName *filter, *filterSettings = trackDbSettingsWildMatch(tdb, FILTER_TEXT_WILDCARD); if (filterSettings) { + struct sqlConnection *conn = NULL; + if (!isHubTrack(db)) + conn = hAllocConnTrack(db, tdb); while ((filter = slPopHead(&filterSettings)) != NULL) { char *setting = trackDbSetting(tdb, filter->name); char *value = cartUsualStringClosestToHome(cart, tdb, FALSE, filter->name, setting); - char *field = cloneString(filter->name); - int ix = strlen(field) - strlen(FILTER_TEXT_NAME); - assert(ix > 0); - field[ix] = '\0'; + char *field = extractFieldName(filter->name, FILTER_TEXT_NAME); + struct asObject *as = asForTdb(conn, tdb); + struct asColumn *asCol = asColumnFind(as, field); + if (asCol == NULL) + errAbort("Building filter on field %s which is not in AS file.", field); printf("<P><B>Filter items in '%s' field: ", field); char cgiVar[128]; safef(cgiVar,sizeof(cgiVar),"%s.%s",tdb->track,filter->name); cgiMakeTextVar(cgiVar, value, 45); char settingString[4096]; safef(settingString, sizeof settingString, "%s%s", field, FILTER_TYPE_NAME); setting = cartOrTdbString(cart, tdb, settingString, FILTERTEXT_WILDCARD); safef(cgiVar,sizeof(cgiVar),"%s.%s",tdb->track,settingString); printf(" using "); printf("<SELECT name='%s'> ", cgiVar); printf("<OPTION %s>%s</OPTION>", sameString(setting, FILTERTEXT_WILDCARD) ? "SELECTED" : "", FILTERTEXT_WILDCARD ); printf("<OPTION %s>%s</OPTION>", sameString(setting, FILTERTEXT_REGEXP) ? "SELECTED" : "", FILTERTEXT_REGEXP );