dbd8fef5786457ba53375f006c4eaedf3d256110 hiram Fri Apr 5 11:46:55 2019 -0700 now output correct string or number json types refs #18869 diff --git src/hg/hubApi/getData.c src/hg/hubApi/getData.c index 8353baf..6deddbb 100644 --- src/hg/hubApi/getData.c +++ src/hg/hubApi/getData.c @@ -18,30 +18,42 @@ for (el = wds->ascii; itemCount < maxItemsOutput && el; el = el->next) { jsonWriteObjectStart(jw, NULL); int s = el->data->chromStart; int e = s + el->span; double val = el->data->value; jsonWriteNumber(jw, "start", (long long)s); jsonWriteNumber(jw, "end", (long long)e); jsonWriteDouble(jw, "value", val); jsonWriteObjectEnd(jw); ++itemCount; } jsonWriteListEnd(jw); } +static void jsonDatumOut(struct jsonWrite *jw, char *name, char *val, + int jsonType) +/* output a json item, determine type, appropriate output */ +{ +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 tableDataOutput(char *db, struct trackDb *tdb, struct sqlConnection *conn, struct jsonWrite *jw, char *table, char *chrom, unsigned start, unsigned end) /* output the table data from the specified query string */ { char query[4096]; /* no chrom specified, return entire table */ if (isEmpty(chrom)) sqlSafef(query, sizeof(query), "select * from %s", table); else if (0 == (start + end)) /* have chrom, no start,end == full chr */ { /* need to extend the chrom column check to allow tName also */ if (! sqlColumnExists(conn, table, "chrom")) apiErrAbort("track '%s' is not a position track, request track without chrom specification, genome: '%s'", table, db); jsonWriteString(jw, "chrom", chrom); @@ -68,104 +80,93 @@ wigTableDataOutput(jw, db, table, chrom, start, end); return; /* DONE */ } else { if (useTxStartEnd) sqlSafef(query, sizeof(query), "select * from %s where chrom='%s' AND txEnd > %u AND txStart < %u", table, chrom, start, end); else sqlSafef(query, sizeof(query), "select * from %s where chrom='%s' AND chromEnd > %u AND chromStart < %u", table, chrom, start, end); } } /* continuing, not a wiggle output */ char **columnNames = NULL; char **columnTypes = NULL; -int columnCount = tableColumns(conn, jw, table, &columnNames, &columnTypes); +int *jsonTypes = NULL; +int columnCount = tableColumns(conn, jw, table, &columnNames, &columnTypes, &jsonTypes); +if (debug) + { + jsonWriteObjectStart(jw, "columnTypes"); + int i = 0; + for (i = 0; i < columnCount; ++i) + { + char bothTypes[1024]; + safef(bothTypes, sizeof(bothTypes), "%s - %s", columnTypes[i], jsonTypeStrings[jsonTypes[i]]); + jsonWriteString(jw, columnNames[i], bothTypes); +// jsonWriteString(jw, columnNames[i], columnTypes[i]); + } + jsonWriteObjectEnd(jw); + } jsonWriteListStart(jw, table); struct sqlResult *sr = sqlGetResult(conn, query); char **row = NULL; unsigned itemCount = 0; while (itemCount < maxItemsOutput && (row = sqlNextRow(sr)) != NULL) { jsonWriteObjectStart(jw, NULL); int i = 0; for (i = 0; i < columnCount; ++i) - jsonWriteString(jw, columnNames[i], row[i]); + { + jsonDatumOut(jw, columnNames[i], row[i], jsonTypes[i]); + } jsonWriteObjectEnd(jw); ++itemCount; } sqlFreeResult(&sr); jsonWriteListEnd(jw); } -/* from hgTables.h */ -struct sqlFieldType -/* List field names and types */ - { - struct sqlFieldType *next; - char *name; /* Name of field. */ - char *type; /* Type of field (MySQL notion) */ - }; - -/* from hgTables.c */ -static struct sqlFieldType *sqlFieldTypeNew(char *name, char *type) -/* Create a new sqlFieldType */ -{ -struct sqlFieldType *ft; -AllocVar(ft); -ft->name = cloneString(name); -ft->type = cloneString(type); -return ft; -} - -/* from hgTables.c */ -static struct sqlFieldType *sqlFieldTypesFromAs(struct asObject *as) -/* Convert asObject to list of sqlFieldTypes */ -{ -struct sqlFieldType *ft, *list = NULL; -struct asColumn *col; -for (col = as->columnList; col != NULL; col = col->next) - { - struct dyString *type = asColumnToSqlType(col); - ft = sqlFieldTypeNew(col->name, type->string); - slAddHead(&list, ft); - dyStringFree(&type); - } -slReverse(&list); -return list; -} - static void bedDataOutput(struct jsonWrite *jw, struct bbiFile *bbi, char *chrom, unsigned start, unsigned end, struct sqlFieldType *fiList) /* output bed data for one chrom in the given bbi file */ { +int *jsonTypes = NULL; +int columnCount = slCount(fiList); +AllocArray(jsonTypes, columnCount); +int i = 0; +struct sqlFieldType *fi; +for ( fi = fiList; fi; fi = fi->next) + { + jsonTypes[i++] = autoSqlToJsonType(fi->type); + } struct lm *bbLm = lmInit(0); struct bigBedInterval *iv, *ivList = NULL; ivList = bigBedIntervalQuery(bbi,chrom, start, end, 0, bbLm); char *row[bbi->fieldCount]; unsigned itemCount = 0; for (iv = ivList; itemCount < maxItemsOutput && iv; iv = iv->next) { char startBuf[16], endBuf[16]; bigBedIntervalToRow(iv, chrom, startBuf, endBuf, row, bbi->fieldCount); jsonWriteObjectStart(jw, NULL); int i; struct sqlFieldType *fi = fiList; for (i = 0; i < bbi->fieldCount; ++i) { - jsonWriteString(jw, fi->name, row[i]); + jsonDatumOut(jw, fi->name, row[i], jsonTypes[i]); +// jsonWriteString(jw, fi->name, row[i]); fi = fi->next; } jsonWriteObjectEnd(jw); ++itemCount; } lmCleanup(&bbLm); } static void wigDataOutput(struct jsonWrite *jw, struct bbiFile *bwf, char *chrom, unsigned start, unsigned end) /* output wig data for one chrom in the given bwf file */ { struct lm *lm = lmInit(0); struct bbiInterval *iv, *ivList = bigWigIntervalQuery(bwf, chrom, start, end, lm); if (NULL == ivList) @@ -196,30 +197,45 @@ struct bbiChromInfo *chromList = NULL; // struct bbiSummaryElement sum = bbiTotalSummary(bwf); if (isEmpty(chrom)) { chromList = bbiChromList(bwf); struct bbiChromInfo *bci; for (bci = chromList; bci; bci = bci->next) { wigDataOutput(jw, bwf, bci->name, 0, bci->size); } } else wigDataOutput(jw, bwf, chrom, start, end); } +static void bigColumnTypes(struct jsonWrite *jw, struct sqlFieldType *fiList) +/* show the column types from a big file autoSql definitions */ +{ +jsonWriteObjectStart(jw, "columnTypes"); +struct sqlFieldType *fi = fiList; +for ( ; fi; fi = fi->next) + { + char bothTypes[1024]; + int jsonType = autoSqlToJsonType(fi->type); + safef(bothTypes, sizeof(bothTypes), "%s - %s", fi->type, jsonTypeStrings[jsonType]); + jsonWriteString(jw, fi->name, bothTypes); + } +jsonWriteObjectEnd(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"); if (isEmpty(genome)) apiErrAbort("missing genome=<name> for endpoint '/getData/track' given hubUrl='%s'", hubUrl); if (isEmpty(track)) apiErrAbort("missing track=<name> for endpoint '/getData/track' given hubUrl='%s'", hubUrl); @@ -274,30 +290,33 @@ if ( ! (isEmpty(start) || isEmpty(end)) ) { uStart = sqlUnsigned(start); uEnd = sqlUnsigned(end); jsonWriteNumber(jw, "start", uStart); jsonWriteNumber(jw, "end", uEnd); } jsonWriteString(jw, "bigDataUrl", bigDataUrl); jsonWriteString(jw, "trackType", thisTrack->type); if (startsWith("bigBed", thisTrack->type)) { struct asObject *as = bigBedAsOrDefault(bbi); struct sqlFieldType *fiList = sqlFieldTypesFromAs(as); + if (debug) + bigColumnTypes(jw, fiList); + jsonWriteListStart(jw, track); if (isEmpty(chrom)) { struct bbiChromInfo *bci; for (bci = chromList; bci; bci = bci->next) { bedDataOutput(jw, bbi, bci->name, 0, bci->size, fiList); } } else bedDataOutput(jw, bbi, chrom, uStart, uEnd, fiList); jsonWriteListEnd(jw); } else if (startsWith("bigWig", thisTrack->type)) { @@ -414,30 +433,32 @@ } jsonWriteString(jw, "bigDataUrl", bigDataUrl); } /* when start, end given, show them */ if ( uEnd > uStart ) { jsonWriteNumber(jw, "start", uStart); jsonWriteNumber(jw, "end", uEnd); } if (startsWith("bigBed", thisTrack->type)) { struct asObject *as = bigBedAsOrDefault(bbi); struct sqlFieldType *fiList = sqlFieldTypesFromAs(as); + if (debug) + bigColumnTypes(jw, fiList); jsonWriteListStart(jw, track); if (isEmpty(chrom)) { struct bbiChromInfo *bci; for (bci = chromList; bci; bci = bci->next) { bedDataOutput(jw, bbi, bci->name, 0, bci->size, fiList); } } else bedDataOutput(jw, bbi, chrom, uStart, uEnd, fiList); jsonWriteListEnd(jw); } else if (startsWith("bigWig", thisTrack->type)) {