diff --git a/expr/parse.go b/expr/parse.go index f4423ad1..c7a8d0a0 100644 --- a/expr/parse.go +++ b/expr/parse.go @@ -611,7 +611,6 @@ func (t *tree) v(depth int) Node { case lex.TokenIdentity: n := NewIdentityNode(&cur) t.Next() // Consume identity - return n case lex.TokenNull: t.Next() diff --git a/lex/lexer.go b/lex/lexer.go index ee2c0930..0120bec4 100644 --- a/lex/lexer.go +++ b/lex/lexer.go @@ -143,7 +143,7 @@ func (l *Lexer) ErrMsg(t Token, msg string) error { // NextToken returns the next token from the input. func (l *Lexer) NextToken() Token { for { - //u.Debugf("token: start=%v pos=%v peek5=%s", l.start, l.pos, l.PeekX(5)) + //debugf("token: start=%v pos=%v peek5=%s", l.start, l.pos, l.PeekX(5)) select { case token := <-l.tokens: return token @@ -2537,9 +2537,10 @@ func LexExpression(l *Lexer) StateFn { l.Emit(TokenUdfExpr) l.ConsumeWord("(") l.Emit(TokenLeftParenthesis) + l.SkipWhiteSpaces() l.Push("LexExpression", l.clauseState()) l.Push("LexParenRight", LexParenRight) - return LexExpression + return LexListOfArgs } l.Emit(TokenExists) return LexExpression diff --git a/rel/parse_filterql_test.go b/rel/parse_filterql_test.go index 2aaeff93..59538321 100644 --- a/rel/parse_filterql_test.go +++ b/rel/parse_filterql_test.go @@ -168,6 +168,19 @@ func parseFilterSelectsTest(t *testing.T, st selsTest) { } } +func TestFilterQLBug234(t *testing.T) { + t.Parallel() + _, err := rel.ParseFilterQL(` + FILTER AND ( + EXISTS(abc), + EXISTS(abcd), -- hello a comment + EXISTS(abcde) + modified < "now-30d" + ) FROM user + `) + assert.Equal(t, nil, err) +} + type foo struct{} func (*foo) Type() value.ValueType { return value.BoolType } diff --git a/vm/vm_test.go b/vm/vm_test.go index 543a9f76..87c5f5c4 100644 --- a/vm/vm_test.go +++ b/vm/vm_test.go @@ -45,22 +45,23 @@ func TestMain(m *testing.M) { var ( t0 = dateparse.MustParse("12/18/2015") - t1 = dateparse.MustParse("12/18/2039") + tfuture = dateparse.MustParse("12/18/2039") tcreated = dateparse.MustParse("12/18/2019") // This is the message context which will be added to all tests below // and be available to the VM runtime for evaluation by using // key's such as "int5" or "user_id" msgContext = datasource.NewContextMap(map[string]interface{}{ - "int5": value.NewIntValue(5), - "str5": value.NewStringValue("5"), - "created": value.NewTimeValue(tcreated), - "bvalt": value.NewBoolValue(true), - "bvalf": value.NewBoolValue(false), - "user_id": value.NewStringValue("abc"), - "urls": value.NewStringsValue([]string{"abc", "123"}), - "hits": value.NewMapIntValue(map[string]int64{"google.com": 5, "bing.com": 1}), - "email": value.NewStringValue("bob@bob.com"), - "mt": value.NewMapTimeValue(map[string]time.Time{"event0": t0, "event1": t1}), + "int5": value.NewIntValue(5), + "str5": value.NewStringValue("5"), + "created": value.NewTimeValue(tcreated), + "createdfuture": value.NewTimeValue(tfuture), + "bvalt": value.NewBoolValue(true), + "bvalf": value.NewBoolValue(false), + "user_id": value.NewStringValue("abc"), + "urls": value.NewStringsValue([]string{"abc", "123"}), + "hits": value.NewMapIntValue(map[string]int64{"google.com": 5, "bing.com": 1}), + "email": value.NewStringValue("bob@bob.com"), + "mt": value.NewMapTimeValue(map[string]time.Time{"event0": t0, "event1": tfuture}), }, true) vmTestsx = []vmTest{ vmt(`mt.event1 > now()`, true, noError), @@ -69,7 +70,7 @@ var ( vmTests = []vmTest{ // Date math - vmt(`created > "now-1M"`, true, noError), + vmt(`createdfuture > "now-1M"`, true, noError), vmt(`now() > todate("01/01/2014")`, true, noError), vmt(`todate("now+3d") > now()`, true, noError), vmt(`created < 2032220220175`, true, noError), // Really not sure i want to support this?