macros.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package mssql
  2. import (
  3. "fmt"
  4. "regexp"
  5. "strings"
  6. "github.com/grafana/grafana/pkg/tsdb"
  7. )
  8. //const rsString = `(?:"([^"]*)")`;
  9. const rsIdentifier = `([_a-zA-Z0-9]+)`
  10. const sExpr = `\$` + rsIdentifier + `\(([^\)]*)\)`
  11. type MsSqlMacroEngine struct {
  12. TimeRange *tsdb.TimeRange
  13. Query *tsdb.Query
  14. }
  15. func NewMssqlMacroEngine() tsdb.SqlMacroEngine {
  16. return &MsSqlMacroEngine{}
  17. }
  18. func (m *MsSqlMacroEngine) Interpolate(query *tsdb.Query, timeRange *tsdb.TimeRange, sql string) (string, error) {
  19. m.TimeRange = timeRange
  20. m.Query = query
  21. rExp, _ := regexp.Compile(sExpr)
  22. var macroError error
  23. sql = replaceAllStringSubmatchFunc(rExp, sql, func(groups []string) string {
  24. args := strings.Split(groups[2], ",")
  25. for i, arg := range args {
  26. args[i] = strings.Trim(arg, " ")
  27. }
  28. res, err := m.evaluateMacro(groups[1], args)
  29. if err != nil && macroError == nil {
  30. macroError = err
  31. return "macro_error()"
  32. }
  33. return res
  34. })
  35. if macroError != nil {
  36. return "", macroError
  37. }
  38. return sql, nil
  39. }
  40. func replaceAllStringSubmatchFunc(re *regexp.Regexp, str string, repl func([]string) string) string {
  41. result := ""
  42. lastIndex := 0
  43. for _, v := range re.FindAllSubmatchIndex([]byte(str), -1) {
  44. groups := []string{}
  45. for i := 0; i < len(v); i += 2 {
  46. groups = append(groups, str[v[i]:v[i+1]])
  47. }
  48. result += str[lastIndex:v[0]] + repl(groups)
  49. lastIndex = v[1]
  50. }
  51. return result + str[lastIndex:]
  52. }
  53. func (m *MsSqlMacroEngine) evaluateMacro(name string, args []string) (string, error) {
  54. switch name {
  55. case "__time":
  56. if len(args) == 0 {
  57. return "", fmt.Errorf("missing time column argument for macro %v", name)
  58. }
  59. return fmt.Sprintf("%s AS time", args[0]), nil
  60. case "__utcTime":
  61. if len(args) == 0 {
  62. return "", fmt.Errorf("missing time column argument for macro %v", name)
  63. }
  64. return fmt.Sprintf("DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), %s) AS time", args[0]), nil
  65. case "__timeEpoch":
  66. if len(args) == 0 {
  67. return "", fmt.Errorf("missing time column argument for macro %v", name)
  68. }
  69. return fmt.Sprintf("DATEDIFF(second, {d '1970-01-01'}, DATEADD(second, DATEDIFF(second,GETDATE(),GETUTCDATE()), %s) ) AS time", args[0]), nil
  70. case "__timeFilter":
  71. if len(args) == 0 {
  72. return "", fmt.Errorf("missing time column argument for macro %v", name)
  73. }
  74. return fmt.Sprintf("%s >= DATEADD(s, %d+DATEDIFF(second,GETUTCDATE(),GETDATE()), '1970-01-01') AND %s <= DATEADD(s, %d+DATEDIFF(second,GETUTCDATE(),GETDATE()), '1970-01-01')", args[0], uint64(m.TimeRange.GetFromAsMsEpoch()/1000), args[0], uint64(m.TimeRange.GetToAsMsEpoch()/1000)), nil
  75. case "__timeFrom":
  76. return fmt.Sprintf("DATEADD(second, %d+DATEDIFF(second,GETUTCDATE(),GETDATE()), '1970-01-01')", uint64(m.TimeRange.GetFromAsMsEpoch()/1000)), nil
  77. case "__timeTo":
  78. return fmt.Sprintf("DATEADD(second, %d+DATEDIFF(second,GETUTCDATE(),GETDATE()), '1970-01-01')", uint64(m.TimeRange.GetToAsMsEpoch()/1000)), nil
  79. case "__unixEpochFilter":
  80. if len(args) == 0 {
  81. return "", fmt.Errorf("missing time column argument for macro %v", name)
  82. }
  83. return fmt.Sprintf("%s >= %d AND %s <= %d", args[0], uint64(m.TimeRange.GetFromAsMsEpoch()/1000), args[0], uint64(m.TimeRange.GetToAsMsEpoch()/1000)), nil
  84. case "__unixEpochFrom":
  85. return fmt.Sprintf("%d", uint64(m.TimeRange.GetFromAsMsEpoch()/1000)), nil
  86. case "__unixEpochTo":
  87. return fmt.Sprintf("%d", uint64(m.TimeRange.GetToAsMsEpoch()/1000)), nil
  88. default:
  89. return "", fmt.Errorf("Unknown macro %v", name)
  90. }
  91. }