ab553b2a1e248cdc8108d39f5e2a8d859216f15b hiram Tue Sep 17 14:21:12 2019 -0700 fix list chromosomes function for bigDataUrl tracks on database genomes refs #23589 diff --git src/hg/hubApi/list.c src/hg/hubApi/list.c index 2f588b1..a5b1047 100644 --- src/hg/hubApi/list.c +++ src/hg/hubApi/list.c @@ -102,30 +102,47 @@ char **columnNames = NULL; char **columnTypes = NULL; int *jsonTypes = NULL; int columnCount = tableColumns(conn, "dbDb", &columnNames, &columnTypes, &jsonTypes); jsonWriteObjectStart(jw, "ucscGenomes"); for ( el=dbList; el != NULL; el = el->next ) { dbDbJsonData(jw, el, columnCount, columnNames); } jsonWriteObjectEnd(jw); apiFinishOutput(0, NULL, jw); hDisconnectCentral(&conn); } +static void bigFileChromInfoOutput(struct jsonWrite *jw, + struct trackDb *thisTrack, char *bigDataUrl) +/* output the chromosome list for the bigDataUrl file */ +{ +struct bbiFile *bbi = bigFileOpen(thisTrack->type, bigDataUrl); +struct bbiChromInfo *chrList = bbiChromList(bbi); +slSort(chrList, chromInfoCmp); +struct bbiChromInfo *el = chrList; +jsonWriteNumber(jw, "chromCount", (long long)slCount(chrList)); +jsonWriteObjectStart(jw, "chromosomes"); +for ( ; el; el = el->next ) + { + jsonWriteNumber(jw, el->name, (long long)el->size); + } +jsonWriteObjectEnd(jw); /* chromosomes */ +} + static void hubChromInfoJsonOutput(FILE *f, char *hubUrl, char *genome) /* for given hubUrl list the chromosomes in the sequence for specified genome */ { struct trackHub *hub = errCatchTrackHubOpen(hubUrl); struct trackHubGenome *ge = NULL; char *track = cgiOptionalString("track"); if (isEmpty(genome)) apiErrAbort(err400, err400Msg, "must specify a 'genome=name' with hubUrl for endpoint: /list/chromosomes?hubUrl=%s;genome=<empty>", hubUrl); struct trackHubGenome *foundGenome = NULL; for (ge = hub->genomeList; ge; ge = ge->next) { @@ -142,41 +159,31 @@ struct jsonWrite *jw = apiStartOutput(); jsonWriteString(jw, "hubUrl", hubUrl); jsonWriteString(jw, "genome", genome); if (isNotEmpty(track)) { jsonWriteString(jw, "track", track); struct trackDb *tdb = obtainTdb(foundGenome, NULL); if (NULL == tdb) apiErrAbort(err400, err400Msg, "failed to find a track hub definition in genome=%s for endpoint '/list/chromosomes' given hubUrl=%s'", genome, hubUrl); struct trackDb *thisTrack = findTrackDb(track, tdb); if (NULL == thisTrack) apiErrAbort(err400, err400Msg, "failed to find specified track=%s in genome=%s for endpoint '/list/chromosomes' given hubUrl='%s'", track, genome, hubUrl); char *bigDataUrl = trackDbSetting(thisTrack, "bigDataUrl"); - struct bbiFile *bbi = bigFileOpen(thisTrack->type, bigDataUrl); - struct bbiChromInfo *chrList = bbiChromList(bbi); - slSort(chrList, chromInfoCmp); - struct bbiChromInfo *el = chrList; - jsonWriteNumber(jw, "chromCount", (long long)slCount(chrList)); - jsonWriteObjectStart(jw, "chromosomes"); - for ( ; el; el = el->next ) - { - jsonWriteNumber(jw, el->name, (long long)el->size); - } - jsonWriteObjectEnd(jw); /* chromosomes */ + bigFileChromInfoOutput(jw, thisTrack, bigDataUrl); } else { struct chromInfo *ci = NULL; /* might be a track hub on a UCSC database */ if (isEmpty(foundGenome->twoBitPath)) { struct sqlConnection *conn = hAllocConnMaybe(foundGenome->trackHub->defaultDb); if (NULL == conn) apiErrAbort(err400, err400Msg, "can not find 'genome=%s' for endpoint '/list/chromosomes", foundGenome->trackHub->defaultDb); else hFreeConn(&conn); ci = createChromInfoList(NULL, foundGenome->trackHub->defaultDb); } else @@ -233,40 +240,42 @@ /* check if table name needs to be modified */ if (hti && hti->isSplit) { char *defaultChrom = hDefaultChrom(db); char fullTableName[256]; safef(fullTableName, sizeof(fullTableName), "%s_%s", defaultChrom, hti->rootName); freeMem(sqlTableName); sqlTableName = cloneString(fullTableName); *splitTableName = cloneString(fullTableName); /* return to caller */ } else { *splitTableName = sqlTableName; /* return to caller */ } +if (! sqlTableExists(conn, sqlTableName)) + returnChrom = NULL; /* may need to extend this in the future for other track types */ -if (sqlColumnExists(conn, sqlTableName, "chrom")) /* standard bed tables */ +else if (sqlColumnExists(conn, sqlTableName, "chrom")) /* standard bed tables */ returnChrom = cloneString("chrom"); else if (sqlColumnExists(conn, sqlTableName, "tName")) /* track type psl */ returnChrom = cloneString("tName"); else if (sqlColumnExists(conn, sqlTableName, "genoName")) /* track type rmsk */ returnChrom = cloneString("genoName"); return returnChrom; -} +} /* static char *validChromName() */ static long long bbiItemCount(char *bigDataUrl, char *type, char *indexFileOrUrl) /* check the bigDataUrl to see what the itemCount is there */ { long long itemCount = 0; struct errCatch *errCatch = errCatchNew(); if (errCatchStart(errCatch)) { if (allowedBigBedType(type)) { struct bbiFile *bbi = NULL; bbi = bigBedFileOpen(bigDataUrl); itemCount = bigBedItemCount(bbi); bbiFileClose(&bbi); } @@ -532,37 +541,49 @@ outputTrackDbVars(jw, thisTrack, itemCount); apiFinishOutput(0, NULL, jw); } /* static void schemaJsonOutput(FILE *f, char *db, char *track) */ static void chromInfoJsonOutput(FILE *f, char *db) /* for given db, if there is a track, list the chromosomes in that track, * for no track, simply list the chromosomes in the sequence */ { char *splitSqlTable = NULL; struct hTableInfo *tableInfo = NULL; char *chromName = NULL; char *table = cgiOptionalString("track"); +char *bigDataUrl = NULL; +struct trackDb *thisTrack = NULL; struct sqlConnection *conn = hAllocConnMaybe(db); if (NULL == conn) apiErrAbort(err400, err400Msg, "can not find 'genome=%s' for endpoint '/list/chromosomes", db); if (table) chromName = validChromName(conn, db, table, &splitSqlTable, &tableInfo); +/* given track can't find a chromName, maybe it is a bigDataUrl */ +if (table && ! chromName) + { + /* 'track' name in trackDb usually refers to a SQL 'table' */ + struct trackDb *tdb = obtainTdb(NULL, db); + thisTrack = findTrackDb(table,tdb); + /* might have a bigDataUrl */ + bigDataUrl = trackDbSetting(thisTrack, "bigDataUrl"); + } + /* in trackDb language: track == table */ /* punting on split tables, just return chromInfo */ if (table && chromName && ! (tableInfo && tableInfo->isSplit) ) { if (! sqlTableExists(conn, splitSqlTable)) apiErrAbort(err400, err400Msg, "can not find specified 'track=%s' for endpoint: /list/chromosomes?genome=%s;track=%s", table, db, table); if (sqlColumnExists(conn, splitSqlTable, chromName)) { char *dataTime = sqlTableUpdate(conn, splitSqlTable); time_t dataTimeStamp = sqlDateToUnixTime(dataTime); replaceChar(dataTime, ' ', 'T'); /* ISO 8601 */ struct jsonWrite *jw = apiStartOutput(); jsonWriteString(jw, "genome", db); jsonWriteString(jw, "track", table); @@ -581,30 +602,39 @@ } sqlFreeResult(&sr); slPairIntSort(&list); slReverse(&list); jsonWriteNumber(jw, "chromCount", (long long)slCount(list)); jsonWriteObjectStart(jw, "chromosomes"); struct slPair *el = list; for ( ; el != NULL; el = el->next ) jsonWriteNumber(jw, el->name, (long long)ptToInt(el->val)); jsonWriteObjectEnd(jw); /* chromosomes */ apiFinishOutput(0, NULL, jw); } else apiErrAbort(err400, err400Msg, "track '%s' is not a position track, request table without chrom specification, genome: '%s'", table, db); } +else if (bigDataUrl) + { + struct jsonWrite *jw = apiStartOutput(); + jsonWriteString(jw, "genome", db); + jsonWriteString(jw, "track", table); + jsonWriteString(jw, "bigDataUrl", bigDataUrl); + bigFileChromInfoOutput(jw, thisTrack, bigDataUrl); + apiFinishOutput(0, NULL, jw); + } else if (table && !chromName) /* only allowing position tables at this time */ apiErrAbort(err400, err400Msg, "track '%s' is not a position track, request table without chrom specification, genome: '%s'", table, db); else { char *dataTime = sqlTableUpdate(conn, "chromInfo"); time_t dataTimeStamp = sqlDateToUnixTime(dataTime); replaceChar(dataTime, ' ', 'T'); /* ISO 8601 */ struct chromInfo *ciList = createChromInfoList(NULL, db); slSort(ciList, chromInfoCmp); struct chromInfo *el = ciList; struct jsonWrite *jw = apiStartOutput(); jsonWriteString(jw, "genome", db); jsonWriteString(jw, "dataTime", dataTime); if (tableInfo && tableInfo->isSplit) /* the split table punt */ jsonWriteString(jw, "track", table);