Merge pull request #15034 from influxdata/fix-ui-newline-parsing
fix(ui): handle parsing Flux strings containing newlinespull/15044/head
commit
78e1a989fd
|
@ -160,7 +160,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@influxdata/clockface": "0.0.28",
|
"@influxdata/clockface": "0.0.28",
|
||||||
"@influxdata/flux-parser": "^0.3.0",
|
"@influxdata/flux-parser": "^0.3.0",
|
||||||
"@influxdata/giraffe": "0.16.2",
|
"@influxdata/giraffe": "0.16.3",
|
||||||
"@influxdata/influx": "0.5.5",
|
"@influxdata/influx": "0.5.5",
|
||||||
"@influxdata/influxdb-templates": "0.7.0",
|
"@influxdata/influxdb-templates": "0.7.0",
|
||||||
"@influxdata/react-custom-scrollbars": "4.3.8",
|
"@influxdata/react-custom-scrollbars": "4.3.8",
|
||||||
|
|
|
@ -19,14 +19,34 @@ export const parseResponseError = (response: string): FluxTable[] => {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
A Flux CSV response can contain multiple CSV files each joined by a newline.
|
||||||
|
This function splits up a CSV response into these individual CSV files.
|
||||||
|
|
||||||
|
See https://github.com/influxdata/flux/blob/master/docs/SPEC.md#multiple-tables.
|
||||||
|
*/
|
||||||
export const parseChunks = (response: string): string[] => {
|
export const parseChunks = (response: string): string[] => {
|
||||||
const trimmedResponse = response.trim()
|
const trimmedResponse = response.trim()
|
||||||
|
|
||||||
if (_.isEmpty(trimmedResponse)) {
|
if (trimmedResponse === '') {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
const chunks = trimmedResponse.split(/\n\s*\n/)
|
// Split the response into separate chunks whenever we encounter:
|
||||||
|
//
|
||||||
|
// 1. A newline
|
||||||
|
// 2. Followed by any amount of whitespace
|
||||||
|
// 3. Followed by a newline
|
||||||
|
// 4. Followed by a `#` character
|
||||||
|
//
|
||||||
|
// The last condition is [necessary][0] for handling CSV responses with
|
||||||
|
// values containing newlines.
|
||||||
|
//
|
||||||
|
// [0]: https://github.com/influxdata/influxdb/issues/15017
|
||||||
|
|
||||||
|
const chunks = trimmedResponse
|
||||||
|
.split(/\n\s*\n#/)
|
||||||
|
.map((s, i) => (i === 0 ? s : `#${s}`))
|
||||||
|
|
||||||
return chunks
|
return chunks
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
import {parseFiles} from './rawFluxDataTable'
|
||||||
|
|
||||||
|
describe('parseFiles', () => {
|
||||||
|
test('can parse multi-csv response', () => {
|
||||||
|
const CSV = `
|
||||||
|
#group,false,false,false,false
|
||||||
|
#datatype,string,long,string,long
|
||||||
|
#default,_result,,,
|
||||||
|
,result,table,message,value
|
||||||
|
,,0,howdy,5
|
||||||
|
,,0,hello there,5
|
||||||
|
,,0,hi,6
|
||||||
|
|
||||||
|
#group,false,false,false,false
|
||||||
|
#datatype,string,long,string,long
|
||||||
|
#default,_result,,,
|
||||||
|
,result,table,message,value
|
||||||
|
,,1,howdy,5
|
||||||
|
,,1,hello there,5
|
||||||
|
,,1,hi,6
|
||||||
|
`.trim()
|
||||||
|
|
||||||
|
const expectedData = [
|
||||||
|
['#group', 'false', 'false', 'false', 'false'],
|
||||||
|
['#datatype', 'string', 'long', 'string', 'long'],
|
||||||
|
['#default', '_result', '', '', ''],
|
||||||
|
['', 'result', 'table', 'message', 'value'],
|
||||||
|
['', '', '0', 'howdy', '5'],
|
||||||
|
['', '', '0', 'hello there', '5'],
|
||||||
|
['', '', '0', 'hi', '6'],
|
||||||
|
[],
|
||||||
|
['#group', 'false', 'false', 'false', 'false'],
|
||||||
|
['#datatype', 'string', 'long', 'string', 'long'],
|
||||||
|
['#default', '_result', '', '', ''],
|
||||||
|
['', 'result', 'table', 'message', 'value'],
|
||||||
|
['', '', '1', 'howdy', '5'],
|
||||||
|
['', '', '1', 'hello there', '5'],
|
||||||
|
['', '', '1', 'hi', '6'],
|
||||||
|
]
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
data: expectedData,
|
||||||
|
maxColumnCount: 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(parseFiles([CSV])).toEqual(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('can parse multi-csv response with values containing newlines', () => {
|
||||||
|
const CSV = `
|
||||||
|
#group,false,false,false,false
|
||||||
|
#datatype,string,long,string,long
|
||||||
|
#default,_result,,,
|
||||||
|
,result,table,message,value
|
||||||
|
,,0,howdy,5
|
||||||
|
,,0,"hello
|
||||||
|
|
||||||
|
there",5
|
||||||
|
,,0,hi,6
|
||||||
|
|
||||||
|
#group,false,false,false,false
|
||||||
|
#datatype,string,long,string,long
|
||||||
|
#default,_result,,,
|
||||||
|
,result,table,message,value
|
||||||
|
,,1,howdy,5
|
||||||
|
,,1,"hello
|
||||||
|
|
||||||
|
there",5
|
||||||
|
,,1,hi,6
|
||||||
|
`.trim()
|
||||||
|
|
||||||
|
const expectedData = [
|
||||||
|
['#group', 'false', 'false', 'false', 'false'],
|
||||||
|
['#datatype', 'string', 'long', 'string', 'long'],
|
||||||
|
['#default', '_result', '', '', ''],
|
||||||
|
['', 'result', 'table', 'message', 'value'],
|
||||||
|
['', '', '0', 'howdy', '5'],
|
||||||
|
['', '', '0', 'hello\n\nthere', '5'],
|
||||||
|
['', '', '0', 'hi', '6'],
|
||||||
|
[],
|
||||||
|
['#group', 'false', 'false', 'false', 'false'],
|
||||||
|
['#datatype', 'string', 'long', 'string', 'long'],
|
||||||
|
['#default', '_result', '', '', ''],
|
||||||
|
['', 'result', 'table', 'message', 'value'],
|
||||||
|
['', '', '1', 'howdy', '5'],
|
||||||
|
['', '', '1', 'hello\n\nthere', '5'],
|
||||||
|
['', '', '1', 'hi', '6'],
|
||||||
|
]
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
data: expectedData,
|
||||||
|
maxColumnCount: 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(parseFiles([CSV])).toEqual(expected)
|
||||||
|
})
|
||||||
|
})
|
|
@ -26,9 +26,6 @@ export const parseFiles = (responses: string[]): ParseFilesResult => {
|
||||||
// exceeded" error for large CSVs
|
// exceeded" error for large CSVs
|
||||||
data.push(parsedChunks[i][j])
|
data.push(parsedChunks[i][j])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add an empty line at the end
|
|
||||||
data.push([])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {data, maxColumnCount}
|
return {data, maxColumnCount}
|
||||||
|
|
|
@ -1090,10 +1090,10 @@
|
||||||
resolved "https://registry.yarnpkg.com/@influxdata/flux-parser/-/flux-parser-0.3.0.tgz#b63123ac814ad32c65e46a4097ba3d8b959416a5"
|
resolved "https://registry.yarnpkg.com/@influxdata/flux-parser/-/flux-parser-0.3.0.tgz#b63123ac814ad32c65e46a4097ba3d8b959416a5"
|
||||||
integrity sha512-nsm801l60kXFulcSWA2YH2YRz9oSsMlTK9Evn6Og9BoQnQMcwUsSUEug8mQRIUljnkNYV58JSs0W0mP8h7Y/ZQ==
|
integrity sha512-nsm801l60kXFulcSWA2YH2YRz9oSsMlTK9Evn6Og9BoQnQMcwUsSUEug8mQRIUljnkNYV58JSs0W0mP8h7Y/ZQ==
|
||||||
|
|
||||||
"@influxdata/giraffe@0.16.2":
|
"@influxdata/giraffe@0.16.3":
|
||||||
version "0.16.2"
|
version "0.16.3"
|
||||||
resolved "https://registry.yarnpkg.com/@influxdata/giraffe/-/giraffe-0.16.2.tgz#a2da3d157c4c751de8348f381a4d1b45d6bc3a43"
|
resolved "https://registry.yarnpkg.com/@influxdata/giraffe/-/giraffe-0.16.3.tgz#0b3e1d4c7894d6234b5001ab9cbcf731dd2e5ce8"
|
||||||
integrity sha512-cUbFwUeXbcyQp1Y5/3kEqb8Gt2Mh8+lFRRkgbpmdzTDub6xl1vJwlQvkXMLgdxebofVuApRjy0xj/Sbuq34Eug==
|
integrity sha512-GaAAOmjUvbpJLmg6sHWayTD/wgGcXgLYhaKyW8Hp0UUGC1840HFWrLuSVG/mpXUen+AJBnZMPFrI64cQNNCzYg==
|
||||||
|
|
||||||
"@influxdata/influx@0.5.5":
|
"@influxdata/influx@0.5.5":
|
||||||
version "0.5.5"
|
version "0.5.5"
|
||||||
|
|
Loading…
Reference in New Issue