From 2027409b0d8875a48fd0017264ba03f5535733ec Mon Sep 17 00:00:00 2001 From: Vivek Patel Date: Wed, 21 Dec 2022 14:32:05 +0530 Subject: [PATCH] Support ql between/not between operator For number type, IE (Field1 BETWEEN X X) or (Field1 NOT BETWEEN X X) --- server/pkg/ql/ast_nodes.go | 21 ++++++++++++++++++--- server/pkg/ql/parser_nodes.go | 8 ++++++++ server/pkg/ql/token_consumers.go | 2 +- server/store/adapters/rdbms/ql/ref.go | 17 +++++++++++++++-- 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/server/pkg/ql/ast_nodes.go b/server/pkg/ql/ast_nodes.go index 417754c70..4c191332a 100644 --- a/server/pkg/ql/ast_nodes.go +++ b/server/pkg/ql/ast_nodes.go @@ -319,15 +319,30 @@ func (nn parserNodes) ToAST() (out *ASTNode) { // Have the op consume what it needs. arg := auxArgs[bestOpIx] if !isUnary(arg.Ref) { - arg.Args = append(arg.Args, auxArgs[bestOpIx-1], auxArgs[bestOpIx+1]) + for i, auxArg := range auxArgs { + if isOperator(auxArg.Ref) { + break + } + + if i == bestOpIx { + continue + } + + arg.Args = append(arg.Args, auxArg) + } + // this is not needed anymore so we can remove it arg.pMeta = nil // Remove the consumed bits and replace it with the new bit aux := auxArgs[0 : bestOpIx-1] aux = append(aux, arg) - // +1 for right side, +1 because the left index is inclusive - aux = append(aux, auxArgs[bestOpIx+2:]...) + // +X for right side, +1 because the left index is inclusive + skip := 2 + if len(arg.Args) > 2 { + skip = len(arg.Args) + } + aux = append(aux, auxArgs[bestOpIx+skip:]...) auxArgs = aux } else { arg.Args = append(arg.Args, auxArgs[bestOpIx+1]) diff --git a/server/pkg/ql/parser_nodes.go b/server/pkg/ql/parser_nodes.go index d5574bc32..efe4fc3ca 100644 --- a/server/pkg/ql/parser_nodes.go +++ b/server/pkg/ql/parser_nodes.go @@ -95,6 +95,10 @@ var ( // str comp. `LIKE`: {name: `like`, weight: 40}, `NOT LIKE`: {name: `nlike`, weight: 40}, + + // range comp. + `BETWEEN`: {name: `between`, weight: 40}, + `NOT BETWEEN`: {name: `nbetween`, weight: 40}, } ) @@ -102,6 +106,10 @@ func isUnary(s string) bool { return s == "!" || s == "not" } +func isOperator(s string) bool { + return s == "and" || s == "or" || s == "xor" +} + func getOp(op string) *opDef { o, ok := ops[strings.ToUpper(op)] if !ok { diff --git a/server/pkg/ql/token_consumers.go b/server/pkg/ql/token_consumers.go index 7cb09d3fc..c1a041d00 100644 --- a/server/pkg/ql/token_consumers.go +++ b/server/pkg/ql/token_consumers.go @@ -89,7 +89,7 @@ func (TokenConsumerIdent) Consume(s RuneReader) Token { return Token{code: LNULL} case "TRUE", "FALSE": return Token{code: LBOOL, literal: lit} - case "IS", "LIKE", "NOT", "AND", "OR", "XOR", "IN": + case "IS", "LIKE", "NOT", "AND", "OR", "XOR", "IN", "BETWEEN": return Token{code: OPERATOR, literal: lit} case "DESC", "ASC", "INTERVAL": return Token{code: KEYWORD, literal: lit} diff --git a/server/store/adapters/rdbms/ql/ref.go b/server/store/adapters/rdbms/ql/ref.go index 30368f0a2..9843c66b3 100644 --- a/server/store/adapters/rdbms/ql/ref.go +++ b/server/store/adapters/rdbms/ql/ref.go @@ -13,8 +13,9 @@ type ( ExprHandlerMap map[string]*ExprHandler ExprHandler struct { - Handler func(...exp.Expression) exp.Expression - HandlerE func(...exp.Expression) (exp.Expression, error) + Handler func(...exp.Expression) exp.Expression + HandlerE func(...exp.Expression) (exp.Expression, error) + RangeHandler func(exp.Expression, exp.RangeVal) exp.Expression } ) @@ -181,6 +182,18 @@ var ( }, }, + // range operation + "between": { + Handler: func(args ...exp.Expression) exp.Expression { + return exp.NewRangeExpression(exp.BetweenOp, args[0], exp.NewRangeVal(args[1], args[2])) + }, + }, + "nbetween": { + Handler: func(args ...exp.Expression) exp.Expression { + return exp.NewRangeExpression(exp.NotBetweenOp, args[0], exp.NewRangeVal(args[1], args[2])) + }, + }, + "is": { Handler: func(args ...exp.Expression) exp.Expression { return exp.NewBooleanExpression(exp.IsOp, args[0], args[1])