Skip to content
Snippets Groups Projects
Commit 86e68a0b authored by Danis Kirasirov's avatar Danis Kirasirov
Browse files

fix expressions "not in" and "object.field"

parent b9a8d9da
No related branches found
No related tags found
No related merge requests found
...@@ -43,6 +43,7 @@ func convertToMongo(ctx context.Context, tree *parser.Tree, env map[string]inter ...@@ -43,6 +43,7 @@ func convertToMongo(ctx context.Context, tree *parser.Tree, env map[string]inter
env[EnvContextKey] = ctx env[EnvContextKey] = ctx
config := GetDefaultConfig(env) config := GetDefaultConfig(env)
config.Visitors = append(config.Visitors, notinPatcher{})
for _, op := range ops { for _, op := range ops {
op(config) op(config)
...@@ -212,6 +213,8 @@ func (c *compiler) UnaryNode(node *ast.UnaryNode) interface{} { ...@@ -212,6 +213,8 @@ func (c *compiler) UnaryNode(node *ast.UnaryNode) interface{} {
case "!", "not": case "!", "not":
return bson.M{"$not": op} return bson.M{"$not": op}
case "":
return op
default: default:
panic(fmt.Sprintf("unknown operator (%v)", node.Operator)) panic(fmt.Sprintf("unknown operator (%v)", node.Operator))
} }
...@@ -329,7 +332,7 @@ func (c *compiler) ChainNode(node *ast.ChainNode) string { ...@@ -329,7 +332,7 @@ func (c *compiler) ChainNode(node *ast.ChainNode) string {
func (c *compiler) MemberNode(node *ast.MemberNode) string { func (c *compiler) MemberNode(node *ast.MemberNode) string {
v := c.compile(node.Node) v := c.compile(node.Node)
if val, ok := v.(string); ok { if val, ok := v.(string); ok {
return fmt.Sprintf("%s.%s", val, node.Property) return fmt.Sprintf("%s.%s", val, c.compile(node.Property))
} }
panic(fmt.Sprintf("unsupported property for %v", ast.Dump(node.Node))) panic(fmt.Sprintf("unsupported property for %v", ast.Dump(node.Node)))
} }
...@@ -639,3 +642,23 @@ func (c *compiler) PairNode(node *ast.PairNode) interface{} { ...@@ -639,3 +642,23 @@ func (c *compiler) PairNode(node *ast.PairNode) interface{} {
//c.compile(node.Key) //c.compile(node.Key)
//c.compile(node.Value) //c.compile(node.Value)
} }
type notinPatcher struct{}
func (t notinPatcher) Visit(node *ast.Node) {
nodeNot, ok := (*node).(*ast.UnaryNode)
if !ok || nodeNot.Operator != "not" {
return
}
inNode, ok := nodeNot.Node.(*ast.BinaryNode)
if !ok || inNode.Operator != "in" {
return
}
nodeNot.Operator = ""
ast.Patch(node, nodeNot)
inNode.Operator = "not in"
ast.Patch(&nodeNot.Node, inNode)
}
\ No newline at end of file
...@@ -30,6 +30,9 @@ func TestConvertToMongo(t *testing.T) { ...@@ -30,6 +30,9 @@ func TestConvertToMongo(t *testing.T) {
{"equal", "s == 3", nil, bson.M{"s": 3}, false}, {"equal", "s == 3", nil, bson.M{"s": 3}, false},
{"in array", "s in [1,2,3]", nil, bson.M{"s": bson.M{"$in": []interface{}{1, 2, 3}}}, false}, {"in array", "s in [1,2,3]", nil, bson.M{"s": bson.M{"$in": []interface{}{1, 2, 3}}}, false},
{"not in array", "s not in [1,2,3]", nil, bson.M{"s": bson.M{"$nin": []interface{}{1, 2, 3}}}, false}, {"not in array", "s not in [1,2,3]", nil, bson.M{"s": bson.M{"$nin": []interface{}{1, 2, 3}}}, false},
{"field#1", "s.test > 3", nil, bson.M{"s.test": bson.M{"$gt": 3}}, false},
{"field#2", "s['test'] > 3", nil, bson.M{"s.test": bson.M{"$gt": 3}}, false},
{"field#3", "s[test] > 3", nil, bson.M{"s.test": bson.M{"$gt": 3}}, false},
{"contains", "s contains 'some'", nil, bson.M{"s": bson.M{"$regex": "some"}}, false}, {"contains", "s contains 'some'", nil, bson.M{"s": bson.M{"$regex": "some"}}, false},
{"contains with . + () $ {} ^", "value contains 'something with . + () $ {} ^'", nil, bson.M{"value": bson.M{"$regex": "something with \\. \\+ \\(\\) \\$ \\{\\} \\^"}}, false}, {"contains with . + () $ {} ^", "value contains 'something with . + () $ {} ^'", nil, bson.M{"value": bson.M{"$regex": "something with \\. \\+ \\(\\) \\$ \\{\\} \\^"}}, false},
{"startsWith", "s startsWith 'some'", nil, bson.M{"s": bson.M{"$regex": "^some.*"}}, false}, {"startsWith", "s startsWith 'some'", nil, bson.M{"s": bson.M{"$regex": "^some.*"}}, false},
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment