Skip to content

Commit bc9170f

Browse files
authored
Short-circuit AND expressions (#899)
Fixes: #898 Signed-off-by: Doug Davis <dug@microsoft.com>
1 parent eae656f commit bc9170f

File tree

4 files changed

+115
-3
lines changed

4 files changed

+115
-3
lines changed

sql/v2/expression/logic_expressions.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import (
1313

1414
type logicExpression struct {
1515
baseBinaryExpression
16-
fn func(x, y bool) bool
16+
fn func(x, y bool) bool
17+
verb string
1718
}
1819

1920
func (s logicExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
@@ -22,12 +23,20 @@ func (s logicExpression) Evaluate(event cloudevents.Event) (interface{}, error)
2223
return nil, err
2324
}
2425

25-
rightVal, err := s.right.Evaluate(event)
26+
leftVal, err = utils.Cast(leftVal, cesql.BooleanType)
2627
if err != nil {
2728
return nil, err
2829
}
2930

30-
leftVal, err = utils.Cast(leftVal, cesql.BooleanType)
31+
// Don't bother to check the other expression unless we need to
32+
if s.verb == "AND" && leftVal.(bool) == false {
33+
return false, nil
34+
}
35+
if s.verb == "OR" && leftVal.(bool) == true {
36+
return true, nil
37+
}
38+
39+
rightVal, err := s.right.Evaluate(event)
3140
if err != nil {
3241
return nil, err
3342
}
@@ -49,6 +58,7 @@ func NewAndExpression(left cesql.Expression, right cesql.Expression) cesql.Expre
4958
fn: func(x, y bool) bool {
5059
return x && y
5160
},
61+
verb: "AND",
5262
}
5363
}
5464

@@ -61,6 +71,7 @@ func NewOrExpression(left cesql.Expression, right cesql.Expression) cesql.Expres
6171
fn: func(x, y bool) bool {
6272
return x || y
6373
},
74+
verb: "OR",
6475
}
6576
}
6677

@@ -73,5 +84,6 @@ func NewXorExpression(left cesql.Expression, right cesql.Expression) cesql.Expre
7384
fn: func(x, y bool) bool {
7485
return x != y
7586
},
87+
verb: "XOR",
7688
}
7789
}

test/sql/go.mod

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module github.com/cloudevents/sdk-go/test/sql
2+
3+
go 1.20
4+
5+
require (
6+
github.com/cloudevents/sdk-go/sql/v2 v2.14.0
7+
github.com/cloudevents/sdk-go/v2 v2.14.0
8+
)
9+
10+
require (
11+
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
12+
github.com/google/uuid v1.1.1 // indirect
13+
github.com/json-iterator/go v1.1.10 // indirect
14+
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
15+
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
16+
go.uber.org/atomic v1.4.0 // indirect
17+
go.uber.org/multierr v1.1.0 // indirect
18+
go.uber.org/zap v1.10.0 // indirect
19+
)

test/sql/go.sum

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves=
2+
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
3+
github.com/cloudevents/sdk-go/sql/v2 v2.14.0 h1:OPi78/DQqGxLQ1Ktg0XMMW+IxJHiJNhVUARXnkaYnh8=
4+
github.com/cloudevents/sdk-go/sql/v2 v2.14.0/go.mod h1:Fp5OvNlqfYIpj3C/RiHx/6TjqZK89Ed706uyBN1u+aE=
5+
github.com/cloudevents/sdk-go/v2 v2.14.0 h1:Nrob4FwVgi5L4tV9lhjzZcjYqFVyJzsA56CwPaPfv6s=
6+
github.com/cloudevents/sdk-go/v2 v2.14.0/go.mod h1:xDmKfzNjM8gBvjaF8ijFjM1VYOVUEeUfapHMUX1T5To=
7+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
8+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9+
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
10+
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
11+
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
12+
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
13+
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
14+
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
15+
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
16+
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
17+
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
18+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
19+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
20+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
21+
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
22+
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
23+
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
24+
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
25+
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
26+
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=

test/sql/shortcircuit_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
Copyright 2021 The CloudEvents Authors
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package sql
7+
8+
import (
9+
"testing"
10+
11+
cesql "github.com/cloudevents/sdk-go/sql/v2/parser"
12+
cloudevents "github.com/cloudevents/sdk-go/v2"
13+
)
14+
15+
func TestShortCircuitAND(t *testing.T) {
16+
17+
sql := "(EXISTS revisiontype AND revisiontype=Branch) OR (branch='master')"
18+
19+
expression, err := cesql.Parse(string(sql))
20+
evt := cloudevents.NewEvent("1.0")
21+
evt.SetID("evt-1")
22+
evt.SetType("what-ever")
23+
evt.SetSource("/event")
24+
evt.SetExtension("branch", "master")
25+
val, err := expression.Evaluate(evt)
26+
27+
if err != nil {
28+
t.Errorf("err should be nil: %s", err.Error())
29+
} else {
30+
if !val.(bool) {
31+
t.Errorf("should be true ,but :%s", val)
32+
}
33+
}
34+
}
35+
36+
func TestShortCircuitOR(t *testing.T) {
37+
38+
sql := "(branch='master' OR revisiontype=Branch)"
39+
40+
expression, err := cesql.Parse(string(sql))
41+
evt := cloudevents.NewEvent("1.0")
42+
evt.SetID("evt-1")
43+
evt.SetType("what-ever")
44+
evt.SetSource("/event")
45+
evt.SetExtension("branch", "master")
46+
val, err := expression.Evaluate(evt)
47+
48+
if err != nil {
49+
t.Errorf("err should be nil: %s", err.Error())
50+
} else {
51+
if !val.(bool) {
52+
t.Errorf("should be true ,but :%s", val)
53+
}
54+
}
55+
}

0 commit comments

Comments
 (0)