diff --git a/src/plugins/expressions/common/expression_types/specs/boolean.ts b/src/plugins/expressions/common/expression_types/specs/boolean.ts index d730f95d7c423..adbdeafc34fd2 100644 --- a/src/plugins/expressions/common/expression_types/specs/boolean.ts +++ b/src/plugins/expressions/common/expression_types/specs/boolean.ts @@ -41,7 +41,8 @@ export const boolean: ExpressionTypeDefinition<'boolean', boolean> = { }, datatable: (value): Datatable => ({ type: 'datatable', - columns: [{ name: 'value', type: name }], + meta: {}, + columns: [{ id: 'value', name: 'value', meta: { type: name } }], rows: [{ value }], }), }, diff --git a/src/plugins/expressions/common/expression_types/specs/datatable.ts b/src/plugins/expressions/common/expression_types/specs/datatable.ts index 5cd53df663e1d..dd3c653878de7 100644 --- a/src/plugins/expressions/common/expression_types/specs/datatable.ts +++ b/src/plugins/expressions/common/expression_types/specs/datatable.ts @@ -23,6 +23,13 @@ import { ExpressionTypeDefinition } from '../types'; import { PointSeries, PointSeriesColumn } from './pointseries'; import { ExpressionValueRender } from './render'; +type State = string | number | boolean | null | undefined | SerializableState; + +/** @internal **/ +export interface SerializableState { + [key: string]: State | State[]; +} + const name = 'datatable'; /** @@ -42,12 +49,23 @@ export type DatatableColumnType = 'string' | 'number' | 'boolean' | 'date' | 'nu */ export type DatatableRow = Record; +export interface DatatableColumnMeta { + type: DatatableColumnType; + field?: string; + params?: SerializableState; +} /** * This type represents the shape of a column in a `Datatable`. */ export interface DatatableColumn { + id: string; name: string; - type: DatatableColumnType; + meta: DatatableColumnMeta; +} + +export interface DatatableMeta { + type?: string; + source?: string; } /** @@ -55,6 +73,7 @@ export interface DatatableColumn { */ export interface Datatable { type: typeof name; + meta?: DatatableMeta; columns: DatatableColumn[]; rows: DatatableRow[]; } @@ -103,14 +122,16 @@ export const datatable: ExpressionTypeDefinition ({ type: name, + meta: {}, rows: [], columns: [], }), pointseries: (value: PointSeries) => ({ type: name, + meta: {}, rows: value.rows, columns: map(value.columns, (val: PointSeriesColumn, colName) => { - return { name: colName, type: val.type }; + return { id: colName, name: colName, meta: { type: val.type } }; }), }), }, @@ -127,13 +148,13 @@ export const datatable: ExpressionTypeDefinition { const validFields = ['x', 'y', 'color', 'size', 'text']; - const columns = table.columns.filter((column) => validFields.includes(column.name)); + const columns = table.columns.filter((column) => validFields.includes(column.id)); const rows = table.rows.map((row) => pick(row, validFields)); return { type: 'pointseries', columns: columns.reduce>((acc, column) => { acc[column.name] = { - type: column.type, + type: column.meta.type, expression: column.name, role: 'dimension', }; diff --git a/src/plugins/expressions/common/expression_types/specs/num.ts b/src/plugins/expressions/common/expression_types/specs/num.ts index 191e617fdc858..041747f39740b 100644 --- a/src/plugins/expressions/common/expression_types/specs/num.ts +++ b/src/plugins/expressions/common/expression_types/specs/num.ts @@ -73,7 +73,8 @@ export const num: ExpressionTypeDefinition<'num', ExpressionValueNum> = { }, datatable: ({ value }): Datatable => ({ type: 'datatable', - columns: [{ name: 'value', type: 'number' }], + meta: {}, + columns: [{ id: 'value', name: 'value', meta: { type: 'number' } }], rows: [{ value }], }), }, diff --git a/src/plugins/expressions/common/expression_types/specs/number.ts b/src/plugins/expressions/common/expression_types/specs/number.ts index 10986659c7848..c5fdacf3408a1 100644 --- a/src/plugins/expressions/common/expression_types/specs/number.ts +++ b/src/plugins/expressions/common/expression_types/specs/number.ts @@ -55,7 +55,8 @@ export const number: ExpressionTypeDefinition = { }, datatable: (value): Datatable => ({ type: 'datatable', - columns: [{ name: 'value', type: 'number' }], + meta: {}, + columns: [{ id: 'value', name: 'value', meta: { type: 'number' } }], rows: [{ value }], }), }, diff --git a/src/plugins/expressions/common/expression_types/specs/string.ts b/src/plugins/expressions/common/expression_types/specs/string.ts index 46f460891c2fb..3d52707279bfc 100644 --- a/src/plugins/expressions/common/expression_types/specs/string.ts +++ b/src/plugins/expressions/common/expression_types/specs/string.ts @@ -40,7 +40,8 @@ export const string: ExpressionTypeDefinition = { }, datatable: (value): Datatable => ({ type: 'datatable', - columns: [{ name: 'value', type: 'string' }], + meta: {}, + columns: [{ id: 'value', name: 'value', meta: { type: 'string' } }], rows: [{ value }], }), }, diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/location.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/location.ts index 4a01df3b0ac50..5c0ca74f5225a 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/location.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/location.ts @@ -10,7 +10,10 @@ import { getFunctionHelp } from '../../../i18n'; const noop = () => {}; interface Return extends Datatable { - columns: [{ name: 'latitude'; type: 'number' }, { name: 'longitude'; type: 'number' }]; + columns: [ + { id: 'latitude'; name: 'latitude'; meta: { type: 'number' } }, + { id: 'longitude'; name: 'longitude'; meta: { type: 'number' } } + ]; rows: [{ latitude: number; longitude: number }]; } @@ -30,8 +33,8 @@ export function location(): ExpressionFunctionDefinition<'location', null, {}, P return resolve({ type: 'datatable', columns: [ - { name: 'latitude', type: 'number' }, - { name: 'longitude', type: 'number' }, + { id: 'latitude', name: 'latitude', meta: { type: 'number' } }, + { id: 'longitude', name: 'longitude', meta: { type: 'number' } }, ], rows: [{ latitude, longitude }], }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_tables.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_tables.ts index b5e5836dc5331..ffb76500a35d6 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_tables.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_tables.ts @@ -16,24 +16,29 @@ const testTable: Datatable = { type: 'datatable', columns: [ { + id: 'name', name: 'name', - type: 'string', + meta: { type: 'string' }, }, { + id: 'time', name: 'time', - type: 'date', + meta: { type: 'date' }, }, { + id: 'price', name: 'price', - type: 'number', + meta: { type: 'number' }, }, { + id: 'quantity', name: 'quantity', - type: 'number', + meta: { type: 'number' }, }, { + id: 'in_stock', name: 'in_stock', - type: 'boolean', + meta: { type: 'boolean' }, }, ], rows: [ @@ -107,24 +112,29 @@ const stringTable: Datatable = { type: 'datatable', columns: [ { + id: 'name', name: 'name', - type: 'string', + meta: { type: 'string' }, }, { + id: 'time', name: 'time', - type: 'string', + meta: { type: 'string' }, }, { + id: 'price', name: 'price', - type: 'string', + meta: { type: 'string' }, }, { + id: 'quantity', name: 'quantity', - type: 'string', + meta: { type: 'string' }, }, { + id: 'in_stock', name: 'in_stock', - type: 'string', + meta: { type: 'string' }, }, ], rows: [ diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js index c46b2277859d0..a8c01f0b2791f 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js @@ -38,7 +38,7 @@ describe('alterColumn', () => { const arbitraryRowIndex = 6; expect(newColumn.name).not.toBe(originalColumn.name); - expect(newColumn.type).not.toBe(originalColumn.type); + expect(newColumn.meta.type).not.toBe(originalColumn.meta.type); expect(typeof dateToString.rows[arbitraryRowIndex].timeISO).toBe('string'); expect(new Date(dateToString.rows[arbitraryRowIndex].timeISO)).toEqual( new Date(testTable.rows[arbitraryRowIndex].time) @@ -60,7 +60,7 @@ describe('alterColumn', () => { it('converts the column to the specified type', () => { const dateToString = fn(testTable, { column: 'time', type: 'string', name: 'timeISO' }); - expect(typeof dateToString.columns[timeColumnIndex].type).toBe('string'); + expect(typeof dateToString.columns[timeColumnIndex].meta.type).toBe('string'); expect(typeof dateToString.rows[timeColumnIndex].timeISO).toBe('string'); expect(new Date(dateToString.rows[timeColumnIndex].timeISO)).toEqual( new Date(testTable.rows[timeColumnIndex].time) @@ -69,10 +69,10 @@ describe('alterColumn', () => { it('does not change column if type is not specified', () => { const unconvertedColumn = fn(testTable, { column: 'price', name: 'foo' }); - const originalType = testTable.columns[priceColumnIndex].type; + const originalType = testTable.columns[priceColumnIndex].meta.type; const arbitraryRowIndex = 2; - expect(unconvertedColumn.columns[priceColumnIndex].type).toBe(originalType); + expect(unconvertedColumn.columns[priceColumnIndex].meta.type).toBe(originalType); expect(typeof unconvertedColumn.rows[arbitraryRowIndex].foo).toBe(originalType); }); @@ -99,7 +99,7 @@ describe('alterColumn', () => { const arbitraryRowIndex = 5; expect(newColumn.name).not.toBe(originalColumn.name); - expect(newColumn.type).not.toBe(originalColumn.type); + expect(newColumn.meta.type).not.toBe(originalColumn.meta.type); expect(typeof overwriteName.rows[arbitraryRowIndex].name).toBe('string'); expect(new Date(overwriteName.rows[arbitraryRowIndex].name)).toEqual( new Date(testTable.rows[arbitraryRowIndex].time) @@ -122,7 +122,7 @@ describe('alterColumn', () => { const numberToString = fn(testTable, { column: 'price', type: 'string' }); expect(numberToString.columns[priceColumnIndex]).toHaveProperty('name', 'price'); - expect(numberToString.columns[priceColumnIndex]).toHaveProperty('type', 'string'); + expect(numberToString.columns[priceColumnIndex].meta).toHaveProperty('type', 'string'); expect(typeof numberToString.rows[arbitraryRowIndex].price).toBe('string'); expect(numberToString.rows[arbitraryRowIndex].price).toBe( @@ -132,7 +132,7 @@ describe('alterColumn', () => { const stringToNumber = fn(numberToString, { column: 'price', type: 'number' }); expect(stringToNumber.columns[priceColumnIndex]).toHaveProperty('name', 'price'); - expect(stringToNumber.columns[priceColumnIndex]).toHaveProperty('type', 'number'); + expect(stringToNumber.columns[priceColumnIndex].meta).toHaveProperty('type', 'number'); expect(typeof stringToNumber.rows[arbitraryRowIndex].price).toBe('number'); @@ -146,7 +146,7 @@ describe('alterColumn', () => { const dateToString = fn(testTable, { column: 'time', type: 'string' }); expect(dateToString.columns[timeColumnIndex]).toHaveProperty('name', 'time'); - expect(dateToString.columns[timeColumnIndex]).toHaveProperty('type', 'string'); + expect(dateToString.columns[timeColumnIndex].meta).toHaveProperty('type', 'string'); expect(typeof dateToString.rows[arbitraryRowIndex].time).toBe('string'); expect(new Date(dateToString.rows[arbitraryRowIndex].time)).toEqual( @@ -156,7 +156,7 @@ describe('alterColumn', () => { const stringToDate = fn(dateToString, { column: 'time', type: 'date' }); expect(stringToDate.columns[timeColumnIndex]).toHaveProperty('name', 'time'); - expect(stringToDate.columns[timeColumnIndex]).toHaveProperty('type', 'date'); + expect(stringToDate.columns[timeColumnIndex].meta).toHaveProperty('type', 'date'); expect(new Date(stringToDate.rows[timeColumnIndex].time)).toBeInstanceOf(Date); expect(new Date(stringToDate.rows[timeColumnIndex].time)).toEqual( @@ -169,7 +169,7 @@ describe('alterColumn', () => { const arbitraryRowIndex = 1; expect(dateToNumber.columns[timeColumnIndex]).toHaveProperty('name', 'time'); - expect(dateToNumber.columns[timeColumnIndex]).toHaveProperty('type', 'number'); + expect(dateToNumber.columns[timeColumnIndex].meta).toHaveProperty('type', 'number'); expect(typeof dateToNumber.rows[arbitraryRowIndex].time).toBe('number'); expect(dateToNumber.rows[arbitraryRowIndex].time).toEqual( @@ -179,7 +179,7 @@ describe('alterColumn', () => { const numberToDate = fn(dateToNumber, { column: 'time', type: 'date' }); expect(numberToDate.columns[timeColumnIndex]).toHaveProperty('name', 'time'); - expect(numberToDate.columns[timeColumnIndex]).toHaveProperty('type', 'date'); + expect(numberToDate.columns[timeColumnIndex].meta).toHaveProperty('type', 'date'); expect(new Date(numberToDate.rows[arbitraryRowIndex].time)).toBeInstanceOf(Date); expect(new Date(numberToDate.rows[arbitraryRowIndex].time)).toEqual( @@ -192,7 +192,7 @@ describe('alterColumn', () => { const arbitraryRowIndex = 7; expect(booleanToNumber.columns[inStockColumnIndex]).toHaveProperty('name', 'in_stock'); - expect(booleanToNumber.columns[inStockColumnIndex]).toHaveProperty('type', 'number'); + expect(booleanToNumber.columns[inStockColumnIndex].meta).toHaveProperty('type', 'number'); expect(typeof booleanToNumber.rows[arbitraryRowIndex].in_stock).toBe('number'); expect(booleanToNumber.rows[arbitraryRowIndex].in_stock).toEqual( @@ -202,7 +202,7 @@ describe('alterColumn', () => { const numberToBoolean = fn(booleanToNumber, { column: 'in_stock', type: 'boolean' }); expect(numberToBoolean.columns[inStockColumnIndex]).toHaveProperty('name', 'in_stock'); - expect(numberToBoolean.columns[inStockColumnIndex]).toHaveProperty('type', 'boolean'); + expect(numberToBoolean.columns[inStockColumnIndex].meta).toHaveProperty('type', 'boolean'); expect(typeof numberToBoolean.rows[arbitraryRowIndex].in_stock).toBe('boolean'); expect(numberToBoolean.rows[arbitraryRowIndex].in_stock).toEqual( @@ -216,7 +216,7 @@ describe('alterColumn', () => { expect(stringToNull.columns[nameColumnIndex]).toHaveProperty('name', 'name'); - expect(stringToNull.columns[nameColumnIndex]).toHaveProperty('type', 'null'); + expect(stringToNull.columns[nameColumnIndex].meta).toHaveProperty('type', 'null'); expect(stringToNull.rows[arbitraryRowIndex].name).toBe(null); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.ts index 68c1957c808a3..531959f6bc63a 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.ts @@ -57,14 +57,14 @@ export function alterColumn(): ExpressionFunctionDefinition< } const name = args.name || column.name; - const type = args.type || column.type; + const type = args.type || column.meta.type; const columns = input.columns.reduce((all: DatatableColumn[], col) => { if (col.name !== args.name) { if (col.name !== column.name) { all.push(col); } else { - all.push({ name, type }); + all.push({ id: name, name, meta: { type } }); } } return all; @@ -76,7 +76,7 @@ export function alterColumn(): ExpressionFunctionDefinition< handler = (function getHandler() { switch (type) { case 'string': - if (column.type === 'date') { + if (column.meta.type === 'date') { return (v: string) => new Date(v).toISOString(); } return String; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.test.js index 2fc9491f6b5b7..49d14622e80f0 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.test.js @@ -13,19 +13,19 @@ describe('as', () => { it('returns a datatable with a single column and single row', () => { expect(fn('foo', { name: 'bar' })).toEqual({ type: 'datatable', - columns: [{ name: 'bar', type: 'string' }], + columns: [{ id: 'bar', name: 'bar', meta: { type: 'string' } }], rows: [{ bar: 'foo' }], }); expect(fn(2, { name: 'num' })).toEqual({ type: 'datatable', - columns: [{ name: 'num', type: 'number' }], + columns: [{ id: 'num', name: 'num', meta: { type: 'number' } }], rows: [{ num: 2 }], }); expect(fn(true, { name: 'bool' })).toEqual({ type: 'datatable', - columns: [{ name: 'bool', type: 'boolean' }], + columns: [{ id: 'bool', name: 'bool', meta: { type: 'boolean' } }], rows: [{ bool: true }], }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.ts index 9c10e85227398..d8fd948c12b2e 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.ts @@ -34,8 +34,9 @@ export function asFn(): ExpressionFunctionDefinition<'as', Input, Arguments, Dat type: 'datatable', columns: [ { + id: args.name, name: args.name, - type: getType(input), + meta: { type: getType(input) }, }, ], rows: [ diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.test.js index e5ef06d1503ee..652d61fd77398 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.test.js @@ -14,13 +14,17 @@ describe('mapColumn', () => { const fn = functionWrapper(mapColumn); it('returns a datatable with a new column with the values from mapping a function over each row in a datatable', () => { - return fn(testTable, { name: 'pricePlusTwo', expression: pricePlusTwo }).then((result) => { + return fn(testTable, { + id: 'pricePlusTwo', + name: 'pricePlusTwo', + expression: pricePlusTwo, + }).then((result) => { const arbitraryRowIndex = 2; expect(result.type).toBe('datatable'); expect(result.columns).toEqual([ ...testTable.columns, - { name: 'pricePlusTwo', type: 'number' }, + { id: 'pricePlusTwo', name: 'pricePlusTwo', meta: { type: 'number' } }, ]); expect(result.columns[result.columns.length - 1]).toHaveProperty('name', 'pricePlusTwo'); expect(result.rows[arbitraryRowIndex]).toHaveProperty('pricePlusTwo'); @@ -35,7 +39,7 @@ describe('mapColumn', () => { expect(result.type).toBe('datatable'); expect(result.columns).toHaveLength(testTable.columns.length); expect(result.columns[nameColumnIndex]).toHaveProperty('name', 'name'); - expect(result.columns[nameColumnIndex]).toHaveProperty('type', 'number'); + expect(result.columns[nameColumnIndex].meta).toHaveProperty('type', 'number'); expect(result.rows[arbitraryRowIndex]).toHaveProperty('name', 202); }); }); @@ -45,7 +49,7 @@ describe('mapColumn', () => { expect(result.type).toBe('datatable'); expect(result.columns).toHaveLength(1); expect(result.columns[0]).toHaveProperty('name', 'name'); - expect(result.columns[0]).toHaveProperty('type', 'null'); + expect(result.columns[0].meta).toHaveProperty('type', 'null'); }); }); @@ -56,7 +60,7 @@ describe('mapColumn', () => { const arbitraryRowIndex = 8; expect(result.columns[emptyColumnIndex]).toHaveProperty('name', 'empty'); - expect(result.columns[emptyColumnIndex]).toHaveProperty('type', 'null'); + expect(result.columns[emptyColumnIndex].meta).toHaveProperty('type', 'null'); expect(result.rows[arbitraryRowIndex]).toHaveProperty('empty', null); }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.ts index 7dd309cba5c64..6d6a432e5553e 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.ts @@ -59,7 +59,7 @@ export function mapColumn(): ExpressionFunctionDefinition< return Promise.all(rowPromises).then((rows) => { const existingColumnIndex = columns.findIndex(({ name }) => name === args.name); const type = rows.length ? getType(rows[0][args.name]) : 'null'; - const newColumn = { name: args.name, type }; + const newColumn = { id: args.name, name: args.name, meta: { type } }; if (existingColumnIndex === -1) { columns.push(newColumn); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js index 2dfb9eeea76bc..07d436007c816 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js @@ -16,7 +16,7 @@ const averagePrice = (datatable) => { return Promise.resolve({ type: 'datatable', - columns: [{ name: 'average_price', type: 'number' }], + columns: [{ id: 'average_price', name: 'average_price', meta: { type: 'number' } }], rows: [{ average_price: average }], }); }; @@ -26,7 +26,7 @@ const doublePrice = (datatable) => { return Promise.resolve({ type: 'datatable', - columns: [{ name: 'double_price', type: 'number' }], + columns: [{ id: 'double_price', name: 'double_price', meta: { type: 'number' } }], rows: newRows, }); }; @@ -34,7 +34,7 @@ const doublePrice = (datatable) => { const rowCount = (datatable) => { return Promise.resolve({ type: 'datatable', - columns: [{ name: 'row_count', type: 'number' }], + columns: [{ id: 'row_count', name: 'row_count', meta: { type: 'number' } }], rows: [ { row_count: datatable.rows.length, @@ -53,10 +53,10 @@ describe('ply', () => { (result) => { expect(result.type).toBe('datatable'); expect(result.columns).toEqual([ - { name: 'name', type: 'string' }, - { name: 'in_stock', type: 'boolean' }, - { name: 'average_price', type: 'number' }, - { name: 'row_count', type: 'number' }, + { id: 'name', name: 'name', meta: { type: 'string' } }, + { id: 'in_stock', name: 'in_stock', meta: { type: 'boolean' } }, + { id: 'average_price', name: 'average_price', meta: { type: 'number' } }, + { id: 'row_count', name: 'row_count', meta: { type: 'number' } }, ]); expect(result.rows[arbitaryRowIndex]).toHaveProperty('average_price'); expect(result.rows[arbitaryRowIndex]).toHaveProperty('row_count'); @@ -75,7 +75,7 @@ describe('ply', () => { expect(result).toEqual({ type: 'datatable', rows: [{ row_count: testTable.rows.length }], - columns: [{ name: 'row_count', type: 'number' }], + columns: [{ id: 'row_count', name: 'row_count', meta: { type: 'number' } }], }) ); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.test.js index ff11669db05f7..d137ce05ccc19 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.test.js @@ -15,7 +15,10 @@ describe('staticColumn', () => { const result = fn(testTable, { name: 'foo', value: 'bar' }); expect(result.type).toBe('datatable'); - expect(result.columns).toEqual([...testTable.columns, { name: 'foo', type: 'string' }]); + expect(result.columns).toEqual([ + ...testTable.columns, + { id: 'foo', name: 'foo', meta: { type: 'string' } }, + ]); expect(result.rows.every((row) => typeof row.foo === 'string')).toBe(true); expect(result.rows.every((row) => row.foo === 'bar')).toBe(true); }); @@ -33,7 +36,10 @@ describe('staticColumn', () => { const result = fn(testTable, { name: 'empty' }); expect(result.type).toBe('datatable'); - expect(result.columns).toEqual([...testTable.columns, { name: 'empty', type: 'null' }]); + expect(result.columns).toEqual([ + ...testTable.columns, + { id: 'empty', name: 'empty', meta: { type: 'null' } }, + ]); expect(result.rows.every((row) => row.empty === null)).toBe(true); }); @@ -41,7 +47,7 @@ describe('staticColumn', () => { const result = fn(emptyTable, { name: 'empty', value: 1 }); expect(result.type).toBe('datatable'); - expect(result.columns).toEqual([{ name: 'empty', type: 'number' }]); + expect(result.columns).toEqual([{ id: 'empty', name: 'empty', meta: { type: 'number' } }]); expect(result.rows.length).toBe(0); }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.ts index 4fa4be0a2f09f..63a115c7e630b 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.ts @@ -48,7 +48,7 @@ export function staticColumn(): ExpressionFunctionDefinition< const type = getType(args.value) as DatatableColumnType; const columns = [...input.columns]; const existingColumnIndex = columns.findIndex(({ name }) => name === args.name); - const newColumn = { name: args.name, type }; + const newColumn = { id: args.name, name: args.name, meta: { type } }; if (existingColumnIndex > -1) { columns[existingColumnIndex] = newColumn; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata/index.ts index 60d5edeb10483..e29f1f511685e 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata/index.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata/index.ts @@ -50,26 +50,26 @@ export function demodata(): ExpressionFunctionDefinition< if (args.type === DemoRows.CI) { set = { columns: [ - { name: '@timestamp', type: 'date' }, - { name: 'time', type: 'date' }, - { name: 'cost', type: 'number' }, - { name: 'username', type: 'string' }, - { name: 'price', type: 'number' }, - { name: 'age', type: 'number' }, - { name: 'country', type: 'string' }, - { name: 'state', type: 'string' }, - { name: 'project', type: 'string' }, - { name: 'percent_uptime', type: 'number' }, + { id: '@timestamp', name: '@timestamp', meta: { type: 'date' } }, + { id: 'time', name: 'time', meta: { type: 'date' } }, + { id: 'cost', name: 'cost', meta: { type: 'number' } }, + { id: 'username', name: 'username', meta: { type: 'string' } }, + { id: 'price', name: 'price', meta: { type: 'number' } }, + { id: 'age', name: 'age', meta: { type: 'number' } }, + { id: 'country', name: 'country', meta: { type: 'string' } }, + { id: 'state', name: 'state', meta: { type: 'string' } }, + { id: 'project', name: 'project', meta: { type: 'string' } }, + { id: 'percent_uptime', name: 'percent_uptime', meta: { type: 'number' } }, ], rows: sortBy(demoRows, 'time'), }; } else if (args.type === DemoRows.SHIRTS) { set = { columns: [ - { name: 'size', type: 'string' }, - { name: 'color', type: 'string' }, - { name: 'price', type: 'number' }, - { name: 'cut', type: 'string' }, + { id: 'size', name: 'size', meta: { type: 'string' } }, + { id: 'color', name: 'color', meta: { type: 'string' } }, + { id: 'price', name: 'price', meta: { type: 'number' } }, + { id: 'cut', name: 'cut', meta: { type: 'string' } }, ], rows: demoRows, }; diff --git a/x-pack/plugins/canvas/common/lib/get_field_type.ts b/x-pack/plugins/canvas/common/lib/get_field_type.ts index db817393a1cdb..d081f8b69956a 100644 --- a/x-pack/plugins/canvas/common/lib/get_field_type.ts +++ b/x-pack/plugins/canvas/common/lib/get_field_type.ts @@ -20,5 +20,5 @@ export function getFieldType(columns: DatatableColumn[], field?: string): string } const realField = unquoteString(field); const column = columns.find((dataTableColumn) => dataTableColumn.name === realField); - return column ? column.type : 'null'; + return column ? column.meta.type : 'null'; } diff --git a/x-pack/plugins/canvas/public/components/datatable/datatable.tsx b/x-pack/plugins/canvas/public/components/datatable/datatable.tsx index 4f06ac0749aaf..bd343b15758bf 100644 --- a/x-pack/plugins/canvas/public/components/datatable/datatable.tsx +++ b/x-pack/plugins/canvas/public/components/datatable/datatable.tsx @@ -41,7 +41,7 @@ const getIcon = (type: IconType) => { const getColumnName = (col: DatatableColumn) => (typeof col === 'string' ? col : col.name); -const getColumnType = (col: DatatableColumn) => col.type || null; +const getColumnType = (col: DatatableColumn) => col.meta?.type || null; const getFormattedValue = (val: any, type: any) => { if (type === 'date') { diff --git a/x-pack/plugins/canvas/public/functions/timelion.ts b/x-pack/plugins/canvas/public/functions/timelion.ts index 4eb34e838d18a..947972fa310c9 100644 --- a/x-pack/plugins/canvas/public/functions/timelion.ts +++ b/x-pack/plugins/canvas/public/functions/timelion.ts @@ -135,10 +135,13 @@ export function timelionFunctionFactory(initialize: InitializeArguments): () => return { type: 'datatable', + meta: { + source: 'timelion', + }, columns: [ - { name: '@timestamp', type: 'date' }, - { name: 'value', type: 'number' }, - { name: 'label', type: 'string' }, + { id: '@timestamp', name: '@timestamp', meta: { type: 'date' } }, + { id: 'value', name: 'value', meta: { type: 'number' } }, + { id: 'label', name: 'label', meta: { type: 'string' } }, ], rows, }; diff --git a/x-pack/plugins/canvas/server/lib/query_es_sql.test.ts b/x-pack/plugins/canvas/server/lib/query_es_sql.test.ts index c3c122d1e301a..c8bdf01ad7991 100644 --- a/x-pack/plugins/canvas/server/lib/query_es_sql.test.ts +++ b/x-pack/plugins/canvas/server/lib/query_es_sql.test.ts @@ -53,7 +53,11 @@ describe('query_es_sql', () => { const result = await queryEsSQL(api, baseArgs); - const expectedColumns = response.columns.map((c) => ({ name: c.name, type: 'string' })); + const expectedColumns = response.columns.map((c) => ({ + id: c.name, + name: c.name, + meta: { type: 'string' }, + })); const columnNames = expectedColumns.map((c) => c.name); const expectedRows = response.rows.map((r) => zipObject(columnNames, r)); diff --git a/x-pack/plugins/canvas/server/lib/query_es_sql.ts b/x-pack/plugins/canvas/server/lib/query_es_sql.ts index 8639cfa31dca8..941dc244330e8 100644 --- a/x-pack/plugins/canvas/server/lib/query_es_sql.ts +++ b/x-pack/plugins/canvas/server/lib/query_es_sql.ts @@ -53,7 +53,11 @@ export const queryEsSQL = async ( }); const columns = response.columns.map(({ name, type }) => { - return { name: sanitizeName(name), type: normalizeType(type) }; + return { + id: sanitizeName(name), + name: sanitizeName(name), + meta: { type: normalizeType(type) }, + }; }); const columnNames = map(columns, 'name'); let rows = response.rows.map((row) => zipObject(columnNames, row)); @@ -82,6 +86,9 @@ export const queryEsSQL = async ( return { type: 'datatable', + meta: { + type: 'essql', + }, columns, rows, };