9956f8a4abe10ace2c6da838141fe71112761bd6
max
  Tue Jun 18 11:11:16 2013 -0700
fixed performance bug #6833, forgot to check for dense mode
diff --git src/hg/hgTracks/pubsTracks.c src/hg/hgTracks/pubsTracks.c
index 0d678a1..893bfbf 100644
--- src/hg/hgTracks/pubsTracks.c
+++ src/hg/hgTracks/pubsTracks.c
@@ -1,27 +1,33 @@
 /* pubsTracks - code for the publications tracks */
 #include "common.h"
 #include "hgTracks.h"
 #include "hgFind.h"
 #include "bedCart.h"
 
 // we distinguish between four levels of impact factors <1, <3, <10 and >10
 static struct rgbColor impact1Color  = {80, 80, 80};
 static struct rgbColor impact2Color  = {0, 80, 255};
 static struct rgbColor impact3Color  = {0, 100, 0};
 static struct rgbColor impact4Color  = {255, 255, 0};
 
+// the cgi can handle "old" or "new" table formats
+// seqTableFormat can be is either 0 (=uninitialized), 1 (=old) or 2(=new)
+int seqTableFormat = 0;
+#define SEQTABLE_NEW 1
+#define SEQTABLE_OLD 2
+
 static char *pubsArticleTable(struct track *tg)
 /* return the name of the pubs articleTable, either
  * the value from the trackDb statement 'articleTable'
  * or the default value: <trackName>Article */
 {
 char *articleTable = trackDbSettingClosestToHome(tg->tdb, "pubsArticleTable");
 if (isEmpty(articleTable))
     {
     char buf[256];
     safef(buf, sizeof(buf), "%sArticle", tg->track);
     articleTable = cloneString(buf);
     }
 return articleTable;
 }
 
@@ -95,78 +101,84 @@
 
 static char *pubsFeatureLabel(char *author, char *year) 
 /* create label <author><year> given authors and year strings */
 {
 char *authorYear = NULL;
 
 if (isEmpty(author))
     author = "NoAuthor";
 if (isEmpty(year))
     year = "NoYear";
 authorYear  = catTwoStrings(author, year);
 
 return authorYear;
 }
 
+static void setFormatFlag(struct sqlConnection* conn, char* tableName) 
+/* We support two different storage places for article data: either the bed table directly 
+ * includes the title + author of the article or we have to look it up from the articles 
+ * table. Having a copy of the title in the bed table is faster 
+ * This function sets the flag to indicate the version we have in our table.
+ * */
+{
+if (seqTableFormat!=0)
+    return;
+if (sqlColumnExists(conn, tableName, "title")) 
+    seqTableFormat = SEQTABLE_NEW;
+else
+    seqTableFormat = SEQTABLE_OLD;
+}
+
 static struct pubsExtra *pubsMakeExtra(struct track* tg, char *articleTable, 
     struct sqlConnection* conn, struct linkedFeatures* lf)
 /* bad solution: a function that is called before the extra field is 
  * accessed and that fills it from a sql query. Will need to redo this like gencode, 
  * drawing from atom, variome and bedLoadN or bedDetails */
 {
 char query[LARGEBUF];
 struct sqlResult *sr = NULL;
 char **row = NULL;
 struct pubsExtra *extra = NULL;
 
-/* support two different storage places for article data: either the bed table directly 
- * includes the title + author of the article or we have to look it up from the articles 
- * table. Having a copy of the title in the bed table is faster */
-bool newFormat = FALSE;
-if (sqlColumnExists(conn, tg->table, "title")) 
-    {
+setFormatFlag(conn, tg->table);
+if (seqTableFormat==SEQTABLE_NEW)
     sqlSafef(query, sizeof(query), "SELECT firstAuthor, year, title, impact, classes FROM %s "
     "WHERE chrom = '%s' and chromStart = '%d' and name='%s'", tg->table, chromName, lf->start, lf->name);
-    newFormat = TRUE;
-    }
 else 
-    {
     sqlSafef(query, sizeof(query), "SELECT firstAuthor, year, title FROM %s WHERE articleId = '%s'", 
         articleTable, lf->name);
-    newFormat = FALSE;
-    }
 
 sr = sqlGetResult(conn, query);
 if ((row = sqlNextRow(sr)) != NULL)
     {
     char *firstAuthor = row[0];
     char *year    = row[1];
     char *title   = row[2];
     char *impact  = NULL;
     char *classes = NULL;
 
 
     extra = needMem(sizeof(struct pubsExtra));
     extra->label = pubsFeatureLabel(firstAuthor, year);
     if (isEmpty(title))
         extra->mouseOver = extra->label;
     else
         extra->mouseOver = cloneString(title);
     extra->color  = NULL;
     extra->shade  = -1;
 
-    if (newFormat) 
+    if (seqTableFormat==SEQTABLE_NEW) 
         {
         impact  = row[3];
         classes = row[4];
         if (!isEmpty(impact)) 
             {
             char *colorBy = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsColorBy");
             if ((colorBy==NULL) || strcmp(colorBy,"topic")==0) 
                 {
                 char *classCopy = classes;
                 char *mainClass = cloneNextWordByDelimiter(&classes, ',');
                 classes = classCopy;
                 if (mainClass!=NULL)
                     {
                     struct rgbColor *col = (struct rgbColor*) hashFindVal(pubsClassColors, mainClass);
                     extra->color = col;
@@ -211,30 +223,36 @@
                     //extra->color = shadesOfGray[yearShade];
                     }
                 }
             }
         }
     }
 
 
 sqlFreeResult(&sr);
 return extra;
 }
 
 static void pubsAddExtra(struct track* tg, struct linkedFeatures* lf)
 /* add authorYear and title to linkedFeatures->extra */
 {
+// no extra field if we're in dense mode
+if (tg->limitedVis == tvDense) 
+    {
+    return;
+    }
+
 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 sqlDyStringPrintfWithSep(struct dyString *ds, char* sep, char *format, ...)
 /*  Printf to end of dyString. Prefix with sep if dyString is not empty. */
 {
@@ -263,30 +281,31 @@
 // convert list to hash
 struct hash *hashA = hashNew(0);
 struct slName *el;
 for (el = artIds; el != NULL; el = el->next)
     hashAddInt(hashA, el->name, 1);
 freeMem(keywords);
 slFreeList(artIds);
 return hashA;
 }
 
 static void pubsLoadKeywordYearItems(struct track *tg)
 /* load items that fulfill keyword and year filter */
 {
 pubsParseClassColors();
 struct sqlConnection *conn = hAllocConn(database);
+setFormatFlag(conn, tg->table);
 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(sameOk(yearFilter, "anytime"))
     yearFilter = NULL;
 if(sameOk(publFilter, "all"))
     publFilter = NULL;
 
 if(isNotEmpty(keywords))
     keywords = makeMysqlMatchStr(keywords);
 
 if (isEmpty(yearFilter) && isEmpty(keywords) && isEmpty(publFilter))
 {
@@ -298,31 +317,31 @@
     // without the keywords specified in hgTrackUi
     char *oldLabel = tg->longLabel;
     tg->longLabel = catTwoStrings(oldLabel, " (filter activated)");
     freeMem(oldLabel);
 
     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 = NULL;
     struct dyString *extraDy = dyStringNew(0);
     struct hash *articleIds = searchForKeywords(conn, articleTable, keywords);
-    if (sqlColumnExists(conn, tg->table, "year"))
+    if (seqTableFormat==SEQTABLE_NEW)
         // new table schema: filter fields are on main bed table
         {
         if (isNotEmpty(yearFilter))
             sqlDyStringPrintfWithSep(extraDy, " AND ", " year >= '%s'", yearFilter);
         if (isNotEmpty(publFilter))
             sqlDyStringPrintfWithSep(extraDy, " AND ", " publisher = '%s'", publFilter);
         }
     else
         // old table schema, filter by doing a join on article table
         {
         if(isNotEmpty(yearFilter))
             sqlDyStringPrintfFrag(extraDy, "name IN (SELECT articleId FROM %s WHERE year>='%s')", articleTable, \
                 yearFilter);
         }