github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/ast/pipesearch/searchQuery_test.go (about) 1 /* 2 Copyright 2023. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package pipesearch 18 19 import ( 20 "encoding/json" 21 "reflect" 22 "testing" 23 24 "github.com/siglens/siglens/pkg/ast" 25 "github.com/siglens/siglens/pkg/segment/structs" 26 "github.com/siglens/siglens/pkg/segment/utils" 27 . "github.com/siglens/siglens/pkg/segment/utils" 28 "github.com/stretchr/testify/assert" 29 ) 30 31 func testParseQuery(query string, want *ast.Node) func(t *testing.T) { 32 return func(t *testing.T) { 33 t.Helper() 34 t.Parallel() 35 n, err := Parse("", []byte(query)) 36 if err != nil { 37 t.Fatalf("unexpected error: %v", err) 38 } 39 if !reflect.DeepEqual(want, n.(ast.QueryStruct).SearchFilter) { 40 wb, _ := json.MarshalIndent(want, "", " ") 41 nb, _ := json.MarshalIndent(n, "", " ") 42 t.Fatalf("expected:\n%s\ngot:\n%s", string(wb), string(nb)) 43 } 44 } 45 } 46 47 func TestAST_simpleEqual(t *testing.T) { 48 json_body := []byte(`something="another"`) 49 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 50 assert.Nil(t, err) 51 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 52 assert.Len(t, res.AndFilterCondition.FilterCriteria, 1) 53 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "something") 54 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "another") 55 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 56 } 57 58 func TestAST_simpleAnd(t *testing.T) { 59 json_body := []byte(`name="t1" AND surname="t2"`) 60 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 61 assert.Nil(t, err) 62 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 63 assert.Len(t, res.AndFilterCondition.FilterCriteria, 2) 64 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "name") 65 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t1") 66 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 67 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "surname") 68 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t2") 69 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, Equals) 70 } 71 72 func TestAST_simpleOr(t *testing.T) { 73 json_body := []byte(`name="t1" OR surname="t2"`) 74 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 75 assert.Nil(t, err) 76 assert.NotNil(t, res.OrFilterCondition.FilterCriteria) 77 assert.Len(t, res.OrFilterCondition.FilterCriteria, 2) 78 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "name") 79 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t1") 80 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 81 assert.Equal(t, res.OrFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "surname") 82 assert.Equal(t, res.OrFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t2") 83 assert.Equal(t, res.OrFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, Equals) 84 } 85 86 func TestAST_AND_Or(t *testing.T) { 87 json_body := []byte(`name="t1" OR name="t2" AND age=100`) 88 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 89 assert.Nil(t, err) 90 assert.NotNil(t, res.OrFilterCondition.FilterCriteria) 91 assert.Len(t, res.OrFilterCondition.FilterCriteria, 1) 92 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "name") 93 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t1") 94 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 95 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "name") 96 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 97 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t2") 98 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "age") 99 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, Equals) 100 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "100") 101 } 102 103 func TestAST_AND_Or_paren(t *testing.T) { 104 json_body := []byte(`(name="t1" OR name="t2") AND age=100`) 105 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 106 assert.Nil(t, err) 107 assert.Len(t, res.AndFilterCondition.FilterCriteria, 1) 108 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "age") 109 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "100") 110 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 111 assert.Equal(t, res.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "name") 112 assert.Equal(t, res.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t1") 113 assert.Equal(t, res.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 114 assert.Equal(t, res.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "name") 115 assert.Equal(t, res.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t2") 116 assert.Equal(t, res.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, Equals) 117 118 } 119 func TestAST_AND_Or_paren_around_condition(t *testing.T) { 120 json_body := []byte(`name="t1" OR (name="t2")`) 121 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 122 assert.Nil(t, err) 123 assert.NotNil(t, res.OrFilterCondition.FilterCriteria) 124 assert.Len(t, res.OrFilterCondition.FilterCriteria, 2) 125 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "name") 126 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t1") 127 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 128 assert.Equal(t, res.OrFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "name") 129 assert.Equal(t, res.OrFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t2") 130 assert.Equal(t, res.OrFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, Equals) 131 } 132 133 func TestAST_AND_Or_multiple(t *testing.T) { 134 json_body := []byte(`name="t1" OR name="t2" OR age=100 AND surname=t3`) 135 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 136 assert.Nil(t, err) 137 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "name") 138 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t1") 139 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 140 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "name") 141 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t2") 142 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 143 144 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "age") 145 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "100") 146 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 147 148 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "surname") 149 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t3") 150 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, Equals) 151 152 } 153 154 func TestAST_freeText_simple(t *testing.T) { 155 json_body := []byte(`test`) 156 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 157 assert.Nil(t, err) 158 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 159 assert.Len(t, res.AndFilterCondition.FilterCriteria, 1) 160 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchColumn, "*") 161 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchOperator, And) 162 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchWords, [][]byte{[]byte("test")}) 163 assert.NotEqual(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchType, structs.MATCH_PHRASE) 164 } 165 166 func TestAST_freeText_simple_matchWords(t *testing.T) { 167 json_body := []byte(`"test this ."`) 168 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 169 assert.Nil(t, err) 170 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 171 assert.Len(t, res.AndFilterCondition.FilterCriteria, 1) 172 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchColumn, "*") 173 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchOperator, And) 174 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchWords, [][]byte{[]byte("test"), []byte("this"), []byte(".")}) 175 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchType, structs.MATCH_PHRASE) 176 } 177 178 func TestAST_freeText_simple_wildcard(t *testing.T) { 179 json_body := []byte(`test*`) 180 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 181 assert.Nil(t, err) 182 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 183 assert.Len(t, res.AndFilterCondition.FilterCriteria, 1) 184 185 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "*") 186 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "test*") 187 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 188 189 } 190 191 func TestAST_freeText_simpleAnd(t *testing.T) { 192 json_body := []byte(`another AND test`) 193 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 194 assert.Nil(t, err) 195 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 196 assert.Len(t, res.AndFilterCondition.FilterCriteria, 2) 197 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchColumn, "*") 198 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchOperator, And) 199 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchWords, [][]byte{[]byte("another")}) 200 assert.NotEqual(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchType, structs.MATCH_PHRASE) 201 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].MatchFilter.MatchColumn, "*") 202 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].MatchFilter.MatchOperator, And) 203 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].MatchFilter.MatchWords, [][]byte{[]byte("test")}) 204 assert.NotEqual(t, res.AndFilterCondition.FilterCriteria[1].MatchFilter.MatchType, structs.MATCH_PHRASE) 205 } 206 207 func TestAST_freeText_simpleAnd_wildcard(t *testing.T) { 208 json_body := []byte(`another* AND test*`) 209 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 210 assert.Nil(t, err) 211 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 212 assert.Len(t, res.AndFilterCondition.FilterCriteria, 2) 213 214 assert.Len(t, res.AndFilterCondition.FilterCriteria, 2) 215 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "*") 216 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "another*") 217 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 218 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "*") 219 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "test*") 220 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, Equals) 221 } 222 223 func TestAST_freeText_complexOrAnd(t *testing.T) { 224 json_body := []byte(`"t2" OR ("t1" AND t3)`) 225 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 226 assert.Nil(t, err) 227 assert.NotNil(t, res.OrFilterCondition.FilterCriteria) 228 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].MatchFilter.MatchColumn, "*") 229 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].MatchFilter.MatchOperator, And) 230 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].MatchFilter.MatchPhrase, []byte("t2")) 231 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].MatchFilter.MatchType, structs.MATCH_PHRASE) 232 233 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].MatchFilter.MatchColumn, "*") 234 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].MatchFilter.MatchOperator, And) 235 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].MatchFilter.MatchPhrase, []byte("t1")) 236 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].MatchFilter.MatchType, structs.MATCH_PHRASE) 237 238 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].MatchFilter.MatchColumn, "*") 239 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].MatchFilter.MatchOperator, And) 240 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].MatchFilter.MatchWords, [][]byte{[]byte("t3")}) 241 assert.NotEqual(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].MatchFilter.MatchType, structs.MATCH_PHRASE) 242 } 243 244 func TestAST_freeText_complexOrAnd_wildcard(t *testing.T) { 245 json_body := []byte(`t2* OR (t1* AND t3*)`) 246 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 247 assert.Nil(t, err) 248 assert.NotNil(t, res.OrFilterCondition.FilterCriteria) 249 assert.Len(t, res.OrFilterCondition.FilterCriteria, 1) 250 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "*") 251 assert.Equal(t, res.OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t2*") 252 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 253 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "*") 254 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t1*") 255 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 256 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "*") 257 assert.Equal(t, res.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t3*") 258 259 } 260 261 func TestAST_freeText_complexAndOr(t *testing.T) { 262 json_body := []byte(`"t2" AND ("t1" OR t3)`) 263 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 264 assert.Nil(t, err) 265 266 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 267 assert.Len(t, res.AndFilterCondition.FilterCriteria, 1) 268 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchColumn, "*") 269 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchOperator, And) 270 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchPhrase, []byte("t2")) 271 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].MatchFilter.MatchType, structs.MATCH_PHRASE) 272 assert.Equal(t, res.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].MatchFilter.MatchColumn, "*") 273 assert.Equal(t, res.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].MatchFilter.MatchPhrase, []byte("t1")) 274 assert.Equal(t, res.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].MatchFilter.MatchColumn, "*") 275 assert.Equal(t, res.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].MatchFilter.MatchWords, [][]byte{[]byte("t3")}) 276 } 277 278 func TestAST_columnValue_complexString(t *testing.T) { 279 json_body := []byte(`click_id = "627af0a5-aeb4-4471-889f-6e850958d98e"`) 280 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 281 assert.Nil(t, err) 282 283 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 284 assert.Len(t, res.AndFilterCondition.FilterCriteria, 1) 285 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "click_id") 286 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 287 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "627af0a5-aeb4-4471-889f-6e850958d98e") 288 } 289 290 func TestAST_columnValue_multiWordValue(t *testing.T) { 291 json_body := []byte(`utm_campaign = "Town apply record."`) 292 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 293 assert.Nil(t, err) 294 295 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 296 assert.Len(t, res.AndFilterCondition.FilterCriteria, 1) 297 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "utm_campaign") 298 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 299 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "Town apply record.") 300 } 301 302 func TestSimpleEqual(t *testing.T) { 303 t.Run("simple minimal condition", testParseQuery(`something="another"`, &ast.Node{ 304 NodeType: ast.NodeTerminal, 305 Comparison: ast.Comparison{ 306 Op: "=", 307 Field: "something", 308 Values: "\"another\"", 309 }, 310 Left: nil, 311 Right: nil, 312 })) 313 314 t.Run("multi part field name", testParseQuery(`name.something = another`, &ast.Node{ 315 NodeType: ast.NodeTerminal, 316 Comparison: ast.Comparison{ 317 Op: "=", 318 Field: "name.something", 319 Values: "another", 320 }, 321 Left: nil, 322 Right: nil, 323 })) 324 325 t.Run("simple AND clause", testParseQuery(`name="t1" AND surname="t2"`, &ast.Node{ 326 NodeType: ast.NodeAnd, 327 Left: &ast.Node{ 328 NodeType: ast.NodeTerminal, 329 Comparison: ast.Comparison{ 330 Op: "=", 331 Field: "name", 332 Values: "\"t1\"", 333 }, 334 }, 335 Right: &ast.Node{ 336 NodeType: ast.NodeTerminal, 337 Comparison: ast.Comparison{ 338 Op: "=", 339 Field: "surname", 340 Values: "\"t2\"", 341 }, 342 }, 343 })) 344 345 t.Run("simple AND clause with parenthesis", testParseQuery(`(name="t1" AND surname="t2")`, &ast.Node{ 346 NodeType: ast.NodeAnd, 347 Left: &ast.Node{ 348 NodeType: ast.NodeTerminal, 349 Comparison: ast.Comparison{ 350 Op: "=", 351 Field: "name", 352 Values: "\"t1\"", 353 }, 354 }, 355 Right: &ast.Node{ 356 NodeType: ast.NodeTerminal, 357 Comparison: ast.Comparison{ 358 Op: "=", 359 Field: "surname", 360 Values: "\"t2\"", 361 }, 362 }, 363 })) 364 365 t.Run("simple OR clause", testParseQuery(`name="t1" OR surname="t2"`, &ast.Node{ 366 NodeType: ast.NodeOr, 367 Left: &ast.Node{ 368 NodeType: ast.NodeTerminal, 369 Comparison: ast.Comparison{ 370 Op: "=", 371 Field: "name", 372 Values: "\"t1\"", 373 }, 374 }, 375 Right: &ast.Node{ 376 NodeType: ast.NodeTerminal, 377 Comparison: ast.Comparison{ 378 Op: "=", 379 Field: "surname", 380 Values: "\"t2\"", 381 }, 382 }, 383 })) 384 385 t.Run("simple OR clause with parenthesis", testParseQuery(`(name="t1" OR surname="t2")`, &ast.Node{ 386 NodeType: ast.NodeOr, 387 Left: &ast.Node{ 388 NodeType: ast.NodeTerminal, 389 Comparison: ast.Comparison{ 390 Op: "=", 391 Field: "name", 392 Values: "\"t1\"", 393 }, 394 }, 395 Right: &ast.Node{ 396 NodeType: ast.NodeTerminal, 397 Comparison: ast.Comparison{ 398 Op: "=", 399 Field: "surname", 400 Values: "\"t2\"", 401 }, 402 }, 403 })) 404 405 t.Run("simple OR clause with parenthesis around condition", testParseQuery(`name="t1" OR (name="t2")`, &ast.Node{ 406 NodeType: ast.NodeOr, 407 Left: &ast.Node{ 408 NodeType: ast.NodeTerminal, 409 Comparison: ast.Comparison{ 410 Op: "=", 411 Field: "name", 412 Values: "\"t1\"", 413 }, 414 }, 415 Right: &ast.Node{ 416 NodeType: ast.NodeTerminal, 417 Comparison: ast.Comparison{ 418 Op: "=", 419 Field: "name", 420 Values: "\"t2\"", 421 }, 422 }, 423 })) 424 425 t.Run("OR / AND clauses", testParseQuery(`name="t1" OR name="t2" AND age=100`, &ast.Node{ 426 NodeType: ast.NodeOr, 427 Left: &ast.Node{ 428 NodeType: ast.NodeTerminal, 429 Comparison: ast.Comparison{ 430 Op: "=", 431 Field: "name", 432 Values: "\"t1\"", 433 }, 434 }, 435 Right: &ast.Node{ 436 NodeType: ast.NodeAnd, 437 Left: &ast.Node{ 438 NodeType: ast.NodeTerminal, 439 Comparison: ast.Comparison{ 440 Op: "=", 441 Field: "name", 442 Values: "\"t2\"", 443 }, 444 }, 445 Right: &ast.Node{ 446 NodeType: ast.NodeTerminal, 447 Comparison: ast.Comparison{ 448 Op: "=", 449 Field: "age", 450 Values: json.Number("100"), 451 }, 452 }, 453 }, 454 })) 455 456 t.Run("OR / AND clauses with paren precedence", testParseQuery(`(name="t1" AND age=100) OR name="t2"`, &ast.Node{ 457 NodeType: ast.NodeOr, 458 Left: &ast.Node{ 459 NodeType: ast.NodeAnd, 460 Left: &ast.Node{ 461 NodeType: ast.NodeTerminal, 462 Comparison: ast.Comparison{ 463 Op: "=", 464 Field: "name", 465 Values: "\"t1\"", 466 }, 467 }, 468 Right: &ast.Node{ 469 NodeType: ast.NodeTerminal, 470 Comparison: ast.Comparison{ 471 Op: "=", 472 Field: "age", 473 Values: json.Number("100"), 474 }, 475 }, 476 }, 477 Right: &ast.Node{ 478 NodeType: ast.NodeTerminal, 479 Comparison: ast.Comparison{ 480 Op: "=", 481 Field: "name", 482 Values: "\"t2\"", 483 }, 484 }, 485 })) 486 487 t.Run("OR / AND clauses with paren precedence variation", testParseQuery(`name="t2" OR (name="t1" AND age=100) `, &ast.Node{ 488 NodeType: ast.NodeOr, 489 Left: &ast.Node{ 490 NodeType: ast.NodeTerminal, 491 Comparison: ast.Comparison{ 492 Op: "=", 493 Field: "name", 494 Values: "\"t2\"", 495 }, 496 }, 497 Right: &ast.Node{ 498 NodeType: ast.NodeAnd, 499 Left: &ast.Node{ 500 NodeType: ast.NodeTerminal, 501 Comparison: ast.Comparison{ 502 Op: "=", 503 Field: "name", 504 Values: "\"t1\"", 505 }, 506 }, 507 Right: &ast.Node{ 508 NodeType: ast.NodeTerminal, 509 Comparison: ast.Comparison{ 510 Op: "=", 511 Field: "age", 512 Values: json.Number("100"), 513 }, 514 }, 515 }, 516 })) 517 518 t.Run("OR / AND clauses", testParseQuery(`name="t1" OR name="t2" OR age=100`, &ast.Node{ 519 NodeType: ast.NodeOr, 520 Left: &ast.Node{ 521 NodeType: ast.NodeTerminal, 522 Comparison: ast.Comparison{ 523 Op: "=", 524 Field: "name", 525 Values: "\"t1\"", 526 }, 527 }, 528 Right: &ast.Node{ 529 NodeType: ast.NodeOr, 530 Left: &ast.Node{ 531 NodeType: ast.NodeTerminal, 532 Comparison: ast.Comparison{ 533 Op: "=", 534 Field: "name", 535 Values: "\"t2\"", 536 }, 537 }, 538 Right: &ast.Node{ 539 NodeType: ast.NodeTerminal, 540 Comparison: ast.Comparison{ 541 Op: "=", 542 Field: "age", 543 Values: json.Number("100"), 544 }, 545 }, 546 }, 547 })) 548 549 t.Run("OR / AND clauses", testParseQuery(`name="t1" OR name="t2" OR age=100 AND surname=t3`, &ast.Node{ 550 NodeType: ast.NodeOr, 551 552 Left: &ast.Node{ 553 NodeType: ast.NodeTerminal, 554 Comparison: ast.Comparison{ 555 Op: "=", 556 Field: "name", 557 Values: "\"t1\"", 558 }, 559 }, 560 Right: &ast.Node{ 561 NodeType: ast.NodeOr, 562 Left: &ast.Node{ 563 NodeType: ast.NodeTerminal, 564 Comparison: ast.Comparison{ 565 Op: "=", 566 Field: "name", 567 Values: "\"t2\"", 568 }, 569 }, 570 Right: &ast.Node{ 571 NodeType: ast.NodeAnd, 572 Left: &ast.Node{ 573 NodeType: ast.NodeTerminal, 574 Comparison: ast.Comparison{ 575 Op: "=", 576 Field: "age", 577 Values: json.Number("100"), 578 }, 579 }, 580 Right: &ast.Node{ 581 NodeType: ast.NodeTerminal, 582 Comparison: ast.Comparison{ 583 Op: "=", 584 Field: "surname", 585 Values: "t3", 586 }, 587 }, 588 }, 589 }, 590 })) 591 592 t.Run("multiple OR / AND clauses", testParseQuery(`name="t1" OR name="t2" OR age=100 AND surname=t3`, &ast.Node{ 593 NodeType: ast.NodeOr, 594 595 Left: &ast.Node{ 596 NodeType: ast.NodeTerminal, 597 Comparison: ast.Comparison{ 598 Op: "=", 599 Field: "name", 600 Values: "\"t1\"", 601 }, 602 }, 603 Right: &ast.Node{ 604 NodeType: ast.NodeOr, 605 Left: &ast.Node{ 606 NodeType: ast.NodeTerminal, 607 Comparison: ast.Comparison{ 608 Op: "=", 609 Field: "name", 610 Values: "\"t2\"", 611 }, 612 }, 613 Right: &ast.Node{ 614 NodeType: ast.NodeAnd, 615 Left: &ast.Node{ 616 NodeType: ast.NodeTerminal, 617 Comparison: ast.Comparison{ 618 Op: "=", 619 Field: "age", 620 Values: json.Number("100"), 621 }, 622 }, 623 Right: &ast.Node{ 624 NodeType: ast.NodeTerminal, 625 Comparison: ast.Comparison{ 626 Op: "=", 627 Field: "surname", 628 Values: "t3", 629 }, 630 }, 631 }, 632 }, 633 })) 634 635 t.Run(" multiple AND clauses", testParseQuery(`name="t1" AND name="t2" AND age=100 AND surname=t3`, &ast.Node{ 636 NodeType: ast.NodeAnd, 637 638 Left: &ast.Node{ 639 NodeType: ast.NodeTerminal, 640 Comparison: ast.Comparison{ 641 Op: "=", 642 Field: "name", 643 Values: "\"t1\"", 644 }, 645 }, 646 Right: &ast.Node{ 647 NodeType: ast.NodeAnd, 648 Left: &ast.Node{ 649 NodeType: ast.NodeTerminal, 650 Comparison: ast.Comparison{ 651 Op: "=", 652 Field: "name", 653 Values: "\"t2\"", 654 }, 655 }, 656 Right: &ast.Node{ 657 NodeType: ast.NodeAnd, 658 Left: &ast.Node{ 659 NodeType: ast.NodeTerminal, 660 Comparison: ast.Comparison{ 661 Op: "=", 662 Field: "age", 663 Values: json.Number("100"), 664 }, 665 }, 666 Right: &ast.Node{ 667 NodeType: ast.NodeTerminal, 668 Comparison: ast.Comparison{ 669 Op: "=", 670 Field: "surname", 671 Values: "t3", 672 }, 673 }, 674 }, 675 }, 676 })) 677 678 t.Run("float value", testParseQuery(`avg=1.4`, &ast.Node{ 679 NodeType: ast.NodeTerminal, 680 Comparison: ast.Comparison{ 681 Op: "=", 682 Field: "avg", 683 Values: json.Number("1.4"), 684 }, 685 Left: nil, 686 Right: nil, 687 })) 688 689 t.Run("negative int value", testParseQuery(`total=-132`, &ast.Node{ 690 NodeType: ast.NodeTerminal, 691 Comparison: ast.Comparison{ 692 Op: "=", 693 Field: "total", 694 Values: json.Number("-132"), 695 }, 696 Left: nil, 697 Right: nil, 698 })) 699 700 t.Run("comparator = ", testParseQuery(`answer=42`, &ast.Node{ 701 NodeType: ast.NodeTerminal, 702 Comparison: ast.Comparison{ 703 Op: "=", 704 Field: "answer", 705 Values: json.Number("42"), 706 }, 707 Left: nil, 708 Right: nil, 709 })) 710 711 t.Run("comparator >", testParseQuery(`answer>42`, &ast.Node{ 712 NodeType: ast.NodeTerminal, 713 Comparison: ast.Comparison{ 714 Op: ">", 715 Field: "answer", 716 Values: json.Number("42"), 717 }, 718 Left: nil, 719 Right: nil, 720 })) 721 722 t.Run("comparator >=", testParseQuery(`answer>=42`, &ast.Node{ 723 NodeType: ast.NodeTerminal, 724 Comparison: ast.Comparison{ 725 Op: ">=", 726 Field: "answer", 727 Values: json.Number("42"), 728 }, 729 Left: nil, 730 Right: nil, 731 })) 732 733 t.Run("comparator <", testParseQuery(`answer<42`, &ast.Node{ 734 NodeType: ast.NodeTerminal, 735 Comparison: ast.Comparison{ 736 Op: "<", 737 Field: "answer", 738 Values: json.Number("42"), 739 }, 740 Left: nil, 741 Right: nil, 742 })) 743 744 t.Run("comparator <", testParseQuery(`answer<=42`, &ast.Node{ 745 NodeType: ast.NodeTerminal, 746 Comparison: ast.Comparison{ 747 Op: "<=", 748 Field: "answer", 749 Values: json.Number("42"), 750 }, 751 Left: nil, 752 Right: nil, 753 })) 754 755 t.Run("comparator <", testParseQuery(`answer!=42`, &ast.Node{ 756 NodeType: ast.NodeTerminal, 757 Comparison: ast.Comparison{ 758 Op: "!=", 759 Field: "answer", 760 Values: json.Number("42"), 761 }, 762 Left: nil, 763 Right: nil, 764 })) 765 766 t.Run("allow dash in field name", testParseQuery(`na-me= "t1-t2"`, &ast.Node{ 767 NodeType: ast.NodeTerminal, 768 Comparison: ast.Comparison{ 769 Op: "=", 770 Field: "na-me", 771 Values: "\"t1-t2\"", 772 }, 773 Left: nil, 774 Right: nil, 775 })) 776 777 t.Run("allow dash and slash in field name", testParseQuery(`na-/me= "t1/t2"`, &ast.Node{ 778 NodeType: ast.NodeTerminal, 779 Comparison: ast.Comparison{ 780 Op: "=", 781 Field: "na-/me", 782 Values: "\"t1/t2\"", 783 }, 784 Left: nil, 785 Right: nil, 786 })) 787 788 t.Run("free text search", testParseQuery(`"another"`, &ast.Node{ 789 NodeType: ast.NodeTerminal, 790 Comparison: ast.Comparison{ 791 Op: "=", 792 Field: "*", 793 Values: "\"another\"", 794 }, 795 Left: nil, 796 Right: nil, 797 })) 798 799 t.Run("search with *", testParseQuery(`*="another"`, &ast.Node{ 800 NodeType: ast.NodeTerminal, 801 Comparison: ast.Comparison{ 802 Op: "=", 803 Field: "*", 804 Values: "\"another\"", 805 }, 806 Left: nil, 807 Right: nil, 808 })) 809 810 t.Run("free text search AND", testParseQuery(`another AND test`, &ast.Node{ 811 NodeType: ast.NodeAnd, 812 Left: &ast.Node{ 813 NodeType: ast.NodeTerminal, 814 Comparison: ast.Comparison{ 815 Op: "=", 816 Field: "*", 817 Values: "another", 818 }, 819 }, 820 Right: &ast.Node{ 821 NodeType: ast.NodeTerminal, 822 Comparison: ast.Comparison{ 823 Op: "=", 824 Field: "*", 825 Values: "test", 826 }, 827 }, 828 })) 829 830 t.Run("free text search OR", testParseQuery(`another OR test`, &ast.Node{ 831 NodeType: ast.NodeOr, 832 Left: &ast.Node{ 833 NodeType: ast.NodeTerminal, 834 Comparison: ast.Comparison{ 835 Op: "=", 836 Field: "*", 837 Values: "another", 838 }, 839 }, 840 Right: &ast.Node{ 841 NodeType: ast.NodeTerminal, 842 Comparison: ast.Comparison{ 843 Op: "=", 844 Field: "*", 845 Values: "test", 846 }, 847 }, 848 })) 849 850 t.Run("free text search OR / AND clauses with paren precedence variation", testParseQuery(`"t2" OR ("t1" AND t3) `, &ast.Node{ 851 NodeType: ast.NodeOr, 852 Left: &ast.Node{ 853 NodeType: ast.NodeTerminal, 854 Comparison: ast.Comparison{ 855 Op: "=", 856 Field: "*", 857 Values: "\"t2\"", 858 }, 859 }, 860 Right: &ast.Node{ 861 NodeType: ast.NodeAnd, 862 Left: &ast.Node{ 863 NodeType: ast.NodeTerminal, 864 Comparison: ast.Comparison{ 865 Op: "=", 866 Field: "*", 867 Values: "\"t1\"", 868 }, 869 }, 870 Right: &ast.Node{ 871 NodeType: ast.NodeTerminal, 872 Comparison: ast.Comparison{ 873 Op: "=", 874 Field: "*", 875 Values: "t3", 876 }, 877 }, 878 }, 879 })) 880 881 t.Run("free text search OR / AND clauses with paren precedence variation", testParseQuery(`"t2" AND ("t1" OR t3) `, &ast.Node{ 882 NodeType: ast.NodeAnd, 883 Left: &ast.Node{ 884 NodeType: ast.NodeTerminal, 885 Comparison: ast.Comparison{ 886 Op: "=", 887 Field: "*", 888 Values: "\"t2\"", 889 }, 890 }, 891 Right: &ast.Node{ 892 NodeType: ast.NodeOr, 893 Left: &ast.Node{ 894 NodeType: ast.NodeTerminal, 895 Comparison: ast.Comparison{ 896 Op: "=", 897 Field: "*", 898 Values: "\"t1\"", 899 }, 900 }, 901 Right: &ast.Node{ 902 NodeType: ast.NodeTerminal, 903 Comparison: ast.Comparison{ 904 Op: "=", 905 Field: "*", 906 Values: "t3", 907 }, 908 }, 909 }, 910 })) 911 912 t.Run("free text search - OR / AND clauses with paren precedence", testParseQuery(`("t1" AND t2) OR name="t3"`, &ast.Node{ 913 NodeType: ast.NodeOr, 914 Left: &ast.Node{ 915 NodeType: ast.NodeAnd, 916 Left: &ast.Node{ 917 NodeType: ast.NodeTerminal, 918 Comparison: ast.Comparison{ 919 Op: "=", 920 Field: "*", 921 Values: "\"t1\"", 922 }, 923 }, 924 Right: &ast.Node{ 925 NodeType: ast.NodeTerminal, 926 Comparison: ast.Comparison{ 927 Op: "=", 928 Field: "*", 929 Values: "t2", 930 }, 931 }, 932 }, 933 Right: &ast.Node{ 934 NodeType: ast.NodeTerminal, 935 Comparison: ast.Comparison{ 936 Op: "=", 937 Field: "name", 938 Values: "\"t3\"", 939 }, 940 }, 941 })) 942 943 t.Run("wildcard - simple minimal condition", testParseQuery(`something="another*"`, &ast.Node{ 944 NodeType: ast.NodeTerminal, 945 Comparison: ast.Comparison{ 946 Op: "=", 947 Field: "something", 948 Values: "\"another*\"", 949 }, 950 Left: nil, 951 Right: nil, 952 })) 953 954 t.Run("wildcard - simple minimal condition", testParseQuery(`"another*"`, &ast.Node{ 955 NodeType: ast.NodeTerminal, 956 Comparison: ast.Comparison{ 957 Op: "=", 958 Field: "*", 959 Values: "\"another*\"", 960 }, 961 Left: nil, 962 Right: nil, 963 })) 964 965 t.Run("wildcard - simple minimal condition-no quotes", testParseQuery(`another*`, &ast.Node{ 966 NodeType: ast.NodeTerminal, 967 Comparison: ast.Comparison{ 968 Op: "=", 969 Field: "*", 970 Values: "another*", 971 }, 972 Left: nil, 973 Right: nil, 974 })) 975 976 t.Run("wildcard - simple minimal condition-no quotes", testParseQuery(`another* AND test*`, &ast.Node{ 977 NodeType: ast.NodeAnd, 978 Left: &ast.Node{ 979 NodeType: ast.NodeTerminal, 980 Comparison: ast.Comparison{ 981 Op: "=", 982 Field: "*", 983 Values: "another*", 984 }, 985 }, 986 Right: &ast.Node{ 987 NodeType: ast.NodeTerminal, 988 Comparison: ast.Comparison{ 989 Op: "=", 990 Field: "*", 991 Values: "test*", 992 }, 993 }, 994 })) 995 996 t.Run("wildcard - simple minimal condition-no quotes", testParseQuery(`another* OR test*`, &ast.Node{ 997 NodeType: ast.NodeOr, 998 Left: &ast.Node{ 999 NodeType: ast.NodeTerminal, 1000 Comparison: ast.Comparison{ 1001 Op: "=", 1002 Field: "*", 1003 Values: "another*", 1004 }, 1005 }, 1006 Right: &ast.Node{ 1007 NodeType: ast.NodeTerminal, 1008 Comparison: ast.Comparison{ 1009 Op: "=", 1010 Field: "*", 1011 Values: "test*", 1012 }, 1013 }, 1014 })) 1015 1016 t.Run("column complex value condition", testParseQuery(`something="phrase-with-special-characters"`, &ast.Node{ 1017 NodeType: ast.NodeTerminal, 1018 Comparison: ast.Comparison{ 1019 Op: "=", 1020 Field: "something", 1021 Values: "\"phrase-with-special-characters\"", 1022 }, 1023 Left: nil, 1024 Right: nil, 1025 })) 1026 1027 t.Run("column multi word condition", testParseQuery(`something="phrase with multiple words"`, &ast.Node{ 1028 NodeType: ast.NodeTerminal, 1029 Comparison: ast.Comparison{ 1030 Op: "=", 1031 Field: "something", 1032 Values: "\"phrase with multiple words\"", 1033 }, 1034 Left: nil, 1035 Right: nil, 1036 })) 1037 1038 t.Run("special characters", testParseQuery(`something=AppleWebKit/532.47.1KHTML,likeGecko`, &ast.Node{ 1039 NodeType: ast.NodeTerminal, 1040 Comparison: ast.Comparison{ 1041 Op: "=", 1042 Field: "something", 1043 Values: "AppleWebKit/532.47.1KHTML,likeGecko", 1044 }, 1045 Left: nil, 1046 Right: nil, 1047 })) 1048 1049 t.Run("special characters free text", testParseQuery(`https://peterson.info/`, &ast.Node{ 1050 NodeType: ast.NodeTerminal, 1051 Comparison: ast.Comparison{ 1052 Op: "=", 1053 Field: "*", 1054 Values: "https://peterson.info/", 1055 }, 1056 Left: nil, 1057 Right: nil, 1058 })) 1059 } 1060 1061 func TestAST_simpleAnd_CommandsAgg(t *testing.T) { 1062 json_body := []byte(`name="t1" AND surname="t2" | columns name`) 1063 res, aggNode, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 1064 assert.Nil(t, err) 1065 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 1066 assert.Len(t, res.AndFilterCondition.FilterCriteria, 2) 1067 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "name") 1068 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t1") 1069 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 1070 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "surname") 1071 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t2") 1072 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, Equals) 1073 assert.NotNil(t, aggNode.OutputTransforms) 1074 assert.Len(t, aggNode.OutputTransforms.OutputColumns.IncludeColumns, 1) 1075 assert.Equal(t, aggNode.OutputTransforms.OutputColumns.IncludeColumns[0], "name") 1076 } 1077 1078 func TestAST_blankSearchFilter_CommandsAgg(t *testing.T) { 1079 json_body := []byte(`| columns name`) 1080 res, aggNode, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 1081 assert.Nil(t, err) 1082 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 1083 assert.Len(t, res.AndFilterCondition.FilterCriteria, 1) 1084 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "*") 1085 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "*") 1086 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 1087 assert.NotNil(t, aggNode.OutputTransforms) 1088 assert.Len(t, aggNode.OutputTransforms.OutputColumns.IncludeColumns, 1) 1089 assert.Equal(t, aggNode.OutputTransforms.OutputColumns.IncludeColumns[0], "name") 1090 } 1091 1092 func TestAST_blankSearchFilter_ColumnAgg_List(t *testing.T) { 1093 json_body := []byte(`| columns name,test`) 1094 res, aggNode, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 1095 assert.Nil(t, err) 1096 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 1097 assert.Len(t, res.AndFilterCondition.FilterCriteria, 1) 1098 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "*") 1099 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "*") 1100 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 1101 assert.NotNil(t, aggNode) 1102 assert.NotNil(t, aggNode.OutputTransforms) 1103 assert.Len(t, aggNode.OutputTransforms.OutputColumns.IncludeColumns, 2) 1104 assert.Equal(t, aggNode.OutputTransforms.OutputColumns.IncludeColumns[0], "name") 1105 assert.Equal(t, aggNode.OutputTransforms.OutputColumns.IncludeColumns[1], "test") 1106 } 1107 1108 func TestAST_simpleAnd_SegLevelStats(t *testing.T) { 1109 json_body := []byte(`name="t1" AND surname="t2" | min(latency)`) 1110 res, aggNode, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 1111 assert.Nil(t, err) 1112 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 1113 assert.Len(t, res.AndFilterCondition.FilterCriteria, 2) 1114 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "name") 1115 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t1") 1116 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 1117 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "surname") 1118 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t2") 1119 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, Equals) 1120 assert.NotNil(t, aggNode) 1121 assert.NotNil(t, aggNode.MeasureOperations) 1122 assert.Equal(t, aggNode.MeasureOperations[0].MeasureCol, "latency") 1123 assert.Equal(t, aggNode.MeasureOperations[0].MeasureFunc, utils.Min) 1124 } 1125 1126 func TestAST_blankSearchFilter_SegLevelStats(t *testing.T) { 1127 json_body := []byte(`| max(cnt)`) 1128 res, aggNode, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 1129 assert.Nil(t, err) 1130 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 1131 assert.Len(t, res.AndFilterCondition.FilterCriteria, 1) 1132 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "*") 1133 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "*") 1134 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 1135 assert.NotNil(t, aggNode) 1136 assert.NotNil(t, aggNode.MeasureOperations) 1137 assert.Equal(t, aggNode.MeasureOperations[0].MeasureCol, "cnt") 1138 assert.Equal(t, aggNode.MeasureOperations[0].MeasureFunc, utils.Max) 1139 } 1140 1141 func TestAST_blankSearchFilter_ColumnAgg_ExcludeList(t *testing.T) { 1142 json_body := []byte(`| columns - name,test`) 1143 res, aggNode, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 1144 assert.Nil(t, err) 1145 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 1146 assert.Len(t, res.AndFilterCondition.FilterCriteria, 1) 1147 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "*") 1148 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "*") 1149 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 1150 assert.NotNil(t, aggNode) 1151 assert.NotNil(t, aggNode.OutputTransforms) 1152 assert.Len(t, aggNode.OutputTransforms.OutputColumns.ExcludeColumns, 2) 1153 assert.Equal(t, aggNode.OutputTransforms.OutputColumns.ExcludeColumns[0], "name") 1154 assert.Equal(t, aggNode.OutputTransforms.OutputColumns.ExcludeColumns[1], "test") 1155 } 1156 1157 func TestAST_simpleAnd_ColumnAgg_Rename(t *testing.T) { 1158 json_body := []byte(`name="t1" AND surname="t2" | columns newname = name`) 1159 res, aggNode, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 1160 assert.Nil(t, err) 1161 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 1162 assert.Len(t, res.AndFilterCondition.FilterCriteria, 2) 1163 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "name") 1164 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t1") 1165 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 1166 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "surname") 1167 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t2") 1168 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, Equals) 1169 assert.NotNil(t, aggNode.OutputTransforms) 1170 assert.Len(t, aggNode.OutputTransforms.OutputColumns.RenameColumns, 1) 1171 assert.Equal(t, aggNode.OutputTransforms.OutputColumns.RenameColumns["name"], "newname") 1172 } 1173 1174 func TestAST_simpleAnd_LetAgg_Single(t *testing.T) { 1175 json_body := []byte(`name="t1" AND surname="t2" | let isError=(status >= 399)`) 1176 res, aggNode, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 1177 assert.Nil(t, err) 1178 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 1179 assert.Len(t, res.AndFilterCondition.FilterCriteria, 2) 1180 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "name") 1181 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t1") 1182 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 1183 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "surname") 1184 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t2") 1185 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, Equals) 1186 assert.NotNil(t, aggNode.OutputTransforms) 1187 assert.NotNil(t, aggNode.OutputTransforms.LetColumns) 1188 assert.Equal(t, aggNode.OutputTransforms.LetColumns.NewColName, "isError") 1189 assert.NotNil(t, aggNode.OutputTransforms.LetColumns.SingleColRequest) 1190 assert.Equal(t, aggNode.OutputTransforms.LetColumns.SingleColRequest.CName, "status") 1191 assert.Equal(t, aggNode.OutputTransforms.LetColumns.SingleColRequest.Oper, utils.LogicalAndArithmeticOperator(10)) 1192 assert.Equal(t, aggNode.OutputTransforms.LetColumns.SingleColRequest.Value.UnsignedVal, uint64(399)) 1193 1194 } 1195 1196 func TestAST_simpleAnd_seglevelStats_commaSeparated(t *testing.T) { 1197 json_body := []byte(`name="t1" AND surname="t2" | min(latency),max(latency)`) 1198 res, aggNode, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 1199 assert.Nil(t, err) 1200 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 1201 assert.Len(t, res.AndFilterCondition.FilterCriteria, 2) 1202 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "name") 1203 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t1") 1204 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 1205 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "surname") 1206 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "t2") 1207 assert.Equal(t, res.AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, Equals) 1208 assert.NotNil(t, aggNode.MeasureOperations) 1209 assert.Equal(t, aggNode.MeasureOperations[0].MeasureCol, "latency") 1210 assert.Equal(t, aggNode.MeasureOperations[0].MeasureFunc, utils.Min) 1211 assert.Equal(t, aggNode.MeasureOperations[1].MeasureCol, "latency") 1212 assert.Equal(t, aggNode.MeasureOperations[1].MeasureFunc, utils.Max) 1213 } 1214 1215 func TestAST_GroupByseglevelStats_commaSeparated(t *testing.T) { 1216 json_body := []byte(` min(latency),max(latency) groupby region`) 1217 res, aggNode, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 1218 assert.Nil(t, err) 1219 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 1220 assert.Len(t, res.AndFilterCondition.FilterCriteria, 1) 1221 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "*") 1222 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "*") 1223 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 1224 assert.NotNil(t, aggNode.GroupByRequest) 1225 assert.NotNil(t, aggNode.GroupByRequest.MeasureOperations) 1226 assert.Equal(t, aggNode.GroupByRequest.MeasureOperations[0].MeasureCol, "latency") 1227 assert.Equal(t, aggNode.GroupByRequest.MeasureOperations[0].MeasureFunc, utils.Min) 1228 assert.Equal(t, aggNode.GroupByRequest.MeasureOperations[1].MeasureCol, "latency") 1229 assert.Equal(t, aggNode.GroupByRequest.MeasureOperations[1].MeasureFunc, utils.Max) 1230 assert.NotNil(t, aggNode.GroupByRequest.GroupByColumns) 1231 assert.Equal(t, aggNode.GroupByRequest.GroupByColumns[0], "region") 1232 } 1233 1234 func TestAST_GroupByseglevelStats_commaSeparated_multipleGroups(t *testing.T) { 1235 json_body := []byte(` min(latency),max(latency) groupby region,os_name`) 1236 res, aggNode, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 1237 assert.Nil(t, err) 1238 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 1239 assert.Len(t, res.AndFilterCondition.FilterCriteria, 1) 1240 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "*") 1241 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "*") 1242 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 1243 assert.NotNil(t, aggNode.GroupByRequest) 1244 assert.NotNil(t, aggNode.GroupByRequest.MeasureOperations) 1245 assert.Equal(t, aggNode.GroupByRequest.MeasureOperations[0].MeasureCol, "latency") 1246 assert.Equal(t, aggNode.GroupByRequest.MeasureOperations[0].MeasureFunc, utils.Min) 1247 assert.Equal(t, aggNode.GroupByRequest.MeasureOperations[1].MeasureCol, "latency") 1248 assert.Equal(t, aggNode.GroupByRequest.MeasureOperations[1].MeasureFunc, utils.Max) 1249 assert.NotNil(t, aggNode.GroupByRequest.GroupByColumns) 1250 assert.Equal(t, aggNode.GroupByRequest.GroupByColumns[0], "region") 1251 assert.Equal(t, aggNode.GroupByRequest.GroupByColumns[1], "os_name") 1252 } 1253 1254 func TestAST_GroupByseglevelStats_commaSeparated_multipleGroups_withPipe(t *testing.T) { 1255 json_body := []byte(`| min(latency),max(latency) groupby region,os_name`) 1256 res, aggNode, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 1257 assert.Nil(t, err) 1258 assert.NotNil(t, res.AndFilterCondition.FilterCriteria) 1259 assert.Len(t, res.AndFilterCondition.FilterCriteria, 1) 1260 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "*") 1261 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "*") 1262 assert.Equal(t, res.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, Equals) 1263 assert.NotNil(t, aggNode.GroupByRequest) 1264 assert.NotNil(t, aggNode.GroupByRequest.MeasureOperations) 1265 assert.Equal(t, aggNode.GroupByRequest.MeasureOperations[0].MeasureCol, "latency") 1266 assert.Equal(t, aggNode.GroupByRequest.MeasureOperations[0].MeasureFunc, utils.Min) 1267 assert.Equal(t, aggNode.GroupByRequest.MeasureOperations[1].MeasureCol, "latency") 1268 assert.Equal(t, aggNode.GroupByRequest.MeasureOperations[1].MeasureFunc, utils.Max) 1269 assert.NotNil(t, aggNode.GroupByRequest.GroupByColumns) 1270 assert.Equal(t, aggNode.GroupByRequest.GroupByColumns[0], "region") 1271 assert.Equal(t, aggNode.GroupByRequest.GroupByColumns[1], "os_name") 1272 } 1273 1274 func TestAST_invalidSearch_SegLevelStats(t *testing.T) { 1275 json_body := []byte(`| max(cnt).`) 1276 res, _, err := parsePipeSearch(string(json_body), "Pipe QL", 1) 1277 assert.NotNil(t, err) 1278 assert.Nil(t, res) 1279 }