query_part.go 5.0 KB

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