a3801c8acc3bee5d65e260dcd842d615be11b3a6 hiram Wed Sep 4 10:18:46 2019 -0700 list schema needs to handle big* files correctly refs #23589 diff --git src/hg/hubApi/list.c src/hg/hubApi/list.c index f3e51cb..2f588b1 100644 --- src/hg/hubApi/list.c +++ src/hg/hubApi/list.c @@ -395,100 +395,153 @@ struct sqlConnection *conn = hAllocConnMaybe(db); if (NULL == conn) apiErrAbort(err400, err400Msg, "can not find 'genome=%s' for endpoint '/list/schema", db); struct trackDb *tdb = obtainTdb(NULL, db); struct trackDb *thisTrack = findTrackDb(track, tdb); if (NULL == thisTrack) /* OK to work with tables without trackDb definitions */ { if (! sqlTableExists(conn, track)) apiErrAbort(err400, err400Msg, "failed to find specified track=%s in genome=%s for endpoint '/list/schema'", track, db); } if (trackHasNoData(thisTrack)) apiErrAbort(err400, err400Msg, "container track '%s' does not contain data, use the children of this container for data access", track); +/* might be a table that points to a big* file + * or is just a bigDataUrl without any table + */ +char *bigDataUrl = trackDbSetting(thisTrack, "bigDataUrl"); + char *sqlTableName = cloneString(track); /* the trackDb might have a specific table defined instead */ char *tableName = trackDbSetting(thisTrack, "table"); if (isNotEmpty(tableName)) { freeMem(sqlTableName); sqlTableName = cloneString(tableName); } /* this function knows how to deal with split chromosomes, the NULL * here for the chrom name means to use the first chrom name in chromInfo */ struct hTableInfo *hti = hFindTableInfoWithConn(conn, NULL, sqlTableName); /* check if table name needs to be modified */ char *splitTableName = NULL; 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); } else { splitTableName = sqlTableName; } -char **columnNames = NULL; -char **columnTypes = NULL; -int *jsonTypes = NULL; -int columnCount = tableColumns(conn, splitTableName, &columnNames, &columnTypes, &jsonTypes); -struct asObject *as = asForTable(conn, splitTableName, thisTrack); -struct asColumn *columnEl = as->columnList; -int asColumnCount = slCount(columnEl); +struct bbiFile *bbi = NULL; +if (thisTrack && startsWith("big", thisTrack->type)) + { + if (bigDataUrl) + bbi = bigFileOpen(thisTrack->type, bigDataUrl); + else + { + char query[4096]; + char quickReturn[2048]; + sqlSafef(query, sizeof(query), "select fileName from %s", splitTableName); + if (sqlQuickQuery(conn, query, quickReturn, sizeof(quickReturn))) + { + bigDataUrl = hReplaceGbdb(cloneString(quickReturn)); + bbi = bigFileOpen(thisTrack->type, bigDataUrl); + } + } + if (NULL == bbi) + apiErrAbort(err400, err400Msg, "failed to find bigDataUrl=%s for track=%s in database=%s for endpoint '/getData/schema'", bigDataUrl, track, db); + } char *dataTime = sqlTableUpdate(conn, splitTableName); time_t dataTimeStamp = sqlDateToUnixTime(dataTime); replaceChar(dataTime, ' ', 'T'); /* ISO 8601 */ struct jsonWrite *jw = apiStartOutput(); jsonWriteString(jw, "genome", db); jsonWriteString(jw, "track", track); jsonWriteString(jw, "dataTime", dataTime); jsonWriteNumber(jw, "dataTimeStamp", (long long)dataTimeStamp); freeMem(dataTime); +char **columnNames = NULL; +char **columnTypes = NULL; +int *jsonTypes = NULL; +int columnCount = 0; +struct asObject *as = NULL; +struct asColumn *columnEl = NULL; +int asColumnCount = 0; long long itemCount = 0; + +if (bbi) + { + /* do not show itemCount for protected data */ + if (! trackDbSetting(thisTrack, "tableBrowser")) + { + char *indexFileOrUrl = hReplaceGbdb(trackDbSetting(thisTrack, "bigDataIndex")); + itemCount = bbiItemCount(bigDataUrl, thisTrack->type, indexFileOrUrl); + } + if (startsWith("bigWig", thisTrack->type)) + { + wigColumnTypes(jw); + } + else + { + as = bigBedAsOrDefault(bbi); + struct sqlFieldType *fiList = sqlFieldTypesFromAs(as); + bigColumnTypes(jw, fiList, as); + } + } +else + { + columnCount = tableColumns(conn, splitTableName, &columnNames, &columnTypes, &jsonTypes); + as = asForTable(conn, splitTableName, thisTrack); + columnEl = as->columnList; + asColumnCount = slCount(columnEl); + /* do not show counts for protected data */ if (! trackDbSetting(thisTrack, "tableBrowser")) { char query[2048]; sqlSafef(query, sizeof(query), "select count(*) from %s", splitTableName); if (hti && hti->isSplit) /* punting on split table item count */ itemCount = 0; else { itemCount = sqlQuickNum(conn, query); } } hFreeConn(&conn); -outputTrackDbVars(jw, thisTrack, itemCount); if (hti && (hti->isSplit || debug)) jsonWriteBoolean(jw, "splitTable", hti->isSplit); outputSchema(thisTrack, jw, columnNames, columnTypes, jsonTypes, hti, columnCount, asColumnCount, columnEl); + } + +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"); struct sqlConnection *conn = hAllocConnMaybe(db);