influxdb/v1/services/storage/predicate_influxql.go

92 lines
1.9 KiB
Go

package storage
import (
"github.com/influxdata/influxdb/v2/models"
"github.com/influxdata/influxql"
)
var measurementRemap = map[string]string{
"_measurement": "_name",
models.MeasurementTagKey: "_name",
models.FieldKeyTagKey: "_field",
}
func RewriteExprRemoveFieldKeyAndValue(expr influxql.Expr) influxql.Expr {
return influxql.RewriteExpr(expr, func(expr influxql.Expr) influxql.Expr {
if be, ok := expr.(*influxql.BinaryExpr); ok {
if ref, ok := be.LHS.(*influxql.VarRef); ok {
if ref.Val == "_field" || ref.Val == "$" {
return &influxql.BooleanLiteral{Val: true}
}
}
}
return expr
})
}
type hasRefs struct {
refs []string
found []bool
}
func (v *hasRefs) allFound() bool {
for _, val := range v.found {
if !val {
return false
}
}
return true
}
func (v *hasRefs) Visit(node influxql.Node) influxql.Visitor {
if v.allFound() {
return nil
}
if n, ok := node.(*influxql.VarRef); ok {
for i, r := range v.refs {
if !v.found[i] && r == n.Val {
v.found[i] = true
if v.allFound() {
return nil
}
}
}
}
return v
}
func HasFieldKeyOrValue(expr influxql.Expr) (bool, bool) {
refs := hasRefs{refs: []string{fieldKey, "$"}, found: make([]bool, 2)}
influxql.Walk(&refs, expr)
return refs.found[0], refs.found[1]
}
type hasAnyTagKeys struct {
found bool
}
func (v *hasAnyTagKeys) Visit(node influxql.Node) influxql.Visitor {
if v.found {
return nil
}
if n, ok := node.(*influxql.VarRef); ok {
// The influxql expression will have had references to "_measurement"
// remapped to "_name" at this point by reads.NodeToExpr, so be sure to
// check for the appropriate value here using the measurementRemap map.
if n.Val != fieldKey && n.Val != measurementRemap[measurementKey] && n.Val != "$" {
v.found = true
return nil
}
}
return v
}
func hasTagKey(expr influxql.Expr) bool {
v := &hasAnyTagKeys{}
influxql.Walk(v, expr)
return v.found
}