Skip to content

Commit 6bc0c09

Browse files
author
AJ Roetker
committed
Reduce expr complexity for passing includer
1 parent e815d97 commit 6bc0c09

File tree

3 files changed

+54
-83
lines changed

3 files changed

+54
-83
lines changed

expr/node.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,6 @@ type (
143143
Get() (bool, bool, error)
144144
Set(bool, bool)
145145
}
146-
IncludeCacheContextV2 interface {
147-
GetOrSet(key string, fn func() (bool, error)) (bool, error)
148-
}
149146
// ContextReader is a key-value interface to read the context of message/row
150147
// using a Get("key") interface. Used by vm to evaluate messages
151148
ContextReader interface {

vm/filterqlvm.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,29 +67,29 @@ func EvalFilterSelect(sel *rel.FilterSelect, writeContext expr.ContextWriter, re
6767
// Matches executes a FilterQL statement against an evaluation context
6868
// returning true if the context matches.
6969
func MatchesInc(inc expr.Includer, cr expr.EvalContext, stmt *rel.FilterStatement) (bool, bool) {
70-
return matchesExpr(filterql{cr, inc}, stmt.Filter)
70+
return matchesExpr(cr, inc, stmt.Filter)
7171
}
7272

7373
// Matches executes a FilterQL statement against an evaluation context
7474
// returning true if the context matches.
7575
func Matches(cr expr.EvalContext, stmt *rel.FilterStatement) (bool, bool) {
76-
return matchesExpr(cr, stmt.Filter)
76+
return matchesExpr(cr, nil, stmt.Filter)
7777
}
7878

7979
// MatchesExpr executes a expr.Node expression against an evaluation context
8080
// returning true if the context matches.
8181
func MatchesExpr(cr expr.EvalContext, node expr.Node) (bool, bool) {
82-
return matchesExpr(cr, node)
82+
return matchesExpr(cr, nil, node)
8383
}
8484

85-
func matchesExpr(cr expr.EvalContext, n expr.Node) (bool, bool) {
85+
func matchesExpr(cr expr.EvalContext, includer expr.Includer, n expr.Node) (bool, bool) {
8686
switch exp := n.(type) {
8787
case *expr.IdentityNode:
8888
if exp.Text == "*" || exp.Text == "match_all" {
8989
return true, true
9090
}
9191
}
92-
val, ok := Eval(cr, n)
92+
val, ok := EvalInc(includer, cr, n)
9393
if !ok || val == nil {
9494
return false, ok
9595
}

vm/vm.go

Lines changed: 49 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,13 @@ type EvalBaseContext struct {
4242
// @ctx is the evaluation context ie the variables/values which the expression will be
4343
// evaluated against. It may be a simple reader of message/data or any
4444
// object whhich implements EvalContext.
45-
func Eval(ctx expr.EvalContext, arg expr.Node) (value.Value, bool) {
45+
func Eval(eCtx expr.EvalContext, arg expr.Node) (value.Value, bool) {
4646
// Initialize a visited includes stack of 10
47-
return evalDepth(ctx, arg, 0, make([]string, 0, 10))
47+
return evalDepth(eCtx, nil, arg, 0, make([]string, 0, 10))
48+
}
49+
func EvalInc(includer expr.Includer, eCtx expr.EvalContext, arg expr.Node) (value.Value, bool) {
50+
// Initialize a visited includes stack of 10
51+
return evalDepth(eCtx, includer, arg, 0, make([]string, 0, 10))
4852
}
4953

5054
// creates a new Value with a nil group and given value.
@@ -117,8 +121,8 @@ func resolveIncludesDepth(ctx expr.Includer, arg expr.Node, depth int, visitedIn
117121
return nil
118122
}
119123

120-
func evalBool(ctx expr.EvalContext, arg expr.Node, depth int, visitedIncludes []string) (bool, bool) {
121-
val, ok := evalDepth(ctx, arg, depth, visitedIncludes)
124+
func evalBool(ctx expr.EvalContext, includer expr.Includer, arg expr.Node, depth int, visitedIncludes []string) (bool, bool) {
125+
val, ok := evalDepth(ctx, includer, arg, depth, visitedIncludes)
122126
if !ok || val == nil {
123127
return false, false
124128
}
@@ -128,7 +132,7 @@ func evalBool(ctx expr.EvalContext, arg expr.Node, depth int, visitedIncludes []
128132
return false, false
129133
}
130134

131-
func evalDepth(ctx expr.EvalContext, arg expr.Node, depth int, visitedIncludes []string) (value.Value, bool) {
135+
func evalDepth(ctx expr.EvalContext, includer expr.Includer, arg expr.Node, depth int, visitedIncludes []string) (value.Value, bool) {
132136
if depth > MaxDepth {
133137
return nil, false
134138
}
@@ -137,17 +141,17 @@ func evalDepth(ctx expr.EvalContext, arg expr.Node, depth int, visitedIncludes [
137141
case *expr.NumberNode:
138142
return numberNodeToValue(argVal)
139143
case *expr.BinaryNode:
140-
return evalBinary(ctx, argVal, depth, visitedIncludes)
144+
return evalBinary(ctx, includer, argVal, depth, visitedIncludes)
141145
case *expr.BooleanNode:
142-
return walkBoolean(ctx, argVal, depth, visitedIncludes)
146+
return walkBoolean(ctx, includer, argVal, depth, visitedIncludes)
143147
case *expr.UnaryNode:
144-
return walkUnary(ctx, argVal, depth, visitedIncludes)
148+
return walkUnary(ctx, includer, argVal, depth, visitedIncludes)
145149
case *expr.TriNode:
146-
return walkTernary(ctx, argVal, depth, visitedIncludes)
150+
return walkTernary(ctx, includer, argVal, depth, visitedIncludes)
147151
case *expr.ArrayNode:
148-
return walkArray(ctx, argVal, depth, visitedIncludes)
152+
return walkArray(ctx, includer, argVal, depth, visitedIncludes)
149153
case *expr.FuncNode:
150-
return walkFunc(ctx, argVal, depth, visitedIncludes)
154+
return walkFunc(ctx, includer, argVal, depth, visitedIncludes)
151155
case *expr.IdentityNode:
152156
return walkIdentity(ctx, argVal)
153157
case *expr.StringNode:
@@ -158,7 +162,7 @@ func evalDepth(ctx expr.EvalContext, arg expr.Node, depth int, visitedIncludes [
158162
// WHERE (`users.user_id` != NULL)
159163
return value.NewNilValue(), true
160164
case *expr.IncludeNode:
161-
return walkInclude(ctx, argVal, depth+1, visitedIncludes)
165+
return walkInclude(ctx, includer, argVal, depth+1, visitedIncludes)
162166
case *expr.ValueNode:
163167
if argVal.Value == nil {
164168
return nil, false
@@ -210,49 +214,10 @@ func resolveInclude(ctx expr.Includer, inc *expr.IncludeNode, depth int, visited
210214

211215
var errFailedInclusion = errors.New("failed inclusion")
212216

213-
func walkInclude(ctx expr.EvalContext, inc *expr.IncludeNode, depth int, visitedIncludes []string) (value.Value, bool) {
217+
func walkInclude(ctx expr.EvalContext, includer expr.Includer, inc *expr.IncludeNode, depth int, visitedIncludes []string) (value.Value, bool) {
214218
var matches, ok bool
215219
var err error
216220
var cachedValue expr.CachedValue
217-
if cacheCtx, hasCacheCtx := ctx.(expr.IncludeCacheContextV2); hasCacheCtx {
218-
matches, err := cacheCtx.GetOrSet(inc.Identity.Text, func() (bool, error) {
219-
if inc.ExprNode == nil {
220-
incCtx, ok := ctx.(expr.EvalIncludeContext)
221-
if !ok {
222-
return false, fmt.Errorf("no Includer context? %T stack:%v", ctx, u.PrettyStack(14))
223-
}
224-
if err := resolveInclude(incCtx, inc, depth, visitedIncludes); err != nil {
225-
return false, fmt.Errorf("could not resolve include %w", err)
226-
}
227-
}
228-
229-
switch exp := inc.ExprNode.(type) {
230-
case *expr.IdentityNode:
231-
if exp.Text == "*" || exp.Text == "match_all" {
232-
return true, nil
233-
}
234-
}
235-
236-
matches, ok = evalBool(ctx, inc.ExprNode, depth+1, visitedIncludes)
237-
if !ok {
238-
return matches, errFailedInclusion
239-
}
240-
return matches, nil
241-
})
242-
if errors.Is(err, errFailedInclusion) {
243-
if inc.Negated() {
244-
return value.NewBoolValue(true), true
245-
}
246-
return nil, false
247-
} else if err != nil {
248-
u.Errorf("failed to get or set include in cache: %v", err)
249-
return nil, false
250-
}
251-
if inc.Negated() {
252-
return value.NewBoolValue(!matches), true
253-
}
254-
return value.NewBoolValue(matches), true
255-
}
256221
if cacheCtx, hasCacheCtx := ctx.(expr.IncludeCacheContext); hasCacheCtx {
257222
var hasCachedValue bool
258223
cachedValue, hasCachedValue = cacheCtx.GetCachedValue(inc.Identity.Text)
@@ -264,24 +229,33 @@ func walkInclude(ctx expr.EvalContext, inc *expr.IncludeNode, depth int, visited
264229
}
265230
if err != nil || cachedValue == nil {
266231
if inc.ExprNode == nil {
267-
incCtx, ok := ctx.(expr.EvalIncludeContext)
268-
if !ok {
269-
u.Errorf("No Includer context? %T stack:%v", ctx, u.PrettyStack(14))
270-
return nil, false
271-
}
272-
if err := resolveInclude(incCtx, inc, depth, visitedIncludes); err != nil {
273-
return nil, false
232+
if includer != nil {
233+
if err := resolveInclude(includer, inc, depth, visitedIncludes); err != nil {
234+
return nil, false
235+
}
236+
} else {
237+
incCtx, ok := ctx.(expr.EvalIncludeContext)
238+
if !ok {
239+
u.Errorf("No Includer context? %T stack:%v", ctx, u.PrettyStack(14))
240+
return nil, false
241+
}
242+
if err := resolveInclude(incCtx, inc, depth, visitedIncludes); err != nil {
243+
return nil, false
244+
}
274245
}
275246
}
276247

277248
switch exp := inc.ExprNode.(type) {
278249
case *expr.IdentityNode:
279250
if exp.Text == "*" || exp.Text == "match_all" {
251+
if cachedValue != nil {
252+
cachedValue.Set(true, true)
253+
}
280254
return value.NewBoolValue(true), true
281255
}
282256
}
283257

284-
matches, ok = evalBool(ctx, inc.ExprNode, depth+1, visitedIncludes)
258+
matches, ok = evalBool(ctx, includer, inc.ExprNode, depth+1, visitedIncludes)
285259
if cachedValue != nil {
286260
cachedValue.Set(matches, ok)
287261
}
@@ -298,7 +272,7 @@ func walkInclude(ctx expr.EvalContext, inc *expr.IncludeNode, depth int, visited
298272
return value.NewBoolValue(matches), true
299273
}
300274

301-
func walkBoolean(ctx expr.EvalContext, n *expr.BooleanNode, depth int, visitedIncludes []string) (value.Value, bool) {
275+
func walkBoolean(ctx expr.EvalContext, includer expr.Includer, n *expr.BooleanNode, depth int, visitedIncludes []string) (value.Value, bool) {
302276
if depth > MaxDepth {
303277
u.Warnf("Recursive query death? %v", n)
304278
return nil, false
@@ -316,7 +290,7 @@ func walkBoolean(ctx expr.EvalContext, n *expr.BooleanNode, depth int, visitedIn
316290

317291
for _, bn := range n.Args {
318292

319-
matches, ok := evalBool(ctx, bn, depth+1, visitedIncludes)
293+
matches, ok := evalBool(ctx, includer, bn, depth+1, visitedIncludes)
320294
if !ok && and {
321295
return nil, false
322296
} else if !ok {
@@ -353,9 +327,9 @@ func walkBoolean(ctx expr.EvalContext, n *expr.BooleanNode, depth int, visitedIn
353327
// x OR y
354328
// x > y
355329
// x < =
356-
func evalBinary(ctx expr.EvalContext, node *expr.BinaryNode, depth int, visitedIncludes []string) (value.Value, bool) {
357-
ar, aok := evalDepth(ctx, node.Args[0], depth+1, visitedIncludes)
358-
br, bok := evalDepth(ctx, node.Args[1], depth+1, visitedIncludes)
330+
func evalBinary(ctx expr.EvalContext, includer expr.Includer, node *expr.BinaryNode, depth int, visitedIncludes []string) (value.Value, bool) {
331+
ar, aok := evalDepth(ctx, includer, node.Args[0], depth+1, visitedIncludes)
332+
br, bok := evalDepth(ctx, includer, node.Args[1], depth+1, visitedIncludes)
359333

360334
// If we could not evaluate either we can shortcut
361335
if !aok && !bok {
@@ -843,9 +817,9 @@ func walkIdentity(ctx expr.EvalContext, node *expr.IdentityNode) (value.Value, b
843817
return ctx.Get(node.Text)
844818
}
845819

846-
func walkUnary(ctx expr.EvalContext, node *expr.UnaryNode, depth int, visitedIncludes []string) (value.Value, bool) {
820+
func walkUnary(ctx expr.EvalContext, includer expr.Includer, node *expr.UnaryNode, depth int, visitedIncludes []string) (value.Value, bool) {
847821

848-
a, ok := evalDepth(ctx, node.Arg, depth, visitedIncludes)
822+
a, ok := evalDepth(ctx, includer, node.Arg, depth, visitedIncludes)
849823
if !ok {
850824
switch node.Operator.T {
851825
case lex.TokenExists:
@@ -890,17 +864,17 @@ func walkUnary(ctx expr.EvalContext, node *expr.UnaryNode, depth int, visitedInc
890864
// walkTernary ternary evaluator
891865
//
892866
// A BETWEEN B AND C
893-
func walkTernary(ctx expr.EvalContext, node *expr.TriNode, depth int, visitedIncludes []string) (value.Value, bool) {
867+
func walkTernary(ctx expr.EvalContext, includer expr.Includer, node *expr.TriNode, depth int, visitedIncludes []string) (value.Value, bool) {
894868

895-
a, aok := evalDepth(ctx, node.Args[0], depth, visitedIncludes)
869+
a, aok := evalDepth(ctx, includer, node.Args[0], depth, visitedIncludes)
896870
if a == nil || !aok {
897871
return nil, false
898872
}
899-
b, bok := evalDepth(ctx, node.Args[1], depth, visitedIncludes)
873+
b, bok := evalDepth(ctx, includer, node.Args[1], depth, visitedIncludes)
900874
if b == nil || !bok {
901875
return nil, false
902876
}
903-
c, cok := evalDepth(ctx, node.Args[2], depth, visitedIncludes)
877+
c, cok := evalDepth(ctx, includer, node.Args[2], depth, visitedIncludes)
904878
if c == nil || !cok {
905879
return nil, false
906880
}
@@ -983,12 +957,12 @@ func walkTernary(ctx expr.EvalContext, node *expr.TriNode, depth int, visitedInc
983957
// walkArray Array evaluator: evaluate multiple values into an array
984958
//
985959
// (b,c,d)
986-
func walkArray(ctx expr.EvalContext, node *expr.ArrayNode, depth int, visitedIncludes []string) (value.Value, bool) {
960+
func walkArray(ctx expr.EvalContext, includer expr.Includer, node *expr.ArrayNode, depth int, visitedIncludes []string) (value.Value, bool) {
987961

988962
vals := make([]value.Value, len(node.Args))
989963

990964
for i := range node.Args {
991-
v, _ := evalDepth(ctx, node.Args[i], depth, visitedIncludes)
965+
v, _ := evalDepth(ctx, includer, node.Args[i], depth, visitedIncludes)
992966
vals[i] = v
993967
}
994968

@@ -997,7 +971,7 @@ func walkArray(ctx expr.EvalContext, node *expr.ArrayNode, depth int, visitedInc
997971
}
998972

999973
// walkFunc evaluates a function
1000-
func walkFunc(ctx expr.EvalContext, node *expr.FuncNode, depth int, visitedIncludes []string) (value.Value, bool) {
974+
func walkFunc(ctx expr.EvalContext, includer expr.Includer, node *expr.FuncNode, depth int, visitedIncludes []string) (value.Value, bool) {
1001975

1002976
if node.F.CustomFunc == nil {
1003977
return nil, false
@@ -1010,7 +984,7 @@ func walkFunc(ctx expr.EvalContext, node *expr.FuncNode, depth int, visitedInclu
1010984
args := make([]value.Value, len(node.Args))
1011985

1012986
for i, a := range node.Args {
1013-
v, ok := evalDepth(ctx, a, depth, visitedIncludes)
987+
v, ok := evalDepth(ctx, includer, a, depth, visitedIncludes)
1014988
if !ok {
1015989
v = value.NewNilValue()
1016990
}

0 commit comments

Comments
 (0)