query_part.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package influxdb
  2. import (
  3. "fmt"
  4. "strings"
  5. "time"
  6. "github.com/grafana/grafana/pkg/tsdb"
  7. )
  8. var renders map[string]QueryDefinition
  9. type DefinitionParameters struct {
  10. Name string
  11. Type string
  12. }
  13. type QueryDefinition struct {
  14. Renderer func(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string
  15. Params []DefinitionParameters
  16. }
  17. func init() {
  18. renders = make(map[string]QueryDefinition)
  19. renders["field"] = QueryDefinition{Renderer: fieldRenderer}
  20. renders["spread"] = QueryDefinition{Renderer: functionRenderer}
  21. renders["count"] = QueryDefinition{Renderer: functionRenderer}
  22. renders["distinct"] = QueryDefinition{Renderer: functionRenderer}
  23. renders["integral"] = QueryDefinition{Renderer: functionRenderer}
  24. renders["mean"] = QueryDefinition{Renderer: functionRenderer}
  25. renders["median"] = QueryDefinition{Renderer: functionRenderer}
  26. renders["sum"] = QueryDefinition{Renderer: functionRenderer}
  27. renders["derivative"] = QueryDefinition{
  28. Renderer: functionRenderer,
  29. Params: []DefinitionParameters{{Name: "duration", Type: "interval"}},
  30. }
  31. renders["non_negative_derivative"] = QueryDefinition{
  32. Renderer: functionRenderer,
  33. Params: []DefinitionParameters{{Name: "duration", Type: "interval"}},
  34. }
  35. renders["difference"] = QueryDefinition{Renderer: functionRenderer}
  36. renders["moving_average"] = QueryDefinition{
  37. Renderer: functionRenderer,
  38. Params: []DefinitionParameters{{Name: "window", Type: "number"}},
  39. }
  40. renders["stddev"] = QueryDefinition{Renderer: functionRenderer}
  41. renders["time"] = QueryDefinition{
  42. Renderer: functionRenderer,
  43. Params: []DefinitionParameters{{Name: "interval", Type: "time"}},
  44. }
  45. renders["fill"] = QueryDefinition{
  46. Renderer: functionRenderer,
  47. Params: []DefinitionParameters{{Name: "fill", Type: "string"}},
  48. }
  49. renders["elapsed"] = QueryDefinition{
  50. Renderer: functionRenderer,
  51. Params: []DefinitionParameters{{Name: "duration", Type: "interval"}},
  52. }
  53. renders["bottom"] = QueryDefinition{
  54. Renderer: functionRenderer,
  55. Params: []DefinitionParameters{{Name: "count", Type: "int"}},
  56. }
  57. renders["first"] = QueryDefinition{Renderer: functionRenderer}
  58. renders["last"] = QueryDefinition{Renderer: functionRenderer}
  59. renders["max"] = QueryDefinition{Renderer: functionRenderer}
  60. renders["min"] = QueryDefinition{Renderer: functionRenderer}
  61. renders["percentile"] = QueryDefinition{
  62. Renderer: functionRenderer,
  63. Params: []DefinitionParameters{{Name: "nth", Type: "int"}},
  64. }
  65. renders["top"] = QueryDefinition{
  66. Renderer: functionRenderer,
  67. Params: []DefinitionParameters{{Name: "count", Type: "int"}},
  68. }
  69. renders["tag"] = QueryDefinition{
  70. Renderer: fieldRenderer,
  71. Params: []DefinitionParameters{{Name: "tag", Type: "string"}},
  72. }
  73. renders["math"] = QueryDefinition{Renderer: suffixRenderer}
  74. renders["alias"] = QueryDefinition{Renderer: aliasRenderer}
  75. }
  76. func fieldRenderer(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string {
  77. if part.Params[0] == "*" {
  78. return "*"
  79. }
  80. return fmt.Sprintf(`"%s"`, part.Params[0])
  81. }
  82. func getDefinedInterval(query *Query, queryContext *tsdb.QueryContext) string {
  83. setInterval := strings.Replace(strings.Replace(query.Interval, "<", "", 1), ">", "", 1)
  84. defaultInterval := tsdb.CalculateInterval(queryContext.TimeRange)
  85. if strings.Contains(query.Interval, ">") {
  86. parsedDefaultInterval, err := time.ParseDuration(defaultInterval)
  87. parsedSetInterval, err2 := time.ParseDuration(setInterval)
  88. if err == nil && err2 == nil && parsedDefaultInterval > parsedSetInterval {
  89. return defaultInterval
  90. }
  91. }
  92. return setInterval
  93. }
  94. func functionRenderer(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string {
  95. for i, param := range part.Params {
  96. if param == "$interval" {
  97. if query.Interval != "" {
  98. part.Params[i] = getDefinedInterval(query, queryContext)
  99. } else {
  100. part.Params[i] = tsdb.CalculateInterval(queryContext.TimeRange)
  101. }
  102. }
  103. }
  104. if innerExpr != "" {
  105. part.Params = append([]string{innerExpr}, part.Params...)
  106. }
  107. params := strings.Join(part.Params, ", ")
  108. return fmt.Sprintf("%s(%s)", part.Type, params)
  109. }
  110. func suffixRenderer(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string {
  111. return fmt.Sprintf("%s %s", innerExpr, part.Params[0])
  112. }
  113. func aliasRenderer(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string {
  114. return fmt.Sprintf(`%s AS "%s"`, innerExpr, part.Params[0])
  115. }
  116. func (r QueryDefinition) Render(query *Query, queryContext *tsdb.QueryContext, part *QueryPart, innerExpr string) string {
  117. return r.Renderer(query, queryContext, part, innerExpr)
  118. }
  119. func NewQueryPart(typ string, params []string) (*QueryPart, error) {
  120. def, exist := renders[typ]
  121. if !exist {
  122. return nil, fmt.Errorf("Missing query definition for %s", typ)
  123. }
  124. return &QueryPart{
  125. Type: typ,
  126. Params: params,
  127. Def: def,
  128. }, nil
  129. }
  130. type QueryPart struct {
  131. Def QueryDefinition
  132. Type string
  133. Params []string
  134. }
  135. func (qp *QueryPart) Render(query *Query, queryContext *tsdb.QueryContext, expr string) string {
  136. return qp.Def.Renderer(query, queryContext, qp, expr)
  137. }