@@ -13,10 +13,11 @@ import (
1313 u "github.com/araddon/gou"
1414 "github.com/mb0/glob"
1515
16+ "slices"
17+
1618 "github.com/lytics/qlbridge/expr"
1719 "github.com/lytics/qlbridge/lex"
1820 "github.com/lytics/qlbridge/value"
19- "slices"
2021)
2122
2223var (
@@ -42,7 +43,8 @@ type EvalBaseContext struct {
4243// evaluated against. It may be a simple reader of message/data or any
4344// object whhich implements EvalContext.
4445func Eval (ctx expr.EvalContext , arg expr.Node ) (value.Value , bool ) {
45- return evalDepth (ctx , arg , 0 , make ([]string , 0 ))
46+ // Initialize a visited includes stack of 10
47+ return evalDepth (ctx , arg , 0 , make ([]string , 0 , 10 ))
4648}
4749
4850// creates a new Value with a nil group and given value.
@@ -52,12 +54,10 @@ func numberNodeToValue(t *expr.NumberNode) (value.Value, bool) {
5254 } else if t .IsFloat {
5355 fv , ok := value .StringToFloat64 (t .Text )
5456 if ! ok {
55- u .Debugf ("Could not perform numeric conversion for %q" , t .Text )
5657 return value .NilValueVal , false
5758 }
5859 return value .NewNumberValue (fv ), true
5960 }
60- u .Debugf ("Could not find numeric conversion for %#v" , t )
6161 return value .NilValueVal , false
6262}
6363
@@ -66,7 +66,7 @@ func numberNodeToValue(t *expr.NumberNode) (value.Value, bool) {
6666// InlineIncludes alternative in expr pkg which actually re-writes the expression
6767// to remove includes and embed the expressions they refer to as part of this expression.
6868func ResolveIncludes (ctx expr.Includer , arg expr.Node ) error {
69- return resolveIncludesDepth (ctx , arg , 0 , make ([]string , 0 ))
69+ return resolveIncludesDepth (ctx , arg , 0 , make ([]string , 0 , 10 ))
7070}
7171func resolveIncludesDepth (ctx expr.Includer , arg expr.Node , depth int , visitedIncludes []string ) error {
7272 if depth > MaxDepth {
@@ -137,17 +137,17 @@ func evalDepth(ctx expr.EvalContext, arg expr.Node, depth int, visitedIncludes [
137137 case * expr.NumberNode :
138138 return numberNodeToValue (argVal )
139139 case * expr.BinaryNode :
140- return walkBinary (ctx , argVal , depth , visitedIncludes )
140+ return evalBinary (ctx , argVal , depth , visitedIncludes )
141141 case * expr.BooleanNode :
142142 return walkBoolean (ctx , argVal , depth , visitedIncludes )
143143 case * expr.UnaryNode :
144- return walkUnary (ctx , argVal )
144+ return walkUnary (ctx , argVal , depth , visitedIncludes )
145145 case * expr.TriNode :
146- return walkTernary (ctx , argVal )
146+ return walkTernary (ctx , argVal , depth , visitedIncludes )
147147 case * expr.ArrayNode :
148- return walkArray (ctx , argVal )
148+ return walkArray (ctx , argVal , depth , visitedIncludes )
149149 case * expr.FuncNode :
150- return walkFunc (ctx , argVal )
150+ return walkFunc (ctx , argVal , depth , visitedIncludes )
151151 case * expr.IdentityNode :
152152 return walkIdentity (ctx , argVal )
153153 case * expr.StringNode :
@@ -196,11 +196,9 @@ func resolveInclude(ctx expr.Includer, inc *expr.IncludeNode, depth int, visited
196196 if err == expr .ErrNoIncluder {
197197 return err
198198 }
199- u .Debugf ("Could not find include for filter:%s err=%v" , inc .String (), err )
200199 return err
201200 }
202201 if incExpr == nil {
203- u .Debugf ("Includer %T returned a nil filter statement!" , inc )
204202 return expr .ErrIncludeNotFound
205203 }
206204 if err = resolveIncludesDepth (ctx , incExpr , depth + 1 , visitedIncludes ); err != nil {
@@ -355,13 +353,6 @@ func walkBoolean(ctx expr.EvalContext, n *expr.BooleanNode, depth int, visitedIn
355353// x OR y
356354// x > y
357355// x < =
358- func walkBinary (ctx expr.EvalContext , node * expr.BinaryNode , depth int , visitedIncludes []string ) (value.Value , bool ) {
359- val , ok := evalBinary (ctx , node , depth , visitedIncludes )
360- if ! ok {
361- return nil , ok
362- }
363- return val , ok
364- }
365356func evalBinary (ctx expr.EvalContext , node * expr.BinaryNode , depth int , visitedIncludes []string ) (value.Value , bool ) {
366357 ar , aok := evalDepth (ctx , node .Args [0 ], depth + 1 , visitedIncludes )
367358 br , bok := evalDepth (ctx , node .Args [1 ], depth + 1 , visitedIncludes )
@@ -444,7 +435,6 @@ func evalBinary(ctx expr.EvalContext, node *expr.BinaryNode, depth int, visitedI
444435 }
445436 return value .NewBoolValue (false ), true
446437 default :
447- u .Debugf ("unsupported op for SliceValue op:%v rhT:%T" , node .Operator , br )
448438 return nil , false
449439 }
450440 case nil , value.NilValue :
@@ -477,7 +467,6 @@ func evalBinary(ctx expr.EvalContext, node *expr.BinaryNode, depth int, visitedI
477467 return value .BoolValueTrue , true
478468 }
479469 default :
480- u .Debugf ("Could not coerce to number: T:%T v:%v" , val , val )
481470 }
482471 }
483472 return value .BoolValueFalse , true
@@ -548,7 +537,6 @@ func evalBinary(ctx expr.EvalContext, node *expr.BinaryNode, depth int, visitedI
548537 }
549538 return value .NewBoolValue (true ), true
550539 default :
551- u .Debugf ("unsupported op: %v" , node .Operator )
552540 return nil , false
553541 }
554542 case value.Slice :
@@ -576,7 +564,6 @@ func evalBinary(ctx expr.EvalContext, node *expr.BinaryNode, depth int, visitedI
576564 }
577565 return value .NewBoolValue (false ), true
578566 default :
579- u .Debugf ("unsupported op for SliceValue op:%v rhT:%T" , node .Operator , br )
580567 return nil , false
581568 }
582569 case value.BoolValue :
@@ -587,7 +574,6 @@ func evalBinary(ctx expr.EvalContext, node *expr.BinaryNode, depth int, visitedI
587574 case lex .TokenNE :
588575 return value .NewBoolValue (value .BoolStringVal (at .Val ()) != bt .Val ()), true
589576 default :
590- u .Debugf ("unsupported op: %v" , node .Operator )
591577 }
592578 }
593579 switch node .Operator .T {
@@ -596,7 +582,6 @@ func evalBinary(ctx expr.EvalContext, node *expr.BinaryNode, depth int, visitedI
596582 return value .NewBoolValue (false ), true
597583 }
598584 // Should we evaluate strings that are non-nil to be = true?
599- u .Debugf ("not handled: boolean %v %T=%v expr: %s" , node .Operator , at .Value (), at .Val (), node .String ())
600585 return nil , false
601586 case value.Map :
602587 switch node .Operator .T {
@@ -607,7 +592,6 @@ func evalBinary(ctx expr.EvalContext, node *expr.BinaryNode, depth int, visitedI
607592 }
608593 return value .NewBoolValue (false ), true
609594 default :
610- u .Debugf ("unsupported op for Map op:%v rhT:%T" , node .Operator , br )
611595 return nil , false
612596 }
613597
@@ -786,16 +770,17 @@ func evalBinary(ctx expr.EvalContext, node *expr.BinaryNode, depth int, visitedI
786770 return operateTime (node .Operator .T , lht , rht )
787771
788772 case value.Map :
789- rhvals := make ( []string , 0 )
773+ var rhvals []string
790774 switch bv := br .(type ) {
791775 case value.StringsValue :
792776 rhvals = bv .Val ()
793777 case value.Slice :
794- for _ , arg := range bv .SliceValue () {
795- rhvals = append (rhvals , arg .ToString ())
778+ sliceValue := bv .SliceValue ()
779+ rhvals := make ([]string , len (sliceValue ))
780+ for i , arg := range sliceValue {
781+ rhvals [i ] = arg .ToString ()
796782 }
797783 default :
798- u .Debugf ("un-handled? %T" , bv )
799784 return nil , false
800785 }
801786
@@ -836,7 +821,6 @@ func evalBinary(ctx expr.EvalContext, node *expr.BinaryNode, depth int, visitedI
836821 return nil , false
837822 }
838823 default :
839- u .Debugf ("Unknown op? %T %T %v" , ar , at , ar )
840824 return value .NewErrorValue (fmt .Errorf ("unsupported left side value: %T in %s" , at , node )), false
841825 }
842826
@@ -857,17 +841,16 @@ func walkIdentity(ctx expr.EvalContext, node *expr.IdentityNode) (value.Value, b
857841 return ctx .Get (node .Text )
858842}
859843
860- func walkUnary (ctx expr.EvalContext , node * expr.UnaryNode ) (value.Value , bool ) {
844+ func walkUnary (ctx expr.EvalContext , node * expr.UnaryNode , depth int , visitedIncludes [] string ) (value.Value , bool ) {
861845
862- a , ok := Eval (ctx , node .Arg )
846+ a , ok := evalDepth (ctx , node .Arg , depth , visitedIncludes )
863847 if ! ok {
864848 switch node .Operator .T {
865849 case lex .TokenExists :
866850 return value .NewBoolValue (false ), true
867851 case lex .TokenNegate :
868852 return value .NewBoolValue (false ), false
869853 }
870- u .Debugf ("unary could not evaluate for[ %s ] and %#v" , node .String (), node )
871854 return a , false
872855 }
873856
@@ -879,7 +862,7 @@ func walkUnary(ctx expr.EvalContext, node *expr.UnaryNode) (value.Value, bool) {
879862 case nil , value.NilValue :
880863 return value .NewBoolValue (false ), false
881864 default :
882- u .LogThrottle (u .WARN , 5 , "unary type not implemented. Unknonwn node type: %T:%v node=%s" , argVal , argVal , node .String ())
865+ // u.LogThrottle(u.WARN, 5, "unary type not implemented. Unknonwn node type: %T:%v node=%s", argVal, argVal, node.String())
883866 return value .NewNilValue (), false
884867 }
885868 case lex .TokenMinus :
@@ -905,18 +888,18 @@ func walkUnary(ctx expr.EvalContext, node *expr.UnaryNode) (value.Value, bool) {
905888// walkTernary ternary evaluator
906889//
907890// A BETWEEN B AND C
908- func walkTernary (ctx expr.EvalContext , node * expr.TriNode ) (value.Value , bool ) {
891+ func walkTernary (ctx expr.EvalContext , node * expr.TriNode , depth int , visitedIncludes [] string ) (value.Value , bool ) {
909892
910- a , aok := Eval (ctx , node .Args [0 ])
911- b , bok := Eval (ctx , node .Args [1 ])
912- c , cok := Eval (ctx , node .Args [2 ])
913- if ! aok {
893+ a , aok := evalDepth (ctx , node .Args [0 ], depth , visitedIncludes )
894+ if a == nil || ! aok {
914895 return nil , false
915896 }
916- if ! bok || ! cok {
897+ b , bok := evalDepth (ctx , node .Args [1 ], depth , visitedIncludes )
898+ if b == nil || ! bok {
917899 return nil , false
918900 }
919- if a == nil || b == nil || c == nil {
901+ c , cok := evalDepth (ctx , node .Args [2 ], depth , visitedIncludes )
902+ if c == nil || ! cok {
920903 return nil , false
921904 }
922905 switch node .Operator .T {
@@ -944,7 +927,6 @@ func walkTernary(ctx expr.EvalContext, node *expr.TriNode) (value.Value, bool) {
944927 }
945928 return value .NewBoolValue (false ), true
946929 case value.NumberValue :
947-
948930 av := at .Val ()
949931 bv , ok := value .ValueToFloat64 (b )
950932 if ! ok {
@@ -966,7 +948,6 @@ func walkTernary(ctx expr.EvalContext, node *expr.TriNode) (value.Value, bool) {
966948 return value .NewBoolValue (false ), true
967949
968950 case value.TimeValue :
969-
970951 av := at .Val ()
971952 bv , ok := value .ValueToTime (b )
972953 if ! ok {
@@ -1000,12 +981,12 @@ func walkTernary(ctx expr.EvalContext, node *expr.TriNode) (value.Value, bool) {
1000981// walkArray Array evaluator: evaluate multiple values into an array
1001982//
1002983// (b,c,d)
1003- func walkArray (ctx expr.EvalContext , node * expr.ArrayNode ) (value.Value , bool ) {
984+ func walkArray (ctx expr.EvalContext , node * expr.ArrayNode , depth int , visitedIncludes [] string ) (value.Value , bool ) {
1004985
1005986 vals := make ([]value.Value , len (node .Args ))
1006987
1007988 for i := range node .Args {
1008- v , _ := Eval (ctx , node .Args [i ])
989+ v , _ := evalDepth (ctx , node .Args [i ], depth , visitedIncludes )
1009990 vals [i ] = v
1010991 }
1011992
@@ -1014,20 +995,20 @@ func walkArray(ctx expr.EvalContext, node *expr.ArrayNode) (value.Value, bool) {
1014995}
1015996
1016997// walkFunc evaluates a function
1017- func walkFunc (ctx expr.EvalContext , node * expr.FuncNode ) (value.Value , bool ) {
998+ func walkFunc (ctx expr.EvalContext , node * expr.FuncNode , depth int , visitedIncludes [] string ) (value.Value , bool ) {
1018999
10191000 if node .F .CustomFunc == nil {
10201001 return nil , false
10211002 }
10221003 if node .Eval == nil {
1023- u .LogThrottle (u .WARN , 10 , "No Eval() for %s" , node .Name )
1004+ // u.LogThrottle(u.WARN, 10, "No Eval() for %s", node.Name)
10241005 return nil , false
10251006 }
10261007
10271008 args := make ([]value.Value , len (node .Args ))
10281009
10291010 for i , a := range node .Args {
1030- v , ok := Eval (ctx , a )
1011+ v , ok := evalDepth (ctx , a , depth , visitedIncludes )
10311012 if ! ok {
10321013 v = value .NewNilValue ()
10331014 }
@@ -1186,16 +1167,34 @@ func operateTime(op lex.TokenType, lht, rht time.Time) (value.BoolValue, bool) {
11861167 }
11871168 return value .BoolValueFalse , true
11881169 default :
1189- u .Debugf ("unhandled date op %v" , op )
11901170 }
11911171 return value .BoolValueFalse , false
11921172}
11931173
1174+ var globber * glob.Globber
1175+
1176+ func init () {
1177+ defaultConfig := glob .Default ()
1178+ defaultConfig .Star = '%'
1179+ var err error
1180+ globber , err = glob .New (defaultConfig )
1181+ if err != nil {
1182+ u .Errorf ("failed to create optimized globber: %v" , err )
1183+ }
1184+ }
1185+
11941186// LikeCompare takes two strings and evaluates them for like equality
11951187func LikeCompare (a , b string ) (value.BoolValue , bool ) {
11961188 // Do we want to always do this replacement? Or do this at parse time or config?
1197- b = strings .Replace (b , "%" , "*" , - 1 )
1198- match , err := glob .Match (b , a )
1189+ //
1190+ var match bool
1191+ var err error
1192+ if globber == nil {
1193+ b = strings .Replace (b , "%" , "*" , - 1 )
1194+ match , err = glob .Match (b , a )
1195+ } else {
1196+ match , err = globber .Match (b , a )
1197+ }
11991198 if err != nil {
12001199 return value .BoolValueFalse , false
12011200 }
0 commit comments