mirror of
https://github.com/grafana/grafana.git
synced 2025-09-25 19:24:22 +08:00
Adds Table in backend datasource contract.
This commit is contained in:
@ -1,15 +1,23 @@
|
||||
package tsdb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/grafana/grafana/pkg/components/null"
|
||||
"github.com/grafana/grafana/pkg/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
proto "github.com/grafana/grafana/pkg/tsdb/models"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func NewDatasourcePluginWrapper(log log.Logger, plugin TsdbPlugin) *DatasourcePluginWrapper {
|
||||
return &DatasourcePluginWrapper{TsdbPlugin: plugin, logger: log}
|
||||
}
|
||||
|
||||
type DatasourcePluginWrapper struct {
|
||||
TsdbPlugin
|
||||
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
func (tw *DatasourcePluginWrapper) Query(ctx context.Context, ds *models.DataSource, query *tsdb.TsdbQuery) (*tsdb.Response, error) {
|
||||
@ -63,7 +71,7 @@ func (tw *DatasourcePluginWrapper) Query(ctx context.Context, ds *models.DataSou
|
||||
Series: []*tsdb.TimeSeries{},
|
||||
}
|
||||
|
||||
for _, s := range r.Series {
|
||||
for _, s := range r.GetSeries() {
|
||||
points := tsdb.TimeSeriesPoints{}
|
||||
|
||||
for _, p := range s.Points {
|
||||
@ -77,7 +85,66 @@ func (tw *DatasourcePluginWrapper) Query(ctx context.Context, ds *models.DataSou
|
||||
Points: points,
|
||||
})
|
||||
}
|
||||
|
||||
mappedTables, err := tw.mapTables(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res.Results[r.RefId].Tables = mappedTables
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
func (tw *DatasourcePluginWrapper) mapTables(r *proto.QueryResult) ([]*tsdb.Table, error) {
|
||||
var tables []*tsdb.Table
|
||||
for _, t := range r.GetTables() {
|
||||
mappedTable, err := tw.mapTable(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tables = append(tables, mappedTable)
|
||||
}
|
||||
return tables, nil
|
||||
}
|
||||
|
||||
func (tw *DatasourcePluginWrapper) mapTable(t *proto.Table) (*tsdb.Table, error) {
|
||||
table := &tsdb.Table{}
|
||||
for _, c := range t.GetColumns() {
|
||||
table.Columns = append(table.Columns, tsdb.TableColumn{
|
||||
Text: c.Name,
|
||||
})
|
||||
}
|
||||
|
||||
for _, r := range t.GetRows() {
|
||||
row := tsdb.RowValues{}
|
||||
for _, rv := range r.Values {
|
||||
mappedRw, err := tw.mapRowValue(rv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
row = append(row, mappedRw)
|
||||
}
|
||||
table.Rows = append(table.Rows, row)
|
||||
}
|
||||
|
||||
return table, nil
|
||||
}
|
||||
func (tw *DatasourcePluginWrapper) mapRowValue(rv *proto.RowValue) (interface{}, error) {
|
||||
switch rv.Kind {
|
||||
case proto.RowValue_TYPE_NULL:
|
||||
return nil, nil
|
||||
case proto.RowValue_TYPE_INT64:
|
||||
return rv.Int64Value, nil
|
||||
case proto.RowValue_TYPE_BOOL:
|
||||
return rv.BoolValue, nil
|
||||
case proto.RowValue_TYPE_STRING:
|
||||
return rv.StringValue, nil
|
||||
case proto.RowValue_TYPE_DOUBLE:
|
||||
return rv.DoubleValue, nil
|
||||
case proto.RowValue_TYPE_BYTES:
|
||||
return rv.BytesValue, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("Unsupported row value %v from plugin", rv.Kind)
|
||||
}
|
||||
}
|
||||
|
108
pkg/plugins/datasource/tsdb/datasource_plugin_wrapper_test.go
Normal file
108
pkg/plugins/datasource/tsdb/datasource_plugin_wrapper_test.go
Normal file
@ -0,0 +1,108 @@
|
||||
package tsdb
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/log"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
"github.com/grafana/grafana/pkg/tsdb/models"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMapTables(t *testing.T) {
|
||||
dpw := NewDatasourcePluginWrapper(log.New("test-logger"), nil)
|
||||
var qr = &proto.QueryResult{}
|
||||
qr.Tables = append(qr.Tables, &proto.Table{
|
||||
Columns: []*proto.TableColumn{},
|
||||
Rows: nil,
|
||||
})
|
||||
want := []*tsdb.Table{{}}
|
||||
|
||||
have, err := dpw.mapTables(qr)
|
||||
if err != nil {
|
||||
t.Errorf("failed to map tables. error: %v", err)
|
||||
}
|
||||
if len(want) != len(have) {
|
||||
t.Errorf("could not map all tables")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapTable(t *testing.T) {
|
||||
dpw := NewDatasourcePluginWrapper(log.New("test-logger"), nil)
|
||||
|
||||
source := &proto.Table{
|
||||
Columns: []*proto.TableColumn{{Name: "column1"}, {Name: "column2"}},
|
||||
Rows: []*proto.TableRow{{
|
||||
Values: []*proto.RowValue{
|
||||
{
|
||||
Kind: proto.RowValue_TYPE_BOOL,
|
||||
BoolValue: true,
|
||||
},
|
||||
{
|
||||
Kind: proto.RowValue_TYPE_INT64,
|
||||
Int64Value: 42,
|
||||
},
|
||||
},
|
||||
}},
|
||||
}
|
||||
|
||||
want := &tsdb.Table{
|
||||
Columns: []tsdb.TableColumn{{Text: "column1"}, {Text: "column2"}},
|
||||
}
|
||||
have, err := dpw.mapTable(source)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to map table. error: %v", err)
|
||||
}
|
||||
|
||||
for i := range have.Columns {
|
||||
if want.Columns[i] != have.Columns[i] {
|
||||
t.Fatalf("have column: %s, want %s", have, want)
|
||||
}
|
||||
}
|
||||
|
||||
if len(have.Rows) != 1 {
|
||||
t.Fatalf("Expects one row but got %d", len(have.Rows))
|
||||
}
|
||||
|
||||
rowValuesCount := len(have.Rows[0])
|
||||
if rowValuesCount != 2 {
|
||||
t.Fatalf("Expects two row values, got %d", rowValuesCount)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMappingRowValue(t *testing.T) {
|
||||
dpw := NewDatasourcePluginWrapper(log.New("test-logger"), nil)
|
||||
|
||||
boolRowValue, _ := dpw.mapRowValue(&proto.RowValue{Kind: proto.RowValue_TYPE_BOOL, BoolValue: true})
|
||||
haveBool, ok := boolRowValue.(bool)
|
||||
if !ok || haveBool != true {
|
||||
t.Fatalf("Expected true, was %s", haveBool)
|
||||
}
|
||||
|
||||
intRowValue, _ := dpw.mapRowValue(&proto.RowValue{Kind: proto.RowValue_TYPE_INT64, Int64Value: 42})
|
||||
haveInt, ok := intRowValue.(int64)
|
||||
if !ok || haveInt != 42 {
|
||||
t.Fatalf("Expected %d, was %d", 42, haveInt)
|
||||
}
|
||||
|
||||
stringRowValue, _ := dpw.mapRowValue(&proto.RowValue{Kind: proto.RowValue_TYPE_STRING, StringValue: "grafana"})
|
||||
haveString, ok := stringRowValue.(string)
|
||||
if !ok || haveString != "grafana" {
|
||||
t.Fatalf("Expected %s, was %s", "grafana", haveString)
|
||||
}
|
||||
|
||||
doubleRowValue, _ := dpw.mapRowValue(&proto.RowValue{Kind: proto.RowValue_TYPE_DOUBLE, DoubleValue: 1.5})
|
||||
haveDouble, ok := doubleRowValue.(float64)
|
||||
if !ok || haveDouble != 1.5 {
|
||||
t.Fatalf("Expected %v, was %v", 1.5, haveDouble)
|
||||
}
|
||||
|
||||
bytesRowValue, _ := dpw.mapRowValue(&proto.RowValue{Kind: proto.RowValue_TYPE_BYTES, BytesValue: []byte{66}})
|
||||
haveBytes, ok := bytesRowValue.([]byte)
|
||||
if !ok || len(haveBytes) != 1 || haveBytes[0] != 66 {
|
||||
t.Fatalf("Expected %v, was %v", []byte{66}, haveBytes)
|
||||
}
|
||||
|
||||
haveNil, _ := dpw.mapRowValue(&proto.RowValue{Kind: proto.RowValue_TYPE_NULL})
|
||||
if haveNil != nil {
|
||||
t.Fatalf("Expected %v, was %v", nil, haveNil)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user