2017-12-04 02:56:21 +08:00
package mssql
import (
pkg/tsdb/mssql/mssql_test.go: pass context.Background() instead of nil
See,
$ gometalinter --vendor --disable-all --enable=megacheck --disable=gotype --deadline 6m ./...
pkg/tsdb/mssql/mssql_test.go:131:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:221:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:268:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:330:34:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:355:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:444:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:466:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:488:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:510:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:532:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:554:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:576:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:598:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:620:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:643:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:666:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:742:34:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:819:34:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:895:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:918:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:944:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:974:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:1004:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:1034:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:1062:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
pkg/tsdb/mssql/mssql_test.go:1090:33:warning: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (SA1012) (megacheck)
2018-10-03 16:21:14 +08:00
"context"
2018-03-15 16:51:29 +08:00
"fmt"
2018-03-16 21:42:54 +08:00
"math/rand"
2017-12-06 15:32:20 +08:00
"strings"
2017-12-04 02:56:21 +08:00
"testing"
"time"
2021-05-05 22:46:07 +08:00
"github.com/grafana/grafana-plugin-sdk-go/data"
2018-07-27 00:11:10 +08:00
"github.com/grafana/grafana/pkg/components/securejsondata"
2017-12-04 02:56:21 +08:00
"github.com/grafana/grafana/pkg/components/simplejson"
2021-03-29 19:03:01 +08:00
"github.com/grafana/grafana/pkg/infra/log"
2018-07-27 00:11:10 +08:00
"github.com/grafana/grafana/pkg/models"
2021-03-08 14:02:49 +08:00
"github.com/grafana/grafana/pkg/plugins"
2021-05-05 22:46:07 +08:00
"github.com/grafana/grafana/pkg/services/sqlstore"
2017-12-04 02:56:21 +08:00
"github.com/grafana/grafana/pkg/services/sqlstore/sqlutil"
2019-09-11 03:50:04 +08:00
"github.com/grafana/grafana/pkg/tsdb/sqleng"
2021-03-29 19:03:01 +08:00
"github.com/stretchr/testify/assert"
2021-03-30 16:54:57 +08:00
"github.com/stretchr/testify/require"
2020-04-01 21:57:21 +08:00
"xorm.io/xorm"
2017-12-04 02:56:21 +08:00
)
2021-05-05 22:46:07 +08:00
// To run this test, set runMssqlTests=true
// Or from the commandline: GRAFANA_TEST_DB=mssql go test -v ./pkg/tsdb/mssql
2018-04-16 17:06:23 +08:00
// The tests require a MSSQL db named grafanatest and a user/password grafana/Password!
2018-03-16 21:42:54 +08:00
// Use the docker/blocks/mssql_tests/docker-compose.yaml to spin up a
// preconfigured MSSQL server suitable for running these tests.
2018-07-27 00:11:10 +08:00
// There is also a datasource and dashboard provisioned by devenv scripts that you can
2020-06-01 23:11:25 +08:00
// use to verify that the generated data are visualized as expected, see
2018-07-27 00:11:10 +08:00
// devenv/README.md for setup instructions.
2018-03-16 21:42:54 +08:00
// If needed, change the variable below to the IP address of the database.
2018-04-28 04:14:36 +08:00
var serverIP = "localhost"
2017-12-06 15:32:20 +08:00
2017-12-04 02:56:21 +08:00
func TestMSSQL ( t * testing . T ) {
2021-05-05 22:46:07 +08:00
// change to true to run the MSSQL tests
const runMssqlTests = false
2017-12-04 02:56:21 +08:00
2021-05-05 22:46:07 +08:00
if ! ( sqlstore . IsTestDBMSSQL ( ) || runMssqlTests ) {
t . Skip ( )
}
2017-12-04 02:56:21 +08:00
2021-05-05 22:46:07 +08:00
x := initMSSQLTestDB ( t )
origXormEngine := sqleng . NewXormEngine
t . Cleanup ( func ( ) {
sqleng . NewXormEngine = origXormEngine
} )
2018-09-13 22:51:00 +08:00
2021-05-05 22:46:07 +08:00
sqleng . NewXormEngine = func ( d , c string ) ( * xorm . Engine , error ) {
return x , nil
}
2017-12-04 02:56:21 +08:00
2021-05-05 22:46:07 +08:00
endpoint , err := NewExecutor ( & models . DataSource {
JsonData : simplejson . New ( ) ,
SecureJsonData : securejsondata . SecureJsonData { } ,
} )
require . NoError ( t , err )
2018-03-16 21:37:16 +08:00
2021-05-05 22:46:07 +08:00
sess := x . NewSession ( )
t . Cleanup ( sess . Close )
2018-07-27 00:11:10 +08:00
2021-05-05 22:46:07 +08:00
fromStart := time . Date ( 2018 , 3 , 15 , 13 , 0 , 0 , 0 , time . UTC ) . In ( time . Local )
t . Run ( "Given a table with different native data types" , func ( t * testing . T ) {
sql := `
2018-03-20 21:38:56 +08:00
IF OBJECT_ID ( ' dbo . [ mssql_types ] ' , 'U' ) IS NOT NULL
DROP TABLE dbo . [ mssql_types ]
CREATE TABLE [ mssql_types ] (
c_bit bit ,
c_tinyint tinyint ,
c_smallint smallint ,
c_int int ,
c_bigint bigint ,
c_money money ,
c_smallmoney smallmoney ,
c_numeric numeric ( 10 , 5 ) ,
c_real real ,
c_decimal decimal ( 10 , 2 ) ,
c_float float ,
c_char char ( 10 ) ,
c_varchar varchar ( 10 ) ,
c_text text ,
c_nchar nchar ( 12 ) ,
c_nvarchar nvarchar ( 12 ) ,
c_ntext ntext ,
c_datetime datetime ,
c_datetime2 datetime2 ,
c_smalldatetime smalldatetime ,
c_date date ,
c_time time ,
2020-06-26 16:11:43 +08:00
c_datetimeoffset datetimeoffset ,
c_uuid uniqueidentifier
2018-03-20 21:38:56 +08:00
)
`
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
_ , err := sess . Exec ( sql )
require . NoError ( t , err )
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
dt := time . Date ( 2018 , 3 , 14 , 21 , 20 , 6 , 527e6 , time . UTC )
const dtFormat = "2006-01-02 15:04:05.999999999"
d := dt . Format ( dtFormat )
dt2 := time . Date ( 2018 , 3 , 14 , 21 , 20 , 6 , 8896406e2 , time . UTC )
const dt2Format = "2006-01-02 15:04:05.999999999 -07:00"
d2 := dt2 . Format ( dt2Format )
uuid := "B33D42A3-AC5A-4D4C-81DD-72F3D5C49025"
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
sql = fmt . Sprintf ( `
2018-03-20 21:38:56 +08:00
INSERT INTO [ mssql_types ]
SELECT
1 , 5 , 20020 , 980300 , 1420070400 , ' $ 20000.15 ' , ' £ 2.15 ' , 12345.12 ,
1.11 , 2.22 , 3.33 ,
' char10 ' , ' varchar10 ' , ' text ' ,
N ' ☺ nchar12 ☺ ' , N ' ☺ nvarchar12 ☺ ' , N ' ☺ text ☺ ' ,
2020-06-26 16:11:43 +08:00
CAST ( ' % s ' AS DATETIME ) , CAST ( ' % s ' AS DATETIME2 ) , CAST ( ' % s ' AS SMALLDATETIME ) , CAST ( ' % s ' AS DATE ) , CAST ( ' % s ' AS TIME ) , SWITCHOFFSET ( CAST ( ' % s ' AS DATETIMEOFFSET ) , ' - 07 : 00 ' ) ,
CONVERT ( uniqueidentifier , ' % s ' )
` , d , d2 , d , d , d , d2 , uuid )
2018-03-14 02:54:29 +08:00
2021-05-05 22:46:07 +08:00
_ , err = sess . Exec ( sql )
require . NoError ( t , err )
t . Run ( "When doing a table query should map MSSQL column types to Go types" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : "SELECT * FROM mssql_types" ,
"format" : "table" ,
} ) ,
RefID : "A" ,
2018-03-15 21:26:53 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
}
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
2021-05-11 20:59:33 +08:00
require . NotNil ( t , queryResult )
require . NoError ( t , queryResult . Error )
require . NotNil ( t , queryResult . Dataframes )
2021-05-05 22:46:07 +08:00
2021-05-11 20:59:33 +08:00
frames , err := queryResult . Dataframes . Decoded ( )
require . NoError ( t , err )
2021-05-05 22:46:07 +08:00
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , 24 , len ( frames [ 0 ] . Fields ) )
2021-05-11 20:59:33 +08:00
require . Equal ( t , true , frames [ 0 ] . Fields [ 0 ] . At ( 0 ) . ( bool ) )
2021-05-05 22:46:07 +08:00
require . Equal ( t , int64 ( 5 ) , * frames [ 0 ] . Fields [ 1 ] . At ( 0 ) . ( * int64 ) )
require . Equal ( t , int64 ( 20020 ) , * frames [ 0 ] . Fields [ 2 ] . At ( 0 ) . ( * int64 ) )
require . Equal ( t , int64 ( 980300 ) , * frames [ 0 ] . Fields [ 3 ] . At ( 0 ) . ( * int64 ) )
require . Equal ( t , int64 ( 1420070400 ) , * frames [ 0 ] . Fields [ 4 ] . At ( 0 ) . ( * int64 ) )
require . Equal ( t , float64 ( 20000.15 ) , * frames [ 0 ] . Fields [ 5 ] . At ( 0 ) . ( * float64 ) )
require . Equal ( t , float64 ( 2.15 ) , * frames [ 0 ] . Fields [ 6 ] . At ( 0 ) . ( * float64 ) )
require . Equal ( t , float64 ( 12345.12 ) , * frames [ 0 ] . Fields [ 7 ] . At ( 0 ) . ( * float64 ) )
require . Equal ( t , float64 ( 1.1100000143051147 ) , * frames [ 0 ] . Fields [ 8 ] . At ( 0 ) . ( * float64 ) )
require . Equal ( t , float64 ( 2.22 ) , * frames [ 0 ] . Fields [ 9 ] . At ( 0 ) . ( * float64 ) )
require . Equal ( t , float64 ( 3.33 ) , * frames [ 0 ] . Fields [ 10 ] . At ( 0 ) . ( * float64 ) )
require . Equal ( t , "char10 " , * frames [ 0 ] . Fields [ 11 ] . At ( 0 ) . ( * string ) )
require . Equal ( t , "varchar10" , * frames [ 0 ] . Fields [ 12 ] . At ( 0 ) . ( * string ) )
require . Equal ( t , "text" , * frames [ 0 ] . Fields [ 13 ] . At ( 0 ) . ( * string ) )
require . Equal ( t , "☺nchar12☺ " , * frames [ 0 ] . Fields [ 14 ] . At ( 0 ) . ( * string ) )
require . Equal ( t , "☺nvarchar12☺" , * frames [ 0 ] . Fields [ 15 ] . At ( 0 ) . ( * string ) )
require . Equal ( t , "☺text☺" , * frames [ 0 ] . Fields [ 16 ] . At ( 0 ) . ( * string ) )
require . Equal ( t , dt . Unix ( ) , ( * frames [ 0 ] . Fields [ 17 ] . At ( 0 ) . ( * time . Time ) ) . Unix ( ) )
require . Equal ( t , dt2 , * frames [ 0 ] . Fields [ 18 ] . At ( 0 ) . ( * time . Time ) )
require . Equal ( t , dt . Truncate ( time . Minute ) , * frames [ 0 ] . Fields [ 19 ] . At ( 0 ) . ( * time . Time ) )
require . Equal ( t , dt . Truncate ( 24 * time . Hour ) , * frames [ 0 ] . Fields [ 20 ] . At ( 0 ) . ( * time . Time ) )
require . Equal ( t , time . Date ( 1 , 1 , 1 , dt . Hour ( ) , dt . Minute ( ) , dt . Second ( ) , dt . Nanosecond ( ) , time . UTC ) , * frames [ 0 ] . Fields [ 21 ] . At ( 0 ) . ( * time . Time ) )
require . Equal ( t , dt2 . In ( time . FixedZone ( "UTC-7" , int ( - 7 * 60 * 60 ) ) ) . Unix ( ) , ( * frames [ 0 ] . Fields [ 22 ] . At ( 0 ) . ( * time . Time ) ) . Unix ( ) )
require . Equal ( t , uuid , * frames [ 0 ] . Fields [ 23 ] . At ( 0 ) . ( * string ) )
} )
} )
2018-03-16 21:37:16 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "Given a table with metrics that lacks data for some series " , func ( t * testing . T ) {
sql := `
IF OBJECT_ID ( ' dbo . [ metric ] ' , 'U' ) IS NOT NULL
DROP TABLE dbo . [ metric ]
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
CREATE TABLE [ metric ] (
time datetime ,
value int
)
`
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
_ , err := sess . Exec ( sql )
require . NoError ( t , err )
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
type metric struct {
Time time . Time
Value int64
}
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
series := [ ] * metric { }
firstRange := genTimeRangeByInterval ( fromStart , 10 * time . Minute , 10 * time . Second )
secondRange := genTimeRangeByInterval ( fromStart . Add ( 20 * time . Minute ) , 10 * time . Minute , 10 * time . Second )
2020-06-26 16:11:43 +08:00
2021-05-05 22:46:07 +08:00
for _ , t := range firstRange {
series = append ( series , & metric {
Time : t ,
Value : 15 ,
2018-03-15 21:26:53 +08:00
} )
2021-05-05 22:46:07 +08:00
}
2018-03-15 16:51:29 +08:00
2021-05-05 22:46:07 +08:00
for _ , t := range secondRange {
series = append ( series , & metric {
Time : t ,
Value : 20 ,
} )
}
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
_ , err = sess . InsertMulti ( series )
require . NoError ( t , err )
t . Run ( "When doing a metric query using timeGroup" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : "SELECT $__timeGroup(time, '5m') AS time, avg(value) as value FROM metric GROUP BY $__timeGroup(time, '5m') ORDER BY 1" ,
"format" : "time_series" ,
} ) ,
RefID : "A" ,
} ,
} ,
}
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-03-15 16:51:29 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Len ( t , frames , 1 )
// without fill this should result in 4 buckets
require . Equal ( t , 4 , frames [ 0 ] . Fields [ 0 ] . Len ( ) )
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
dt := fromStart
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
for i := 0 ; i < 2 ; i ++ {
aValue := * frames [ 0 ] . Fields [ 1 ] . At ( i ) . ( * float64 )
aTime := * frames [ 0 ] . Fields [ 0 ] . At ( i ) . ( * time . Time )
require . Equal ( t , float64 ( 15 ) , aValue )
require . Equal ( t , dt , aTime )
dt = dt . Add ( 5 * time . Minute )
2018-03-15 21:26:53 +08:00
}
2021-05-05 22:46:07 +08:00
// adjust for 10 minute gap between first and second set of points
dt = dt . Add ( 10 * time . Minute )
for i := 2 ; i < 4 ; i ++ {
aValue := * frames [ 0 ] . Fields [ 1 ] . At ( i ) . ( * float64 )
aTime := * frames [ 0 ] . Fields [ 0 ] . At ( i ) . ( * time . Time )
require . Equal ( t , float64 ( 20 ) , aValue )
require . Equal ( t , dt , aTime )
dt = dt . Add ( 5 * time . Minute )
2018-03-15 21:26:53 +08:00
}
2021-05-05 22:46:07 +08:00
} )
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing a metric query using timeGroup with NULL fill enabled" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : "SELECT $__timeGroup(time, '5m', NULL) AS time, avg(value) as value FROM metric GROUP BY $__timeGroup(time, '5m') ORDER BY 1" ,
"format" : "time_series" ,
} ) ,
RefID : "A" ,
2018-03-15 21:26:53 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
TimeRange : & plugins . DataTimeRange {
From : fmt . Sprintf ( "%v" , fromStart . Unix ( ) * 1000 ) ,
To : fmt . Sprintf ( "%v" , fromStart . Add ( 34 * time . Minute ) . Unix ( ) * 1000 ) ,
} ,
}
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Len ( t , frames , 1 )
require . Equal ( t , 7 , frames [ 0 ] . Fields [ 0 ] . Len ( ) )
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
dt := fromStart
2018-03-22 21:49:40 +08:00
2021-05-05 22:46:07 +08:00
for i := 0 ; i < 2 ; i ++ {
aValue := * frames [ 0 ] . Fields [ 1 ] . At ( i ) . ( * float64 )
aTime := * frames [ 0 ] . Fields [ 0 ] . At ( i ) . ( * time . Time )
require . Equal ( t , float64 ( 15 ) , aValue )
require . Equal ( t , dt . Unix ( ) , aTime . Unix ( ) )
dt = dt . Add ( 5 * time . Minute )
}
2018-03-15 21:26:53 +08:00
2021-05-05 22:46:07 +08:00
// check for NULL values inserted by fill
require . Nil ( t , frames [ 0 ] . Fields [ 1 ] . At ( 2 ) . ( * float64 ) )
require . Nil ( t , frames [ 0 ] . Fields [ 1 ] . At ( 3 ) . ( * float64 ) )
// adjust for 10 minute gap between first and second set of points
dt = dt . Add ( 10 * time . Minute )
for i := 4 ; i < 6 ; i ++ {
aValue := * frames [ 0 ] . Fields [ 1 ] . At ( i ) . ( * float64 )
aTime := * frames [ 0 ] . Fields [ 0 ] . At ( i ) . ( * time . Time )
require . Equal ( t , float64 ( 20 ) , aValue )
require . Equal ( t , dt . Unix ( ) , aTime . Unix ( ) )
dt = dt . Add ( 5 * time . Minute )
}
require . Nil ( t , frames [ 0 ] . Fields [ 1 ] . At ( 6 ) . ( * float64 ) )
} )
2018-03-15 22:06:54 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing a metric query using timeGroup and $__interval" , func ( t * testing . T ) {
t . Run ( "Should replace $__interval" , func ( t * testing . T ) {
2021-03-08 14:02:49 +08:00
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
2018-03-15 22:06:54 +08:00
{
2021-05-05 22:46:07 +08:00
DataSource : & models . DataSource { } ,
2018-03-15 22:06:54 +08:00
Model : simplejson . NewFromAny ( map [ string ] interface { } {
2021-05-05 22:46:07 +08:00
"rawSql" : "SELECT $__timeGroup(time, $__interval) AS time, avg(value) as value FROM metric GROUP BY $__timeGroup(time, $__interval) ORDER BY 1" ,
2018-03-15 22:06:54 +08:00
"format" : "time_series" ,
} ) ,
2021-03-08 14:02:49 +08:00
RefID : "A" ,
2018-03-15 22:06:54 +08:00
} ,
} ,
2021-03-08 14:02:49 +08:00
TimeRange : & plugins . DataTimeRange {
2018-03-15 22:06:54 +08:00
From : fmt . Sprintf ( "%v" , fromStart . Unix ( ) * 1000 ) ,
2021-05-05 22:46:07 +08:00
To : fmt . Sprintf ( "%v" , fromStart . Add ( 30 * time . Minute ) . Unix ( ) * 1000 ) ,
2018-03-15 22:06:54 +08:00
} ,
}
2021-03-08 14:02:49 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
2021-05-05 22:46:07 +08:00
require . NoError ( t , err )
2018-03-22 21:49:40 +08:00
queryResult := resp . Results [ "A" ]
2021-05-05 22:46:07 +08:00
require . NoError ( t , queryResult . Error )
2018-03-15 22:06:54 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Len ( t , frames , 1 )
require . Equal ( t , "SELECT FLOOR(DATEDIFF(second, '1970-01-01', time)/60)*60 AS time, avg(value) as value FROM metric GROUP BY FLOOR(DATEDIFF(second, '1970-01-01', time)/60)*60 ORDER BY 1" , frames [ 0 ] . Meta . ExecutedQueryString )
} )
} )
t . Run ( "When doing a metric query using timeGroup with float fill enabled" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : "SELECT $__timeGroup(time, '5m', 1.5) AS time, avg(value) as value FROM metric GROUP BY $__timeGroup(time, '5m') ORDER BY 1" ,
"format" : "time_series" ,
} ) ,
RefID : "A" ,
} ,
} ,
TimeRange : & plugins . DataTimeRange {
From : fmt . Sprintf ( "%v" , fromStart . Unix ( ) * 1000 ) ,
To : fmt . Sprintf ( "%v" , fromStart . Add ( 34 * time . Minute ) . Unix ( ) * 1000 ) ,
} ,
}
2018-03-15 22:06:54 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-03-22 21:49:40 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , 7 , frames [ 0 ] . Fields [ 0 ] . Len ( ) )
require . Equal ( t , 1.5 , * frames [ 0 ] . Fields [ 1 ] . At ( 3 ) . ( * float64 ) )
} )
} )
2018-03-22 21:49:40 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "Given a table with metrics having multiple values and measurements" , func ( t * testing . T ) {
type metric_values struct {
Time time . Time
TimeInt64 int64 ` xorm:"bigint 'timeInt64' not null" `
TimeInt64Nullable * int64 ` xorm:"bigint 'timeInt64Nullable' null" `
TimeFloat64 float64 ` xorm:"float 'timeFloat64' not null" `
TimeFloat64Nullable * float64 ` xorm:"float 'timeFloat64Nullable' null" `
TimeInt32 int32 ` xorm:"int(11) 'timeInt32' not null" `
TimeInt32Nullable * int32 ` xorm:"int(11) 'timeInt32Nullable' null" `
TimeFloat32 float32 ` xorm:"float(11) 'timeFloat32' not null" `
TimeFloat32Nullable * float32 ` xorm:"float(11) 'timeFloat32Nullable' null" `
Measurement string
ValueOne int64 ` xorm:"integer 'valueOne'" `
ValueTwo int64 ` xorm:"integer 'valueTwo'" `
}
2018-07-01 21:57:02 +08:00
2021-05-05 22:46:07 +08:00
exists , err := sess . IsTableExist ( metric_values { } )
require . NoError ( t , err )
if exists {
err := sess . DropTable ( metric_values { } )
require . NoError ( t , err )
}
err = sess . CreateTable ( metric_values { } )
require . NoError ( t , err )
2018-03-15 22:06:54 +08:00
2021-05-05 22:46:07 +08:00
rand . Seed ( time . Now ( ) . Unix ( ) )
rnd := func ( min , max int64 ) int64 {
return rand . Int63n ( max - min ) + min
}
2018-09-13 22:51:00 +08:00
2021-05-05 22:46:07 +08:00
var tInitial time . Time
2018-09-13 22:51:00 +08:00
2021-05-05 22:46:07 +08:00
series := [ ] * metric_values { }
for i , t := range genTimeRangeByInterval ( fromStart . Add ( - 30 * time . Minute ) , 90 * time . Minute , 5 * time . Minute ) {
if i == 0 {
tInitial = t
}
tSeconds := t . Unix ( )
tSecondsInt32 := int32 ( tSeconds )
tSecondsFloat32 := float32 ( tSeconds )
tMilliseconds := tSeconds * 1e3
tMillisecondsFloat := float64 ( tMilliseconds )
first := metric_values {
Time : t ,
TimeInt64 : tMilliseconds ,
TimeInt64Nullable : & ( tMilliseconds ) ,
TimeFloat64 : tMillisecondsFloat ,
TimeFloat64Nullable : & tMillisecondsFloat ,
TimeInt32 : tSecondsInt32 ,
TimeInt32Nullable : & tSecondsInt32 ,
TimeFloat32 : tSecondsFloat32 ,
TimeFloat32Nullable : & tSecondsFloat32 ,
Measurement : "Metric A" ,
ValueOne : rnd ( 0 , 100 ) ,
ValueTwo : rnd ( 0 , 100 ) ,
}
second := first
second . Measurement = "Metric B"
second . ValueOne = rnd ( 0 , 100 )
second . ValueTwo = rnd ( 0 , 100 )
2018-09-13 22:51:00 +08:00
2021-05-05 22:46:07 +08:00
series = append ( series , & first )
series = append ( series , & second )
}
2018-09-13 22:51:00 +08:00
2021-05-05 22:46:07 +08:00
_ , err = sess . InsertMulti ( series )
require . NoError ( t , err )
t . Run ( "When doing a metric query using epoch (int64) as time column and value column (int64) should return metric with time in time.Time" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : ` SELECT TOP 1 timeInt64 as time, timeInt64 FROM metric_values ORDER BY time ` ,
"format" : "time_series" ,
} ) ,
RefID : "A" ,
2018-03-15 22:06:54 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
}
2018-03-15 22:06:54 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-03-15 22:06:54 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , tInitial , * frames [ 0 ] . Fields [ 0 ] . At ( 0 ) . ( * time . Time ) )
2017-12-04 02:56:21 +08:00
} )
2018-03-16 21:42:54 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing a metric query using epoch (int64 nullable) as time column and value column (int64 nullable) should return metric with time in time.Time" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : ` SELECT TOP 1 timeInt64Nullable as time, timeInt64Nullable FROM metric_values ORDER BY time ` ,
"format" : "time_series" ,
} ) ,
RefID : "A" ,
} ,
} ,
2018-03-16 21:42:54 +08:00
}
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
frames , _ := queryResult . Dataframes . Decoded ( )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , tInitial , * frames [ 0 ] . Fields [ 0 ] . At ( 0 ) . ( * time . Time ) )
} )
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing a metric query using epoch (float64) as time column and value column (float64) should return metric with time in time.Time" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : ` SELECT TOP 1 timeFloat64 as time, timeFloat64 FROM metric_values ORDER BY time ` ,
"format" : "time_series" ,
} ) ,
RefID : "A" ,
} ,
} ,
2018-03-16 21:42:54 +08:00
}
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , tInitial , * frames [ 0 ] . Fields [ 0 ] . At ( 0 ) . ( * time . Time ) )
} )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing a metric query using epoch (float64 nullable) as time column and value column (float64 nullable) should return metric with time in time.Time" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : ` SELECT TOP 1 timeFloat64Nullable as time, timeFloat64Nullable FROM metric_values ORDER BY time ` ,
"format" : "time_series" ,
} ) ,
RefID : "A" ,
} ,
} ,
2018-03-16 21:42:54 +08:00
}
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , tInitial , * frames [ 0 ] . Fields [ 0 ] . At ( 0 ) . ( * time . Time ) )
} )
t . Run ( "When doing a metric query using epoch (int32) as time column and value column (int32) should return metric with time in time.Time" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : ` SELECT TOP 1 timeInt32 as time, timeInt32 FROM metric_values ORDER BY time ` ,
"format" : "time_series" ,
} ) ,
RefID : "A" ,
2018-04-10 17:10:56 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
}
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , tInitial , * frames [ 0 ] . Fields [ 0 ] . At ( 0 ) . ( * time . Time ) )
} )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing a metric query using epoch (int32 nullable) as time column and value column (int32 nullable) should return metric with time in time.Time" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : ` SELECT TOP 1 timeInt32Nullable as time, timeInt32Nullable FROM metric_values ORDER BY time ` ,
"format" : "time_series" ,
} ) ,
RefID : "A" ,
2018-04-10 17:10:56 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
}
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , tInitial , * frames [ 0 ] . Fields [ 0 ] . At ( 0 ) . ( * time . Time ) )
} )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing a metric query using epoch (float32) as time column and value column (float32) should return metric with time in time.Time" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : ` SELECT TOP 1 timeFloat32 as time, timeFloat32 FROM metric_values ORDER BY time ` ,
"format" : "time_series" ,
} ) ,
RefID : "A" ,
2018-04-10 17:10:56 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
}
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , tInitial , * frames [ 0 ] . Fields [ 0 ] . At ( 0 ) . ( * time . Time ) )
} )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing a metric query using epoch (float32 nullable) as time column and value column (float32 nullable) should return metric with time in milliseconds" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : ` SELECT TOP 1 timeFloat32Nullable as time, timeFloat32Nullable FROM metric_values ORDER BY time ` ,
"format" : "time_series" ,
} ) ,
RefID : "A" ,
2018-04-10 17:10:56 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
}
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Equal ( t , 1 , len ( frames ) )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
require . Equal ( t , time . Unix ( 0 , int64 ( float64 ( float32 ( tInitial . Unix ( ) ) ) * 1e3 ) * int64 ( time . Millisecond ) ) , * frames [ 0 ] . Fields [ 0 ] . At ( 0 ) . ( * time . Time ) )
} )
t . Run ( "When doing a metric query grouping by time and select metric column should return correct series" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : "SELECT $__timeEpoch(time), measurement + ' - value one' as metric, valueOne FROM metric_values ORDER BY 1" ,
"format" : "time_series" ,
} ) ,
RefID : "A" ,
2018-04-10 17:10:56 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
}
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
frames , err := queryResult . Dataframes . Decoded ( )
require . NoError ( t , err )
require . Equal ( t , 1 , len ( frames ) )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
require . Equal ( t , 3 , len ( frames [ 0 ] . Fields ) )
require . Equal ( t , data . Labels { "metric" : "Metric A - value one" } , frames [ 0 ] . Fields [ 1 ] . Labels )
require . Equal ( t , data . Labels { "metric" : "Metric B - value one" } , frames [ 0 ] . Fields [ 2 ] . Labels )
} )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing a metric query grouping by time should return correct series" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : "SELECT $__timeEpoch(time), valueOne, valueTwo FROM metric_values ORDER BY 1" ,
"format" : "time_series" ,
} ) ,
RefID : "A" ,
} ,
} ,
}
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
frames , err := queryResult . Dataframes . Decoded ( )
require . NoError ( t , err )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , 3 , len ( frames [ 0 ] . Fields ) )
require . Equal ( t , "valueOne" , frames [ 0 ] . Fields [ 1 ] . Name )
require . Equal ( t , "valueTwo" , frames [ 0 ] . Fields [ 2 ] . Name )
} )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing a metric query with metric column and multiple value columns" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : "SELECT $__timeEpoch(time), measurement, valueOne, valueTwo FROM metric_values ORDER BY 1" ,
"format" : "time_series" ,
} ) ,
RefID : "A" ,
2018-04-10 17:10:56 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
}
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
frames , err := queryResult . Dataframes . Decoded ( )
require . NoError ( t , err )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , 5 , len ( frames [ 0 ] . Fields ) )
require . Equal ( t , "valueOne" , frames [ 0 ] . Fields [ 1 ] . Name )
require . Equal ( t , data . Labels { "measurement" : "Metric A" } , frames [ 0 ] . Fields [ 1 ] . Labels )
require . Equal ( t , "valueOne" , frames [ 0 ] . Fields [ 2 ] . Name )
require . Equal ( t , data . Labels { "measurement" : "Metric B" } , frames [ 0 ] . Fields [ 2 ] . Labels )
require . Equal ( t , "valueTwo" , frames [ 0 ] . Fields [ 3 ] . Name )
require . Equal ( t , data . Labels { "measurement" : "Metric A" } , frames [ 0 ] . Fields [ 3 ] . Labels )
require . Equal ( t , "valueTwo" , frames [ 0 ] . Fields [ 4 ] . Name )
require . Equal ( t , data . Labels { "measurement" : "Metric B" } , frames [ 0 ] . Fields [ 4 ] . Labels )
} )
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing a query with timeFrom,timeTo,unixEpochFrom,unixEpochTo macros" , func ( t * testing . T ) {
timeRange := plugins . DataTimeRange { From : "5m" , To : "now" , Now : fromStart }
query := plugins . DataQuery {
TimeRange : & timeRange ,
Queries : [ ] plugins . DataSubQuery {
{
DataSource : & models . DataSource { JsonData : simplejson . New ( ) } ,
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : ` SELECT time FROM metric_values WHERE time > $__timeFrom() OR time < $__timeFrom() OR 1 < $__unixEpochFrom() OR $__unixEpochTo() > 1 ORDER BY 1 ` ,
"format" : "time_series" ,
} ) ,
RefID : "A" ,
2018-04-10 17:10:56 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
}
2018-04-10 17:10:56 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
frames , err := queryResult . Dataframes . Decoded ( )
require . NoError ( t , err )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , "SELECT time FROM metric_values WHERE time > '2018-03-15T12:55:00Z' OR time < '2018-03-15T12:55:00Z' OR 1 < 1521118500 OR 1521118800 > 1 ORDER BY 1" , frames [ 0 ] . Meta . ExecutedQueryString )
} )
2018-03-16 21:42:54 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "Given a stored procedure that takes @from and @to in epoch time" , func ( t * testing . T ) {
sql := `
IF object_id ( ' sp_test_epoch ' ) IS NOT NULL
DROP PROCEDURE sp_test_epoch
`
2018-03-16 21:42:54 +08:00
2021-05-05 22:46:07 +08:00
_ , err := sess . Exec ( sql )
require . NoError ( t , err )
sql = `
CREATE PROCEDURE sp_test_epoch (
@ from int ,
@ to int ,
@ interval nvarchar ( 50 ) = ' 5 m ' ,
@ metric nvarchar ( 200 ) = ' ALL '
) AS
BEGIN
DECLARE @ dInterval int
SELECT @ dInterval = 300
IF @ interval = ' 10 m '
SELECT @ dInterval = 600
SELECT
CAST ( ROUND ( DATEDIFF ( second , ' 1970 - 01 - 01 ' , time ) / CAST ( @ dInterval as float ) , 0 ) as bigint ) * @ dInterval as time ,
measurement as metric ,
avg ( valueOne ) as valueOne ,
avg ( valueTwo ) as valueTwo
FROM
metric_values
WHERE
time BETWEEN DATEADD ( s , @ from , ' 1970 - 01 - 01 ' ) AND DATEADD ( s , @ to , ' 1970 - 01 - 01 ' ) AND
( @ metric = ' ALL ' OR measurement = @ metric )
GROUP BY
CAST ( ROUND ( DATEDIFF ( second , ' 1970 - 01 - 01 ' , time ) / CAST ( @ dInterval as float ) , 0 ) as bigint ) * @ dInterval ,
measurement
ORDER BY 1
END
`
2018-03-16 21:42:54 +08:00
2021-05-05 22:46:07 +08:00
_ , err = sess . Exec ( sql )
require . NoError ( t , err )
2018-03-16 21:42:54 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing a metric query using stored procedure should return correct result" , func ( t * testing . T ) {
endpoint , err := NewExecutor ( & models . DataSource {
JsonData : simplejson . New ( ) ,
SecureJsonData : securejsondata . SecureJsonData { } ,
} )
require . NoError ( t , err )
2021-03-08 14:02:49 +08:00
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
2018-03-16 21:42:54 +08:00
{
2021-05-05 22:46:07 +08:00
DataSource : & models . DataSource { JsonData : simplejson . New ( ) } ,
2018-03-16 21:42:54 +08:00
Model : simplejson . NewFromAny ( map [ string ] interface { } {
2021-05-05 22:46:07 +08:00
"rawSql" : ` DECLARE
@ from int = $ __unixEpochFrom ( ) ,
@ to int = $ __unixEpochTo ( )
EXEC dbo . sp_test_epoch @ from , @ to ` ,
2018-03-16 21:42:54 +08:00
"format" : "time_series" ,
} ) ,
2021-03-08 14:02:49 +08:00
RefID : "A" ,
2018-03-16 21:42:54 +08:00
} ,
} ,
2021-05-05 22:46:07 +08:00
TimeRange : & plugins . DataTimeRange {
From : "1521117000000" ,
To : "1521122100000" ,
} ,
2018-03-16 21:42:54 +08:00
}
2021-03-08 14:02:49 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
2021-05-05 22:46:07 +08:00
require . NoError ( t , err )
2018-03-22 22:23:12 +08:00
queryResult := resp . Results [ "A" ]
2021-05-05 22:46:07 +08:00
require . NoError ( t , queryResult . Error )
frames , err := queryResult . Dataframes . Decoded ( )
require . NoError ( t , err )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , 5 , len ( frames [ 0 ] . Fields ) )
require . Equal ( t , "valueOne" , frames [ 0 ] . Fields [ 1 ] . Name )
require . Equal ( t , data . Labels { "metric" : "Metric A" } , frames [ 0 ] . Fields [ 1 ] . Labels )
require . Equal ( t , "valueOne" , frames [ 0 ] . Fields [ 2 ] . Name )
require . Equal ( t , data . Labels { "metric" : "Metric B" } , frames [ 0 ] . Fields [ 2 ] . Labels )
require . Equal ( t , "valueTwo" , frames [ 0 ] . Fields [ 3 ] . Name )
require . Equal ( t , data . Labels { "metric" : "Metric A" } , frames [ 0 ] . Fields [ 3 ] . Labels )
require . Equal ( t , "valueTwo" , frames [ 0 ] . Fields [ 4 ] . Name )
require . Equal ( t , data . Labels { "metric" : "Metric B" } , frames [ 0 ] . Fields [ 4 ] . Labels )
2018-03-16 21:42:54 +08:00
} )
2021-05-05 22:46:07 +08:00
} )
2018-03-20 02:56:34 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "Given a stored procedure that takes @from and @to in datetime" , func ( t * testing . T ) {
sql := `
IF object_id ( ' sp_test_datetime ' ) IS NOT NULL
DROP PROCEDURE sp_test_datetime
`
2018-07-28 00:13:19 +08:00
2021-05-05 22:46:07 +08:00
_ , err := sess . Exec ( sql )
require . NoError ( t , err )
sql = `
CREATE PROCEDURE sp_test_datetime (
@ from datetime ,
@ to datetime ,
@ interval nvarchar ( 50 ) = ' 5 m ' ,
@ metric nvarchar ( 200 ) = ' ALL '
) AS
BEGIN
DECLARE @ dInterval int
SELECT @ dInterval = 300
IF @ interval = ' 10 m '
SELECT @ dInterval = 600
SELECT
CAST ( ROUND ( DATEDIFF ( second , ' 1970 - 01 - 01 ' , time ) / CAST ( @ dInterval as float ) , 0 ) as bigint ) * @ dInterval as time ,
measurement as metric ,
avg ( valueOne ) as valueOne ,
avg ( valueTwo ) as valueTwo
FROM
metric_values
WHERE
time BETWEEN @ from AND @ to AND
( @ metric = ' ALL ' OR measurement = @ metric )
GROUP BY
CAST ( ROUND ( DATEDIFF ( second , ' 1970 - 01 - 01 ' , time ) / CAST ( @ dInterval as float ) , 0 ) as bigint ) * @ dInterval ,
measurement
ORDER BY 1
END
`
2018-07-28 00:13:19 +08:00
2021-05-05 22:46:07 +08:00
_ , err = sess . Exec ( sql )
require . NoError ( t , err )
2018-07-28 00:13:19 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing a metric query using stored procedure should return correct result" , func ( t * testing . T ) {
2021-03-08 14:02:49 +08:00
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
2018-10-03 15:53:51 +08:00
{
DataSource : & models . DataSource { JsonData : simplejson . New ( ) } ,
Model : simplejson . NewFromAny ( map [ string ] interface { } {
2021-05-05 22:46:07 +08:00
"rawSql" : ` DECLARE
@ from int = $ __unixEpochFrom ( ) ,
@ to int = $ __unixEpochTo ( )
EXEC dbo . sp_test_epoch @ from , @ to ` ,
2018-10-03 15:53:51 +08:00
"format" : "time_series" ,
} ) ,
2021-03-08 14:02:49 +08:00
RefID : "A" ,
2018-10-03 15:53:51 +08:00
} ,
} ,
2021-05-05 22:46:07 +08:00
TimeRange : & plugins . DataTimeRange {
From : "1521117000000" ,
To : "1521122100000" ,
} ,
2018-10-03 15:53:51 +08:00
}
2021-03-08 14:02:49 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
2021-05-05 22:46:07 +08:00
require . NoError ( t , err )
2018-10-03 15:53:51 +08:00
queryResult := resp . Results [ "A" ]
2021-05-05 22:46:07 +08:00
require . NoError ( t , queryResult . Error )
frames , err := queryResult . Dataframes . Decoded ( )
require . NoError ( t , err )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , 5 , len ( frames [ 0 ] . Fields ) )
require . Equal ( t , "valueOne" , frames [ 0 ] . Fields [ 1 ] . Name )
require . Equal ( t , data . Labels { "metric" : "Metric A" } , frames [ 0 ] . Fields [ 1 ] . Labels )
require . Equal ( t , "valueOne" , frames [ 0 ] . Fields [ 2 ] . Name )
require . Equal ( t , data . Labels { "metric" : "Metric B" } , frames [ 0 ] . Fields [ 2 ] . Labels )
require . Equal ( t , "valueTwo" , frames [ 0 ] . Fields [ 3 ] . Name )
require . Equal ( t , data . Labels { "metric" : "Metric A" } , frames [ 0 ] . Fields [ 3 ] . Labels )
require . Equal ( t , "valueTwo" , frames [ 0 ] . Fields [ 4 ] . Name )
require . Equal ( t , data . Labels { "metric" : "Metric B" } , frames [ 0 ] . Fields [ 4 ] . Labels )
2018-10-03 15:53:51 +08:00
} )
2021-05-05 22:46:07 +08:00
} )
} )
2018-10-03 15:53:51 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "Given a table with event data" , func ( t * testing . T ) {
sql := `
IF OBJECT_ID ( ' dbo . [ event ] ' , 'U' ) IS NOT NULL
DROP TABLE dbo . [ event ]
CREATE TABLE [ event ] (
time_sec int ,
description nvarchar ( 100 ) ,
tags nvarchar ( 100 ) ,
)
`
_ , err := sess . Exec ( sql )
require . NoError ( t , err )
type event struct {
TimeSec int64
Description string
Tags string
}
2018-03-20 02:56:34 +08:00
2021-05-05 22:46:07 +08:00
events := [ ] * event { }
for _ , t := range genTimeRangeByInterval ( fromStart . Add ( - 20 * time . Minute ) , 60 * time . Minute , 25 * time . Minute ) {
events = append ( events , & event {
TimeSec : t . Unix ( ) ,
Description : "Someone deployed something" ,
Tags : "deploy" ,
2018-03-20 02:56:34 +08:00
} )
2021-05-05 22:46:07 +08:00
events = append ( events , & event {
TimeSec : t . Add ( 5 * time . Minute ) . Unix ( ) ,
Description : "New support ticket registered" ,
Tags : "ticket" ,
} )
}
2018-03-16 21:42:54 +08:00
2021-05-05 22:46:07 +08:00
for _ , e := range events {
sql = fmt . Sprintf ( `
INSERT [ event ] ( time_sec , description , tags )
VALUES ( % d , ' % s ' , ' % s ' )
` , e . TimeSec , e . Description , e . Tags )
2018-03-16 21:42:54 +08:00
2021-05-05 22:46:07 +08:00
_ , err = sess . Exec ( sql )
require . NoError ( t , err )
}
2018-03-16 21:42:54 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing an annotation query of deploy events should return expected result" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
DataSource : & models . DataSource { } ,
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : "SELECT time_sec as time, description as [text], tags FROM [event] WHERE $__unixEpochFilter(time_sec) AND tags='deploy' ORDER BY 1 ASC" ,
"format" : "table" ,
} ) ,
RefID : "Deploys" ,
} ,
} ,
TimeRange : & plugins . DataTimeRange {
From : fmt . Sprintf ( "%v" , fromStart . Add ( - 20 * time . Minute ) . Unix ( ) * 1000 ) ,
To : fmt . Sprintf ( "%v" , fromStart . Add ( 40 * time . Minute ) . Unix ( ) * 1000 ) ,
} ,
2018-03-16 21:42:54 +08:00
}
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "Deploys" ]
frames , err := queryResult . Dataframes . Decoded ( )
require . NoError ( t , err )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , 3 , frames [ 0 ] . Fields [ 0 ] . Len ( ) )
} )
2018-03-16 21:42:54 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing an annotation query of ticket events should return expected result" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : "SELECT time_sec as time, description as [text], tags FROM [event] WHERE $__unixEpochFilter(time_sec) AND tags='ticket' ORDER BY 1 ASC" ,
"format" : "table" ,
} ) ,
RefID : "Tickets" ,
} ,
} ,
TimeRange : & plugins . DataTimeRange {
From : fmt . Sprintf ( "%v" , fromStart . Add ( - 20 * time . Minute ) . Unix ( ) * 1000 ) ,
To : fmt . Sprintf ( "%v" , fromStart . Add ( 40 * time . Minute ) . Unix ( ) * 1000 ) ,
} ,
2018-03-16 21:42:54 +08:00
}
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "Tickets" ]
frames , err := queryResult . Dataframes . Decoded ( )
require . NoError ( t , err )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , 3 , frames [ 0 ] . Fields [ 0 ] . Len ( ) )
} )
t . Run ( "When doing an annotation query with a time column in datetime format" , func ( t * testing . T ) {
dt := time . Date ( 2018 , 3 , 14 , 21 , 20 , 6 , 527e6 , time . UTC )
const dtFormat = "2006-01-02 15:04:05.999999999"
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : fmt . Sprintf ( ` SELECT
CAST ( ' % s ' AS DATETIME ) as time ,
' message ' as text ,
' tag1 , tag2 ' as tags
` , dt . Format ( dtFormat ) ) ,
"format" : "table" ,
} ) ,
RefID : "A" ,
2018-03-16 21:42:54 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
}
2018-03-16 21:42:54 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-03-16 21:42:54 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , 1 , frames [ 0 ] . Fields [ 0 ] . Len ( ) )
2018-03-16 21:42:54 +08:00
2021-05-05 22:46:07 +08:00
// Should be in time.Time
require . Equal ( t , dt , * frames [ 0 ] . Fields [ 0 ] . At ( 0 ) . ( * time . Time ) )
} )
2018-03-20 21:38:56 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing an annotation query with a time column in epoch second format should return ms" , func ( t * testing . T ) {
dt := time . Date ( 2018 , 3 , 14 , 21 , 20 , 6 , 527e6 , time . UTC )
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : fmt . Sprintf ( ` SELECT
% d as time ,
' message ' as text ,
' tag1 , tag2 ' as tags
` , dt . Unix ( ) ) ,
"format" : "table" ,
} ) ,
RefID : "A" ,
2018-03-20 21:38:56 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
}
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , 1 , frames [ 0 ] . Fields [ 0 ] . Len ( ) )
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
// Should be in time.Time
require . Equal ( t , dt . Unix ( ) , ( * frames [ 0 ] . Fields [ 0 ] . At ( 0 ) . ( * time . Time ) ) . Unix ( ) )
} )
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing an annotation query with a time column in epoch second format (int) should return ms" , func ( t * testing . T ) {
dt := time . Date ( 2018 , 3 , 14 , 21 , 20 , 6 , 527e6 , time . UTC )
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : fmt . Sprintf ( ` SELECT
cast ( % d as int ) as time ,
' message ' as text ,
' tag1 , tag2 ' as tags
` , dt . Unix ( ) ) ,
"format" : "table" ,
} ) ,
RefID : "A" ,
2018-03-20 21:38:56 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
}
2018-03-20 21:38:56 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-03-20 21:38:56 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , 1 , frames [ 0 ] . Fields [ 0 ] . Len ( ) )
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
// Should be in time.Time
require . Equal ( t , dt . Unix ( ) , ( * frames [ 0 ] . Fields [ 0 ] . At ( 0 ) . ( * time . Time ) ) . Unix ( ) )
} )
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing an annotation query with a time column in epoch millisecond format should return ms" , func ( t * testing . T ) {
dt := time . Date ( 2018 , 3 , 14 , 21 , 20 , 6 , 527e6 , time . UTC )
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : fmt . Sprintf ( ` SELECT
% d as time ,
' message ' as text ,
' tag1 , tag2 ' as tags
` , dt . Unix ( ) * 1000 ) ,
"format" : "table" ,
} ) ,
RefID : "A" ,
2018-03-22 22:23:12 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
}
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , 1 , frames [ 0 ] . Fields [ 0 ] . Len ( ) )
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
// Should be in time.Time
require . Equal ( t , dt . Unix ( ) , ( * frames [ 0 ] . Fields [ 0 ] . At ( 0 ) . ( * time . Time ) ) . Unix ( ) )
} )
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing an annotation query with a time column holding a bigint null value should return nil" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : ` SELECT
cast ( null as bigint ) as time ,
' message ' as text ,
' tag1 , tag2 ' as tags
` ,
"format" : "table" ,
} ) ,
RefID : "A" ,
2018-03-22 22:23:12 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
}
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , 1 , frames [ 0 ] . Fields [ 0 ] . Len ( ) )
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
// Should be in time.Time
require . Nil ( t , frames [ 0 ] . Fields [ 0 ] . At ( 0 ) )
} )
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
t . Run ( "When doing an annotation query with a time column holding a datetime null value should return nil" , func ( t * testing . T ) {
query := plugins . DataQuery {
Queries : [ ] plugins . DataSubQuery {
{
Model : simplejson . NewFromAny ( map [ string ] interface { } {
"rawSql" : ` SELECT
cast ( null as datetime ) as time ,
' message ' as text ,
' tag1 , tag2 ' as tags
` ,
"format" : "table" ,
} ) ,
RefID : "A" ,
2018-03-22 22:23:12 +08:00
} ,
2021-05-05 22:46:07 +08:00
} ,
}
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
resp , err := endpoint . DataQuery ( context . Background ( ) , nil , query )
require . NoError ( t , err )
queryResult := resp . Results [ "A" ]
require . NoError ( t , queryResult . Error )
2018-03-22 22:23:12 +08:00
2021-05-05 22:46:07 +08:00
frames , _ := queryResult . Dataframes . Decoded ( )
require . Equal ( t , 1 , len ( frames ) )
require . Equal ( t , 1 , frames [ 0 ] . Fields [ 0 ] . Len ( ) )
// Should be in time.Time
require . Nil ( t , frames [ 0 ] . Fields [ 0 ] . At ( 0 ) )
2018-03-16 21:42:54 +08:00
} )
2017-12-04 02:56:21 +08:00
} )
}
2021-03-29 19:03:01 +08:00
func TestTransformQueryError ( t * testing . T ) {
transformer := & mssqlQueryResultTransformer {
log : log . New ( "test" ) ,
}
randomErr := fmt . Errorf ( "random error" )
tests := [ ] struct {
err error
expectedErr error
} {
{ err : fmt . Errorf ( "Unable to open tcp connection with host 'localhost:5000': dial tcp: connection refused" ) , expectedErr : sqleng . ErrConnectionFailed } ,
{ err : fmt . Errorf ( "unable to open tcp connection with host 'localhost:5000': dial tcp: connection refused" ) , expectedErr : sqleng . ErrConnectionFailed } ,
{ err : randomErr , expectedErr : randomErr } ,
}
for _ , tc := range tests {
resultErr := transformer . TransformQueryError ( tc . err )
assert . ErrorIs ( t , resultErr , tc . expectedErr )
}
}
2021-03-30 16:54:57 +08:00
func TestGenerateConnectionString ( t * testing . T ) {
testCases := [ ] struct {
desc string
dataSource * models . DataSource
expConnStr string
} {
{
desc : "From URL w/ port" ,
dataSource : & models . DataSource {
Url : "localhost:1001" ,
Database : "database" ,
User : "user" ,
JsonData : simplejson . NewFromAny ( map [ string ] interface { } { } ) ,
} ,
expConnStr : "server=localhost;database=database;user id=user;password=;port=1001;" ,
} ,
// When no port is specified, the driver should be allowed to choose
{
desc : "From URL w/o port" ,
dataSource : & models . DataSource {
Url : "localhost" ,
Database : "database" ,
User : "user" ,
JsonData : simplejson . NewFromAny ( map [ string ] interface { } { } ) ,
} ,
expConnStr : "server=localhost;database=database;user id=user;password=;" ,
} ,
// Port 0 should be equivalent to not specifying a port, i.e. let the driver choose
{
desc : "From URL w port 0" ,
dataSource : & models . DataSource {
Url : "localhost:0" ,
Database : "database" ,
User : "user" ,
JsonData : simplejson . NewFromAny ( map [ string ] interface { } { } ) ,
} ,
expConnStr : "server=localhost;database=database;user id=user;password=;" ,
} ,
{
desc : "Defaults" ,
dataSource : & models . DataSource {
Database : "database" ,
User : "user" ,
JsonData : simplejson . NewFromAny ( map [ string ] interface { } { } ) ,
} ,
expConnStr : "server=localhost;database=database;user id=user;password=;" ,
} ,
}
for _ , tc := range testCases {
t . Run ( tc . desc , func ( t * testing . T ) {
connStr , err := generateConnectionString ( tc . dataSource )
require . NoError ( t , err )
assert . Equal ( t , tc . expConnStr , connStr )
} )
}
}
func initMSSQLTestDB ( t * testing . T ) * xorm . Engine {
t . Helper ( )
2020-07-10 22:09:21 +08:00
testDB := sqlutil . MSSQLTestDB ( )
x , err := xorm . NewEngine ( testDB . DriverName , strings . Replace ( testDB . ConnStr , "localhost" ,
serverIP , 1 ) )
2021-03-30 16:54:57 +08:00
require . NoError ( t , err )
2018-04-10 17:10:56 +08:00
2018-03-22 22:23:12 +08:00
x . DatabaseTZ = time . UTC
x . TZLocation = time . UTC
2017-12-04 02:56:21 +08:00
// x.ShowSQL()
return x
}
2018-03-15 16:51:29 +08:00
func genTimeRangeByInterval ( from time . Time , duration time . Duration , interval time . Duration ) [ ] time . Time {
durationSec := int64 ( duration . Seconds ( ) )
intervalSec := int64 ( interval . Seconds ( ) )
timeRange := [ ] time . Time { }
2018-03-15 21:26:53 +08:00
for i := int64 ( 0 ) ; i < durationSec ; i += intervalSec {
2018-03-15 16:51:29 +08:00
timeRange = append ( timeRange , from )
from = from . Add ( time . Duration ( int64 ( time . Second ) * intervalSec ) )
}
return timeRange
}