MSSQL Datasource: Revert functions within macros change (#63592)

* Revert functions within macros change
* Add tests for function and macro for mssql
* Remove macro support tests

---------

Co-authored-by: Oscar Kilhed <oscar.kilhed@grafana.com>
This commit is contained in:
Kyle Cunningham 2023-02-22 22:02:05 +01:00 committed by GitHub
parent 05a9946b18
commit 356e2e1933
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 0 additions and 172 deletions

View File

@ -13,7 +13,6 @@ import (
const rsIdentifier = `([_a-zA-Z0-9]+)`
const sExpr = `\$` + rsIdentifier + `\(([^\)]*)\)`
const argFuncExpr = `[\(|,|\s]([_a-zA-Z0-9]+\([^\(]*?\))`
type msSQLMacroEngine struct {
*sqleng.SQLMacroEngineBase
@ -23,45 +22,16 @@ func newMssqlMacroEngine() sqleng.SQLMacroEngine {
return &msSQLMacroEngine{SQLMacroEngineBase: sqleng.NewSQLMacroEngineBase()}
}
func replaceFunctionCallArgsWithPlaceholders(sql string) (string, map[string]string) {
rExp, _ := regexp.Compile(argFuncExpr)
functionCalls := rExp.FindAllString(sql, -1)
replacedArgs := make(map[string]string)
if len(functionCalls) > 0 {
sql = strings.Replace(sql, "\n", "", -1)
for i, functionCall := range functionCalls {
key := fmt.Sprintf("$%d", i)
formattedVal := functionCall[1:]
sql = strings.Replace(sql, formattedVal, key, 1)
replacedArgs[key] = formattedVal
}
return sql, replacedArgs
}
return sql, nil
}
func (m *msSQLMacroEngine) Interpolate(query *backend.DataQuery, timeRange backend.TimeRange,
sql string) (string, error) {
// TODO: Return any error
rExp, _ := regexp.Compile(sExpr)
var macroError error
var fctCallArgsMap map[string]string
if rExp.FindAllSubmatchIndex([]byte(sql), -1) != nil {
sql, fctCallArgsMap = replaceFunctionCallArgsWithPlaceholders(sql)
}
sql = m.ReplaceAllStringSubmatchFunc(rExp, sql, func(groups []string) string {
args := strings.Split(groups[2], ",")
for i, arg := range args {
args[i] = strings.Trim(arg, " ")
if fctCallArgsMap != nil && fctCallArgsMap[args[i]] != "" {
args[i] = strings.Replace(args[i], args[i], fctCallArgsMap[args[i]], 1)
}
}
res, err := m.evaluateMacro(timeRange, query, groups[1], args)
if err != nil && macroError == nil {

View File

@ -208,148 +208,6 @@ func TestMacroEngine(t *testing.T) {
require.Equal(t, fmt.Sprintf("select time_column >= %d AND time_column <= %d", from.UnixNano(), to.UnixNano()), sql)
})
t.Run("interpolate __timeGroup with function calls as params successfully", func(t *testing.T) {
//various queries with function calls as params tested with different spacings
sqls := []struct {
query string
expected string
}{
{
query: "select $__timeGroup(test, 5m)",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', test)/300)*300",
},
{
query: "select $__timeGroup(try_convert(timestamp, time), 5m)",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert(timestamp, time))/300)*300",
},
{
query: "select $__timeGroup(func(), 5m)",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', func())/300)*300",
},
{
query: "select $__timeGroup( try_convert(timestamp, time), 5m)",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert(timestamp, time))/300)*300",
},
{
query: "select $__timeGroup( \n try_convert(timestamp, time), 5m)",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert(timestamp, time))/300)*300",
},
{
query: "select $__timeGroup( \n\n\ntry_convert(timestamp, time), 5m)",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert(timestamp, time))/300)*300",
},
{
query: "select $__timeGroup( try_convert(timestamp, time) , 5m)",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert(timestamp, time))/300)*300",
},
{
query: "select $__timeGroup( try_convert(timestamp, time) ,5m)",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert(timestamp, time))/300)*300",
},
{
query: "select $__timeGroup(try_convert(timestamp, time),5m)",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert(timestamp, time))/300)*300",
},
{
query: "select $__timeGroup(try_convert(timestamp, time), 5m)",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert(timestamp, time))/300)*300",
},
{
query: "select $__timeGroup(try_convert(timestamp, time), 5m)",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert(timestamp, time))/300)*300",
},
}
for _, sql := range sqls {
actual, err := engine.Interpolate(query, timeRange, sql.query)
require.Nil(t, err)
require.Equal(t, sql.expected, actual)
}
})
t.Run("interpolate macros with function calls as params successfully", func(t *testing.T) {
filterInterpolated := fmt.Sprintf("BETWEEN '%s' AND '%s'", from.Format(time.RFC3339), to.Format(time.RFC3339))
unixEpochFilter := fmt.Sprintf("select try_convert(timestamp, time) >= %d AND try_convert(timestamp, time) <= %d", from.Unix(), to.Unix())
unixEphocNanoFilter := fmt.Sprintf("select try_convert(timestamp, time) >= %d AND try_convert(timestamp, time) <= %d", from.UnixNano(), to.UnixNano())
//queries with macros and fct calls as params. fct calls are tested with various params and spaces
sqls := []struct {
query string
expected string
}{
{
query: "select $__timeGroup(try_convert(timestamp, time), 5m) from test where $__timeFilter(time)",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert(timestamp, time))/300)*300 from test where time " + filterInterpolated,
},
{
query: "select $__timeGroup(try_convert(timestamp, time), 5m) from test where $__timeFilter(func(time))",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert(timestamp, time))/300)*300 from test where func(time) " + filterInterpolated,
},
{
query: "select $__timeGroup(try_convert(timestamp, time), 5m) from test where $__timeFilter(func(time));",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert(timestamp, time))/300)*300 from test where func(time) " + filterInterpolated + ";",
},
{
query: "select $__timeGroup(try_convert(timestamp, time), 5m) from test where $__timeFilter(func(time, var2));",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert(timestamp, time))/300)*300 from test where func(time, var2) " + filterInterpolated + ";",
},
{
query: "select $__timeGroup(try_convert(timestamp, time), 5m), $__timeGroup(func2( var1 , var2, var3 ), 15m) from test where $__timeFilter(func(time, var2));",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert(timestamp, time))/300)*300, FLOOR(DATEDIFF(second, '1970-01-01', func2( var1 , var2, var3 ))/900)*900 from test where func(time, var2) " + filterInterpolated + ";",
},
{
query: "select $__timeGroupAlias(try_convert(), 5m)",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert())/300)*300 AS [time]",
},
{
query: "select $__timeEpoch(try_convert(timestamp, time))",
expected: "select DATEDIFF(second, '1970-01-01', try_convert(timestamp, time)) AS time",
},
{
query: "select $__time(try_convert(timestamp, time))",
expected: "select try_convert(timestamp, time) AS time",
},
{
query: "select $__timeGroup(try_convert(timestamp, time), 15m, NULL)",
expected: "select FLOOR(DATEDIFF(second, '1970-01-01', try_convert(timestamp, time))/900)*900",
},
{
query: "select $__unixEpochFilter(try_convert(timestamp, time))",
expected: unixEpochFilter,
},
{
query: "select $__unixEpochNanoFilter(try_convert(timestamp, time))",
expected: unixEphocNanoFilter,
},
{
query: "select $__unixEpochGroup(try_convert(timestamp, time), 15m)",
expected: "select FLOOR(try_convert(timestamp, time)/900)*900",
},
{
query: "select $__unixEpochGroupAlias(try_convert(timestamp, time), 15m)",
expected: "select FLOOR(try_convert(timestamp, time)/900)*900 AS [time]",
},
}
for _, sql := range sqls {
actual, err := engine.Interpolate(query, timeRange, sql.query)
require.Nil(t, err)
require.Equal(t, sql.expected, actual)
}
})
t.Run("interpolate macros with function calls as params unsuccessfully", func(t *testing.T) {
sqls := []string{
"select $__timeGroup(func1(func2()), 5m)", //cannot go beyond 1st level of nested function calls
"select $__timeGroup(func1(), func2())", //second param must be interval
}
for _, sql := range sqls {
_, err := engine.Interpolate(query, timeRange, sql)
require.NotNil(t, err)
}
})
t.Run("should return unmodified sql if there are no macros present", func(t *testing.T) {
sqls := []string{
"select * from table",