Commit 73c4bef7 by Kyle Brandt Committed by GitHub

Dependency: sdk's dataframe package renamed to data (#22700)

* use sdk 0.24.0
parent 2c6993f1
......@@ -32,7 +32,7 @@ require (
github.com/gorilla/websocket v1.4.1
github.com/gosimple/slug v1.4.2
github.com/grafana/grafana-plugin-model v0.0.0-20190930120109-1fc953a61fb4
github.com/grafana/grafana-plugin-sdk-go v0.21.0
github.com/grafana/grafana-plugin-sdk-go v0.24.0
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd
github.com/hashicorp/go-plugin v1.0.1
github.com/hashicorp/go-version v1.1.0
......
......@@ -135,6 +135,10 @@ github.com/grafana/grafana-plugin-model v0.0.0-20190930120109-1fc953a61fb4 h1:SP
github.com/grafana/grafana-plugin-model v0.0.0-20190930120109-1fc953a61fb4/go.mod h1:nc0XxBzjeGcrMltCDw269LoWF9S8ibhgxolCdA1R8To=
github.com/grafana/grafana-plugin-sdk-go v0.21.0 h1:5en5MdVFgeD9tuHDuJgwHYdIVjPs0PN0a7ZQ2bZNxNk=
github.com/grafana/grafana-plugin-sdk-go v0.21.0/go.mod h1:G6Ov9M+FDOZXNw8eKXINO6XzqdUvTs7huwyQp5jLTBQ=
github.com/grafana/grafana-plugin-sdk-go v0.22.1-0.20200310164332-6b4c0d952d70 h1:VQFBaWHlxwjb4VB5HuXtuucMzXJ7xZGGASzbqA3VtVo=
github.com/grafana/grafana-plugin-sdk-go v0.22.1-0.20200310164332-6b4c0d952d70/go.mod h1:G6Ov9M+FDOZXNw8eKXINO6XzqdUvTs7huwyQp5jLTBQ=
github.com/grafana/grafana-plugin-sdk-go v0.24.0 h1:sgd9rAQMmB0rAIMd4JVMFM0Gc+CTHoDwN5oxkPjVrGw=
github.com/grafana/grafana-plugin-sdk-go v0.24.0/go.mod h1:G6Ov9M+FDOZXNw8eKXINO6XzqdUvTs7huwyQp5jLTBQ=
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd h1:rNuUHR+CvK1IS89MMtcF0EpcVMZtjKfPRp4MEmt/aTs=
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
github.com/hashicorp/go-plugin v1.0.1 h1:4OtAfUGbnKC6yS48p0CtMX2oFYtzFZVv6rok3cRWgnE=
......
......@@ -7,7 +7,7 @@ import (
"path"
"strconv"
"github.com/grafana/grafana-plugin-sdk-go/dataframe"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana-plugin-sdk-go/genproto/pluginv2"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
......@@ -189,7 +189,7 @@ func (s *transformCallback) QueryData(ctx context.Context, req *pluginv2.QueryDa
if err != nil {
return nil, err
}
encFrame, err := dataframe.MarshalArrow(frame)
encFrame, err := data.MarshalArrow(frame)
if err != nil {
return nil, err
}
......
......@@ -3,19 +3,19 @@ package tsdb
import (
"time"
"github.com/grafana/grafana-plugin-sdk-go/dataframe"
"github.com/grafana/grafana-plugin-sdk-go/data"
)
// SeriesToFrame converts a TimeSeries to a sdk Frame
func SeriesToFrame(series *TimeSeries) (*dataframe.Frame, error) {
func SeriesToFrame(series *TimeSeries) (*data.Frame, error) {
timeVec := make([]*time.Time, len(series.Points))
floatVec := make([]*float64, len(series.Points))
for idx, point := range series.Points {
timeVec[idx], floatVec[idx] = convertTSDBTimePoint(point)
}
frame := dataframe.New(series.Name,
dataframe.NewField("time", nil, timeVec),
dataframe.NewField("value", dataframe.Labels(series.Tags), floatVec),
frame := data.NewFrame(series.Name,
data.NewField("time", nil, timeVec),
data.NewField("value", data.Labels(series.Tags), floatVec),
)
return frame, nil
......
package plugin
import (
"fmt"
"net/http"
"net/http/pprof"
"os"
hclog "github.com/hashicorp/go-hclog"
)
// SetupPluginEnvironment will read the environment variables and apply the
// standard environment behavior. As the SDK evolves, this will likely change!
func SetupPluginEnvironment(pluginID string) hclog.Logger {
pluginLogger := hclog.New(&hclog.LoggerOptions{
Name: pluginID,
// TODO: How to make level configurable?
Level: hclog.LevelFromString("DEBUG"),
JSONFormat: true,
// Color: hclog.ColorOff, (when we use 0.12)
})
// Enable profiler
profilerEnabled := false
if value, ok := os.LookupEnv("GF_PLUGINS_PROFILER"); ok {
// compare value to plugin name
if value == pluginID {
profilerEnabled = true
}
}
pluginLogger.Info("Profiler", "enabled", profilerEnabled)
if profilerEnabled {
profilerPort := "6060"
if value, ok := os.LookupEnv("GF_PLUGINS_PROFILER_PORT"); ok {
profilerPort = value
}
pluginLogger.Info("Profiler", "port", profilerPort)
portConfig := fmt.Sprintf(":%s", profilerPort)
r := http.NewServeMux()
r.HandleFunc("/debug/pprof/", pprof.Index)
r.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
r.HandleFunc("/debug/pprof/profile", pprof.Profile)
r.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
r.HandleFunc("/debug/pprof/trace", pprof.Trace)
go func() {
if err := http.ListenAndServe(portConfig, r); err != nil {
pluginLogger.Error("Error Running profiler: %s", err.Error())
}
}()
}
return pluginLogger
}
package dataframe
package data
import (
"encoding/json"
......@@ -70,7 +70,7 @@ func MarshalArrow(f *Frame) ([]byte, error) {
return fb.Buff.Bytes(), nil
}
// buildArrowFields builds Arrow field definitions from a DataFrame.
// buildArrowFields builds Arrow field definitions from a Frame.
func buildArrowFields(f *Frame) ([]arrow.Field, error) {
arrowFields := make([]arrow.Field, len(f.Fields))
......@@ -107,13 +107,13 @@ func buildArrowFields(f *Frame) ([]arrow.Field, error) {
return arrowFields, nil
}
// buildArrowColumns builds Arrow columns from a DataFrame.
// buildArrowColumns builds Arrow columns from a Frame.
func buildArrowColumns(f *Frame, arrowFields []arrow.Field) ([]array.Column, error) {
pool := memory.NewGoAllocator()
columns := make([]array.Column, len(f.Fields))
for fieldIdx, field := range f.Fields {
switch v := field.Vector.(type) {
switch v := field.vector.(type) {
case *int8Vector:
columns[fieldIdx] = *buildInt8Column(pool, arrowFields[fieldIdx], v)
......@@ -187,7 +187,7 @@ func buildArrowColumns(f *Frame, arrowFields []arrow.Field) ([]array.Column, err
return columns, nil
}
// buildArrowSchema builds an Arrow schema for a DataFrame.
// buildArrowSchema builds an Arrow schema for a Frame.
func buildArrowSchema(f *Frame, fs []arrow.Field) (*arrow.Schema, error) {
tableMetaMap := map[string]string{
"name": f.Name,
......@@ -215,7 +215,7 @@ func buildArrowSchema(f *Frame, fs []arrow.Field) (*arrow.Schema, error) {
// fieldToArrow returns the corresponding Arrow primitive type and nullable property to the fields'
// Vector primitives.
func fieldToArrow(f *Field) (arrow.DataType, bool, error) {
switch f.Vector.(type) {
switch f.vector.(type) {
case *stringVector:
return &arrow.StringType{}, false, nil
......@@ -285,7 +285,7 @@ func fieldToArrow(f *Field) (arrow.DataType, bool, error) {
return &arrow.TimestampType{}, true, nil
default:
return nil, false, fmt.Errorf("unsupported type for conversion to arrow: %T", f.Vector)
return nil, false, fmt.Errorf("unsupported type for conversion to arrow: %T", f.vector)
}
}
......@@ -317,82 +317,82 @@ func initializeFrameFields(schema *arrow.Schema, frame *Frame) ([]bool, error) {
switch field.Type.ID() {
case arrow.STRING:
if nullable[idx] {
sdkField.Vector = newNullableStringVector(0)
sdkField.vector = newNullableStringVector(0)
break
}
sdkField.Vector = newStringVector(0)
sdkField.vector = newStringVector(0)
case arrow.INT8:
if nullable[idx] {
sdkField.Vector = newNullableInt8Vector(0)
sdkField.vector = newNullableInt8Vector(0)
break
}
sdkField.Vector = newInt8Vector(0)
sdkField.vector = newInt8Vector(0)
case arrow.INT16:
if nullable[idx] {
sdkField.Vector = newNullableInt16Vector(0)
sdkField.vector = newNullableInt16Vector(0)
break
}
sdkField.Vector = newInt16Vector(0)
sdkField.vector = newInt16Vector(0)
case arrow.INT32:
if nullable[idx] {
sdkField.Vector = newNullableInt32Vector(0)
sdkField.vector = newNullableInt32Vector(0)
break
}
sdkField.Vector = newInt32Vector(0)
sdkField.vector = newInt32Vector(0)
case arrow.INT64:
if nullable[idx] {
sdkField.Vector = newNullableInt64Vector(0)
sdkField.vector = newNullableInt64Vector(0)
break
}
sdkField.Vector = newInt64Vector(0)
sdkField.vector = newInt64Vector(0)
case arrow.UINT8:
if nullable[idx] {
sdkField.Vector = newNullableUint8Vector(0)
sdkField.vector = newNullableUint8Vector(0)
break
}
sdkField.Vector = newUint8Vector(0)
sdkField.vector = newUint8Vector(0)
case arrow.UINT16:
if nullable[idx] {
sdkField.Vector = newNullableUint16Vector(0)
sdkField.vector = newNullableUint16Vector(0)
break
}
sdkField.Vector = newUint16Vector(0)
sdkField.vector = newUint16Vector(0)
case arrow.UINT32:
if nullable[idx] {
sdkField.Vector = newNullableUint32Vector(0)
sdkField.vector = newNullableUint32Vector(0)
break
}
sdkField.Vector = newUint32Vector(0)
sdkField.vector = newUint32Vector(0)
case arrow.UINT64:
if nullable[idx] {
sdkField.Vector = newNullableUint64Vector(0)
sdkField.vector = newNullableUint64Vector(0)
break
}
sdkField.Vector = newUint64Vector(0)
sdkField.vector = newUint64Vector(0)
case arrow.FLOAT32:
if nullable[idx] {
sdkField.Vector = newNullableFloat32Vector(0)
sdkField.vector = newNullableFloat32Vector(0)
break
}
sdkField.Vector = newFloat32Vector(0)
sdkField.vector = newFloat32Vector(0)
case arrow.FLOAT64:
if nullable[idx] {
sdkField.Vector = newNullableFloat64Vector(0)
sdkField.vector = newNullableFloat64Vector(0)
break
}
sdkField.Vector = newFloat64Vector(0)
sdkField.vector = newFloat64Vector(0)
case arrow.BOOL:
if nullable[idx] {
sdkField.Vector = newNullableBoolVector(0)
sdkField.vector = newNullableBoolVector(0)
break
}
sdkField.Vector = newBoolVector(0)
sdkField.vector = newBoolVector(0)
case arrow.TIMESTAMP:
if nullable[idx] {
sdkField.Vector = newNullableTimeTimeVector(0)
sdkField.vector = newNullableTimeTimeVector(0)
break
}
sdkField.Vector = newTimeTimeVector(0)
sdkField.vector = newTimeTimeVector(0)
default:
return nullable, fmt.Errorf("unsupported conversion from arrow to sdk type for arrow type %v", field.Type.ID().String())
}
......@@ -420,14 +420,14 @@ func populateFrameFields(fR *ipc.FileReader, nullable []bool, frame *Frame) erro
if nullable[i] {
if v.IsNull(rIdx) {
var ns *string
frame.Fields[i].Vector.Append(ns)
frame.Fields[i].vector.Append(ns)
continue
}
rv := v.Value(rIdx)
frame.Fields[i].Vector.Append(&rv)
frame.Fields[i].vector.Append(&rv)
continue
}
frame.Fields[i].Vector.Append(v.Value(rIdx))
frame.Fields[i].vector.Append(v.Value(rIdx))
}
case arrow.INT8:
v := array.NewInt8Data(col.Data())
......@@ -435,14 +435,14 @@ func populateFrameFields(fR *ipc.FileReader, nullable []bool, frame *Frame) erro
if nullable[i] {
if v.IsNull(rIdx) {
var ns *int8
frame.Fields[i].Vector.Append(ns)
frame.Fields[i].vector.Append(ns)
continue
}
rv := v.Value(rIdx)
frame.Fields[i].Vector.Append(&rv)
frame.Fields[i].vector.Append(&rv)
continue
}
frame.Fields[i].Vector.Append(v.Value(rIdx))
frame.Fields[i].vector.Append(v.Value(rIdx))
}
case arrow.INT16:
v := array.NewInt16Data(col.Data())
......@@ -450,14 +450,14 @@ func populateFrameFields(fR *ipc.FileReader, nullable []bool, frame *Frame) erro
if nullable[i] {
if v.IsNull(rIdx) {
var ns *int16
frame.Fields[i].Vector.Append(ns)
frame.Fields[i].vector.Append(ns)
continue
}
rv := v.Value(rIdx)
frame.Fields[i].Vector.Append(&rv)
frame.Fields[i].vector.Append(&rv)
continue
}
frame.Fields[i].Vector.Append(v.Value(rIdx))
frame.Fields[i].vector.Append(v.Value(rIdx))
}
case arrow.INT32:
v := array.NewInt32Data(col.Data())
......@@ -465,14 +465,14 @@ func populateFrameFields(fR *ipc.FileReader, nullable []bool, frame *Frame) erro
if nullable[i] {
if v.IsNull(rIdx) {
var ns *int32
frame.Fields[i].Vector.Append(ns)
frame.Fields[i].vector.Append(ns)
continue
}
rv := v.Value(rIdx)
frame.Fields[i].Vector.Append(&rv)
frame.Fields[i].vector.Append(&rv)
continue
}
frame.Fields[i].Vector.Append(v.Value(rIdx))
frame.Fields[i].vector.Append(v.Value(rIdx))
}
case arrow.INT64:
v := array.NewInt64Data(col.Data())
......@@ -480,14 +480,14 @@ func populateFrameFields(fR *ipc.FileReader, nullable []bool, frame *Frame) erro
if nullable[i] {
if v.IsNull(rIdx) {
var ns *int64
frame.Fields[i].Vector.Append(ns)
frame.Fields[i].vector.Append(ns)
continue
}
rv := v.Value(rIdx)
frame.Fields[i].Vector.Append(&rv)
frame.Fields[i].vector.Append(&rv)
continue
}
frame.Fields[i].Vector.Append(v.Value(rIdx))
frame.Fields[i].vector.Append(v.Value(rIdx))
}
case arrow.UINT8:
v := array.NewUint8Data(col.Data())
......@@ -495,14 +495,14 @@ func populateFrameFields(fR *ipc.FileReader, nullable []bool, frame *Frame) erro
if nullable[i] {
if v.IsNull(rIdx) {
var ns *uint8
frame.Fields[i].Vector.Append(ns)
frame.Fields[i].vector.Append(ns)
continue
}
rv := v.Value(rIdx)
frame.Fields[i].Vector.Append(&rv)
frame.Fields[i].vector.Append(&rv)
continue
}
frame.Fields[i].Vector.Append(v.Value(rIdx))
frame.Fields[i].vector.Append(v.Value(rIdx))
}
case arrow.UINT32:
v := array.NewUint32Data(col.Data())
......@@ -510,14 +510,14 @@ func populateFrameFields(fR *ipc.FileReader, nullable []bool, frame *Frame) erro
if nullable[i] {
if v.IsNull(rIdx) {
var ns *uint32
frame.Fields[i].Vector.Append(ns)
frame.Fields[i].vector.Append(ns)
continue
}
rv := v.Value(rIdx)
frame.Fields[i].Vector.Append(&rv)
frame.Fields[i].vector.Append(&rv)
continue
}
frame.Fields[i].Vector.Append(v.Value(rIdx))
frame.Fields[i].vector.Append(v.Value(rIdx))
}
case arrow.UINT64:
v := array.NewUint64Data(col.Data())
......@@ -525,14 +525,14 @@ func populateFrameFields(fR *ipc.FileReader, nullable []bool, frame *Frame) erro
if nullable[i] {
if v.IsNull(rIdx) {
var ns *uint64
frame.Fields[i].Vector.Append(ns)
frame.Fields[i].vector.Append(ns)
continue
}
rv := v.Value(rIdx)
frame.Fields[i].Vector.Append(&rv)
frame.Fields[i].vector.Append(&rv)
continue
}
frame.Fields[i].Vector.Append(v.Value(rIdx))
frame.Fields[i].vector.Append(v.Value(rIdx))
}
case arrow.UINT16:
v := array.NewUint16Data(col.Data())
......@@ -540,14 +540,14 @@ func populateFrameFields(fR *ipc.FileReader, nullable []bool, frame *Frame) erro
if nullable[i] {
if v.IsNull(rIdx) {
var ns *uint16
frame.Fields[i].Vector.Append(ns)
frame.Fields[i].vector.Append(ns)
continue
}
rv := v.Value(rIdx)
frame.Fields[i].Vector.Append(&rv)
frame.Fields[i].vector.Append(&rv)
continue
}
frame.Fields[i].Vector.Append(v.Value(rIdx))
frame.Fields[i].vector.Append(v.Value(rIdx))
}
case arrow.FLOAT32:
v := array.NewFloat32Data(col.Data())
......@@ -555,14 +555,14 @@ func populateFrameFields(fR *ipc.FileReader, nullable []bool, frame *Frame) erro
if nullable[i] {
if v.IsNull(vIdx) {
var nf *float32
frame.Fields[i].Vector.Append(nf)
frame.Fields[i].vector.Append(nf)
continue
}
vF := f
frame.Fields[i].Vector.Append(&vF)
frame.Fields[i].vector.Append(&vF)
continue
}
frame.Fields[i].Vector.Append(f)
frame.Fields[i].vector.Append(f)
}
case arrow.FLOAT64:
v := array.NewFloat64Data(col.Data())
......@@ -570,14 +570,14 @@ func populateFrameFields(fR *ipc.FileReader, nullable []bool, frame *Frame) erro
if nullable[i] {
if v.IsNull(vIdx) {
var nf *float64
frame.Fields[i].Vector.Append(nf)
frame.Fields[i].vector.Append(nf)
continue
}
vF := f
frame.Fields[i].Vector.Append(&vF)
frame.Fields[i].vector.Append(&vF)
continue
}
frame.Fields[i].Vector.Append(f)
frame.Fields[i].vector.Append(f)
}
case arrow.BOOL:
v := array.NewBooleanData(col.Data())
......@@ -585,14 +585,14 @@ func populateFrameFields(fR *ipc.FileReader, nullable []bool, frame *Frame) erro
if nullable[i] {
if v.IsNull(sIdx) {
var ns *bool
frame.Fields[i].Vector.Append(ns)
frame.Fields[i].vector.Append(ns)
continue
}
vB := v.Value(sIdx)
frame.Fields[i].Vector.Append(&vB)
frame.Fields[i].vector.Append(&vB)
continue
}
frame.Fields[i].Vector.Append(v.Value(sIdx))
frame.Fields[i].vector.Append(v.Value(sIdx))
}
case arrow.TIMESTAMP:
v := array.NewTimestampData(col.Data())
......@@ -601,13 +601,13 @@ func populateFrameFields(fR *ipc.FileReader, nullable []bool, frame *Frame) erro
if nullable[i] {
if v.IsNull(vIdx) {
var nt *time.Time
frame.Fields[i].Vector.Append(nt)
frame.Fields[i].vector.Append(nt)
continue
}
frame.Fields[i].Vector.Append(&t)
frame.Fields[i].vector.Append(&t)
continue
}
frame.Fields[i].Vector.Append(t)
frame.Fields[i].vector.Append(t)
}
default:
return fmt.Errorf("unsupported arrow type %s for conversion", col.DataType().ID())
......
package dataframe
package data
import "encoding/json"
// Warning contains information about problems in a dataframe.
// Warning contains information about problems in a data.
type Warning struct {
// Short message (typically shown in the header)
Message string `json:"message,omitempty"`
......
package dataframe
// Package data provides data structures that Grafana recognizes. The Frame
// object represents a Grafana Dataframe which can represent data such as tables
// and time series.
package data
import (
"fmt"
"math"
"sort"
"strings"
"time"
"github.com/google/go-cmp/cmp"
)
// Frame represents a columnar storage with optional labels.
......@@ -21,7 +27,7 @@ type Frame struct {
type Field struct {
Name string
Config *FieldConfig
Vector Vector // TODO? in the frontend, the variable is called "Values"
vector vector // TODO? in the frontend, the variable is called "Values"
Labels Labels
}
......@@ -29,13 +35,13 @@ type Field struct {
type Fields []*Field
// AppendRow adds a new row to the Frame by appending to each element of vals to
// the corresponding Field in the dataframe.
// The dataframe's Fields and the Fields' Vectors must be initalized or AppendRow will panic.
// the corresponding Field in the data.
// The Frame's Fields must be initalized or AppendRow will panic.
// The number of arguments must match the number of Fields in the Frame and each type must coorespond
// to the Field type or AppendRow will panic.
func (f *Frame) AppendRow(vals ...interface{}) {
for i, v := range vals {
f.Fields[i].Vector.Append(v)
f.Fields[i].vector.Append(v)
}
}
......@@ -45,7 +51,7 @@ func (f *Frame) AppendWarning(message string, details string) {
}
// AppendRowSafe adds a new row to the Frame by appending to each each element of vals to
// the corresponding Field in the dataframe. It has the some constraints as AppendRow but will
// the corresponding Field in the data. It has the some constraints as AppendRow but will
// return an error under those conditions instead of panicing.
func (f *Frame) AppendRowSafe(vals ...interface{}) error {
if len(vals) != len(f.Fields) {
......@@ -53,29 +59,44 @@ func (f *Frame) AppendRowSafe(vals ...interface{}) error {
}
// check validity before any modification
for i, v := range vals {
if f.Fields[i] == nil {
if f.Fields[i] == nil || f.Fields[i].vector == nil {
return fmt.Errorf("can not append to uninitalized Field at field index %v", i)
}
if f.Fields[i].Vector == nil {
return fmt.Errorf("can not append to uninitalized Field Vector at field index %v", i)
}
dfPType := f.Fields[i].Vector.PrimitiveType()
dfPType := f.Fields[i].Type()
if v == nil {
if !dfPType.Nullable() {
return fmt.Errorf("can not append nil to non-nullable vector with underlying type %s at field index %v", dfPType, i)
}
}
if v != nil && pTypeFromVal(v) != dfPType {
if v != nil && fieldTypeFromVal(v) != dfPType {
return fmt.Errorf("invalid type appending row at index %v, got %T want %v", i, v, dfPType.ItemTypeString())
}
f.Fields[i].Vector.Append(v)
f.Fields[i].vector.Append(v)
}
return nil
}
// TypeIndices returns a slice of Field index positions for the given pTypes.
func (f *Frame) TypeIndices(pTypes ...FieldType) []int {
indices := []int{}
if f.Fields == nil {
return indices
}
for fieldIdx, f := range f.Fields {
vecType := f.Type()
for _, pType := range pTypes {
if pType == vecType {
indices = append(indices, fieldIdx)
break
}
}
}
return indices
}
// NewField returns a new instance of Field.
func NewField(name string, labels Labels, values interface{}) *Field {
var vec Vector
var vec vector
switch v := values.(type) {
case []int8:
vec = newVector(v, len(v))
......@@ -213,14 +234,66 @@ func NewField(name string, labels Labels, values interface{}) *Field {
return &Field{
Name: name,
Vector: vec,
vector: vec,
Labels: labels,
}
}
// Len returns the number of elements in the field.
// Set sets the Field's value at index idx to val.
// It will panic if idx is out of range.
func (f *Field) Set(idx int, val interface{}) {
f.vector.Set(idx, val)
}
// Append appends element i to the Field.
func (f *Field) Append(i interface{}) {
f.vector.Append(i)
}
// Extend extends the Field length by i.
func (f *Field) Extend(i int) {
f.vector.Extend(i)
}
// At returns the the element at index idx of the Field.
// It will panic if idx is out of range.
func (f *Field) At(idx int) interface{} {
return f.vector.At(idx)
}
// Len returns the number of elements in the Field.
func (f *Field) Len() int {
return f.Vector.Len()
return f.vector.Len()
}
// Type returns the underlying primitive type of the Field.
func (f *Field) Type() FieldType {
return f.vector.Type()
}
// PointerAt returns a pointer to the value at idx of the Field.
// It will panic if idx is out of range.
func (f *Field) PointerAt(idx int) interface{} {
return f.vector.PointerAt(idx)
}
// CopyAt returns a copy of the value of the specified index idx.
// It will panic if idx is out of range.
func (f *Field) CopyAt(idx int) interface{} {
return f.vector.CopyAt(idx)
}
// ConcreteAt returns the concrete value at the specified index idx.
// A non-pointer type is returned regardless if the underlying vector is a pointer
// type or not. If the value is a pointer type, and is nil, then the zero value
// is returned and ok will be false.
func (f *Field) ConcreteAt(idx int) (val interface{}, ok bool) {
return f.vector.ConcreteAt(idx)
}
// Nullable returns if the the Field's elements are nullable.
func (f *Field) Nullable() bool {
return f.Type().Nullable()
}
// SetConfig modifies the Field's Config property to
......@@ -303,8 +376,8 @@ func LabelsFromString(s string) (Labels, error) {
return labels, nil
}
// New returns a new instance of a Frame.
func New(name string, fields ...*Field) *Frame {
// NewFrame returns a new instance of a Frame.
func NewFrame(name string, fields ...*Field) *Frame {
return &Frame{
Name: name,
Fields: fields,
......@@ -318,3 +391,97 @@ func (f *Frame) Rows() int {
}
return 0
}
// At returns the value of the specified fieldIdx and rowIdx.
// It will panic if either the fieldIdx or rowIdx are out of range.
func (f *Frame) At(fieldIdx int, rowIdx int) interface{} {
return f.Fields[fieldIdx].vector.At(rowIdx)
}
// CopyAt returns a copy of the value of the specified fieldIdx and rowIdx.
// It will panic if either the fieldIdx or rowIdx are out of range.
func (f *Frame) CopyAt(fieldIdx int, rowIdx int) interface{} {
return f.Fields[fieldIdx].vector.CopyAt(rowIdx)
}
// Set set the val to the specified fieldIdx and rowIdx.
// It will panic if either the fieldIdx or rowIdx are out of range.
func (f *Frame) Set(fieldIdx int, rowIdx int, val interface{}) {
f.Fields[fieldIdx].vector.Set(rowIdx, val)
}
// Extend extends all the Fields by length by i.
func (f *Frame) Extend(i int) {
for _, f := range f.Fields {
f.vector.Extend(i)
}
}
// ConcreteAt returns the concrete value at the specified fieldIdx and rowIdx.
// A non-pointer type is returned regardless if the underlying type is a pointer
// type or not. If the value is a pointer type, and is nil, then the zero value
// is returned and ok will be false.
func (f *Frame) ConcreteAt(fieldIdx int, rowIdx int) (val interface{}, ok bool) {
return f.Fields[fieldIdx].vector.ConcreteAt(rowIdx)
}
// RowLen returns the the length of the Frame Fields.
// If the Length of all the Fields is not the same then error is returned.
// If the Frame's Fields are nil an error is returned.
func (f *Frame) RowLen() (int, error) {
if f.Fields == nil || len(f.Fields) == 0 {
return 0, fmt.Errorf("frame's fields are nil or of zero length")
}
var l int
for i := 0; i < len(f.Fields); i++ {
if f.Fields[i].vector == nil {
return 0, fmt.Errorf("frame's field at index %v is nil", i)
}
if i == 0 {
l = f.Fields[i].Len()
continue
}
if l != f.Fields[i].Len() {
return 0, fmt.Errorf("frame has different field lengths, field 0 is len %v but field %v is len %v", l, i, f.Fields[i].vector.Len())
}
}
return l, nil
}
// FrameTestCompareOptions returns go-cmp testing options to allow testing of Frame equivelnce.
// The intent is to only use this for testing.
func FrameTestCompareOptions() []cmp.Option {
confFloats := cmp.Comparer(func(x, y *ConfFloat64) bool {
if x == nil && y == nil {
return true
}
if y == nil {
if math.IsNaN(float64(*x)) {
return true
}
if math.IsInf(float64(*x), 1) {
return true
}
if math.IsInf(float64(*x), -1) {
return true
}
}
if x == nil {
if math.IsNaN(float64(*y)) {
return true
}
if math.IsInf(float64(*y), 1) {
return true
}
if math.IsInf(float64(*y), -1) {
return true
}
}
return *x == *y
})
unexportedField := cmp.AllowUnexported(Field{})
return []cmp.Option{confFloats, unexportedField}
}
package dataframe
package data
//go:generate genny -in=$GOFILE -out=nullable_vector.gen.go gen "gen=uint8,uint16,uint32,uint64,int8,int16,int32,int64,float32,float64,string,bool,time.Time"
......@@ -25,6 +25,26 @@ func (v *nullablegenVector) At(i int) interface{} {
return (*v)[i]
}
func (v *nullablegenVector) CopyAt(i int) interface{} {
if (*v)[i] == nil {
var g *gen
return g
}
var g gen
g = *(*v)[i]
return &g
}
func (v *nullablegenVector) ConcreteAt(i int) (interface{}, bool) {
var g gen
val := (*v)[i]
if val == nil {
return g, false
}
g = *val
return g, true
}
func (v *nullablegenVector) PointerAt(i int) interface{} {
return &(*v)[i]
}
......@@ -33,8 +53,8 @@ func (v *nullablegenVector) Len() int {
return len((*v))
}
func (v *nullablegenVector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *nullablegenVector) Type() FieldType {
return vectorFieldType(v)
}
func (v *nullablegenVector) Extend(i int) {
......
package dataframe
package data
import (
"github.com/cheekybits/genny/generic"
......@@ -35,8 +35,18 @@ func (v *genVector) Len() int {
return len((*v))
}
func (v *genVector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *genVector) CopyAt(i int) interface{} {
var g gen
g = (*v)[i]
return g
}
func (v *genVector) ConcreteAt(i int) (interface{}, bool) {
return v.At(i), true
}
func (v *genVector) Type() FieldType {
return vectorFieldType(v)
}
func (v *genVector) Extend(i int) {
......
......@@ -2,7 +2,7 @@
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package dataframe
package data
import "time"
......@@ -31,6 +31,26 @@ func (v *nullableUint8Vector) At(i int) interface{} {
return (*v)[i]
}
func (v *nullableUint8Vector) CopyAt(i int) interface{} {
if (*v)[i] == nil {
var g *uint8
return g
}
var g uint8
g = *(*v)[i]
return &g
}
func (v *nullableUint8Vector) ConcreteAt(i int) (interface{}, bool) {
var g uint8
val := (*v)[i]
if val == nil {
return g, false
}
g = *val
return g, true
}
func (v *nullableUint8Vector) PointerAt(i int) interface{} {
return &(*v)[i]
}
......@@ -39,8 +59,8 @@ func (v *nullableUint8Vector) Len() int {
return len((*v))
}
func (v *nullableUint8Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *nullableUint8Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *nullableUint8Vector) Extend(i int) {
......@@ -72,6 +92,26 @@ func (v *nullableUint16Vector) At(i int) interface{} {
return (*v)[i]
}
func (v *nullableUint16Vector) CopyAt(i int) interface{} {
if (*v)[i] == nil {
var g *uint16
return g
}
var g uint16
g = *(*v)[i]
return &g
}
func (v *nullableUint16Vector) ConcreteAt(i int) (interface{}, bool) {
var g uint16
val := (*v)[i]
if val == nil {
return g, false
}
g = *val
return g, true
}
func (v *nullableUint16Vector) PointerAt(i int) interface{} {
return &(*v)[i]
}
......@@ -80,8 +120,8 @@ func (v *nullableUint16Vector) Len() int {
return len((*v))
}
func (v *nullableUint16Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *nullableUint16Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *nullableUint16Vector) Extend(i int) {
......@@ -113,6 +153,26 @@ func (v *nullableUint32Vector) At(i int) interface{} {
return (*v)[i]
}
func (v *nullableUint32Vector) CopyAt(i int) interface{} {
if (*v)[i] == nil {
var g *uint32
return g
}
var g uint32
g = *(*v)[i]
return &g
}
func (v *nullableUint32Vector) ConcreteAt(i int) (interface{}, bool) {
var g uint32
val := (*v)[i]
if val == nil {
return g, false
}
g = *val
return g, true
}
func (v *nullableUint32Vector) PointerAt(i int) interface{} {
return &(*v)[i]
}
......@@ -121,8 +181,8 @@ func (v *nullableUint32Vector) Len() int {
return len((*v))
}
func (v *nullableUint32Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *nullableUint32Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *nullableUint32Vector) Extend(i int) {
......@@ -154,6 +214,26 @@ func (v *nullableUint64Vector) At(i int) interface{} {
return (*v)[i]
}
func (v *nullableUint64Vector) CopyAt(i int) interface{} {
if (*v)[i] == nil {
var g *uint64
return g
}
var g uint64
g = *(*v)[i]
return &g
}
func (v *nullableUint64Vector) ConcreteAt(i int) (interface{}, bool) {
var g uint64
val := (*v)[i]
if val == nil {
return g, false
}
g = *val
return g, true
}
func (v *nullableUint64Vector) PointerAt(i int) interface{} {
return &(*v)[i]
}
......@@ -162,8 +242,8 @@ func (v *nullableUint64Vector) Len() int {
return len((*v))
}
func (v *nullableUint64Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *nullableUint64Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *nullableUint64Vector) Extend(i int) {
......@@ -195,6 +275,26 @@ func (v *nullableInt8Vector) At(i int) interface{} {
return (*v)[i]
}
func (v *nullableInt8Vector) CopyAt(i int) interface{} {
if (*v)[i] == nil {
var g *int8
return g
}
var g int8
g = *(*v)[i]
return &g
}
func (v *nullableInt8Vector) ConcreteAt(i int) (interface{}, bool) {
var g int8
val := (*v)[i]
if val == nil {
return g, false
}
g = *val
return g, true
}
func (v *nullableInt8Vector) PointerAt(i int) interface{} {
return &(*v)[i]
}
......@@ -203,8 +303,8 @@ func (v *nullableInt8Vector) Len() int {
return len((*v))
}
func (v *nullableInt8Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *nullableInt8Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *nullableInt8Vector) Extend(i int) {
......@@ -236,6 +336,26 @@ func (v *nullableInt16Vector) At(i int) interface{} {
return (*v)[i]
}
func (v *nullableInt16Vector) CopyAt(i int) interface{} {
if (*v)[i] == nil {
var g *int16
return g
}
var g int16
g = *(*v)[i]
return &g
}
func (v *nullableInt16Vector) ConcreteAt(i int) (interface{}, bool) {
var g int16
val := (*v)[i]
if val == nil {
return g, false
}
g = *val
return g, true
}
func (v *nullableInt16Vector) PointerAt(i int) interface{} {
return &(*v)[i]
}
......@@ -244,8 +364,8 @@ func (v *nullableInt16Vector) Len() int {
return len((*v))
}
func (v *nullableInt16Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *nullableInt16Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *nullableInt16Vector) Extend(i int) {
......@@ -277,6 +397,26 @@ func (v *nullableInt32Vector) At(i int) interface{} {
return (*v)[i]
}
func (v *nullableInt32Vector) CopyAt(i int) interface{} {
if (*v)[i] == nil {
var g *int32
return g
}
var g int32
g = *(*v)[i]
return &g
}
func (v *nullableInt32Vector) ConcreteAt(i int) (interface{}, bool) {
var g int32
val := (*v)[i]
if val == nil {
return g, false
}
g = *val
return g, true
}
func (v *nullableInt32Vector) PointerAt(i int) interface{} {
return &(*v)[i]
}
......@@ -285,8 +425,8 @@ func (v *nullableInt32Vector) Len() int {
return len((*v))
}
func (v *nullableInt32Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *nullableInt32Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *nullableInt32Vector) Extend(i int) {
......@@ -318,6 +458,26 @@ func (v *nullableInt64Vector) At(i int) interface{} {
return (*v)[i]
}
func (v *nullableInt64Vector) CopyAt(i int) interface{} {
if (*v)[i] == nil {
var g *int64
return g
}
var g int64
g = *(*v)[i]
return &g
}
func (v *nullableInt64Vector) ConcreteAt(i int) (interface{}, bool) {
var g int64
val := (*v)[i]
if val == nil {
return g, false
}
g = *val
return g, true
}
func (v *nullableInt64Vector) PointerAt(i int) interface{} {
return &(*v)[i]
}
......@@ -326,8 +486,8 @@ func (v *nullableInt64Vector) Len() int {
return len((*v))
}
func (v *nullableInt64Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *nullableInt64Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *nullableInt64Vector) Extend(i int) {
......@@ -359,6 +519,26 @@ func (v *nullableFloat32Vector) At(i int) interface{} {
return (*v)[i]
}
func (v *nullableFloat32Vector) CopyAt(i int) interface{} {
if (*v)[i] == nil {
var g *float32
return g
}
var g float32
g = *(*v)[i]
return &g
}
func (v *nullableFloat32Vector) ConcreteAt(i int) (interface{}, bool) {
var g float32
val := (*v)[i]
if val == nil {
return g, false
}
g = *val
return g, true
}
func (v *nullableFloat32Vector) PointerAt(i int) interface{} {
return &(*v)[i]
}
......@@ -367,8 +547,8 @@ func (v *nullableFloat32Vector) Len() int {
return len((*v))
}
func (v *nullableFloat32Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *nullableFloat32Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *nullableFloat32Vector) Extend(i int) {
......@@ -400,6 +580,26 @@ func (v *nullableFloat64Vector) At(i int) interface{} {
return (*v)[i]
}
func (v *nullableFloat64Vector) CopyAt(i int) interface{} {
if (*v)[i] == nil {
var g *float64
return g
}
var g float64
g = *(*v)[i]
return &g
}
func (v *nullableFloat64Vector) ConcreteAt(i int) (interface{}, bool) {
var g float64
val := (*v)[i]
if val == nil {
return g, false
}
g = *val
return g, true
}
func (v *nullableFloat64Vector) PointerAt(i int) interface{} {
return &(*v)[i]
}
......@@ -408,8 +608,8 @@ func (v *nullableFloat64Vector) Len() int {
return len((*v))
}
func (v *nullableFloat64Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *nullableFloat64Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *nullableFloat64Vector) Extend(i int) {
......@@ -441,6 +641,26 @@ func (v *nullableStringVector) At(i int) interface{} {
return (*v)[i]
}
func (v *nullableStringVector) CopyAt(i int) interface{} {
if (*v)[i] == nil {
var g *string
return g
}
var g string
g = *(*v)[i]
return &g
}
func (v *nullableStringVector) ConcreteAt(i int) (interface{}, bool) {
var g string
val := (*v)[i]
if val == nil {
return g, false
}
g = *val
return g, true
}
func (v *nullableStringVector) PointerAt(i int) interface{} {
return &(*v)[i]
}
......@@ -449,8 +669,8 @@ func (v *nullableStringVector) Len() int {
return len((*v))
}
func (v *nullableStringVector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *nullableStringVector) Type() FieldType {
return vectorFieldType(v)
}
func (v *nullableStringVector) Extend(i int) {
......@@ -482,6 +702,26 @@ func (v *nullableBoolVector) At(i int) interface{} {
return (*v)[i]
}
func (v *nullableBoolVector) CopyAt(i int) interface{} {
if (*v)[i] == nil {
var g *bool
return g
}
var g bool
g = *(*v)[i]
return &g
}
func (v *nullableBoolVector) ConcreteAt(i int) (interface{}, bool) {
var g bool
val := (*v)[i]
if val == nil {
return g, false
}
g = *val
return g, true
}
func (v *nullableBoolVector) PointerAt(i int) interface{} {
return &(*v)[i]
}
......@@ -490,8 +730,8 @@ func (v *nullableBoolVector) Len() int {
return len((*v))
}
func (v *nullableBoolVector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *nullableBoolVector) Type() FieldType {
return vectorFieldType(v)
}
func (v *nullableBoolVector) Extend(i int) {
......@@ -523,6 +763,26 @@ func (v *nullableTimeTimeVector) At(i int) interface{} {
return (*v)[i]
}
func (v *nullableTimeTimeVector) CopyAt(i int) interface{} {
if (*v)[i] == nil {
var g *time.Time
return g
}
var g time.Time
g = *(*v)[i]
return &g
}
func (v *nullableTimeTimeVector) ConcreteAt(i int) (interface{}, bool) {
var g time.Time
val := (*v)[i]
if val == nil {
return g, false
}
g = *val
return g, true
}
func (v *nullableTimeTimeVector) PointerAt(i int) interface{} {
return &(*v)[i]
}
......@@ -531,8 +791,8 @@ func (v *nullableTimeTimeVector) Len() int {
return len((*v))
}
func (v *nullableTimeTimeVector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *nullableTimeTimeVector) Type() FieldType {
return vectorFieldType(v)
}
func (v *nullableTimeTimeVector) Extend(i int) {
......
package dataframe
package data
import (
"database/sql"
......@@ -6,13 +6,13 @@ import (
"reflect"
)
// NewFromSQLRows returns a new dataframe populated with the data from rows. The Field Vector types
// NewFromSQLRows returns a new Frame populated with the data from rows. The Field Vector types
// will be Vectors of pointer types, []*T, if the SQL column is nullable or if the nullable property is unknown.
// Otherwise, they will be []T types.
//
// Fields will be named to match name of the SQL columns and the SQL column names must be unique (https://github.com/grafana/grafana-plugin-sdk-go/issues/59).
//
// All the types must be supported by the dataframe or a SQLStringConverter will be created and
// All the types must be supported by the Frame or a SQLStringConverter will be created and
// the resulting Field Vector type will be of type []*string.
//
// The SQLStringConverter's ConversionFunc will be applied to matching rows if it is not nil.
......@@ -39,11 +39,11 @@ func NewFromSQLRows(rows *sql.Rows, converters ...SQLStringConverter) (*Frame, m
}
vec := frame.Fields[fieldIdx]
for i := 0; i < vec.Len(); i++ {
v, err := mapper.ConversionFunc(vec.Vector.At(i).(*string))
v, err := mapper.ConversionFunc(vec.vector.At(i).(*string))
if err != nil {
return nil, nil, err
}
vec.Vector.Set(i, v)
vec.vector.Set(i, v)
}
if mapper.Replacer == nil {
continue
......@@ -100,7 +100,7 @@ func newForSQLRows(rows *sql.Rows, converters ...SQLStringConverter) (*Frame, ma
// Nullabe types get passed to scan as a pointer to a pointer
vec = reflect.MakeSlice(reflect.SliceOf(ptrType), 0, 0).Interface()
}
if !ValidVectorType(vec) {
if !ValidFieldType(vec) {
// Automatically create string mapper if we end up with an unsupported type
mapping[i] = SQLStringConverter{
Name: fmt.Sprintf("Autogenerated for column %v", i),
......@@ -115,13 +115,13 @@ func newForSQLRows(rows *sql.Rows, converters ...SQLStringConverter) (*Frame, ma
return frame, mapping, nil
}
// newScannableRow adds a row to the dataframe by extending each Field's Vector. It returns
// newScannableRow adds a row to the Frame by extending each Field's Vector. It returns
// a slice of references that can be passed to the database/sql rows.Scan() to scan directly into
// the extended Vectors of the dataframe.
// the extended Vectors of the data.
func (f *Frame) newScannableRow() []interface{} {
row := make([]interface{}, len(f.Fields))
for i, field := range f.Fields {
vec := field.Vector
vec := field.vector
vec.Extend(1)
// non-nullable fields will be *T, and nullable fields will be **T
vecItemPointer := vec.PointerAt(vec.Len() - 1)
......@@ -131,7 +131,7 @@ func (f *Frame) newScannableRow() []interface{} {
}
// SQLStringConverter can be used to store types not supported by
// a dataframe into a *string. When scanning, if a SQL's row's InputScanType's Kind
// a Frame into a *string. When scanning, if a SQL's row's InputScanType's Kind
// and InputScanKind match that returned by the sql response, then the
// conversion func will be run on the row.
type SQLStringConverter struct {
......@@ -150,7 +150,7 @@ type SQLStringConverter struct {
// Note: SQLStringConverter is perhaps better understood as []byte. However, currently
// the Vector type ([][]byte) is not supported. https://github.com/grafana/grafana-plugin-sdk-go/issues/57
// StringFieldReplacer is used to replace a *string Field in a dataframe. The type
// StringFieldReplacer is used to replace a *string Field in a data. The type
// returned by the ReplaceFunc must match the type of elements of VectorType.
// Both properties must be non-nil.
type StringFieldReplacer struct {
......@@ -165,22 +165,22 @@ func Replace(frame *Frame, fieldIdx int, replacer *StringFieldReplacer) error {
return fmt.Errorf("fieldIdx is out of bounds, field len: %v", len(frame.Fields))
}
field := frame.Fields[fieldIdx]
if field.Vector.PrimitiveType() != VectorPTypeNullableString {
return fmt.Errorf("can only replace []*string vectors, vector is of type %s", field.Vector.PrimitiveType())
if field.Type() != FieldTypeNullableString {
return fmt.Errorf("can only replace []*string vectors, vector is of type %s", field.Type())
}
if !ValidVectorType(replacer.VectorType) {
if !ValidFieldType(replacer.VectorType) {
return fmt.Errorf("can not replace column with unsupported type %T", replacer.VectorType)
}
newVector := newVector(replacer.VectorType, field.Vector.Len())
newVector := newVector(replacer.VectorType, field.vector.Len())
for i := 0; i < newVector.Len(); i++ {
oldVal := field.Vector.At(i).(*string) // Vector type is checked earlier above
oldVal := field.vector.At(i).(*string) // Vector type is checked earlier above
newVal, err := replacer.ReplaceFunc(oldVal)
if err != nil {
return err
}
newVector.Set(i, newVal)
}
field.Vector = newVector
field.vector = newVector
return nil
}
package data
import (
"encoding/json"
"fmt"
"sort"
"strconv"
"time"
)
// TimeSeriesType represents the type of time series the schema can be treated as (if any).
type TimeSeriesType int
// TODO: Create and link to Grafana documentation on Long vs Wide
const (
// TimeSeriesTypeNot means this Frame is not a valid time series. This means it lacks at least
// one of a time Field and another (value) Field.
TimeSeriesTypeNot TimeSeriesType = iota
// TimeSeriesTypeLong means this Frame can be treated as a "Long" time series.
//
// A Long series has one or more string Fields, disregards Labels on Fields, and generally
// repeated time values in the time index.
TimeSeriesTypeLong
// TimeSeriesTypeWide means this Frame can be treated as a "Wide" time series.
//
// A Wide series has no string fields, should not have repeated time values, and generally
// uses labels.
TimeSeriesTypeWide
)
func (t TimeSeriesType) String() string {
switch t {
case TimeSeriesTypeLong:
return "long"
case TimeSeriesTypeWide:
return "wide"
}
return "not"
}
// TimeSeriesSchema returns the TimeSeriesSchema of the frame. The TimeSeriesSchema's Type
// value will be TimeSeriesNot if it is not a time series.
func (f *Frame) TimeSeriesSchema() (tsSchema TimeSeriesSchema) {
tsSchema.Type = TimeSeriesTypeNot
if f.Fields == nil || len(f.Fields) == 0 {
return
}
nonValueIndices := make(map[int]struct{})
timeIndices := f.TypeIndices(FieldTypeTime, FieldTypeNullableTime)
if len(timeIndices) == 0 {
return
}
tsSchema.TimeIndex = timeIndices[0]
nonValueIndices[tsSchema.TimeIndex] = struct{}{}
tsSchema.TimeIsNullable = f.Fields[tsSchema.TimeIndex].Nullable()
tsSchema.FactorIndices = f.TypeIndices(FieldTypeString, FieldTypeNullableString)
for _, factorIdx := range tsSchema.FactorIndices {
nonValueIndices[factorIdx] = struct{}{}
}
for i := range f.Fields {
if _, ok := nonValueIndices[i]; ok {
continue
}
tsSchema.ValueIndices = append(tsSchema.ValueIndices, i)
}
if len(tsSchema.ValueIndices) == 0 {
return
}
if len(tsSchema.FactorIndices) == 0 {
tsSchema.Type = TimeSeriesTypeWide
return
}
tsSchema.Type = TimeSeriesTypeLong
return
}
// LongToWide converts a Long formated time series Frame to a Wide format (see TimeSeriesType for descriptions).
// The first Field of type time.Time or *time.Time will be the time index for the series,
// and will be the first field of the outputted longFrame.
//
// During conversion: String Fields in the longFrame become Labels on the Fields of wideFrame. The name of each string Field becomes a label key, and the values of that Field become label values.
// Each unique combination of value Fields and set of Label key/values become a Field of longFrame.
//
// Additionally, if the time index is a *time.Time field, it will become time.Time Field. If a *string Field has nil values, they are equivalent to "" when converted into labels.
//
// An error is returned if any of the following are true:
// The input frame is not a long formated time series frame.
// The input frame's Fields are of length 0.
// The time index is not sorted ascending by time.
// The time index has null values.
//
// With a conversion of Long to Wide, and then back to Long via WideToLong(), the outputted Long Frame
// may not match the original inputted Long frame.
func LongToWide(longFrame *Frame) (*Frame, error) {
tsSchema := longFrame.TimeSeriesSchema()
if tsSchema.Type != TimeSeriesTypeLong {
return nil, fmt.Errorf("can not convert to wide series, expected long format series input but got %s series", tsSchema.Type)
}
longLen, err := longFrame.RowLen()
if err != nil {
return nil, err
} else if longLen == 0 {
return nil, fmt.Errorf("can not convert to wide series, input fields have no rows")
}
wideFrame := NewFrame(longFrame.Name, NewField(longFrame.Fields[tsSchema.TimeIndex].Name, nil, []time.Time{}))
wideFrameRowCounter := 0
seenFactors := map[string]struct{}{} // seen factor combinations
valueFactorToWideFieldIdx := make(map[int]map[string]int) // value field idx and factors key -> fieldIdx of longFrame (for insertion)
for _, i := range tsSchema.ValueIndices { // initialize nested maps
valueFactorToWideFieldIdx[i] = make(map[string]int)
}
timeAt := func(idx int) (time.Time, error) { // get time.Time regardless if pointer
val, ok := longFrame.ConcreteAt(tsSchema.TimeIndex, idx)
if !ok {
return time.Time{}, fmt.Errorf("can not convert to wide series, input has null time values")
}
return val.(time.Time), nil
}
lastTime, err := timeAt(0) // set initial time value
if err != nil {
return nil, err
}
wideFrame.Fields[0].Append(lastTime)
for longRowIdx := 0; longRowIdx < longLen; longRowIdx++ { // loop over each row of longFrame
currentTime, err := timeAt(longRowIdx)
if err != nil {
return nil, err
}
if currentTime.After(lastTime) { // time advance means new row in wideFrame
wideFrameRowCounter++
lastTime = currentTime
for _, field := range wideFrame.Fields {
// extend all wideFrame Field Vectors for new row. If no value found, it will have zero value
field.Extend(1)
}
wideFrame.Set(0, wideFrameRowCounter, currentTime)
}
if currentTime.Before(lastTime) {
return nil, fmt.Errorf("long series must be sorted ascending by time to be converted")
}
sliceKey := make(tupleLabels, len(tsSchema.FactorIndices)) // factor columns idx:value tuples (used for lookup)
namedKey := make(tupleLabels, len(tsSchema.FactorIndices)) // factor columns name:value tuples (used for labels)
// build labels
for i, factorLongFieldIdx := range tsSchema.FactorIndices {
val, _ := longFrame.ConcreteAt(factorLongFieldIdx, longRowIdx)
sliceKey[i] = tupleLabel{strconv.FormatInt(int64(factorLongFieldIdx), 10), val.(string)}
namedKey[i] = tupleLabel{longFrame.Fields[factorLongFieldIdx].Name, val.(string)}
}
factorKey, err := sliceKey.MapKey()
if err != nil {
return nil, err
}
// make new Fields as new factor combinations are found
if _, ok := seenFactors[factorKey]; !ok {
currentFieldLen := len(wideFrame.Fields) // first index for the set of factors.
seenFactors[factorKey] = struct{}{}
for offset, longFieldIdx := range tsSchema.ValueIndices {
// a new Field is created for each value Field from inFrame
labels, err := tupleLablesToLabels(namedKey)
if err != nil {
return nil, err
}
longField := longFrame.Fields[tsSchema.ValueIndices[offset]]
newWideField := NewFieldFromFieldType(longField.Type(), wideFrameRowCounter+1)
newWideField.Name, newWideField.Labels = longField.Name, labels
wideFrame.Fields = append(wideFrame.Fields, newWideField)
valueFactorToWideFieldIdx[longFieldIdx][factorKey] = currentFieldLen + offset
}
}
for _, longFieldIdx := range tsSchema.ValueIndices {
wideFieldIdx := valueFactorToWideFieldIdx[longFieldIdx][factorKey]
wideFrame.Set(wideFieldIdx, wideFrameRowCounter, longFrame.CopyAt(longFieldIdx, longRowIdx))
}
}
return wideFrame, nil
}
// WideToLong converts a Wide formated time series Frame to a Long formated time series Frame (see TimeSeriesType for descriptions). The first Field of type time.Time or *time.Time in wideFrame will be the time index for the series, and will be the first field of the outputted wideFrame.
//
// During conversion: All the unique keys in all of the Labels across the Fields of wideFrame become string
// Fields with the corresponding name in longFrame. The corresponding Labels values become values in those Fields of longFrame.
// For each unique non-timeIndex Field across the Fields of wideFrame (value fields), a Field of the same type is created in longFrame.
// For each unique set of Labels across the Fields of wideFrame, a row is added to longFrame, and then
// for each unique value Field, the corresponding value Field of longFrame is set.
//
// An error is returned if any of the following are true:
// The input frame is not a wide formated time series frame.
// The input row has no rows.
// The time index not sorted ascending by time.
// The time index has null values.
// Two numeric Fields have the same name but different types.
//
// With a conversion of Wide to Long, and then back to Wide via LongToWide(), the outputted Wide Frame
// may not match the original inputted Wide frame.
func WideToLong(wideFrame *Frame) (*Frame, error) {
tsSchema := wideFrame.TimeSeriesSchema()
if tsSchema.Type != TimeSeriesTypeWide {
return nil, fmt.Errorf("can not convert to long series, expected wide format series input but got %s series", tsSchema.Type)
}
wideLen, err := wideFrame.RowLen()
if err != nil {
return nil, err
} else if wideLen == 0 {
return nil, fmt.Errorf("can not convert to long series, input fields have no rows")
}
uniqueValueNames := []string{} // unique names of Fields that are value types
uniqueValueNamesToType := make(map[string]FieldType) // unique value Field names to Field type
uniqueLabelKeys := make(map[string]struct{}) // unique Label keys, used to build schema
labelKeyToWideIndices := make(map[string][]int) // unique label sets to corresponding Field indices of wideFrame
// Gather schema information from wideFrame required to build longFrame
for _, vIdx := range tsSchema.ValueIndices {
wideField := wideFrame.Fields[vIdx]
if pType, ok := uniqueValueNamesToType[wideField.Name]; ok {
if wideField.Type() != pType {
return nil, fmt.Errorf("two fields in input frame may not have the same name but different types, field name %s has type %s but also type %s and field idx %v", wideField.Name, pType, wideField.Type(), vIdx)
}
} else {
uniqueValueNamesToType[wideField.Name] = wideField.Type()
uniqueValueNames = append(uniqueValueNames, wideField.Name)
}
tKey, err := labelsTupleKey(wideField.Labels) // labels to a string, so it can be a map key
if err != nil {
return nil, err
}
labelKeyToWideIndices[tKey] = append(labelKeyToWideIndices[tKey], vIdx)
for k := range wideField.Labels {
uniqueLabelKeys[k] = struct{}{}
}
}
// Sort things for more deterministic output
sort.Strings(uniqueValueNames)
sortedUniqueLabelKeys := []string{}
for k := range labelKeyToWideIndices {
sortedUniqueLabelKeys = append(sortedUniqueLabelKeys, k)
}
sort.Strings(sortedUniqueLabelKeys)
uniqueFactorNames := make([]string, 0, len(uniqueLabelKeys))
for k := range uniqueLabelKeys {
uniqueFactorNames = append(uniqueFactorNames, k)
}
sort.Strings(uniqueFactorNames)
// build new Frame with new schema
longFrame := NewFrame(wideFrame.Name, // time, value fields..., factor fields (strings)...
NewField(wideFrame.Fields[tsSchema.TimeIndex].Name, nil, []time.Time{})) // time field is first field
i := 1
valueNameToLongFieldIdx := map[string]int{} // valueName -> field index of longFrame
for _, name := range uniqueValueNames {
newWideField := NewFieldFromFieldType(uniqueValueNamesToType[name], 0) // create value Fields
newWideField.Name = name
longFrame.Fields = append(longFrame.Fields, newWideField)
valueNameToLongFieldIdx[name] = i
i++
}
factorNameToLongFieldIdx := map[string]int{} // label Key -> field index for label value of longFrame
for _, name := range uniqueFactorNames {
longFrame.Fields = append(longFrame.Fields, NewField(name, nil, []string{})) // create factor fields
factorNameToLongFieldIdx[name] = i
i++
}
// Populate data of longFrame from wideframe
longFrameCounter := 0
for wideRowIdx := 0; wideRowIdx < wideLen; wideRowIdx++ { // loop over each row of wideFrame
time, ok := wideFrame.ConcreteAt(tsSchema.TimeIndex, wideRowIdx)
if !ok {
return nil, fmt.Errorf("time may not have nil values")
}
for _, labelKey := range sortedUniqueLabelKeys {
longFrame.Extend(1) // grow each Fields's vector by 1
longFrame.Set(0, longFrameCounter, time)
for i, wideFieldIdx := range labelKeyToWideIndices[labelKey] {
wideField := wideFrame.Fields[wideFieldIdx]
if i == 0 {
for k, v := range wideField.Labels {
longFrame.Set(factorNameToLongFieldIdx[k], longFrameCounter, v)
}
}
longValueFieldIdx := valueNameToLongFieldIdx[wideField.Name]
longFrame.Set(longValueFieldIdx, longFrameCounter, wideFrame.CopyAt(wideFieldIdx, wideRowIdx))
}
longFrameCounter++
}
}
return longFrame, nil
}
// TimeSeriesSchema is information about a Frame's schema. It is populated from
// the Frame's TimeSeriesSchema() method.
type TimeSeriesSchema struct {
Type TimeSeriesType // the type of series, as determinted by frame.TimeSeriesSchema()
TimeIndex int // Field index of the time series index
TimeIsNullable bool // true if the time index is nullable (of *time.Time)
ValueIndices []int // Field indices of value columns (All fields excluding string fields and the time index)
FactorIndices []int // Field indices of string or *string Fields
}
// tupleLables is an alternative representation of Labels (map[string]string) that can be sorted
// and then marshalled into a consistent string that can be used a map key. All tupleLabel objects
// in tupleLabels should have unique first elements (keys).
type tupleLabels []tupleLabel
// tupleLabel is an element of tupleLabels and should be in the form of [2]{"key", "value"}.
type tupleLabel [2]string
// tupleLabelsToLabels converts tupleLabels to Labels (map[string]string), erroring if there are duplicate keys.
func tupleLablesToLabels(tuples tupleLabels) (Labels, error) {
labels := make(map[string]string)
for _, tuple := range tuples {
if key, ok := labels[tuple[0]]; ok {
return nil, fmt.Errorf("duplicate key '%v' in lables: %v", key, tuples)
}
labels[tuple[0]] = tuple[1]
}
return labels, nil
}
// MapKey gets a string key that can be used as a map key.
func (t *tupleLabels) MapKey() (string, error) {
t.SortBtKey()
b, err := json.Marshal(t)
if err != nil {
return "", err
}
return string(b), nil
}
// Sort tupleLabels by each elements first property (key).
func (t *tupleLabels) SortBtKey() {
if t == nil {
return
}
sort.Slice((*t)[:], func(i, j int) bool {
return (*t)[i][0] < (*t)[j][0]
})
}
// labelsToTupleLabels converts Labels (map[string]string) to tupleLabels.
func labelsToTupleLabels(l Labels) tupleLabels {
t := make(tupleLabels, 0, len(l))
for k, v := range l {
t = append(t, tupleLabel{k, v})
}
t.SortBtKey()
return t
}
// labelsTupleKey gets a string key from Labels.
func labelsTupleKey(l Labels) (string, error) {
// sorts twice, meh.
t := labelsToTupleLabels(l)
return t.MapKey()
}
......@@ -2,7 +2,7 @@
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package dataframe
package data
import "time"
......@@ -35,8 +35,18 @@ func (v *uint8Vector) Len() int {
return len((*v))
}
func (v *uint8Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *uint8Vector) CopyAt(i int) interface{} {
var g uint8
g = (*v)[i]
return g
}
func (v *uint8Vector) ConcreteAt(i int) (interface{}, bool) {
return v.At(i), true
}
func (v *uint8Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *uint8Vector) Extend(i int) {
......@@ -72,8 +82,18 @@ func (v *uint16Vector) Len() int {
return len((*v))
}
func (v *uint16Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *uint16Vector) CopyAt(i int) interface{} {
var g uint16
g = (*v)[i]
return g
}
func (v *uint16Vector) ConcreteAt(i int) (interface{}, bool) {
return v.At(i), true
}
func (v *uint16Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *uint16Vector) Extend(i int) {
......@@ -109,8 +129,18 @@ func (v *uint32Vector) Len() int {
return len((*v))
}
func (v *uint32Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *uint32Vector) CopyAt(i int) interface{} {
var g uint32
g = (*v)[i]
return g
}
func (v *uint32Vector) ConcreteAt(i int) (interface{}, bool) {
return v.At(i), true
}
func (v *uint32Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *uint32Vector) Extend(i int) {
......@@ -146,8 +176,18 @@ func (v *uint64Vector) Len() int {
return len((*v))
}
func (v *uint64Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *uint64Vector) CopyAt(i int) interface{} {
var g uint64
g = (*v)[i]
return g
}
func (v *uint64Vector) ConcreteAt(i int) (interface{}, bool) {
return v.At(i), true
}
func (v *uint64Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *uint64Vector) Extend(i int) {
......@@ -183,8 +223,18 @@ func (v *int8Vector) Len() int {
return len((*v))
}
func (v *int8Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *int8Vector) CopyAt(i int) interface{} {
var g int8
g = (*v)[i]
return g
}
func (v *int8Vector) ConcreteAt(i int) (interface{}, bool) {
return v.At(i), true
}
func (v *int8Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *int8Vector) Extend(i int) {
......@@ -220,8 +270,18 @@ func (v *int16Vector) Len() int {
return len((*v))
}
func (v *int16Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *int16Vector) CopyAt(i int) interface{} {
var g int16
g = (*v)[i]
return g
}
func (v *int16Vector) ConcreteAt(i int) (interface{}, bool) {
return v.At(i), true
}
func (v *int16Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *int16Vector) Extend(i int) {
......@@ -257,8 +317,18 @@ func (v *int32Vector) Len() int {
return len((*v))
}
func (v *int32Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *int32Vector) CopyAt(i int) interface{} {
var g int32
g = (*v)[i]
return g
}
func (v *int32Vector) ConcreteAt(i int) (interface{}, bool) {
return v.At(i), true
}
func (v *int32Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *int32Vector) Extend(i int) {
......@@ -294,8 +364,18 @@ func (v *int64Vector) Len() int {
return len((*v))
}
func (v *int64Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *int64Vector) CopyAt(i int) interface{} {
var g int64
g = (*v)[i]
return g
}
func (v *int64Vector) ConcreteAt(i int) (interface{}, bool) {
return v.At(i), true
}
func (v *int64Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *int64Vector) Extend(i int) {
......@@ -331,8 +411,18 @@ func (v *float32Vector) Len() int {
return len((*v))
}
func (v *float32Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *float32Vector) CopyAt(i int) interface{} {
var g float32
g = (*v)[i]
return g
}
func (v *float32Vector) ConcreteAt(i int) (interface{}, bool) {
return v.At(i), true
}
func (v *float32Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *float32Vector) Extend(i int) {
......@@ -368,8 +458,18 @@ func (v *float64Vector) Len() int {
return len((*v))
}
func (v *float64Vector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *float64Vector) CopyAt(i int) interface{} {
var g float64
g = (*v)[i]
return g
}
func (v *float64Vector) ConcreteAt(i int) (interface{}, bool) {
return v.At(i), true
}
func (v *float64Vector) Type() FieldType {
return vectorFieldType(v)
}
func (v *float64Vector) Extend(i int) {
......@@ -405,8 +505,18 @@ func (v *stringVector) Len() int {
return len((*v))
}
func (v *stringVector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *stringVector) CopyAt(i int) interface{} {
var g string
g = (*v)[i]
return g
}
func (v *stringVector) ConcreteAt(i int) (interface{}, bool) {
return v.At(i), true
}
func (v *stringVector) Type() FieldType {
return vectorFieldType(v)
}
func (v *stringVector) Extend(i int) {
......@@ -442,8 +552,18 @@ func (v *boolVector) Len() int {
return len((*v))
}
func (v *boolVector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *boolVector) CopyAt(i int) interface{} {
var g bool
g = (*v)[i]
return g
}
func (v *boolVector) ConcreteAt(i int) (interface{}, bool) {
return v.At(i), true
}
func (v *boolVector) Type() FieldType {
return vectorFieldType(v)
}
func (v *boolVector) Extend(i int) {
......@@ -479,8 +599,18 @@ func (v *timeTimeVector) Len() int {
return len((*v))
}
func (v *timeTimeVector) PrimitiveType() VectorPType {
return vectorPType(v)
func (v *timeTimeVector) CopyAt(i int) interface{} {
var g time.Time
g = (*v)[i]
return g
}
func (v *timeTimeVector) ConcreteAt(i int) (interface{}, bool) {
return v.At(i), true
}
func (v *timeTimeVector) Type() FieldType {
return vectorFieldType(v)
}
func (v *timeTimeVector) Extend(i int) {
......
package dataframe
package data
import (
"fmt"
"time"
)
// Vector represents a collection of Elements.
type Vector interface {
// vector represents a Field's collection of Elements.
type vector interface {
Set(idx int, i interface{})
Append(i interface{})
Extend(i int)
At(i int) interface{}
Len() int
PrimitiveType() VectorPType
Type() FieldType
PointerAt(i int) interface{}
//buildArrowColumn(pool memory.Allocator, field arrow.Field) *array.Column
CopyAt(i int) interface{}
ConcreteAt(i int) (val interface{}, ok bool)
}
func newVector(t interface{}, n int) (v Vector) {
func newVector(t interface{}, n int) (v vector) {
switch t.(type) {
// ints
case []int8:
......@@ -83,9 +84,8 @@ func newVector(t interface{}, n int) (v Vector) {
return
}
// ValidVectorType returns if a primitive slice is a valid / supported Vector type
func ValidVectorType(t interface{}) bool {
// ValidFieldType returns if a primitive slice is a valid supported Field type.
func ValidFieldType(t interface{}) bool {
switch t.(type) {
// ints
case []int8:
......@@ -150,218 +150,218 @@ func ValidVectorType(t interface{}) bool {
}
}
// VectorPType indicates the go type underlying the Vector.
type VectorPType int
// FieldType indicates the Go type underlying the Field.
type FieldType int
const (
// VectorPTypeInt8 indicates the underlying primitive is a []int8.
VectorPTypeInt8 VectorPType = iota
// VectorPTypeNullableInt8 indicates the underlying primitive is a []*int8.
VectorPTypeNullableInt8
// VectorPTypeInt16 indicates the underlying primitive is a []Int16.
VectorPTypeInt16
// VectorPTypeNullableInt16 indicates the underlying primitive is a []*Int16.
VectorPTypeNullableInt16
// VectorPTypeInt32 indicates the underlying primitive is a []int32.
VectorPTypeInt32
// VectorPTypeNullableInt32 indicates the underlying primitive is a []*int32.
VectorPTypeNullableInt32
// VectorPTypeInt64 indicates the underlying primitive is a []int64.
VectorPTypeInt64
// VectorPTypeNullableInt64 indicates the underlying primitive is a []*int64.
VectorPTypeNullableInt64
// VectorPTypeUint8 indicates the underlying primitive is a []int8.
VectorPTypeUint8
// VectorPTypeNullableUint8 indicates the underlying primitive is a []*int8.
VectorPTypeNullableUint8
// VectorPTypeUint16 indicates the underlying primitive is a []uint16.
VectorPTypeUint16
// VectorPTypeNullableUint16 indicates the underlying primitive is a []*uint16.
VectorPTypeNullableUint16
// VectorPTypeUint32 indicates the underlying primitive is a []uint32.
VectorPTypeUint32
// VectorPTypeNullableUint32 indicates the underlying primitive is a []*uint32.
VectorPTypeNullableUint32
// VectorPTypeUint64 indicates the underlying primitive is a []uint64.
VectorPTypeUint64
// VectorPTypeNullableUint64 indicates the underlying primitive is a []*uint64.
VectorPTypeNullableUint64
// VectorPTypeFloat32 indicates the underlying primitive is a []float32.
VectorPTypeFloat32
// VectorPTypeNullableFloat32 indicates the underlying primitive is a []*float32.
VectorPTypeNullableFloat32
// VectorPTypeFloat64 indicates the underlying primitive is a []float64.
VectorPTypeFloat64
// VectorPTypeNullableFloat64 indicates the underlying primitive is a []*float64.
VectorPTypeNullableFloat64
// VectorPTypeString indicates the underlying primitive is a []string.
VectorPTypeString
// VectorPTypeNullableString indicates the underlying primitive is a []*string.
VectorPTypeNullableString
// VectorPTypeBool indicates the underlying primitive is a []bool.
VectorPTypeBool
// VectorPTypeNullableBool indicates the underlying primitive is a []*bool.
VectorPTypeNullableBool
// VectorPTypeTime indicates the underlying primitive is a []time.Time.
VectorPTypeTime
// VectorPTypeNullableTime indicates the underlying primitive is a []*time.Time.
VectorPTypeNullableTime
// FieldTypeInt8 indicates the underlying primitive is a []int8.
FieldTypeInt8 FieldType = iota
// FieldTypeNullableInt8 indicates the underlying primitive is a []*int8.
FieldTypeNullableInt8
// FieldTypeInt16 indicates the underlying primitive is a []Int16.
FieldTypeInt16
// FieldTypeNullableInt16 indicates the underlying primitive is a []*Int16.
FieldTypeNullableInt16
// FieldTypeInt32 indicates the underlying primitive is a []int32.
FieldTypeInt32
// FieldTypeNullableInt32 indicates the underlying primitive is a []*int32.
FieldTypeNullableInt32
// FieldTypeInt64 indicates the underlying primitive is a []int64.
FieldTypeInt64
// FieldTypeNullableInt64 indicates the underlying primitive is a []*int64.
FieldTypeNullableInt64
// FieldTypeUint8 indicates the underlying primitive is a []int8.
FieldTypeUint8
// FieldTypeNullableUint8 indicates the underlying primitive is a []*int8.
FieldTypeNullableUint8
// FieldTypeUint16 indicates the underlying primitive is a []uint16.
FieldTypeUint16
// FieldTypeNullableUint16 indicates the underlying primitive is a []*uint16.
FieldTypeNullableUint16
// FieldTypeUint32 indicates the underlying primitive is a []uint32.
FieldTypeUint32
// FieldTypeNullableUint32 indicates the underlying primitive is a []*uint32.
FieldTypeNullableUint32
// FieldTypeUint64 indicates the underlying primitive is a []uint64.
FieldTypeUint64
// FieldTypeNullableUint64 indicates the underlying primitive is a []*uint64.
FieldTypeNullableUint64
// FieldTypeFloat32 indicates the underlying primitive is a []float32.
FieldTypeFloat32
// FieldTypeNullableFloat32 indicates the underlying primitive is a []*float32.
FieldTypeNullableFloat32
// FieldTypeFloat64 indicates the underlying primitive is a []float64.
FieldTypeFloat64
// FieldTypeNullableFloat64 indicates the underlying primitive is a []*float64.
FieldTypeNullableFloat64
// FieldTypeString indicates the underlying primitive is a []string.
FieldTypeString
// FieldTypeNullableString indicates the underlying primitive is a []*string.
FieldTypeNullableString
// FieldTypeBool indicates the underlying primitive is a []bool.
FieldTypeBool
// FieldTypeNullableBool indicates the underlying primitive is a []*bool.
FieldTypeNullableBool
// FieldTypeTime indicates the underlying primitive is a []time.Time.
FieldTypeTime
// FieldTypeNullableTime indicates the underlying primitive is a []*time.Time.
FieldTypeNullableTime
)
func vectorPType(v Vector) VectorPType {
func vectorFieldType(v vector) FieldType {
switch v.(type) {
case *int8Vector:
return VectorPTypeInt8
return FieldTypeInt8
case *nullableInt8Vector:
return VectorPTypeNullableInt8
return FieldTypeNullableInt8
case *int16Vector:
return VectorPTypeInt16
return FieldTypeInt16
case *nullableInt16Vector:
return VectorPTypeNullableInt16
return FieldTypeNullableInt16
case *int32Vector:
return VectorPTypeInt32
return FieldTypeInt32
case *nullableInt32Vector:
return VectorPTypeNullableInt32
return FieldTypeNullableInt32
case *int64Vector:
return VectorPTypeInt64
return FieldTypeInt64
case *nullableInt64Vector:
return VectorPTypeNullableInt64
return FieldTypeNullableInt64
case *uint8Vector:
return VectorPTypeUint8
return FieldTypeUint8
case *nullableUint8Vector:
return VectorPTypeNullableUint8
return FieldTypeNullableUint8
case *uint16Vector:
return VectorPTypeUint16
return FieldTypeUint16
case *nullableUint16Vector:
return VectorPTypeNullableUint16
return FieldTypeNullableUint16
case *uint32Vector:
return VectorPTypeUint32
return FieldTypeUint32
case *nullableUint32Vector:
return VectorPTypeNullableUint32
return FieldTypeNullableUint32
case *uint64Vector:
return VectorPTypeUint64
return FieldTypeUint64
case *nullableUint64Vector:
return VectorPTypeNullableUint64
return FieldTypeNullableUint64
case *float32Vector:
return VectorPTypeFloat32
return FieldTypeFloat32
case *nullableFloat32Vector:
return VectorPTypeNullableFloat32
return FieldTypeNullableFloat32
case *float64Vector:
return VectorPTypeFloat64
return FieldTypeFloat64
case *nullableFloat64Vector:
return VectorPTypeNullableFloat64
return FieldTypeNullableFloat64
case *stringVector:
return VectorPTypeString
return FieldTypeString
case *nullableStringVector:
return VectorPTypeNullableString
return FieldTypeNullableString
case *boolVector:
return VectorPTypeBool
return FieldTypeBool
case *nullableBoolVector:
return VectorPTypeNullableBool
return FieldTypeNullableBool
case *timeTimeVector:
return VectorPTypeTime
return FieldTypeTime
case *nullableTimeTimeVector:
return VectorPTypeNullableTime
return FieldTypeNullableTime
}
return VectorPType(-1)
return FieldType(-1)
}
func pTypeFromVal(v interface{}) VectorPType {
func fieldTypeFromVal(v interface{}) FieldType {
switch v.(type) {
case int8:
return VectorPTypeInt8
return FieldTypeInt8
case *int8:
return VectorPTypeNullableInt8
return FieldTypeNullableInt8
case int16:
return VectorPTypeInt16
return FieldTypeInt16
case *int16:
return VectorPTypeNullableInt16
return FieldTypeNullableInt16
case int32:
return VectorPTypeInt32
return FieldTypeInt32
case *int32:
return VectorPTypeNullableInt32
return FieldTypeNullableInt32
case int64:
return VectorPTypeInt64
return FieldTypeInt64
case *int64:
return VectorPTypeNullableInt64
return FieldTypeNullableInt64
case uint8:
return VectorPTypeUint8
return FieldTypeUint8
case *uint8:
return VectorPTypeNullableUint8
return FieldTypeNullableUint8
case uint16:
return VectorPTypeUint16
return FieldTypeUint16
case *uint16:
return VectorPTypeNullableUint16
return FieldTypeNullableUint16
case uint32:
return VectorPTypeUint32
return FieldTypeUint32
case *uint32:
return VectorPTypeNullableUint32
return FieldTypeNullableUint32
case uint64:
return VectorPTypeUint64
return FieldTypeUint64
case *uint64:
return VectorPTypeNullableUint64
return FieldTypeNullableUint64
case float32:
return VectorPTypeFloat32
return FieldTypeFloat32
case *float32:
return VectorPTypeNullableFloat32
return FieldTypeNullableFloat32
case float64:
return VectorPTypeFloat64
return FieldTypeFloat64
case *float64:
return VectorPTypeNullableFloat64
return FieldTypeNullableFloat64
case string:
return VectorPTypeString
return FieldTypeString
case *string:
return VectorPTypeNullableString
return FieldTypeNullableString
case bool:
return VectorPTypeBool
return FieldTypeBool
case *bool:
return VectorPTypeNullableBool
return FieldTypeNullableBool
case time.Time:
return VectorPTypeTime
return FieldTypeTime
case *time.Time:
return VectorPTypeNullableTime
return FieldTypeNullableTime
}
return VectorPType(-1)
return FieldType(-1)
}
func (p VectorPType) String() string {
func (p FieldType) String() string {
if p < 0 {
return "invalid/unsupported"
}
......@@ -369,97 +369,191 @@ func (p VectorPType) String() string {
}
// NewFieldFromFieldType creates a new Field of the given pType of length n.
func NewFieldFromFieldType(p FieldType, n int) *Field {
f := &Field{}
switch p {
// ints
case FieldTypeInt8:
f.vector = newInt8Vector(n)
case FieldTypeNullableInt8:
f.vector = newNullableInt8Vector(n)
case FieldTypeInt16:
f.vector = newInt16Vector(n)
case FieldTypeNullableInt16:
f.vector = newNullableInt16Vector(n)
case FieldTypeInt32:
f.vector = newInt32Vector(n)
case FieldTypeNullableInt32:
f.vector = newNullableInt32Vector(n)
case FieldTypeInt64:
f.vector = newInt64Vector(n)
case FieldTypeNullableInt64:
f.vector = newNullableInt64Vector(n)
// uints
case FieldTypeUint8:
f.vector = newUint8Vector(n)
case FieldTypeNullableUint8:
f.vector = newNullableUint8Vector(n)
case FieldTypeUint16:
f.vector = newUint16Vector(n)
case FieldTypeNullableUint16:
f.vector = newNullableUint16Vector(n)
case FieldTypeUint32:
f.vector = newUint32Vector(n)
case FieldTypeNullableUint32:
f.vector = newNullableUint32Vector(n)
case FieldTypeUint64:
f.vector = newUint64Vector(n)
case FieldTypeNullableUint64:
f.vector = newNullableUint64Vector(n)
// floats
case FieldTypeFloat32:
f.vector = newFloat32Vector(n)
case FieldTypeNullableFloat32:
f.vector = newNullableFloat32Vector(n)
case FieldTypeFloat64:
f.vector = newFloat64Vector(n)
case FieldTypeNullableFloat64:
f.vector = newNullableFloat64Vector(n)
// other
case FieldTypeString:
f.vector = newStringVector(n)
case FieldTypeNullableString:
f.vector = newNullableStringVector(n)
case FieldTypeBool:
f.vector = newBoolVector(n)
case FieldTypeNullableBool:
f.vector = newNullableBoolVector(n)
case FieldTypeTime:
f.vector = newTimeTimeVector(n)
case FieldTypeNullableTime:
f.vector = newNullableTimeTimeVector(n)
default:
panic(fmt.Sprint("unsupported vector ptype"))
}
return f
}
// ItemTypeString returns the string representation of the type of element within in the vector
func (p VectorPType) ItemTypeString() string {
func (p FieldType) ItemTypeString() string {
switch p {
case VectorPTypeInt8:
case FieldTypeInt8:
return "int8"
case VectorPTypeNullableInt8:
case FieldTypeNullableInt8:
return "*int8"
case VectorPTypeInt16:
case FieldTypeInt16:
return "int16"
case VectorPTypeNullableInt16:
case FieldTypeNullableInt16:
return "*int16"
case VectorPTypeInt32:
case FieldTypeInt32:
return "int32"
case VectorPTypeNullableInt32:
case FieldTypeNullableInt32:
return "*int32"
case VectorPTypeInt64:
case FieldTypeInt64:
return "int64"
case VectorPTypeNullableInt64:
case FieldTypeNullableInt64:
return "*int64"
case VectorPTypeUint8:
case FieldTypeUint8:
return "unit8"
case VectorPTypeNullableUint8:
case FieldTypeNullableUint8:
return "*uint8"
case VectorPTypeUint16:
case FieldTypeUint16:
return "uint16"
case VectorPTypeNullableUint16:
case FieldTypeNullableUint16:
return "*uint16"
case VectorPTypeUint32:
case FieldTypeUint32:
return "uint32"
case VectorPTypeNullableUint32:
case FieldTypeNullableUint32:
return "*uint32"
case VectorPTypeUint64:
case FieldTypeUint64:
return "uint64"
case VectorPTypeNullableUint64:
case FieldTypeNullableUint64:
return "*uint64"
case VectorPTypeFloat32:
case FieldTypeFloat32:
return "float32"
case VectorPTypeNullableFloat32:
case FieldTypeNullableFloat32:
return "*float32"
case VectorPTypeFloat64:
case FieldTypeFloat64:
return "float64"
case VectorPTypeNullableFloat64:
case FieldTypeNullableFloat64:
return "*float64"
case VectorPTypeString:
case FieldTypeString:
return "string"
case VectorPTypeNullableString:
case FieldTypeNullableString:
return "*string"
case VectorPTypeBool:
case FieldTypeBool:
return "bool"
case VectorPTypeNullableBool:
case FieldTypeNullableBool:
return "*bool"
case VectorPTypeTime:
case FieldTypeTime:
return "time.Time"
case VectorPTypeNullableTime:
case FieldTypeNullableTime:
return "*time.Time"
}
return "invalid/unsupported type"
}
// Nullable returns if type is a nullable type
func (p VectorPType) Nullable() bool {
// Nullable returns if Field type is a nullable type
func (p FieldType) Nullable() bool {
switch p {
case VectorPTypeNullableInt8, VectorPTypeNullableInt16, VectorPTypeNullableInt32, VectorPTypeNullableInt64:
case FieldTypeNullableInt8, FieldTypeNullableInt16, FieldTypeNullableInt32, FieldTypeNullableInt64:
return true
case VectorPTypeNullableUint8, VectorPTypeNullableUint16, VectorPTypeNullableUint32, VectorPTypeNullableUint64:
case FieldTypeNullableUint8, FieldTypeNullableUint16, FieldTypeNullableUint32, FieldTypeNullableUint64:
return true
case VectorPTypeNullableFloat32, VectorPTypeNullableFloat64:
case FieldTypeNullableFloat32, FieldTypeNullableFloat64:
return true
case VectorPTypeNullableString:
case FieldTypeNullableString:
return true
case VectorPTypeNullableBool:
case FieldTypeNullableBool:
return true
case VectorPTypeNullableTime:
case FieldTypeNullableTime:
return true
}
return false
}
// numericFieldTypes is an array of FieldTypes that are numeric.
var numericFieldTypes = [...]FieldType{
FieldTypeInt8, FieldTypeInt16, FieldTypeInt32, FieldTypeInt64,
FieldTypeNullableInt8, FieldTypeNullableInt16, FieldTypeNullableInt32, FieldTypeNullableInt64,
FieldTypeUint8, FieldTypeUint16, FieldTypeUint32, FieldTypeUint64,
FieldTypeNullableUint8, FieldTypeNullableUint16, FieldTypeNullableUint32, FieldTypeNullableUint64,
FieldTypeFloat32, FieldTypeFloat64,
FieldTypeNullableFloat32, FieldTypeNullableFloat64}
// NumericFieldTypes returns a slice of FieldTypes that are numeric.
func NumericFieldTypes() []FieldType {
return numericFieldTypes[:]
}
......@@ -147,9 +147,9 @@ github.com/gosimple/slug
# github.com/grafana/grafana-plugin-model v0.0.0-20190930120109-1fc953a61fb4
github.com/grafana/grafana-plugin-model/go/datasource
github.com/grafana/grafana-plugin-model/go/renderer
# github.com/grafana/grafana-plugin-sdk-go v0.21.0
# github.com/grafana/grafana-plugin-sdk-go v0.24.0
github.com/grafana/grafana-plugin-sdk-go/backend/plugin
github.com/grafana/grafana-plugin-sdk-go/dataframe
github.com/grafana/grafana-plugin-sdk-go/data
github.com/grafana/grafana-plugin-sdk-go/genproto/pluginv2
# github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd
github.com/hashicorp/go-hclog
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment