06d7be056190c14b85e71bc12523f18ea6815b5e markd Mon Dec 7 00:50:29 2020 -0800 BLAT mmap index support merge with master diff --git src/hg/lib/hui.c src/hg/lib/hui.c index 0794478..fad4bc0 100644 --- src/hg/lib/hui.c +++ src/hg/lib/hui.c @@ -9240,39 +9240,39 @@ { timep = bbiUpdateTime(bbi); bbiFileClose(&bbi); } printBbiUpdateTime(&timep); } else { tableName = hTableForTrack(database, tdb->table); conn = hAllocConnTrack(database, tdb); } if (tableName) { char *date = firstWordInLine(sqlTableUpdate(conn, tableName)); if (date != NULL) - printf("<B>Data last updated: </B>%s<BR>\n", date); + printf("<B>Data last updated at UCSC: </B>%s<BR>\n", date); } hFreeConn(&conn); } void printBbiUpdateTime(time_t *timep) /* for bbi files, print out the timep value */ { - printf("<B>Data last updated: </B>%s<BR>\n", sqlUnixTimeToDate(timep, FALSE)); + printf("<B>Data last updated at UCSC: </B>%s<BR>\n", sqlUnixTimeToDate(timep, FALSE)); } static boolean tableDescriptionsExists(struct sqlConnection *conn) /* Cache flag for whether tableDescriptions exists in conn, in case we will need to * fetch a lot of descriptions from tableDescriptions. */ { static struct hash *hash = NULL; if (hash == NULL) hash = hashNew(0); char *db = sqlGetDatabase(conn); int exists = hashIntValDefault(hash, db, -1); if (exists < 0) { exists = sqlTableExists(conn, "tableDescriptions"); hashAddInt(hash, db, exists); @@ -9401,39 +9401,56 @@ return list; } static struct dyString *subMultiField(char *pattern, int fieldCount, char *in[], char *out[]) /* Substitute $in with out values in pattern */ { int i; struct dyString *s = newDyString(256), *d = NULL; dyStringAppend(s, pattern); for (i=0; i<fieldCount; ++i) { if (out[i]==NULL) continue; - // prefix field with $ + // If a field is a prefix or suffix to another field, for example 'chrom' and 'chromStart' + // we don't want to erroneously sub out the 'chrom' in 'chromStart'. Allow the wrapping + // protected fields in ${} to prevent the substitution: char *field = in[i]; - char *spec = needMem(strlen(field) + 2); + int fieldLen = strlen(field); + char *spec = needMem(fieldLen + 2); + char *strictSpec = needMem(fieldLen + 4); *spec = '$'; + *strictSpec = '$'; + strictSpec[1] = '{'; strcpy(spec + 1, field); + strcpy(strictSpec + 2, field); + strictSpec[fieldLen + 2] = '}'; + strictSpec[fieldLen + 3] = '\0'; + if (stringIn(strictSpec, s->string)) + { + d = dyStringSub(s->string, strictSpec, out[i]); + s = d; + } + // the user may have both a ${} enclosed instance and a non-enclosed one! d = dyStringSub(s->string, spec, out[i]); + dyStringFree(&s); freeMem(spec); + freeMem(strictSpec); s = d; d = NULL; } return s; } char *replaceFieldInPattern(char *pattern, int fieldCount, char **fieldNames, char **fieldVals) /* Replace $fieldName in pattern with value. Used in trackDb mouseOver setting */ { struct dyString *ds = subMultiField(pattern, fieldCount, fieldNames, fieldVals); return dyStringCannibalize(&ds); } static struct dyString *subMulti(char *orig, int subCount, char *in[], char *out[]) @@ -9452,32 +9469,32 @@ dyStringFree(&s); s = d; d = NULL; } return s; } char *replaceInUrl(char *url, char *idInUrl, struct cart *cart, char *db, char *seqName, int winStart, int winEnd, char *track, boolean encode, struct slPair *fields) /* replace $$ in url with idInUrl. Supports many other wildchards, and custom fields $<field> * XX Do we have readable docs for these parameters somewhere? * Look at http://genome.ucsc.edu/goldenpath/help/trackDb/trackDbHub.html */ { struct dyString *uUrl = NULL; struct dyString *eUrl = NULL; -char startString[64], endString[64]; -char *ins[13], *outs[13]; +char startString[64], endString[64],oneBasedStart[64]; +char *ins[14], *outs[14]; char *eItem = (encode ? cgiEncode(idInUrl) : cloneString(idInUrl)); char *scName = NULL; // try to avoid the mysql query it not necessary if (stringIn("$n", url)) { char *tmp = hScientificName(db); scName = replaceChars(tmp, " ", "_"); freeMem(tmp); } char *taxId = NULL; // try to avoid the mysql query it not necessary if (stringIn("$taxId", url)) { @@ -9516,41 +9533,46 @@ if (nextColon) /* terminate suffixClone suffix */ *nextColon = '\0'; /* when next colon is present */ *suffix = '\0'; /* terminate itemClone prefix */ outs[7] = itemClone; outs[8] = suffixClone; /* small memory leak here for these cloned strings */ /* not important for a one-time operation in a CGI that will exit */ } else { outs[7] = idInUrl; /* otherwise, these are not expected */ outs[8] = idInUrl; /* to be used */ } // URL may now contain item boundaries ins[9] = "${"; ins[10] = "$}"; +ins[13] = "$#"; if (cart!=NULL && cartOptionalString(cart, "o") && cartOptionalString(cart, "t")) { char *itemBeg = cartString(cart, "o"); // unexpected commas? char *itemEnd = cartString(cart, "t"); outs[9] = itemBeg; outs[10] = itemEnd; + safef(oneBasedStart, sizeof(oneBasedStart), "%d", cartInt(cart, "o") + 1); + outs[13] = oneBasedStart; } else // should never be but I am unwilling to bet the farm { outs[9] = startString; outs[10] = endString; + safef(oneBasedStart, sizeof(oneBasedStart), "%d", winStart + 1); + outs[13] = oneBasedStart; } ins[11] = "$n"; outs[11] = scName; ins[12] = "$taxId"; outs[12] = taxId; uUrl = subMulti(url, ArraySize(ins), ins, outs); outs[0] = eItem; eUrl = subMulti(url, ArraySize(ins), ins, outs); freeDyString(&uUrl); freeMem(eItem); freeMem(scName); @@ -9609,31 +9631,31 @@ { char *version = checkDataVersion(database, tdb); if (version == NULL) { // try the hgFixed.trackVersion table struct trackVersion *trackVersion = getTrackVersion(database, tdb->track); // try trackVersion table with parent, for composites/superTracks if (trackVersion == NULL && tdb->parent != NULL) trackVersion = getTrackVersion(database, tdb->parent->track); if (trackVersion != NULL) version = trackVersion->version; } if (isNotEmpty(version)) - printf("<B>Data version:</B> %s <BR>\n", version); + printf("<B>Source data version:</B> %s <BR>\n", version); } void printRelatedTracks(char *database, struct hash *trackHash, struct trackDb *tdb, struct cart *cart) /* Maybe print a "related track" section */ { if (!cfgOption("db.relatedTrack") || trackHubDatabase(database)) return; char *relatedTrackTable = cfgOptionDefault("db.relatedTrack","relatedTrack"); struct sqlConnection *conn = hAllocConn(database); if (!sqlTableExists(conn, relatedTrackTable)) { hFreeConn(&conn); return; }