Commit 6e7a0678 by linux chips

adding support for sgl native time datatypes

parent dd7ab43d
......@@ -31,7 +31,6 @@ Example:
```sql
CREATE USER grafanareader WITH PASSWORD 'password'
GRANT SELECT ON dbo.YourTable3 TO grafanareader
```
......@@ -43,7 +42,9 @@ To simplify syntax and to allow for dynamic parts, like date range filters, the
Macro example | Description
------------ | -------------
*$__time(dateColumn)* | Will be replaced by an expression to convert a DATETIME column type to unix timestamp and rename the it to `time_sec`. For example, *DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), dateColumn) ) as time_sec*
*$__time(dateColumn)* | Will rename the column to `time`. For example, *dateColumn AS time*.
*$__utcTime(dateColumn)* | Will be replaced by an expression to convert a DATETIME column type to UTC depending on the server's local timeoffset and rename it to `time`. For example, *DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), dateColumn) ) AS time*
*$__timeEpoch(dateColumn)* | Will be replaced by an expression to convert a DATETIME column type to unix timestamp and rename the it to `time`. For example, *DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), dateColumn) ) AS time*
*$__timeFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name. For example, *dateColumn >= DATEADD(s, 1494410783+DATEDIFF(second,GETUTCDATE(),GETDATE()), '1970-01-01') AND dateColumn <= DATEADD(s, 1494497183+DATEDIFF(second,GETUTCDATE(),GETDATE()), '1970-01-01')*
*$__timeFrom()* | Will be replaced by the start of the currently active time selection. For example, *DATEADD(second, 1494410783+DATEDIFF(second,GETUTCDATE(),GETDATE()), '1970-01-01')*
*$__timeTo()* | Will be replaced by the end of the currently active time selection. For example, *DATEADD(second, 1494497183+DATEDIFF(second,GETUTCDATE(),GETDATE()), '1970-01-01')*
......@@ -77,7 +78,7 @@ FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'mssql_types';
```
You can control the name of the Table panel columns by using regular `as ` SQL column selection syntax.
You can control the name of the Table panel columns by using regular `AS ` SQL column selection syntax.
The resulting table panel:
......@@ -85,23 +86,48 @@ The resulting table panel:
### Time series queries
If you set `Format as` to `Time series`, for use in Graph panel for example, then the query must follow these rules:
- Must be a column named `time_sec` representing a unix epoch in seconds.
- Must be a column named `value` representing the time series value.
- Must be a column named `metric` representing the time series name.
If you set `Format as` to `Time series`, for use in Graph panel for example, then the query must must have a column named `time` that returns either a sql datetime or any numeric datatype representing unix epoch in seconds. You may return a column named `metric` that is used as metric name for the value column. Any column except `time` and `metric` is treated as a value column. If you ommit the `metric` column, tha name of the value column will be the metric name. You may select multiple value columns, each will have its name as metric. If you select multiple value columns along with a `metric` column, the names ("MetircName - ColumnName") will be combined to make the metric name.
Example with `metric` column
```sql
SELECT
MIN(DATEDIFF(second,{d '1970-01-01'},[time_date_time])) as [time_sec],
MAX([value_double]) as [value],
[time_date_time] as [time],
[value_double] as [value],
[metric1] as [metric]
FROM [test_data]
WHERE $__timeFilter([time_date_time])
GROUP BY metric1, DATEDIFF(second,{d '1970-01-01'},[time_date_time])/300
ORDER BY [time_date_time]
```
Example with multiple `value` culumns
```sql
SELECT
[time_date_time] as [time],
[value_double1] as [metric_name1],
[value_int2] as [metric_name2]
FROM [test_data]
WHERE $__timeFilter([time_date_time])
ORDER BY [time_date_time]
```
Example with multiple `value` culumns combined with a `metric` column
```sql
SELECT
[time_date_time] as [time],
[value_double1] as [value1],
[value_int2] as [value2],
[metric_col] as [metric]
FROM [test_data]
WHERE $__timeFilter([time_date_time])
ORDER BY [time_date_time]
```
The result of the above query would look something like the below
![](/img/docs/v47/mssql_metric_value.png)
Currently, there is no support for a dynamic group by time based on time range & panel width.
This is something we plan to add.
......@@ -138,7 +164,7 @@ You can also create nested variables. For example if you had another variable na
the hosts variable only show hosts from the current selected region with a query like this (if `region` is a multi-value variable then use the `IN` comparison operator rather than `=` to match against multiple values):
```sql
SELECT hostname FROM host WHERE region IN($region)
SELECT hostname FROM host WHERE region IN ($region)
```
### Using Variables in Queries
......@@ -155,7 +181,7 @@ There are two syntaxes:
```sql
SELECT
atimestamp time_sec,
atimestamp time,
aint value
FROM table
WHERE $__timeFilter(atimestamp) and hostname in($hostname)
......@@ -166,7 +192,7 @@ ORDER BY atimestamp
```sql
SELECT
atimestamp as time_sec,
atimestamp as time,
aint as value
FROM table
WHERE $__timeFilter(atimestamp) and hostname in([[hostname]])
......@@ -181,7 +207,7 @@ An example query:
```sql
SELECT
DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), time_column) ) as [time_sec],
DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), time_column) ) as [time],
metric1 as [text],
convert(varvhar, metric1) + ',' + convert(varchar, metric2) as [tags]
FROM
......@@ -192,7 +218,7 @@ WHERE
Name | Description
------------ | -------------
time_sec | The name of the date/time field.
time | The name of the date/time field. could be in a native sql time datatype
text | Event description field.
tags | Optional field name to use for event tags as a comma separated string.
......
......@@ -64,7 +64,17 @@ func (m *MsSqlMacroEngine) evaluateMacro(name string, args []string) (string, er
if len(args) == 0 {
return "", fmt.Errorf("missing time column argument for macro %v", name)
}
return fmt.Sprintf("DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), %s) ) as time_sec", args[0]), nil
return fmt.Sprintf("%s AS time", args[0]), nil
case "__utcTime":
if len(args) == 0 {
return "", fmt.Errorf("missing time column argument for macro %v", name)
}
return fmt.Sprintf("DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), %s) AS time", args[0]), nil
case "__timeEpoch":
if len(args) == 0 {
return "", fmt.Errorf("missing time column argument for macro %v", name)
}
return fmt.Sprintf("DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), %s) ) AS time", args[0]), nil
case "__timeFilter":
if len(args) == 0 {
return "", fmt.Errorf("missing time column argument for macro %v", name)
......
......@@ -16,14 +16,28 @@ func TestMacroEngine(t *testing.T) {
sql, err := engine.Interpolate(nil, "select $__time(time_column)")
So(err, ShouldBeNil)
So(sql, ShouldEqual, "select DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), time_column) ) as time_sec")
So(sql, ShouldEqual, "select time_column AS time")
})
Convey("interpolate __time function wrapped in aggregation", func() {
sql, err := engine.Interpolate(nil, "select min($__time(time_column))")
Convey("interpolate __utcTime function", func() {
sql, err := engine.Interpolate(nil, "select $__utcTime(time_column)")
So(err, ShouldBeNil)
So(sql, ShouldEqual, "select min(DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), time_column) ) as time_sec)")
So(sql, ShouldEqual, "select DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), time_column) AS time")
})
Convey("interpolate __timeEpoch function", func() {
sql, err := engine.Interpolate(nil, "select $__timeEpoch(time_column)")
So(err, ShouldBeNil)
So(sql, ShouldEqual, "select DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), time_column) ) AS time")
})
Convey("interpolate __timeEpoch function wrapped in aggregation", func() {
sql, err := engine.Interpolate(nil, "select min($__timeEpoch(time_column))")
So(err, ShouldBeNil)
So(sql, ShouldEqual, "select min(DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), time_column) ) AS time)")
})
Convey("interpolate __timeFilter function", func() {
......
......@@ -5,10 +5,9 @@ import (
"context"
"database/sql"
"fmt"
"strconv"
"strings"
_ "time"
"time"
_ "github.com/denisenkom/go-mssqldb"
"github.com/go-xorm/core"
......@@ -69,6 +68,10 @@ func (e MssqlQueryEndpoint) transformToTable(query *tsdb.Query, rows *core.Rows,
return err
}
rowLimit := 1000000
rowCount := 0
timeIndex := -1
table := &tsdb.Table{
Columns: make([]tsdb.TableColumn, columnCount),
Rows: make([]tsdb.RowValues, 0),
......@@ -76,6 +79,12 @@ func (e MssqlQueryEndpoint) transformToTable(query *tsdb.Query, rows *core.Rows,
for i, name := range columnNames {
table.Columns[i].Text = name
// check if there is a column named time
switch name {
case "time":
timeIndex = i
}
}
columnTypes, err := rows.ColumnTypes()
......@@ -83,9 +92,6 @@ func (e MssqlQueryEndpoint) transformToTable(query *tsdb.Query, rows *core.Rows,
return err
}
rowLimit := 1000000
rowCount := 0
for ; rows.Next(); rowCount++ {
if rowCount > rowLimit {
return fmt.Errorf("MsSQL query row limit exceeded, limit %d", rowLimit)
......@@ -96,6 +102,15 @@ func (e MssqlQueryEndpoint) transformToTable(query *tsdb.Query, rows *core.Rows,
return err
}
// convert column named time to unix timestamp to make
// native datetime mssql types work in annotation queries
if timeIndex != -1 {
switch value := values[timeIndex].(type) {
case time.Time:
values[timeIndex] = float64(value.Unix())
}
}
table.Rows = append(table.Rows, values)
}
......@@ -123,42 +138,107 @@ func (e MssqlQueryEndpoint) getTypedRowData(types []*sql.ColumnType, rows *core.
func (e MssqlQueryEndpoint) transformToTimeSeries(query *tsdb.Query, rows *core.Rows, result *tsdb.QueryResult) error {
pointsBySeries := make(map[string]*tsdb.TimeSeries)
seriesByQueryOrder := list.New()
columnNames, err := rows.Columns()
if err != nil {
return err
}
columnTypes, err := rows.ColumnTypes()
if err != nil {
return err
}
rowData := NewStringStringScan(columnNames)
rowLimit := 1000
rowLimit := 1000000
rowCount := 0
timeIndex := -1
metricIndex := -1
// check columns of resultset: a column named time is mandatory
// the first text column is treated as metric name unless a column named metric is present
for i, col := range columnNames {
switch col {
case "time":
timeIndex = i
case "metric":
metricIndex = i
default:
if metricIndex == -1 {
switch columnTypes[i].DatabaseTypeName() {
case "VARCHAR", "CHAR", "NVARCHAR", "NCHAR":
metricIndex = i
}
}
}
}
if timeIndex == -1 {
return fmt.Errorf("Found no column named time")
}
for rows.Next() {
var timestamp float64
var value null.Float
var metricColVal string
var metric string
for ; rows.Next(); rowCount++ {
if rowCount > rowLimit {
return fmt.Errorf("MsSQL query row limit exceeded, limit %d", rowLimit)
return fmt.Errorf("MSSQL query row limit exceeded, limit %d", rowLimit)
}
err := rowData.Update(rows.Rows)
values, err := e.getTypedRowData(columnTypes, rows)
if err != nil {
e.log.Error("MsSQL response parsing", "error", err)
return fmt.Errorf("MsSQL response parsing error %v", err)
return err
}
if rowData.metric == "" {
rowData.metric = "Unknown"
switch columnValue := values[timeIndex].(type) {
case int64:
timestamp = float64(columnValue * 1000)
case float64:
timestamp = columnValue * 1000
case time.Time:
timestamp = (float64(columnValue.Unix()) * 1000) + float64(columnValue.Nanosecond()/1e6) // in case someone is trying to map times beyond 2262 :D
default:
return fmt.Errorf("Invalid type for column time, must be of type timestamp or unix timestamp")
}
if !rowData.time.Valid {
return fmt.Errorf("Found row with no time value")
if metricIndex >= 0 {
if columnValue, ok := values[metricIndex].(string); ok == true {
metricColVal = columnValue
} else {
return fmt.Errorf("Column metric must be of type CHAR, VARCHAR, NCHAR or NVARCHAR. metric column name: %s type: %s but datatype is %T", columnNames[metricIndex], columnTypes[metricIndex].DatabaseTypeName(), values[metricIndex])
}
}
for i, col := range columnNames {
if i == timeIndex || i == metricIndex {
continue
}
if series, exist := pointsBySeries[rowData.metric]; exist {
series.Points = append(series.Points, tsdb.TimePoint{rowData.value, rowData.time})
switch columnValue := values[i].(type) {
case int64:
value = null.FloatFrom(float64(columnValue))
case float64:
value = null.FloatFrom(columnValue)
case nil:
value.Valid = false
default:
return fmt.Errorf("Value column must have numeric datatype, column: %s type: %T value: %v", col, columnValue, columnValue)
}
// construct the metric name
// if there is more than 3 columns (more than one value) and there is
// a metric column, join them to make the metric name
if metricIndex == -1 {
metric = col
} else if len(columnNames) > 3 {
metric = metricColVal + " - " + col
} else {
series := &tsdb.TimeSeries{Name: rowData.metric}
series.Points = append(series.Points, tsdb.TimePoint{rowData.value, rowData.time})
pointsBySeries[rowData.metric] = series
seriesByQueryOrder.PushBack(rowData.metric)
metric = metricColVal
}
e.appendTimePoint(pointsBySeries, seriesByQueryOrder, metric, timestamp, value)
rowCount++
}
}
......@@ -171,61 +251,14 @@ func (e MssqlQueryEndpoint) transformToTimeSeries(query *tsdb.Query, rows *core.
return nil
}
type stringStringScan struct {
rowPtrs []interface{}
rowValues []string
columnNames []string
columnCount int
time null.Float
value null.Float
metric string
}
func NewStringStringScan(columnNames []string) *stringStringScan {
s := &stringStringScan{
columnCount: len(columnNames),
columnNames: columnNames,
rowPtrs: make([]interface{}, len(columnNames)),
rowValues: make([]string, len(columnNames)),
}
for i := 0; i < s.columnCount; i++ {
s.rowPtrs[i] = new(sql.RawBytes)
}
return s
}
func (s *stringStringScan) Update(rows *sql.Rows) error {
if err := rows.Scan(s.rowPtrs...); err != nil {
return err
}
s.time = null.FloatFromPtr(nil)
s.value = null.FloatFromPtr(nil)
for i := 0; i < s.columnCount; i++ {
if rb, ok := s.rowPtrs[i].(*sql.RawBytes); ok {
s.rowValues[i] = string(*rb)
switch s.columnNames[i] {
case "time_sec":
if sec, err := strconv.ParseInt(s.rowValues[i], 10, 64); err == nil {
s.time = null.FloatFrom(float64(sec * 1000))
}
case "value":
if value, err := strconv.ParseFloat(s.rowValues[i], 64); err == nil {
s.value = null.FloatFrom(value)
}
case "metric":
s.metric = s.rowValues[i]
}
*rb = nil // reset pointer to discard current value to avoid a bug
func (e MssqlQueryEndpoint) appendTimePoint(pointsBySeries map[string]*tsdb.TimeSeries, seriesByQueryOrder *list.List, metric string, timestamp float64, value null.Float) {
if series, exist := pointsBySeries[metric]; exist {
series.Points = append(series.Points, tsdb.TimePoint{value, null.FloatFrom(timestamp)})
} else {
return fmt.Errorf("Cannot convert index %d column %s to type *sql.RawBytes", i, s.columnNames[i])
}
series := &tsdb.TimeSeries{Name: metric}
series.Points = append(series.Points, tsdb.TimePoint{value, null.FloatFrom(timestamp)})
pointsBySeries[metric] = series
seriesByQueryOrder.PushBack(metric)
}
return nil
e.log.Debug("Rows", "metric", metric, "time", timestamp, "value", value)
}
......@@ -20,7 +20,6 @@ import (
var serverIP string = "10.20.30.40"
func TestMSSQL(t *testing.T) {
//SkipConvey("MSSQL", t, func() {
SkipConvey("MSSQL", t, func() {
x := InitMSSQLTestDB(t)
......@@ -52,7 +51,8 @@ func TestMSSQL(t *testing.T) {
sql += "afloat float, "
sql += "adatetime datetime, "
sql += "adate date, "
sql += "atime time) "
sql += "atime time, "
sql += "adatetimeoffset datetimeoffset) "
_, err := sess.Exec(sql)
So(err, ShouldBeNil)
......@@ -60,11 +60,11 @@ func TestMSSQL(t *testing.T) {
sql += "(abit, atinyint, asmallint, aint, abigint, "
sql += "avarchar, achar, anewvarchar, anewchar, "
sql += "areal, anewdecimal, afloat, "
sql += "adatetime, adate, atime ) "
sql += "adatetime, adate, atime, adatetimeoffset ) "
sql += "VALUES(1, 5, 20020, 980300, 1420070400, "
sql += "'abc', 'def', 'hi varchar', 'I am only char', "
sql += "1.11, 2.22, 3.33, "
sql += "GETUTCDATE(), CAST(GETUTCDATE() AS DATE), CAST(GETUTCDATE() AS TIME) );"
sql += "GETUTCDATE(), CAST(GETUTCDATE() AS DATE), CAST(GETUTCDATE() AS TIME), SWITCHOFFSET(SYSDATETIMEOFFSET(), '-07:00') );"
_, err = sess.Exec(sql)
So(err, ShouldBeNil)
......@@ -98,12 +98,13 @@ func TestMSSQL(t *testing.T) {
So(column[8].(string), ShouldEqual, "I am only char")
So(column[9].(float64), ShouldEqual, 1.1100000143051147) // MSSQL dose not have precision for "real" datatype
// fiix me: MSSQL driver puts the decimal inside an array of chars. and the test fails despite the values are correct.
// fix me: MSSQL driver puts the decimal inside an array of chars. and the test fails despite the values are correct.
//So(column[10].([]uint8), ShouldEqual, []uint8{'2', '.', '2', '2'})
So(column[11].(float64), ShouldEqual, 3.33)
So(column[12].(time.Time), ShouldHappenWithin, time.Duration(15*time.Second), time.Now().UTC())
So(column[13].(time.Time), ShouldHappenWithin, time.Duration(15*time.Second), time.Now().UTC().Truncate(24*time.Hour))
So(column[14].(time.Time), ShouldHappenWithin, time.Duration(15*time.Second), time.Date(1, time.January, 1, time.Now().UTC().Hour(), time.Now().UTC().Minute(), time.Now().UTC().Second(), 0, time.UTC))
So(column[12].(time.Time), ShouldHappenWithin, time.Duration(10*time.Second), time.Now().UTC())
So(column[13].(time.Time), ShouldHappenWithin, time.Duration(10*time.Second), time.Now().UTC().Truncate(24*time.Hour)) // ShouldEqual dose not work here !!?
So(column[14].(time.Time), ShouldHappenWithin, time.Duration(10*time.Second), time.Date(1, time.January, 1, time.Now().UTC().Hour(), time.Now().UTC().Minute(), time.Now().UTC().Second(), 0, time.UTC))
So(column[15].(time.Time), ShouldHappenWithin, time.Duration(10*time.Second), time.Now().UTC())
})
})
}
......
......@@ -8,7 +8,7 @@ class MssqlConfigCtrl {
}
const defaultQuery = `SELECT TOP 100
DATEDIFF(second, {d '1970-01-01'}, DATEADD(second,DATEDIFF(second,GETDATE(),GETUTCDATE()),<time_column>) ) as time_sec,
$__utcTime(<time_column>),
<text_column> as text,
<tags_column> as tags
FROM <table name>
......
......@@ -18,16 +18,17 @@
<div class="gf-form" ng-show="ctrl.showHelp">
<pre class="gf-form-pre alert alert-info"><h6>Annotation Query Format</h6>
An annotation is an event that is overlayed on top of graphs. The query can have up to four columns per row, the time_sec column is mandatory. Annotation rendering is expensive so it is important to limit the number of rows returned.
An annotation is an event that is overlayed on top of graphs. The query can have up to four columns per row, the <b>time</b> column is mandatory. Annotation rendering is expensive so it is important to limit the number of rows returned.
- column with alias: <b>time_sec</b> for the annotation event. Format is UTC in seconds, use the below to convert a datetime column to UTC unix time stamp:
DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), column_name) )
- column with alias: <b>time</b> for the annotation event time (in UTC), as a unix time stamp or any sql native date datatype.
- column with alias: <b>text</b> for the annotation text
- column with alias: <b>tags</b> for annotation tags. This is a comma separated string of tags e.g. 'tag1,tag2'
Macros:
- $__time(column) -&gt; DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), column) ) as time_sec
- $__time(column) -&gt; column AS time
- $__utcTime(column) -&gt; DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), column) AS time
- $__timeEpoch(column) -&gt; DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), column) ) AS time
- $__timeFilter(column) -&gt; column &gt; DATEADD(s, 1492750877+DATEDIFF(second,GETUTCDATE(),GETDATE()), '1970-01-01') AND column &lt; DATEADD(s, 1492750877+DATEDIFF(second,GETUTCDATE(),GETDATE()), '1970-01-01')
- $__unixEpochFilter(column) -&gt; column &gt; 1492750877 AND column &lt; 1492750877
......
......@@ -38,16 +38,18 @@
<div class="gf-form" ng-show="ctrl.showHelp">
<pre class="gf-form-pre alert alert-info">Time series:
- return column named time_sec (UTC in seconds), use the below to convert a datetime column to UTC unix time stamp:
DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), column_name) )
- return column named value for the time point value
- return column named metric to represent the series name
- return column named time (in UTC), as a unix time stamp or any sql native date datatype. you can use the macros below.
- optional: return column named metric to represent the series names.
- any other columns returned will be the time point values.
- if multiple value columns are present and a metric column is provided. the series name will be the combination of "MetricName - ValueColumnName".
Table:
- return any set of columns
Macros:
- $__time(column) -&gt; DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), column) ) as time_sec
- $__time(column) -&gt; column AS time
- $__utcTime(column) -&gt; DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), column) AS time
- $__timeEpoch(column) -&gt; DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), column) ) AS time
- $__timeFilter(column) -&gt; column &gt; DATEADD(s, 1492750877+DATEDIFF(second,GETUTCDATE(),GETDATE()), '1970-01-01') AND column &lt; DATEADD(s, 1492750877+DATEDIFF(second,GETUTCDATE(),GETDATE()), '1970-01-01')
- $__unixEpochFilter(column) -&gt; column &gt; 1492750877 AND column &lt; 1492750877
......
......@@ -16,7 +16,7 @@ export interface QueryMeta {
const defaultQuery = `SELECT
DATEDIFF(second, {d '1970-01-01'}, DATEADD(second,DATEDIFF(second,GETDATE(),GETUTCDATE()),<time_column>)) as time_sec,
$__utcTime(<time_column>),
<value column> as value,
<series name column> as metric
FROM <table name>
......
......@@ -110,7 +110,7 @@ export default class ResponseParser {
let tagsColumnIndex = -1;
for (let i = 0; i < table.columns.length; i++) {
if (table.columns[i].text === 'time_sec') {
if (table.columns[i].text === 'time') {
timeColumnIndex = i;
} else if (table.columns[i].text === 'title') {
return this.$q.reject({message: 'The title column for annotations is deprecated, now only a column named text is returned'});
......@@ -122,7 +122,7 @@ export default class ResponseParser {
}
if (timeColumnIndex === -1) {
return this.$q.reject({message: 'Missing mandatory time column (with time_sec column alias) in annotation query.'});
return this.$q.reject({message: 'Missing mandatory time column (with time column alias) in annotation query.'});
}
const list = [];
......
......@@ -28,7 +28,7 @@ describe('MSSQLDatasource', function() {
const options = {
annotation: {
name: annotationName,
rawQuery: 'select time_sec, text, tags from table;'
rawQuery: 'select time, text, tags from table;'
},
range: {
from: moment(1432288354),
......@@ -42,7 +42,7 @@ describe('MSSQLDatasource', function() {
refId: annotationName,
tables: [
{
columns: [{text: 'time_sec'}, {text: 'text'}, {text: 'tags'}],
columns: [{text: 'time'}, {text: 'text'}, {text: 'tags'}],
rows: [
[1432288355, 'some text', 'TagA,TagB'],
[1432288390, 'some text2', ' TagB , TagC'],
......
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