|
|
|
@ -1,4 +1,5 @@ |
|
|
|
|
import { DataFrame, FieldType, Field, Vector } from '../types'; |
|
|
|
|
import { FunctionalVector } from '../vector/FunctionalVector'; |
|
|
|
|
|
|
|
|
|
import { |
|
|
|
|
Table, |
|
|
|
@ -48,14 +49,18 @@ export function arrowTableToDataFrame(table: Table): ArrowDataFrame { |
|
|
|
|
if (col) { |
|
|
|
|
const schema = table.schema.fields[i]; |
|
|
|
|
let type = FieldType.other; |
|
|
|
|
const values: Vector<any> = col; |
|
|
|
|
let values: Vector<any> = col; |
|
|
|
|
switch ((schema.typeId as unknown) as ArrowType) { |
|
|
|
|
case ArrowType.Decimal: |
|
|
|
|
case ArrowType.Int: |
|
|
|
|
case ArrowType.FloatingPoint: { |
|
|
|
|
type = FieldType.number; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case ArrowType.Int: { |
|
|
|
|
type = FieldType.number; |
|
|
|
|
values = new NumberColumn(col); // Cast to number
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case ArrowType.Bool: { |
|
|
|
|
type = FieldType.boolean; |
|
|
|
|
break; |
|
|
|
@ -73,7 +78,7 @@ export function arrowTableToDataFrame(table: Table): ArrowDataFrame { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fields.push({ |
|
|
|
|
name: stripFieldNamePrefix(col.name), |
|
|
|
|
name: col.name, |
|
|
|
|
type, |
|
|
|
|
values, |
|
|
|
|
config: parseOptionalMeta(col.metadata.get('config')) || {}, |
|
|
|
@ -92,17 +97,6 @@ export function arrowTableToDataFrame(table: Table): ArrowDataFrame { |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// fieldNamePrefixSep is the delimiter used with fieldNamePrefix.
|
|
|
|
|
const fieldNamePrefixSep = '🦥: '; |
|
|
|
|
|
|
|
|
|
function stripFieldNamePrefix(name: string): string { |
|
|
|
|
const idx = name.indexOf(fieldNamePrefixSep); |
|
|
|
|
if (idx > 0) { |
|
|
|
|
return name.substring(idx + fieldNamePrefixSep.length); |
|
|
|
|
} |
|
|
|
|
return name; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function toArrowVector(field: Field): ArrowVector { |
|
|
|
|
// OR: Float64Vector.from([1, 2, 3]));
|
|
|
|
|
|
|
|
|
@ -129,17 +123,10 @@ export function grafanaDataFrameToArrowTable(data: DataFrame): Table { |
|
|
|
|
if (table instanceof Table) { |
|
|
|
|
return table as Table; |
|
|
|
|
} |
|
|
|
|
// Make sure the names are unique
|
|
|
|
|
const names = new Set<string>(); |
|
|
|
|
|
|
|
|
|
table = Table.new( |
|
|
|
|
data.fields.map((field, index) => { |
|
|
|
|
let name = field.name; |
|
|
|
|
if (names.has(field.name)) { |
|
|
|
|
name = `${index}${fieldNamePrefixSep}${field.name}`; |
|
|
|
|
} |
|
|
|
|
names.add(name); |
|
|
|
|
const column = Column.new(name, toArrowVector(field)); |
|
|
|
|
const column = Column.new(field.name, toArrowVector(field)); |
|
|
|
|
if (field.labels) { |
|
|
|
|
column.metadata.set('labels', JSON.stringify(field.labels)); |
|
|
|
|
} |
|
|
|
@ -161,3 +148,26 @@ export function grafanaDataFrameToArrowTable(data: DataFrame): Table { |
|
|
|
|
} |
|
|
|
|
return table; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
class NumberColumn extends FunctionalVector<number> { |
|
|
|
|
constructor(private col: Column) { |
|
|
|
|
super(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
get length() { |
|
|
|
|
return this.col.length; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
get(index: number): number { |
|
|
|
|
const v = this.col.get(index); |
|
|
|
|
if (v === null || isNaN(v)) { |
|
|
|
|
return v; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// The conversion operations are always silent, never give errors,
|
|
|
|
|
// but if the bigint is too huge and won’t fit the number type,
|
|
|
|
|
// then extra bits will be cut off, so we should be careful doing such conversion.
|
|
|
|
|
// See https://javascript.info/bigint
|
|
|
|
|
return Number(v); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|