diff --git a/packages/grafana-data/src/dataframe/processDataFrame.test.ts b/packages/grafana-data/src/dataframe/processDataFrame.test.ts index e7d0e8f7274..29bc386967e 100644 --- a/packages/grafana-data/src/dataframe/processDataFrame.test.ts +++ b/packages/grafana-data/src/dataframe/processDataFrame.test.ts @@ -11,6 +11,7 @@ import { DataFrameDTO, FieldType, TableData, TimeSeries } from '../types/index'; import { dateTime } from '../datetime/moment_wrapper'; import { MutableDataFrame } from './MutableDataFrame'; import { ArrayDataFrame } from './ArrayDataFrame'; +import { getFieldTypeFromValue } from '.'; describe('toDataFrame', () => { it('converts timeseries to series', () => { @@ -118,15 +119,13 @@ describe('toDataFrame', () => { expect(guessFieldTypeFromValue('xxxx')).toBe(FieldType.string); }); - it('Guess Column Types from strings', () => { - expect(guessFieldTypeFromValue('1')).toBe(FieldType.number); - expect(guessFieldTypeFromValue('1.234')).toBe(FieldType.number); - expect(guessFieldTypeFromValue('NaN')).toBe(FieldType.number); - expect(guessFieldTypeFromValue('3.125e7')).toBe(FieldType.number); - expect(guessFieldTypeFromValue('True')).toBe(FieldType.boolean); - expect(guessFieldTypeFromValue('FALSE')).toBe(FieldType.boolean); - expect(guessFieldTypeFromValue('true')).toBe(FieldType.boolean); - expect(guessFieldTypeFromValue('xxxx')).toBe(FieldType.string); + it('Get column types from values', () => { + expect(getFieldTypeFromValue(1)).toBe(FieldType.number); + expect(getFieldTypeFromValue(1.234)).toBe(FieldType.number); + expect(getFieldTypeFromValue(NaN)).toBe(FieldType.number); + expect(getFieldTypeFromValue(3.125e7)).toBe(FieldType.number); + expect(getFieldTypeFromValue(true)).toBe(FieldType.boolean); + expect(getFieldTypeFromValue('xxxx')).toBe(FieldType.string); }); it('Guess Column Types from series', () => { diff --git a/packages/grafana-data/src/dataframe/processDataFrame.ts b/packages/grafana-data/src/dataframe/processDataFrame.ts index d1e10576b54..4f19314cb61 100644 --- a/packages/grafana-data/src/dataframe/processDataFrame.ts +++ b/packages/grafana-data/src/dataframe/processDataFrame.ts @@ -189,10 +189,33 @@ export function guessFieldTypeFromNameAndValue(name: string, v: any): FieldType return guessFieldTypeFromValue(v); } +/** + * Check the field type to see what the contents are + */ +export function getFieldTypeFromValue(v: any): FieldType { + if (v instanceof Date || isDateTime(v)) { + return FieldType.time; + } + + if (isNumber(v)) { + return FieldType.number; + } + + if (isString(v)) { + return FieldType.string; + } + + if (isBoolean(v)) { + return FieldType.boolean; + } + + return FieldType.other; +} + /** * Given a value this will guess the best column type * - * TODO: better Date/Time support! Look for standard date strings? + * NOTE: this is will try to see if string values can be mapped to other types (like number) */ export function guessFieldTypeFromValue(v: any): FieldType { if (v instanceof Date || isDateTime(v)) { @@ -237,7 +260,7 @@ export function guessFieldTypeForField(field: Field): FieldType | undefined { // 2. Check the first non-null value for (let i = 0; i < field.values.length; i++) { const v = field.values.get(i); - if (v !== null) { + if (v != null) { return guessFieldTypeFromValue(v); } } diff --git a/public/app/core/components/TransformersUI/extractFields/extractFields.test.ts b/public/app/core/components/TransformersUI/extractFields/extractFields.test.ts index baaefefc97a..753cd065950 100644 --- a/public/app/core/components/TransformersUI/extractFields/extractFields.test.ts +++ b/public/app/core/components/TransformersUI/extractFields/extractFields.test.ts @@ -14,23 +14,28 @@ describe('Fields from JSON', () => { const frames = extractFieldsTransformer.transformer(cfg)([data]); expect(frames.length).toEqual(1); - expect(frames[0].fields.map((v) => v.name)).toMatchInlineSnapshot(` - Array [ - "a", - "av", - "c", - "e", - "ev", - "h", - "l", - "o", - "op", - "s", - "sym", - "v", - "vw", - "z", - ] + expect( + frames[0].fields.reduce((acc, v) => { + acc[v.name] = v.type; + return acc; + }, {} as any) + ).toMatchInlineSnapshot(` + Object { + "a": "string", + "av": "number", + "c": "string", + "e": "number", + "ev": "string", + "h": "string", + "l": "string", + "o": "string", + "op": "string", + "s": "number", + "sym": "string", + "v": "number", + "vw": "string", + "z": "number", + } `); }); }); diff --git a/public/app/core/components/TransformersUI/extractFields/extractFields.ts b/public/app/core/components/TransformersUI/extractFields/extractFields.ts index 33136cd46af..2d2707ee959 100644 --- a/public/app/core/components/TransformersUI/extractFields/extractFields.ts +++ b/public/app/core/components/TransformersUI/extractFields/extractFields.ts @@ -4,7 +4,7 @@ import { DataTransformerID, Field, FieldType, - guessFieldTypeForField, + getFieldTypeFromValue, SynchronousDataTransformerInfo, } from '@grafana/data'; import { findField } from 'app/features/dimensions'; @@ -72,14 +72,13 @@ function addExtractedFields(frame: DataFrame, options: ExtractFieldsOptions): Da } const fields = names.map((name) => { - const f: Field = { + const buffer = values.get(name); + return { name, - values: new ArrayVector(values.get(name)), - type: FieldType.boolean, + values: new ArrayVector(buffer), + type: buffer ? getFieldTypeFromValue(buffer.find((v) => v != null)) : FieldType.other, config: {}, - }; - f.type = guessFieldTypeForField(f) ?? FieldType.other; - return f; + } as Field; }); if (!options.replace) {