params.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package influxql
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "strconv"
  6. "strings"
  7. "time"
  8. )
  9. // Value represents a value that can be bound
  10. // to a parameter when parsing the query.
  11. type Value interface {
  12. TokenType() Token
  13. Value() string
  14. }
  15. type (
  16. // Identifier is an identifier value.
  17. Identifier string
  18. // StringValue is a string literal.
  19. StringValue string
  20. // RegexValue is a regexp literal.
  21. RegexValue string
  22. // NumberValue is a number literal.
  23. NumberValue float64
  24. // IntegerValue is an integer literal.
  25. IntegerValue int64
  26. // BooleanValue is a boolean literal.
  27. BooleanValue bool
  28. // DurationValue is a duration literal.
  29. DurationValue string
  30. // ErrorValue is a special value that returns an error during parsing
  31. // when it is used.
  32. ErrorValue string
  33. )
  34. // BindValue will bind an interface value to its influxql value.
  35. // This method of binding values only supports literals.
  36. func BindValue(v interface{}) Value {
  37. if jv, ok := v.(json.Number); ok {
  38. var err error
  39. v, err = jsonNumberToValue(jv)
  40. if err != nil {
  41. return ErrorValue(err.Error())
  42. }
  43. }
  44. switch v := v.(type) {
  45. case float64:
  46. return NumberValue(v)
  47. case int64:
  48. return IntegerValue(v)
  49. case string:
  50. return StringValue(v)
  51. case bool:
  52. return BooleanValue(v)
  53. case map[string]interface{}:
  54. return bindObjectValue(v)
  55. default:
  56. s := fmt.Sprintf("unable to bind parameter with type %T", v)
  57. return ErrorValue(s)
  58. }
  59. }
  60. // bindObjectValue will bind an object to a value.
  61. func bindObjectValue(m map[string]interface{}) Value {
  62. if len(m) != 1 {
  63. return ErrorValue("bound object parameter value must have exactly one entry")
  64. }
  65. var (
  66. k string
  67. v interface{}
  68. )
  69. for k, v = range m {
  70. // Nothing done here.
  71. }
  72. if jv, ok := v.(json.Number); ok {
  73. var err error
  74. v, err = jsonNumberToValue(jv)
  75. if err != nil {
  76. return ErrorValue(err.Error())
  77. }
  78. }
  79. switch k {
  80. case "ident", "identifier":
  81. s, ok := v.(string)
  82. if !ok {
  83. return ErrorValue("identifier must be a string value")
  84. }
  85. return Identifier(s)
  86. case "regex":
  87. s, ok := v.(string)
  88. if !ok {
  89. return ErrorValue("regex literal must be a string value")
  90. }
  91. return RegexValue(s)
  92. case "string":
  93. s, ok := v.(string)
  94. if !ok {
  95. return ErrorValue("string literal must be a string value")
  96. }
  97. return StringValue(s)
  98. case "float", "number":
  99. switch f := v.(type) {
  100. case float64:
  101. return NumberValue(f)
  102. case int64:
  103. return NumberValue(f)
  104. default:
  105. return ErrorValue("number literal must be a float value")
  106. }
  107. case "int", "integer":
  108. i, ok := v.(int64)
  109. if !ok {
  110. return ErrorValue("integer literal must be an integer value")
  111. }
  112. return IntegerValue(i)
  113. case "duration":
  114. switch d := v.(type) {
  115. case string:
  116. return DurationValue(d)
  117. case int64:
  118. return DurationValue(FormatDuration(time.Duration(d)))
  119. default:
  120. return ErrorValue("duration literal must be a string or integer value")
  121. }
  122. default:
  123. return ErrorValue(fmt.Sprintf("unknown bind object type: %s", k))
  124. }
  125. }
  126. func (v Identifier) TokenType() Token { return IDENT }
  127. func (v Identifier) Value() string { return string(v) }
  128. func (v StringValue) TokenType() Token { return STRING }
  129. func (v StringValue) Value() string { return string(v) }
  130. func (v RegexValue) TokenType() Token { return REGEX }
  131. func (v RegexValue) Value() string { return string(v) }
  132. func (v NumberValue) TokenType() Token { return NUMBER }
  133. func (v NumberValue) Value() string { return strconv.FormatFloat(float64(v), 'f', -1, 64) }
  134. func (v IntegerValue) TokenType() Token { return INTEGER }
  135. func (v IntegerValue) Value() string { return strconv.FormatInt(int64(v), 10) }
  136. func (v BooleanValue) TokenType() Token {
  137. if v {
  138. return TRUE
  139. } else {
  140. return FALSE
  141. }
  142. }
  143. func (v BooleanValue) Value() string { return "" }
  144. func (v DurationValue) TokenType() Token { return DURATIONVAL }
  145. func (v DurationValue) Value() string { return string(v) }
  146. func (e ErrorValue) TokenType() Token { return BOUNDPARAM }
  147. func (e ErrorValue) Value() string { return string(e) }
  148. func jsonNumberToValue(v json.Number) (interface{}, error) {
  149. if strings.Contains(string(v), ".") {
  150. f, err := v.Float64()
  151. if err != nil {
  152. return nil, err
  153. }
  154. return f, nil
  155. } else {
  156. i, err := v.Int64()
  157. if err != nil {
  158. return nil, err
  159. }
  160. return i, nil
  161. }
  162. }