0a456bff8d6200e3bda8bc9f73cfd5d75f135f73
max
  Tue Apr 30 15:23:37 2013 -0700
filters work on main table now if table is in new format, added publisher filter
diff --git src/hg/hgTracks/pubsTracks.c src/hg/hgTracks/pubsTracks.c
index 44ead49..ec05414 100644
--- src/hg/hgTracks/pubsTracks.c
+++ src/hg/hgTracks/pubsTracks.c
@@ -201,100 +201,135 @@
 /* add authorYear and title to linkedFeatures->extra */
 {
 char *articleTable = trackDbSettingClosestToHome(tg->tdb, "pubsArticleTable");
 if(isEmpty(articleTable))
     return;
 if (lf->extra != NULL) {
     return;
     }
 
 struct sqlConnection *conn = hAllocConn(database);
 struct pubsExtra* extra = pubsMakeExtra(tg, articleTable, conn, lf);
 lf->extra = extra;
 hFreeConn(&conn);
 }
 
+static void dyStringPrintfWithSep(struct dyString *ds, char* sep, char *format, ...)
+/*  Printf to end of dyString. Prefix with sep if dyString is not empty. */
+{
+if (ds->stringSize!=0)
+    dyStringAppend(ds, sep);
+va_list args;
+va_start(args, format);
+dyStringVaPrintf(ds, format, args);
+va_end(args);
+}
+
 static void pubsLoadKeywordYearItems(struct track *tg)
 /* load items that fulfill keyword and year filter */
 {
 pubsParseClassColors();
 struct sqlConnection *conn = hAllocConn(database);
-char *keywords = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsKeywords");
-char *yearFilter = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsYear");
+char *keywords = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsFilterKeywords");
+char *yearFilter = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsFilterYear");
+char *publFilter = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsFilterPublisher");
 char *articleTable = pubsArticleTable(tg);
 
 if(yearFilter == NULL || sameWord(yearFilter, "anytime"))
     yearFilter = NULL;
 
 if(isNotEmpty(keywords))
     keywords = makeMysqlMatchStr(sqlEscapeString(keywords));
 
 if(isEmpty(yearFilter) && isEmpty(keywords))
 {
     loadGappedBed(tg);
 }
 else
     {
     char* oldLabel = tg->longLabel;
     tg->longLabel = catTwoStrings(oldLabel, " (filter activated)");
     freeMem(oldLabel);
 
-    char extra[2048], yearWhere[256], keywordsWhere[1024], prefix[256];
+    char yearWhere[256], keywordsWhere[1024], prefix[256];
     char **row;
     struct linkedFeatures *lfList = NULL;
     struct trackDb *tdb = tg->tdb;
     int scoreMin = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMin", "0"));
     int scoreMax = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMax", "1000"));
     boolean useItemRgb = bedItemRgb(tdb);
 
+    char *extra;
+    struct dyString *extraDy = dyStringNew(0);
+    if (sqlColumnExists(conn, tg->table, "year"))
+        // new table schema: filter fields are on main bed table
+        {
+        if (isNotEmpty(keywords))
+            dyStringPrintf(extraDy, "name IN (SELECT articleId FROM %s WHERE " 
+                "MATCH (citation, title, authors, abstract) AGAINST ('%s' IN BOOLEAN MODE))",
+                articleTable, keywords);
+        if (isNotEmpty(yearFilter))
+            dyStringPrintfWithSep(extraDy, " AND ", " year >= '%s'", sqlEscapeString(yearFilter));
+        if (isNotEmpty(publFilter))
+            dyStringPrintfWithSep(extraDy, " AND ", " publisher = '%s'", sqlEscapeString(publFilter));
+        extra = extraDy->string;
+        }
+    else
+        // old table schema, filter by doing a join on article table
+        {
+        char extraTmp[4096];
     safef(prefix, sizeof(prefix),  "name IN (SELECT articleId FROM %s WHERE", articleTable);
     if(isNotEmpty(keywords))
         safef(keywordsWhere, sizeof(keywordsWhere), \
         "MATCH (citation, title, authors, abstract) AGAINST ('%s' IN BOOLEAN MODE)", keywords);
     if(isNotEmpty(yearFilter))
         safef(yearWhere, sizeof(yearWhere), "year >= '%s'", sqlEscapeString(yearFilter));
 
     if(isEmpty(keywords))
-        safef(extra, sizeof(extra), "%s %s)", prefix, yearWhere);
+            safef(extraTmp, sizeof(extraTmp), "%s %s)", prefix, yearWhere);
     else if(isEmpty(yearFilter))
-        safef(extra, sizeof(extra), "%s %s)", prefix, keywordsWhere);
+            safef(extraTmp, sizeof(extraTmp), "%s %s)", prefix, keywordsWhere);
     else
-        safef(extra, sizeof(extra), "%s %s AND %s)", prefix, yearWhere, keywordsWhere);
+            safef(extraTmp, sizeof(extraTmp), "%s %s AND %s)", prefix, yearWhere, keywordsWhere);
+        extra = extraTmp;
+        }
 
     int rowOffset = 0;
     struct sqlResult *sr = hExtendedRangeQuery(conn, tg->table, chromName, winStart, winEnd, extra,
                                                FALSE, NULL, &rowOffset);
+    freeDyString(&extraDy);
+
     while ((row = sqlNextRow(sr)) != NULL)
 	{
         struct bed *bed = bedLoad12(row+rowOffset);
         slAddHead(&lfList, bedMungToLinkedFeatures(&bed, tdb, 12, scoreMin, scoreMax, useItemRgb));
         }
     sqlFreeResult(&sr);
     slReverse(&lfList);
     slSort(&lfList, linkedFeaturesCmp);
     tg->items = lfList;
     }
 hFreeConn(&conn);
 }
 
 #define PUBSFILTERNAME "pubsFilterArticleId"
 
 static void activatePslTrackIfCgi(struct track *tg)
 /* the publications hgc creates links back to the browser with 
  * the cgi param pubsFilterArticleId to show only a single type
  * of feature for the pubsBlatPsl track. 
- * If the parameter was supplied, we save this parameter here
+ * If the parameter was supplied, we save it here 
  * into the cart and activate the track.
  */
 {
 char *articleId = cgiOptionalString(PUBSFILTERNAME);
 //if (articleId==NULL) 
     //articleId = cartOptionalString(cart, PUBSFILTERNAME);
 
 if (articleId!=NULL) 
 {
     cartSetString(cart, PUBSFILTERNAME, articleId);
     tdbSetCartVisibility(tg->tdb, cart, hCarefulTrackOpenVis(database, tg->track));
     tg->visibility=tvPack;
 }
 }