mirror of
https://github.com/grafana/grafana.git
synced 2024-11-23 09:26:43 -06:00
Postgres/MySQL/MSSQL: Fix region annotations not displayed correctly (#38936)
Fix region annotations not displayed correctly when returning timeend column as epoch timestamp and by that making sure that the returned data frame field named timeend is treated as time type. Fixes #38533
This commit is contained in:
parent
9aa03acfa6
commit
fbdaf56a84
@ -1163,6 +1163,32 @@ func TestMSSQL(t *testing.T) {
|
||||
// Should be in time.Time
|
||||
require.Nil(t, frames[0].Fields[0].At(0))
|
||||
})
|
||||
|
||||
t.Run("When doing an annotation query with a time and timeend column should return two fields of type time", func(t *testing.T) {
|
||||
query := &backend.QueryDataRequest{
|
||||
Queries: []backend.DataQuery{
|
||||
{
|
||||
JSON: []byte(`{
|
||||
"rawSql": "SELECT 1631053772276 as time, 1631054012276 as timeend, '' as text, '' as tags",
|
||||
"format": "table"
|
||||
}`),
|
||||
RefID: "A",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := endpoint.QueryData(context.Background(), query)
|
||||
require.NoError(t, err)
|
||||
queryResult := resp.Responses["A"]
|
||||
require.NoError(t, queryResult.Error)
|
||||
|
||||
frames := queryResult.Frames
|
||||
require.Equal(t, 1, len(frames))
|
||||
require.Equal(t, 4, len(frames[0].Fields))
|
||||
|
||||
require.Equal(t, data.FieldTypeNullableTime, frames[0].Fields[0].Type())
|
||||
require.Equal(t, data.FieldTypeNullableTime, frames[0].Fields[1].Type())
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1125,6 +1125,32 @@ func TestMySQL(t *testing.T) {
|
||||
//Should be in time.Time
|
||||
require.Nil(t, frames[0].Fields[0].At(0))
|
||||
})
|
||||
|
||||
t.Run("When doing an annotation query with a time and timeend column should return two fields of type time", func(t *testing.T) {
|
||||
query := &backend.QueryDataRequest{
|
||||
Queries: []backend.DataQuery{
|
||||
{
|
||||
JSON: []byte(`{
|
||||
"rawSql": "SELECT 1631053772276 as time, 1631054012276 as timeend, '' as text, '' as tags",
|
||||
"format": "table"
|
||||
}`),
|
||||
RefID: "A",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := exe.QueryData(context.Background(), query)
|
||||
require.NoError(t, err)
|
||||
queryResult := resp.Responses["A"]
|
||||
require.NoError(t, queryResult.Error)
|
||||
|
||||
frames := queryResult.Frames
|
||||
require.Equal(t, 1, len(frames))
|
||||
require.Equal(t, 4, len(frames[0].Fields))
|
||||
|
||||
require.Equal(t, data.FieldTypeNullableTime, frames[0].Fields[0].Type())
|
||||
require.Equal(t, data.FieldTypeNullableTime, frames[0].Fields[1].Type())
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1199,6 +1199,32 @@ func TestPostgres(t *testing.T) {
|
||||
// Should be in time.Time
|
||||
assert.Nil(t, frames[0].Fields[0].At(0))
|
||||
})
|
||||
|
||||
t.Run("When doing an annotation query with a time and timeend column should return two fields of type time", func(t *testing.T) {
|
||||
query := &backend.QueryDataRequest{
|
||||
Queries: []backend.DataQuery{
|
||||
{
|
||||
JSON: []byte(`{
|
||||
"rawSql": "SELECT 1631053772276 as time, 1631054012276 as timeend, '' as text, '' as tags",
|
||||
"format": "table"
|
||||
}`),
|
||||
RefID: "A",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := exe.QueryData(context.Background(), query)
|
||||
require.NoError(t, err)
|
||||
queryResult := resp.Responses["A"]
|
||||
require.NoError(t, queryResult.Error)
|
||||
|
||||
frames := queryResult.Frames
|
||||
require.Equal(t, 1, len(frames))
|
||||
require.Equal(t, 4, len(frames[0].Fields))
|
||||
|
||||
require.Equal(t, data.FieldTypeNullableTime, frames[0].Fields[0].Type())
|
||||
require.Equal(t, data.FieldTypeNullableTime, frames[0].Fields[1].Type())
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
|
||||
"github.com/grafana/grafana/pkg/util/errutil"
|
||||
"xorm.io/core"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
@ -300,11 +301,9 @@ func (e *DataSourceHandler) executeQuery(query backend.DataQuery, wg *sync.WaitG
|
||||
return
|
||||
}
|
||||
|
||||
if qm.timeIndex != -1 {
|
||||
if err := convertSQLTimeColumnToEpochMS(frame, qm.timeIndex); err != nil {
|
||||
errAppendDebug("db convert time column failed", err, interpolatedQuery)
|
||||
return
|
||||
}
|
||||
if err := convertSQLTimeColumnsToEpochMS(frame, qm); err != nil {
|
||||
errAppendDebug("converting time columns failed", err, interpolatedQuery)
|
||||
return
|
||||
}
|
||||
|
||||
if qm.Format == dataQueryFormatSeries {
|
||||
@ -408,6 +407,7 @@ func (e *DataSourceHandler) newProcessCfg(query backend.DataQuery, queryContext
|
||||
columnNames: columnNames,
|
||||
rows: rows,
|
||||
timeIndex: -1,
|
||||
timeEndIndex: -1,
|
||||
metricIndex: -1,
|
||||
metricPrefix: false,
|
||||
queryContext: queryContext,
|
||||
@ -454,6 +454,12 @@ func (e *DataSourceHandler) newProcessCfg(query backend.DataQuery, queryContext
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if qm.Format == dataQueryFormatTable && col == "timeend" {
|
||||
qm.timeEndIndex = i
|
||||
continue
|
||||
}
|
||||
|
||||
switch col {
|
||||
case "metric":
|
||||
qm.metricIndex = i
|
||||
@ -492,6 +498,7 @@ type dataQueryModel struct {
|
||||
columnNames []string
|
||||
columnTypes []*sql.ColumnType
|
||||
timeIndex int
|
||||
timeEndIndex int
|
||||
metricIndex int
|
||||
rows *core.Rows
|
||||
metricPrefix bool
|
||||
@ -821,6 +828,22 @@ func convertNullableFloat32ToEpochMS(origin *data.Field, newField *data.Field) {
|
||||
}
|
||||
}
|
||||
|
||||
func convertSQLTimeColumnsToEpochMS(frame *data.Frame, qm *dataQueryModel) error {
|
||||
if qm.timeIndex != -1 {
|
||||
if err := convertSQLTimeColumnToEpochMS(frame, qm.timeIndex); err != nil {
|
||||
return errutil.Wrap("failed to convert time column", err)
|
||||
}
|
||||
}
|
||||
|
||||
if qm.timeEndIndex != -1 {
|
||||
if err := convertSQLTimeColumnToEpochMS(frame, qm.timeEndIndex); err != nil {
|
||||
return errutil.Wrap("failed to convert timeend column", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// convertSQLTimeColumnToEpochMS converts column named time to unix timestamp in milliseconds
|
||||
// to make native datetime types and epoch dates work in annotation and table queries.
|
||||
func convertSQLTimeColumnToEpochMS(frame *data.Frame, timeIndex int) error {
|
||||
|
Loading…
Reference in New Issue
Block a user