| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- package influxql
- import (
- "encoding/json"
- "fmt"
- "strconv"
- "strings"
- "time"
- )
- // Value represents a value that can be bound
- // to a parameter when parsing the query.
- type Value interface {
- TokenType() Token
- Value() string
- }
- type (
- // Identifier is an identifier value.
- Identifier string
- // StringValue is a string literal.
- StringValue string
- // RegexValue is a regexp literal.
- RegexValue string
- // NumberValue is a number literal.
- NumberValue float64
- // IntegerValue is an integer literal.
- IntegerValue int64
- // BooleanValue is a boolean literal.
- BooleanValue bool
- // DurationValue is a duration literal.
- DurationValue string
- // ErrorValue is a special value that returns an error during parsing
- // when it is used.
- ErrorValue string
- )
- // BindValue will bind an interface value to its influxql value.
- // This method of binding values only supports literals.
- func BindValue(v interface{}) Value {
- if jv, ok := v.(json.Number); ok {
- var err error
- v, err = jsonNumberToValue(jv)
- if err != nil {
- return ErrorValue(err.Error())
- }
- }
- switch v := v.(type) {
- case float64:
- return NumberValue(v)
- case int64:
- return IntegerValue(v)
- case string:
- return StringValue(v)
- case bool:
- return BooleanValue(v)
- case map[string]interface{}:
- return bindObjectValue(v)
- default:
- s := fmt.Sprintf("unable to bind parameter with type %T", v)
- return ErrorValue(s)
- }
- }
- // bindObjectValue will bind an object to a value.
- func bindObjectValue(m map[string]interface{}) Value {
- if len(m) != 1 {
- return ErrorValue("bound object parameter value must have exactly one entry")
- }
- var (
- k string
- v interface{}
- )
- for k, v = range m {
- // Nothing done here.
- }
- if jv, ok := v.(json.Number); ok {
- var err error
- v, err = jsonNumberToValue(jv)
- if err != nil {
- return ErrorValue(err.Error())
- }
- }
- switch k {
- case "ident", "identifier":
- s, ok := v.(string)
- if !ok {
- return ErrorValue("identifier must be a string value")
- }
- return Identifier(s)
- case "regex":
- s, ok := v.(string)
- if !ok {
- return ErrorValue("regex literal must be a string value")
- }
- return RegexValue(s)
- case "string":
- s, ok := v.(string)
- if !ok {
- return ErrorValue("string literal must be a string value")
- }
- return StringValue(s)
- case "float", "number":
- switch f := v.(type) {
- case float64:
- return NumberValue(f)
- case int64:
- return NumberValue(f)
- default:
- return ErrorValue("number literal must be a float value")
- }
- case "int", "integer":
- i, ok := v.(int64)
- if !ok {
- return ErrorValue("integer literal must be an integer value")
- }
- return IntegerValue(i)
- case "duration":
- switch d := v.(type) {
- case string:
- return DurationValue(d)
- case int64:
- return DurationValue(FormatDuration(time.Duration(d)))
- default:
- return ErrorValue("duration literal must be a string or integer value")
- }
- default:
- return ErrorValue(fmt.Sprintf("unknown bind object type: %s", k))
- }
- }
- func (v Identifier) TokenType() Token { return IDENT }
- func (v Identifier) Value() string { return string(v) }
- func (v StringValue) TokenType() Token { return STRING }
- func (v StringValue) Value() string { return string(v) }
- func (v RegexValue) TokenType() Token { return REGEX }
- func (v RegexValue) Value() string { return string(v) }
- func (v NumberValue) TokenType() Token { return NUMBER }
- func (v NumberValue) Value() string { return strconv.FormatFloat(float64(v), 'f', -1, 64) }
- func (v IntegerValue) TokenType() Token { return INTEGER }
- func (v IntegerValue) Value() string { return strconv.FormatInt(int64(v), 10) }
- func (v BooleanValue) TokenType() Token {
- if v {
- return TRUE
- } else {
- return FALSE
- }
- }
- func (v BooleanValue) Value() string { return "" }
- func (v DurationValue) TokenType() Token { return DURATIONVAL }
- func (v DurationValue) Value() string { return string(v) }
- func (e ErrorValue) TokenType() Token { return BOUNDPARAM }
- func (e ErrorValue) Value() string { return string(e) }
- func jsonNumberToValue(v json.Number) (interface{}, error) {
- if strings.Contains(string(v), ".") {
- f, err := v.Float64()
- if err != nil {
- return nil, err
- }
- return f, nil
- } else {
- i, err := v.Int64()
- if err != nil {
- return nil, err
- }
- return i, nil
- }
- }
|