fix(predicate): add special tag key, fixed children number
parent
0dde41f895
commit
45cbd5fd31
|
@ -31,7 +31,7 @@ func (op LogicalOperator) Value() (datatypes.Node_Logical, error) {
|
|||
// LogicalNode is a node type includes a logical expression with other nodes.
|
||||
type LogicalNode struct {
|
||||
Operator LogicalOperator `json:"operator"`
|
||||
Children []Node `json:"children"`
|
||||
Children [2]Node `json:"children"`
|
||||
}
|
||||
|
||||
// ToDataType convert a LogicalNode to datatypes.Node.
|
||||
|
|
|
@ -73,9 +73,7 @@ func Parse(sts string) (n Node, err error) {
|
|||
}
|
||||
|
||||
func (p *parser) parseLogicalNode() (Node, error) {
|
||||
n := &LogicalNode{
|
||||
Children: make([]Node, 0),
|
||||
}
|
||||
n := new(LogicalNode)
|
||||
for {
|
||||
tok, pos, _ := p.scanIgnoreWhitespace()
|
||||
switch tok {
|
||||
|
@ -91,9 +89,30 @@ func (p *parser) parseLogicalNode() (Node, error) {
|
|||
if err != nil {
|
||||
return *n, err
|
||||
}
|
||||
n.Children = append(n.Children, tr)
|
||||
if n.Children[0] == nil {
|
||||
n.Children[0] = tr
|
||||
} else {
|
||||
n.Children[1] = tr
|
||||
}
|
||||
case influxql.AND:
|
||||
n.Operator = LogicalAnd
|
||||
if n.Children[1] == nil {
|
||||
continue
|
||||
}
|
||||
var n1 Node
|
||||
var err error
|
||||
if tokNext := p.peekTok(); tokNext == influxql.LPAREN {
|
||||
n1, err = p.parseLogicalNode()
|
||||
} else {
|
||||
n1, err = p.parseTagRuleNode()
|
||||
}
|
||||
if err != nil {
|
||||
return *n, err
|
||||
}
|
||||
n = &LogicalNode{
|
||||
Children: [2]Node{*n, n1},
|
||||
Operator: LogicalAnd,
|
||||
}
|
||||
case influxql.OR:
|
||||
return *n, &influxdb.Error{
|
||||
Code: influxdb.EInvalid,
|
||||
|
@ -112,7 +131,11 @@ func (p *parser) parseLogicalNode() (Node, error) {
|
|||
Msg: fmt.Sprintf("extra ( seen"),
|
||||
}
|
||||
}
|
||||
n.Children = append(n.Children, n1)
|
||||
if n.Children[0] == nil {
|
||||
n.Children[0] = n1
|
||||
} else {
|
||||
n.Children[1] = n1
|
||||
}
|
||||
case influxql.RPAREN:
|
||||
p.openParen--
|
||||
fallthrough
|
||||
|
@ -123,7 +146,7 @@ func (p *parser) parseLogicalNode() (Node, error) {
|
|||
Msg: fmt.Sprintf("extra ) seen"),
|
||||
}
|
||||
}
|
||||
if len(n.Children) == 1 {
|
||||
if n.Children[1] == nil {
|
||||
return n.Children[0], nil
|
||||
}
|
||||
return *n, nil
|
||||
|
@ -201,3 +224,13 @@ scanRegularTagValue:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// peekRune returns the next rune that would be read by the scanner.
|
||||
func (p *parser) peekTok() influxql.Token {
|
||||
tok, _, _ := p.scanIgnoreWhitespace()
|
||||
if tok != influxql.EOF {
|
||||
p.unscan()
|
||||
}
|
||||
|
||||
return tok
|
||||
}
|
||||
|
|
|
@ -18,10 +18,23 @@ func TestParseNode(t *testing.T) {
|
|||
err error
|
||||
}{
|
||||
{
|
||||
str: ` abc="opq" AND gender="male" AND temp=1123`,
|
||||
node: LogicalNode{Operator: LogicalAnd, Children: []Node{
|
||||
str: `abc=opq`,
|
||||
node: TagRuleNode{Tag: influxdb.Tag{Key: "abc", Value: "opq"}},
|
||||
},
|
||||
{
|
||||
str: `abc=opq and gender="male"`,
|
||||
node: LogicalNode{Operator: LogicalAnd, Children: [2]Node{
|
||||
TagRuleNode{Tag: influxdb.Tag{Key: "abc", Value: "opq"}},
|
||||
TagRuleNode{Tag: influxdb.Tag{Key: "gender", Value: "male"}},
|
||||
}},
|
||||
},
|
||||
{
|
||||
str: ` abc="opq" AND gender="male" AND temp=1123`,
|
||||
node: LogicalNode{Operator: LogicalAnd, Children: [2]Node{
|
||||
LogicalNode{Operator: LogicalAnd, Children: [2]Node{
|
||||
TagRuleNode{Tag: influxdb.Tag{Key: "abc", Value: "opq"}},
|
||||
TagRuleNode{Tag: influxdb.Tag{Key: "gender", Value: "male"}},
|
||||
}},
|
||||
TagRuleNode{Tag: influxdb.Tag{Key: "temp", Value: "1123"}},
|
||||
}},
|
||||
},
|
||||
|
@ -34,16 +47,18 @@ func TestParseNode(t *testing.T) {
|
|||
},
|
||||
{
|
||||
str: ` (t1="v1" and t2="v2") and (t3=v3 and (t4=v4 and t5=v5 and t6=v6))`,
|
||||
node: LogicalNode{Operator: LogicalAnd, Children: []Node{
|
||||
LogicalNode{Operator: LogicalAnd, Children: []Node{
|
||||
node: LogicalNode{Operator: LogicalAnd, Children: [2]Node{
|
||||
LogicalNode{Operator: LogicalAnd, Children: [2]Node{
|
||||
TagRuleNode{Tag: influxdb.Tag{Key: "t1", Value: "v1"}},
|
||||
TagRuleNode{Tag: influxdb.Tag{Key: "t2", Value: "v2"}},
|
||||
}},
|
||||
LogicalNode{Operator: LogicalAnd, Children: []Node{
|
||||
LogicalNode{Operator: LogicalAnd, Children: [2]Node{
|
||||
TagRuleNode{Tag: influxdb.Tag{Key: "t3", Value: "v3"}},
|
||||
LogicalNode{Operator: LogicalAnd, Children: []Node{
|
||||
TagRuleNode{Tag: influxdb.Tag{Key: "t4", Value: "v4"}},
|
||||
TagRuleNode{Tag: influxdb.Tag{Key: "t5", Value: "v5"}},
|
||||
LogicalNode{Operator: LogicalAnd, Children: [2]Node{
|
||||
LogicalNode{Operator: LogicalAnd, Children: [2]Node{
|
||||
TagRuleNode{Tag: influxdb.Tag{Key: "t4", Value: "v4"}},
|
||||
TagRuleNode{Tag: influxdb.Tag{Key: "t5", Value: "v5"}},
|
||||
}},
|
||||
TagRuleNode{Tag: influxdb.Tag{Key: "t6", Value: "v6"}},
|
||||
}},
|
||||
}},
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/influxdata/influxdb"
|
||||
"github.com/influxdata/influxdb/models"
|
||||
"github.com/influxdata/influxdb/storage/reads/datatypes"
|
||||
influxtesting "github.com/influxdata/influxdb/testing"
|
||||
)
|
||||
|
@ -45,11 +46,63 @@ func TestDataTypeConversion(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "measurement tag rule",
|
||||
node: &TagRuleNode{
|
||||
Operator: influxdb.Equal,
|
||||
Tag: influxdb.Tag{
|
||||
Key: "_measurement",
|
||||
Value: "cpu",
|
||||
},
|
||||
},
|
||||
dataType: &datatypes.Node{
|
||||
NodeType: datatypes.NodeTypeComparisonExpression,
|
||||
Value: &datatypes.Node_Comparison_{Comparison: datatypes.ComparisonEqual},
|
||||
Children: []*datatypes.Node{
|
||||
{
|
||||
NodeType: datatypes.NodeTypeTagRef,
|
||||
Value: &datatypes.Node_TagRefValue{TagRefValue: models.MeasurementTagKey},
|
||||
},
|
||||
{
|
||||
NodeType: datatypes.NodeTypeLiteral,
|
||||
Value: &datatypes.Node_StringValue{
|
||||
StringValue: "cpu",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "field tag rule",
|
||||
node: &TagRuleNode{
|
||||
Operator: influxdb.Equal,
|
||||
Tag: influxdb.Tag{
|
||||
Key: "_field",
|
||||
Value: "cpu",
|
||||
},
|
||||
},
|
||||
dataType: &datatypes.Node{
|
||||
NodeType: datatypes.NodeTypeComparisonExpression,
|
||||
Value: &datatypes.Node_Comparison_{Comparison: datatypes.ComparisonEqual},
|
||||
Children: []*datatypes.Node{
|
||||
{
|
||||
NodeType: datatypes.NodeTypeTagRef,
|
||||
Value: &datatypes.Node_TagRefValue{TagRefValue: models.FieldKeyTagKey},
|
||||
},
|
||||
{
|
||||
NodeType: datatypes.NodeTypeLiteral,
|
||||
Value: &datatypes.Node_StringValue{
|
||||
StringValue: "cpu",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "logical",
|
||||
node: &LogicalNode{
|
||||
Operator: LogicalAnd,
|
||||
Children: []Node{
|
||||
Children: [2]Node{
|
||||
&TagRuleNode{
|
||||
Operator: influxdb.Equal,
|
||||
Tag: influxdb.Tag{
|
||||
|
@ -111,10 +164,10 @@ func TestDataTypeConversion(t *testing.T) {
|
|||
name: "conplex logical",
|
||||
node: &LogicalNode{
|
||||
Operator: LogicalAnd,
|
||||
Children: []Node{
|
||||
Children: [2]Node{
|
||||
&LogicalNode{
|
||||
Operator: LogicalAnd,
|
||||
Children: []Node{
|
||||
Children: [2]Node{
|
||||
&TagRuleNode{
|
||||
Operator: influxdb.Equal,
|
||||
Tag: influxdb.Tag{
|
||||
|
|
|
@ -4,12 +4,18 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/influxdata/influxdb"
|
||||
"github.com/influxdata/influxdb/models"
|
||||
"github.com/influxdata/influxdb/storage/reads/datatypes"
|
||||
)
|
||||
|
||||
// TagRuleNode is a node type of a single tag rule.
|
||||
type TagRuleNode influxdb.TagRule
|
||||
|
||||
var specialKey = map[string]string{
|
||||
"_measurement": models.MeasurementTagKey,
|
||||
"_field": models.FieldKeyTagKey,
|
||||
}
|
||||
|
||||
// NodeTypeLiteral convert a TagRuleNode to a nodeTypeLiteral.
|
||||
func NodeTypeLiteral(tr TagRuleNode) *datatypes.Node {
|
||||
switch tr.Operator {
|
||||
|
@ -61,6 +67,9 @@ func (n TagRuleNode) ToDataType() (*datatypes.Node, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if special, ok := specialKey[n.Key]; ok {
|
||||
n.Key = special
|
||||
}
|
||||
return &datatypes.Node{
|
||||
NodeType: datatypes.NodeTypeComparisonExpression,
|
||||
Value: &datatypes.Node_Comparison_{Comparison: compare},
|
||||
|
|
Loading…
Reference in New Issue