8b4f30c62401568eb2b560d42a145418f44968fe hiram Thu Apr 18 15:46:50 2019 -0700 objects for tableColumns information refs #18869 diff --git src/hg/hubApi/getData.c src/hg/hubApi/getData.c index d45f568..90a2fc1 100644 --- src/hg/hubApi/getData.c +++ src/hg/hubApi/getData.c @@ -45,33 +45,52 @@ int jsonType) /* output a json item, determine type, appropriate output, name can be NULL */ { if (JSON_DOUBLE == jsonType) jsonWriteDouble(jw, name, sqlDouble(val)); else if (JSON_NUMBER == jsonType) jsonWriteNumber(jw, name, sqlLongLong(val)); else jsonWriteString(jw, name, val); } static void wigColumnTypes(struct jsonWrite *jw) /* output column headers for a wiggle data output schema */ { jsonWriteListStart(jw, "columnTypes"); -jsonWriteString(jw, NULL, "start - int - number"); -jsonWriteString(jw, NULL, "end - int - number"); -jsonWriteString(jw, NULL, "value - float - number"); + +jsonWriteObjectStart(jw, NULL); +jsonWriteString(jw, "name", "start"); +jsonWriteString(jw, "sqlType", "int"); +jsonWriteString(jw, "jsonType", "number"); +jsonWriteString(jw, "description", "chromStart: 0-based chromosome start position"); +jsonWriteObjectEnd(jw); + +jsonWriteObjectStart(jw, NULL); +jsonWriteString(jw, "name", "end"); +jsonWriteString(jw, "sqlType", "int"); +jsonWriteString(jw, "jsonType", "number"); +jsonWriteString(jw, "description", "chromEnd: 1-based chromosome end position"); +jsonWriteObjectEnd(jw); + +jsonWriteObjectStart(jw, NULL); +jsonWriteString(jw, "name", "value"); +jsonWriteString(jw, "sqlType", "float"); +jsonWriteString(jw, "jsonType", "number"); +jsonWriteString(jw, "description", "numerical data value for this location:start-end"); +jsonWriteObjectEnd(jw); + jsonWriteListEnd(jw); } /* static void wigColumnTypes(struct jsonWrite jw) */ static unsigned sqlQueryJsonOutput(struct sqlConnection *conn, struct jsonWrite *jw, char *query, int columnCount, char **columnNames, int *jsonTypes, unsigned itemsDone) /* with the SQL query set up, run through those selected items */ { struct sqlResult *sr = sqlGetResult(conn, query); char **row = NULL; unsigned itemCount = 0; while ((itemCount+itemsDone) < maxItemsOutput && (row = sqlNextRow(sr)) != NULL) { int i = 0; if (jsonOutputArrays) @@ -117,38 +136,38 @@ char *tableName = trackDbSetting(tdb, "table"); if (isNotEmpty(tableName)) { freeMem(sqlTable); sqlTable = cloneString(tableName); jsonWriteString(jw, "sqlTable", sqlTable); } /* to be determined if this name is used or changes */ char *splitSqlTable = cloneString(sqlTable); /* 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, sqlTable); -if (debug) +if (debug && hti) { jsonWriteBoolean(jw, "isPos", hti->isPos); jsonWriteBoolean(jw, "isSplit", hti->isSplit); jsonWriteBoolean(jw, "hasBin", hti->hasBin); } /* check if table name needs to be modified */ -if (hti->isSplit) +if (hti && hti->isSplit) { if (isNotEmpty(chrom)) { char fullTableName[256]; safef(fullTableName, sizeof(fullTableName), "%s_%s", chrom, hti->rootName); freeMem(splitSqlTable); splitSqlTable = cloneString(fullTableName); if (debug) jsonWriteString(jw, "splitSqlTable", splitSqlTable); } else { char *defaultChrom = hDefaultChrom(db); char fullTableName[256]; safef(fullTableName, sizeof(fullTableName), "%s_%s", defaultChrom, hti->rootName); @@ -228,49 +247,59 @@ /* continuing, not a wiggle output */ char **columnNames = NULL; char **columnTypes = NULL; int *jsonTypes = NULL; struct asObject *as = asForTable(conn, splitSqlTable, tdb); struct asColumn *columnEl = as->columnList; int asColumnCount = slCount(columnEl); int columnCount = tableColumns(conn, jw, splitSqlTable, &columnNames, &columnTypes, &jsonTypes); if (jsonOutputArrays || debug) { jsonWriteListStart(jw, "columnTypes"); int i = 0; for (i = 0; i < columnCount; ++i) { - char typeString[1024]; - if ((0 == i) && (asColumnCount == (columnCount - 1)) && (sameWord("bin", columnNames[i]))) - safef(typeString, sizeof(typeString), "%s - %s - %s - Indexing field to speed chromosome range queries", columnNames[i], columnTypes[i], jsonTypeStrings[jsonTypes[i]]); + jsonWriteObjectStart(jw, NULL); + jsonWriteString(jw, "name", columnNames[i]); + jsonWriteString(jw, "sqlType", columnTypes[i]); + jsonWriteString(jw, "jsonType", jsonTypeStrings[jsonTypes[i]]); + if ((0 == i) && (hti && hti->hasBin)) + jsonWriteString(jw, "description", "Indexing field to speed chromosome range queries"); else if (columnEl && isNotEmpty(columnEl->comment)) - safef(typeString, sizeof(typeString), "%s - %s - %s - %s", columnNames[i], columnTypes[i], jsonTypeStrings[jsonTypes[i]], columnEl->comment); + jsonWriteString(jw, "description", columnEl->comment); else - safef(typeString, sizeof(typeString), "%s - %s - %s", columnNames[i], columnTypes[i], jsonTypeStrings[jsonTypes[i]]); - jsonWriteString(jw, NULL, typeString); - if (columnEl && ! ((0 == i) && (sameWord("bin", columnNames[i])))) + jsonWriteString(jw, "description", ""); + + /* perhaps move the comment pointer forward */ + if (columnEl) + { + if (asColumnCount == columnCount) + columnEl = columnEl->next; + else if (! ((0 == i) && (hti && hti->hasBin))) columnEl = columnEl->next; } + jsonWriteObjectEnd(jw); + } jsonWriteListEnd(jw); } jsonWriteListStart(jw, track); unsigned itemsDone = 0; /* empty chrom and isSplit, needs to run through all chrom names */ -if (hti->isSplit && isEmpty(chrom)) +if ((hti && hti->isSplit) && isEmpty(chrom)) { struct chromInfo *ciList = createChromInfoList(NULL, db); slSort(ciList, chromInfoCmp); struct chromInfo *el = ciList; char fullTableName[256]; for ( ; itemsDone < maxItemsOutput && el != NULL; el = el->next ) { freeDyString(&query); query = dyStringNew(64); safef(fullTableName, sizeof(fullTableName), "%s_%s", el->chrom, hti->rootName); sqlDyStringPrintf(query, "select * from %s", fullTableName); itemsDone += sqlQueryJsonOutput(conn, jw, query->string, columnCount, columnNames, jsonTypes, itemsDone); } } @@ -412,37 +441,40 @@ } } else wigDataOutput(jw, bwf, chrom, start, end); } static void bigColumnTypes(struct jsonWrite *jw, struct sqlFieldType *fiList, struct asObject *as) /* show the column types from a big file autoSql definitions */ { struct asColumn *columnEl = as->columnList; jsonWriteListStart(jw, "columnTypes"); struct sqlFieldType *fi = fiList; for ( ; fi; fi = fi->next, columnEl = columnEl->next) { - char typeString[1024]; int jsonType = autoSqlToJsonType(fi->type); - if (columnEl->comment) - safef(typeString, sizeof(typeString), "%s - %s - %s - %s", fi->name, fi->type, jsonTypeStrings[jsonType], columnEl->comment); + jsonWriteObjectStart(jw, NULL); + jsonWriteString(jw, "name", fi->name); + jsonWriteString(jw, "sqlType", fi->type); + jsonWriteString(jw, "jsonType",jsonTypeStrings[jsonType]); + if (columnEl && isNotEmpty(columnEl->comment)) + jsonWriteString(jw, "description", columnEl->comment); else - safef(typeString, sizeof(typeString), "%s - %s - %s", fi->name, fi->type, jsonTypeStrings[jsonType]); - jsonWriteString(jw, NULL, typeString); + jsonWriteString(jw, "description", ""); + jsonWriteObjectEnd(jw); } jsonWriteListEnd(jw); } static void getHubTrackData(char *hubUrl) /* return data from a hub track, optionally just one chrom data, * optionally just one section of that chrom data */ { char *genome = cgiOptionalString("genome"); char *track = cgiOptionalString("track"); char *chrom = cgiOptionalString("chrom"); char *start = cgiOptionalString("start"); char *end = cgiOptionalString("end"); @@ -583,61 +615,61 @@ char *tableName = trackDbSetting(thisTrack, "table"); if (isNotEmpty(tableName)) { freeMem(sqlTable); sqlTable = cloneString(tableName); } struct sqlConnection *conn = hAllocConnMaybe(db); if (NULL == conn) apiErrAbort(err400, err400Msg, "can not find database 'db=%s' for endpoint '/getData/track", db); struct hTableInfo *hti = hFindTableInfoWithConn(conn, NULL, sqlTable); char *splitSqlTable = NULL; -if (hti->isSplit) +if (hti && hti->isSplit) { if (isNotEmpty(chrom)) { char fullTableName[256]; safef(fullTableName, sizeof(fullTableName), "%s_%s", chrom, hti->rootName); splitSqlTable = cloneString(fullTableName); } else { char *defaultChrom = hDefaultChrom(db); char fullTableName[256]; safef(fullTableName, sizeof(fullTableName), "%s_%s", defaultChrom, hti->rootName); splitSqlTable = cloneString(fullTableName); } } if (! hTableOrSplitExists(db, sqlTable)) { if (! bigDataUrl) apiErrAbort(err400, err400Msg, "can not find specified 'track=%s' for endpoint: /getData/track?db=%s;track=%s", track, db, track); else tableTrack = FALSE; } struct jsonWrite *jw = apiStartOutput(); jsonWriteString(jw, "db", db); if (tableTrack) { char *dataTime = NULL; - if (hti->isSplit) + if (hti && hti->isSplit) dataTime = sqlTableUpdate(conn, splitSqlTable); else dataTime = sqlTableUpdate(conn, sqlTable); time_t dataTimeStamp = sqlDateToUnixTime(dataTime); replaceChar(dataTime, ' ', 'T'); /* ISO 8601 */ jsonWriteString(jw, "dataTime", dataTime); jsonWriteNumber(jw, "dataTimeStamp", (long long)dataTimeStamp); if (differentStringNullOk(sqlTable,track)) jsonWriteString(jw, "sqlTable", sqlTable); } jsonWriteString(jw, "trackType", thisTrack->type); jsonWriteString(jw, "track", track); if (debug) jsonWriteBoolean(jw, "jsonOutputArrays", jsonOutputArrays);