Skip to content

Commit 0d3169d

Browse files
author
Dean Karn
authored
Extend contains (#9)
1 parent 9b323a9 commit 0d3169d

File tree

4 files changed

+88
-33
lines changed

4 files changed

+88
-33
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
## [0.4.0] - 2022-07-29
10+
### Added
11+
- The ability for CONTAINS_ANY and CONTAINS_ALL to check if a String contains any|all of the values
12+
within an Array. Any non-string data types return a false.
13+
914
## [0.3.2] - 2022-07-29
1015
### Fixed
1116
- && and || expression chaining.
@@ -39,7 +44,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3944
### Added
4045
- Initial conversion from https://github.com/rust-playground/ksql.
4146

42-
[Unreleased]: https://github.com/go-playground/ksql/compare/v0.3.2...HEAD
47+
[Unreleased]: https://github.com/go-playground/ksql/compare/v0.4.0...HEAD
48+
[0.4.0]: https://github.com/go-playground/ksql/compare/v0.3.2...v0.4.0
4349
[0.3.2]: https://github.com/go-playground/ksql/compare/v0.3.1...v0.3.2
4450
[0.3.1]: https://github.com/go-playground/ksql/compare/v0.3.0...v0.3.1
4551
[0.3.0]: https://github.com/go-playground/ksql/compare/v0.2.0...v0.3.0

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
ksql
22
=====
3-
![Project status](https://img.shields.io/badge/version-0.3.2-green.svg)
3+
![Project status](https://img.shields.io/badge/version-0.4.0-green.svg)
44
[![GoDoc](https://godoc.org/github.com/go-playground/ksql?status.svg)](https://pkg.go.dev/github.com/go-playground/ksql)
55
![License](https://img.shields.io/dub/l/vibe-d.svg)
66

parser.go

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,23 +1058,35 @@ func (c containsAny) Calculate(src []byte) (any, error) {
10581058
return nil, err
10591059
}
10601060

1061-
leftTypeOf := reflect.TypeOf(left)
1062-
typesEqual := leftTypeOf == reflect.TypeOf(right)
1063-
1064-
if !typesEqual && leftTypeOf.Kind() != reflect.Slice {
1065-
return nil, ErrUnsupportedTypeComparison{s: fmt.Sprintf("%s CONTAINS %s", left, right)}
1066-
}
1067-
10681061
switch l := left.(type) {
10691062
case string:
10701063

1071-
// betting that lists are short and so less expensive than iterating one to create a hash set
1072-
for _, c := range right.(string) {
1073-
for _, c2 := range l {
1074-
if c == c2 {
1064+
switch r := right.(type) {
1065+
case string:
1066+
1067+
// betting that lists are short and so less expensive than iterating one to create a hash set
1068+
for _, c := range r {
1069+
for _, c2 := range l {
1070+
if c == c2 {
1071+
return true, nil
1072+
}
1073+
}
1074+
}
1075+
1076+
case []any:
1077+
for _, v := range r {
1078+
s, ok := v.(string)
1079+
if !ok {
1080+
continue
1081+
}
1082+
if l == s {
10751083
return true, nil
10761084
}
10771085
}
1086+
return false, nil
1087+
1088+
default:
1089+
return nil, ErrUnsupportedTypeComparison{s: fmt.Sprintf("%s CONTAINS_ANY %s", left, right)}
10781090
}
10791091

10801092
case []any:
@@ -1098,10 +1110,13 @@ func (c containsAny) Calculate(src []byte) (any, error) {
10981110
}
10991111
}
11001112
}
1113+
1114+
default:
1115+
return nil, ErrUnsupportedTypeComparison{s: fmt.Sprintf("%s CONTAINS_ANY %s", left, right)}
11011116
}
11021117

11031118
default:
1104-
return nil, ErrUnsupportedTypeComparison{s: fmt.Sprintf("%s CONTAINS %s !", left, right)}
1119+
return nil, ErrUnsupportedTypeComparison{s: fmt.Sprintf("%s CONTAINS_ANY %s !", left, right)}
11051120
}
11061121
return false, nil
11071122
}
@@ -1123,55 +1138,65 @@ func (c containsAll) Calculate(src []byte) (any, error) {
11231138
return nil, err
11241139
}
11251140

1126-
leftTypeOf := reflect.TypeOf(left)
1127-
typesEqual := leftTypeOf == reflect.TypeOf(right)
1128-
1129-
if !typesEqual && leftTypeOf.Kind() != reflect.Slice {
1130-
return nil, ErrUnsupportedTypeComparison{s: fmt.Sprintf("%s CONTAINS %s", left, right)}
1131-
}
1132-
11331141
switch l := left.(type) {
11341142
case string:
1135-
// betting that lists are short and so less expensive than iterating one to create a hash set
1136-
OUTER1:
1137-
for _, c := range right.(string) {
1138-
for _, c2 := range l {
1139-
if c == c2 {
1140-
continue OUTER1
1143+
switch r := right.(type) {
1144+
case string:
1145+
// betting that lists are short and so less expensive than iterating one to create a hash set
1146+
OUTER1:
1147+
for _, c := range r {
1148+
for _, c2 := range l {
1149+
if c == c2 {
1150+
continue OUTER1
1151+
}
11411152
}
1153+
return false, nil
11421154
}
1143-
return false, nil
1155+
1156+
case []any:
1157+
for _, v := range r {
1158+
s, ok := v.(string)
1159+
if !ok || !strings.Contains(l, s) {
1160+
return false, nil
1161+
}
1162+
}
1163+
return true, nil
1164+
1165+
default:
1166+
return nil, ErrUnsupportedTypeComparison{s: fmt.Sprintf("%s CONTAINS_ALL %s", left, right)}
11441167
}
11451168

11461169
case []any:
11471170
switch r := right.(type) {
11481171
case []any:
11491172
// betting that lists are short and so less expensive than iterating one to create a hash set
1150-
OUTER2:
1173+
OUTER3:
11511174
for _, rv := range r {
11521175
for _, lv := range l {
11531176
if reflect.DeepEqual(rv, lv) {
1154-
continue OUTER2
1177+
continue OUTER3
11551178
}
11561179
}
11571180
return false, nil
11581181
}
11591182

11601183
case string:
11611184
// betting that lists are short and so less expensive than iterating one to create a hash set
1162-
OUTER3:
1185+
OUTER4:
11631186
for _, c := range r {
11641187
for _, v := range l {
11651188
if reflect.DeepEqual(string(c), v) {
1166-
continue OUTER3
1189+
continue OUTER4
11671190
}
11681191
}
11691192
return false, nil
11701193
}
1194+
default:
1195+
return nil, ErrUnsupportedTypeComparison{s: fmt.Sprintf("%s CONTAINS_ALL %s", left, right)}
11711196
}
11721197

11731198
default:
1174-
return nil, ErrUnsupportedTypeComparison{s: fmt.Sprintf("%s CONTAINS %s !", left, right)}
1199+
return nil, ErrUnsupportedTypeComparison{s: fmt.Sprintf("%s CONTAINS_ALL %s !", left, right)}
11751200
}
11761201
return true, nil
11771202
}

parser_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,30 @@ func TestParser(t *testing.T) {
554554
src: `{"AnnualRevenue":"2000000","NumberOfEmployees":"201","FirstName":"scott"}`,
555555
expected: true,
556556
},
557+
{
558+
name: "CONTAINS_ANY string + array 1",
559+
exp: `.FirstName CONTAINS_ANY ["noah", "emily", "alexandra","scott"]`,
560+
src: `{"AnnualRevenue":"2000000","NumberOfEmployees":"201","FirstName":"scott"}`,
561+
expected: true,
562+
},
563+
{
564+
name: "CONTAINS_ANY string + array 2",
565+
exp: `.FirstName CONTAINS_ANY ["noah", "emily", "alexandra"]`,
566+
src: `{"AnnualRevenue":"2000000","NumberOfEmployees":"201","FirstName":"scott"}`,
567+
expected: false,
568+
},
569+
{
570+
name: "CONTAINS_ALL string + array 1",
571+
exp: `.FirstName CONTAINS_ALL ["sc", "ot", "ott","cot"]`,
572+
src: `{"AnnualRevenue":"2000000","NumberOfEmployees":"201","FirstName":"scott"}`,
573+
expected: true,
574+
},
575+
{
576+
name: "CONTAINS_ALL string + array 2",
577+
exp: `.FirstName CONTAINS_ALL ["sc", "ot", "ott","b"]`,
578+
src: `{"AnnualRevenue":"2000000","NumberOfEmployees":"201","FirstName":"scott"}`,
579+
expected: false,
580+
},
557581
}
558582

559583
for _, tc := range tests {

0 commit comments

Comments
 (0)