The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/tsdb/sql_engine_test.go

335 lines
10 KiB

package tsdb
import (
"fmt"
"testing"
"time"
"github.com/grafana/grafana/pkg/components/null"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
. "github.com/smartystreets/goconvey/convey"
)
func TestSqlEngine(t *testing.T) {
Convey("SqlEngine", t, func() {
dt := time.Date(2018, 3, 14, 21, 20, 6, int(527345*time.Microsecond), time.UTC)
earlyDt := time.Date(1970, 3, 14, 21, 20, 6, int(527345*time.Microsecond), time.UTC)
Convey("Given a time range between 2018-04-12 00:00 and 2018-04-12 00:05", func() {
from := time.Date(2018, 4, 12, 18, 0, 0, 0, time.UTC)
to := from.Add(5 * time.Minute)
timeRange := NewFakeTimeRange("5m", "now", to)
query := &Query{DataSource: &models.DataSource{}, Model: simplejson.New()}
Convey("interpolate $__interval", func() {
sql, err := Interpolate(query, timeRange, "select $__interval ")
So(err, ShouldBeNil)
So(sql, ShouldEqual, "select 1m ")
})
Convey("interpolate $__interval in $__timeGroup", func() {
sql, err := Interpolate(query, timeRange, "select $__timeGroupAlias(time,$__interval)")
So(err, ShouldBeNil)
So(sql, ShouldEqual, "select $__timeGroupAlias(time,1m)")
})
Convey("interpolate $__interval_ms", func() {
sql, err := Interpolate(query, timeRange, "select $__interval_ms ")
So(err, ShouldBeNil)
So(sql, ShouldEqual, "select 60000 ")
})
Convey("interpolate __unixEpochFrom function", func() {
sql, err := Interpolate(query, timeRange, "select $__unixEpochFrom()")
So(err, ShouldBeNil)
So(sql, ShouldEqual, fmt.Sprintf("select %d", from.Unix()))
})
Convey("interpolate __unixEpochTo function", func() {
sql, err := Interpolate(query, timeRange, "select $__unixEpochTo()")
So(err, ShouldBeNil)
So(sql, ShouldEqual, fmt.Sprintf("select %d", to.Unix()))
})
})
Convey("Given row values with time.Time as time columns", func() {
var nilPointer *time.Time
fixtures := make([]interface{}, 5)
fixtures[0] = dt
fixtures[1] = &dt
fixtures[2] = earlyDt
fixtures[3] = &earlyDt
fixtures[4] = nilPointer
for i := range fixtures {
ConvertSqlTimeColumnToEpochMs(fixtures, i)
}
Convey("When converting them should return epoch time with millisecond precision ", func() {
expected := float64(dt.UnixNano()) / float64(time.Millisecond)
expectedEarly := float64(earlyDt.UnixNano()) / float64(time.Millisecond)
So(fixtures[0].(float64), ShouldEqual, expected)
So(fixtures[1].(float64), ShouldEqual, expected)
So(fixtures[2].(float64), ShouldEqual, expectedEarly)
So(fixtures[3].(float64), ShouldEqual, expectedEarly)
So(fixtures[4], ShouldBeNil)
})
})
Convey("Given row values with int64 as time columns", func() {
tSeconds := dt.Unix()
tMilliseconds := dt.UnixNano() / 1e6
tNanoSeconds := dt.UnixNano()
var nilPointer *int64
fixtures := make([]interface{}, 7)
fixtures[0] = tSeconds
fixtures[1] = &tSeconds
fixtures[2] = tMilliseconds
fixtures[3] = &tMilliseconds
fixtures[4] = tNanoSeconds
fixtures[5] = &tNanoSeconds
fixtures[6] = nilPointer
for i := range fixtures {
ConvertSqlTimeColumnToEpochMs(fixtures, i)
}
Convey("When converting them should return epoch time with millisecond precision ", func() {
So(fixtures[0].(int64), ShouldEqual, tSeconds*1e3)
So(fixtures[1].(int64), ShouldEqual, tSeconds*1e3)
So(fixtures[2].(int64), ShouldEqual, tMilliseconds)
So(fixtures[3].(int64), ShouldEqual, tMilliseconds)
So(fixtures[4].(int64), ShouldEqual, tMilliseconds)
So(fixtures[5].(int64), ShouldEqual, tMilliseconds)
So(fixtures[6], ShouldBeNil)
})
})
Convey("Given row values with uin64 as time columns", func() {
tSeconds := uint64(dt.Unix())
tMilliseconds := uint64(dt.UnixNano() / 1e6)
tNanoSeconds := uint64(dt.UnixNano())
var nilPointer *uint64
fixtures := make([]interface{}, 7)
fixtures[0] = tSeconds
fixtures[1] = &tSeconds
fixtures[2] = tMilliseconds
fixtures[3] = &tMilliseconds
fixtures[4] = tNanoSeconds
fixtures[5] = &tNanoSeconds
fixtures[6] = nilPointer
for i := range fixtures {
ConvertSqlTimeColumnToEpochMs(fixtures, i)
}
Convey("When converting them should return epoch time with millisecond precision ", func() {
So(fixtures[0].(int64), ShouldEqual, tSeconds*1e3)
So(fixtures[1].(int64), ShouldEqual, tSeconds*1e3)
So(fixtures[2].(int64), ShouldEqual, tMilliseconds)
So(fixtures[3].(int64), ShouldEqual, tMilliseconds)
So(fixtures[4].(int64), ShouldEqual, tMilliseconds)
So(fixtures[5].(int64), ShouldEqual, tMilliseconds)
So(fixtures[6], ShouldBeNil)
})
})
Convey("Given row values with int32 as time columns", func() {
tSeconds := int32(dt.Unix())
var nilInt *int32
fixtures := make([]interface{}, 3)
fixtures[0] = tSeconds
fixtures[1] = &tSeconds
fixtures[2] = nilInt
for i := range fixtures {
ConvertSqlTimeColumnToEpochMs(fixtures, i)
}
Convey("When converting them should return epoch time with millisecond precision ", func() {
So(fixtures[0].(int64), ShouldEqual, dt.Unix()*1e3)
So(fixtures[1].(int64), ShouldEqual, dt.Unix()*1e3)
So(fixtures[2], ShouldBeNil)
})
})
Convey("Given row values with uint32 as time columns", func() {
tSeconds := uint32(dt.Unix())
var nilInt *uint32
fixtures := make([]interface{}, 3)
fixtures[0] = tSeconds
fixtures[1] = &tSeconds
fixtures[2] = nilInt
for i := range fixtures {
ConvertSqlTimeColumnToEpochMs(fixtures, i)
}
Convey("When converting them should return epoch time with millisecond precision ", func() {
So(fixtures[0].(int64), ShouldEqual, dt.Unix()*1e3)
So(fixtures[1].(int64), ShouldEqual, dt.Unix()*1e3)
So(fixtures[2], ShouldBeNil)
})
})
Convey("Given row values with float64 as time columns", func() {
tSeconds := float64(dt.UnixNano()) / float64(time.Second)
tMilliseconds := float64(dt.UnixNano()) / float64(time.Millisecond)
tNanoSeconds := float64(dt.UnixNano())
var nilPointer *float64
fixtures := make([]interface{}, 7)
fixtures[0] = tSeconds
fixtures[1] = &tSeconds
fixtures[2] = tMilliseconds
fixtures[3] = &tMilliseconds
fixtures[4] = tNanoSeconds
fixtures[5] = &tNanoSeconds
fixtures[6] = nilPointer
for i := range fixtures {
ConvertSqlTimeColumnToEpochMs(fixtures, i)
}
Convey("When converting them should return epoch time with millisecond precision ", func() {
So(fixtures[0].(float64), ShouldEqual, tMilliseconds)
So(fixtures[1].(float64), ShouldEqual, tMilliseconds)
So(fixtures[2].(float64), ShouldEqual, tMilliseconds)
So(fixtures[3].(float64), ShouldEqual, tMilliseconds)
So(fixtures[4].(float64), ShouldEqual, tMilliseconds)
So(fixtures[5].(float64), ShouldEqual, tMilliseconds)
So(fixtures[6], ShouldBeNil)
})
})
Convey("Given row values with float32 as time columns", func() {
tSeconds := float32(dt.Unix())
var nilInt *float32
fixtures := make([]interface{}, 3)
fixtures[0] = tSeconds
fixtures[1] = &tSeconds
fixtures[2] = nilInt
for i := range fixtures {
ConvertSqlTimeColumnToEpochMs(fixtures, i)
}
Convey("When converting them should return epoch time with millisecond precision ", func() {
So(fixtures[0].(float64), ShouldEqual, float32(dt.Unix()*1e3))
So(fixtures[1].(float64), ShouldEqual, float32(dt.Unix()*1e3))
So(fixtures[2], ShouldBeNil)
})
})
Convey("Given row with value columns", func() {
intValue := 1
int64Value := int64(1)
int32Value := int32(1)
int16Value := int16(1)
int8Value := int8(1)
float64Value := float64(1)
float32Value := float32(1)
uintValue := uint(1)
uint64Value := uint64(1)
uint32Value := uint32(1)
uint16Value := uint16(1)
uint8Value := uint8(1)
fixtures := make([]interface{}, 24)
fixtures[0] = intValue
fixtures[1] = &intValue
fixtures[2] = int64Value
fixtures[3] = &int64Value
fixtures[4] = int32Value
fixtures[5] = &int32Value
fixtures[6] = int16Value
fixtures[7] = &int16Value
fixtures[8] = int8Value
fixtures[9] = &int8Value
fixtures[10] = float64Value
fixtures[11] = &float64Value
fixtures[12] = float32Value
fixtures[13] = &float32Value
fixtures[14] = uintValue
fixtures[15] = &uintValue
fixtures[16] = uint64Value
fixtures[17] = &uint64Value
fixtures[18] = uint32Value
fixtures[19] = &uint32Value
fixtures[20] = uint16Value
fixtures[21] = &uint16Value
fixtures[22] = uint8Value
fixtures[23] = &uint8Value
var intNilPointer *int
var int64NilPointer *int64
var int32NilPointer *int32
var int16NilPointer *int16
var int8NilPointer *int8
var float64NilPointer *float64
var float32NilPointer *float32
var uintNilPointer *uint
var uint64NilPointer *uint64
var uint32NilPointer *uint32
var uint16NilPointer *uint16
var uint8NilPointer *uint8
nilPointerFixtures := make([]interface{}, 12)
nilPointerFixtures[0] = intNilPointer
nilPointerFixtures[1] = int64NilPointer
nilPointerFixtures[2] = int32NilPointer
nilPointerFixtures[3] = int16NilPointer
nilPointerFixtures[4] = int8NilPointer
nilPointerFixtures[5] = float64NilPointer
nilPointerFixtures[6] = float32NilPointer
nilPointerFixtures[7] = uintNilPointer
nilPointerFixtures[8] = uint64NilPointer
nilPointerFixtures[9] = uint32NilPointer
nilPointerFixtures[10] = uint16NilPointer
nilPointerFixtures[11] = uint8NilPointer
Convey("When converting values to float should return expected value", func() {
for _, f := range fixtures {
value, _ := ConvertSqlValueColumnToFloat("col", f)
if !value.Valid {
t.Fatalf("Failed to convert %T value, expected a valid float value", f)
}
if value.Float64 != null.FloatFrom(1).Float64 {
t.Fatalf("Failed to convert %T value, expected a float value of 1.000, but got %v", f, value)
}
}
})
Convey("When converting nil pointer values to float should return expected value", func() {
for _, f := range nilPointerFixtures {
value, err := ConvertSqlValueColumnToFloat("col", f)
if err != nil {
t.Fatalf("Failed to convert %T value, expected a non nil error, but got %v", f, err)
}
if value.Valid {
t.Fatalf("Failed to convert %T value, expected an invalid float value", f)
}
}
})
})
})
}