github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/ast/spl/tests/splParser_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 tests 18 19 import ( 20 "encoding/json" 21 "io" 22 "os" 23 "regexp" 24 "testing" 25 26 "github.com/siglens/siglens/pkg/ast" 27 "github.com/siglens/siglens/pkg/ast/pipesearch" 28 "github.com/siglens/siglens/pkg/ast/spl" 29 segquery "github.com/siglens/siglens/pkg/segment/query" 30 "github.com/siglens/siglens/pkg/segment/structs" 31 "github.com/siglens/siglens/pkg/segment/utils" 32 log "github.com/sirupsen/logrus" 33 "github.com/stretchr/testify/assert" 34 ) 35 36 // Helper functions 37 38 func extractMatchFilter(t *testing.T, node *ast.Node) *structs.MatchFilter { 39 astNode := &structs.ASTNode{} 40 err := pipesearch.SearchQueryToASTnode(node, astNode, 0) 41 assert.Nil(t, err) 42 assert.NotNil(t, astNode.AndFilterCondition) 43 44 criteria := astNode.AndFilterCondition.FilterCriteria 45 assert.NotNil(t, criteria) 46 assert.Equal(t, 1, len(criteria)) 47 assert.Nil(t, criteria[0].ExpressionFilter) 48 49 matchFilter := criteria[0].MatchFilter 50 assert.NotNil(t, matchFilter) 51 52 return matchFilter 53 } 54 55 func extractExpressionFilter(t *testing.T, node *ast.Node) *structs.ExpressionFilter { 56 astNode := &structs.ASTNode{} 57 err := pipesearch.SearchQueryToASTnode(node, astNode, 0) 58 assert.Nil(t, err) 59 assert.NotNil(t, astNode.AndFilterCondition) 60 61 criteria := astNode.AndFilterCondition.FilterCriteria 62 assert.NotNil(t, criteria) 63 assert.Equal(t, 1, len(criteria)) 64 assert.Nil(t, criteria[0].MatchFilter) 65 66 expressionFilter := criteria[0].ExpressionFilter 67 assert.NotNil(t, expressionFilter) 68 69 return expressionFilter 70 } 71 72 // Initial setup. 73 func TestMain(m *testing.M) { 74 // Suppress log output. 75 log.SetOutput(io.Discard) 76 77 // Run the tests. 78 os.Exit(m.Run()) 79 } 80 81 // Tests 82 83 func Test_searchQuotedStringNoBreakers(t *testing.T) { 84 query := []byte(`search "abc"`) 85 res, err := spl.Parse("", query) 86 assert.Nil(t, err) 87 filterNode := res.(ast.QueryStruct).SearchFilter 88 89 assert.NotNil(t, filterNode) 90 assert.Equal(t, filterNode.Comparison.Op, "=") 91 assert.Equal(t, filterNode.Comparison.Field, "*") 92 assert.Equal(t, filterNode.Comparison.Values, `"abc"`) 93 94 matchFilter := extractMatchFilter(t, filterNode) 95 assert.Equal(t, structs.MATCH_PHRASE, matchFilter.MatchType) 96 97 // Note: the double quotes got stripped off in ast.ProcessSingleFilter(), so 98 // it's just abc and not "abc" 99 assert.Equal(t, []byte(`abc`), matchFilter.MatchPhrase) 100 } 101 102 func Test_searchQuotedStringMinorBreakers(t *testing.T) { 103 query := []byte(`search "abc./\\:=@#$%-_DEF"`) 104 res, err := spl.Parse("", query) 105 assert.Nil(t, err) 106 filterNode := res.(ast.QueryStruct).SearchFilter 107 108 assert.NotNil(t, filterNode) 109 assert.Equal(t, filterNode.Comparison.Op, "=") 110 assert.Equal(t, filterNode.Comparison.Field, "*") 111 assert.Equal(t, filterNode.Comparison.Values, `"abc./\\:=@#$%-_DEF"`) 112 113 matchFilter := extractMatchFilter(t, filterNode) 114 assert.Equal(t, structs.MATCH_PHRASE, matchFilter.MatchType) 115 assert.Equal(t, []byte(`abc./\\:=@#$%-_DEF`), matchFilter.MatchPhrase) 116 } 117 118 func Test_searchQuotedStringMajorBreakers(t *testing.T) { 119 query := []byte(`search "abc DEF < > [ ] ( ) { } ! ? ; , ' &"`) 120 res, err := spl.Parse("", query) 121 assert.Nil(t, err) 122 filterNode := res.(ast.QueryStruct).SearchFilter 123 124 assert.NotNil(t, filterNode) 125 assert.Equal(t, filterNode.Comparison.Op, "=") 126 assert.Equal(t, filterNode.Comparison.Field, "*") 127 assert.Equal(t, filterNode.Comparison.Values, `"abc DEF < > [ ] ( ) { } ! ? ; , ' &"`) 128 129 matchFilter := extractMatchFilter(t, filterNode) 130 assert.Equal(t, structs.MATCH_PHRASE, matchFilter.MatchType) 131 assert.Equal(t, []byte(`abc DEF < > [ ] ( ) { } ! ? ; , ' &`), matchFilter.MatchPhrase) 132 } 133 134 func Test_impliedSearchCommand(t *testing.T) { 135 query := []byte(`"apple"`) 136 res, err := spl.Parse("", query) 137 assert.Nil(t, err) 138 filterNode := res.(ast.QueryStruct).SearchFilter 139 140 assert.NotNil(t, filterNode) 141 assert.Equal(t, filterNode.Comparison.Op, "=") 142 assert.Equal(t, filterNode.Comparison.Field, "*") 143 assert.Equal(t, filterNode.Comparison.Values, `"apple"`) 144 145 matchFilter := extractMatchFilter(t, filterNode) 146 assert.Equal(t, structs.MATCH_PHRASE, matchFilter.MatchType) 147 assert.Equal(t, []byte(`apple`), matchFilter.MatchPhrase) 148 } 149 150 func Test_searchUnquotedStringNoBreakers(t *testing.T) { 151 query := []byte(`search abc`) 152 res, err := spl.Parse("", query) 153 assert.Nil(t, err) 154 filterNode := res.(ast.QueryStruct).SearchFilter 155 156 assert.NotNil(t, filterNode) 157 assert.Equal(t, filterNode.Comparison.Op, "=") 158 assert.Equal(t, filterNode.Comparison.Field, "*") 159 assert.Equal(t, filterNode.Comparison.Values, `"abc"`) 160 161 matchFilter := extractMatchFilter(t, filterNode) 162 assert.Equal(t, structs.MATCH_PHRASE, matchFilter.MatchType) 163 assert.Equal(t, []byte(`abc`), matchFilter.MatchPhrase) 164 } 165 166 func Test_searchUnquotedStringMinorBreakers(t *testing.T) { 167 query := []byte(`search "abc./\\:=@#$%-_DEF"`) 168 res, err := spl.Parse("", query) 169 assert.Nil(t, err) 170 filterNode := res.(ast.QueryStruct).SearchFilter 171 172 assert.NotNil(t, filterNode) 173 assert.Equal(t, filterNode.Comparison.Op, "=") 174 assert.Equal(t, filterNode.Comparison.Field, "*") 175 assert.Equal(t, filterNode.Comparison.Values, `"abc./\\:=@#$%-_DEF"`) 176 177 matchFilter := extractMatchFilter(t, filterNode) 178 assert.Equal(t, structs.MATCH_PHRASE, matchFilter.MatchType) 179 assert.Equal(t, []byte(`abc./\\:=@#$%-_DEF`), matchFilter.MatchPhrase) 180 } 181 182 func Test_searchUnquotedStringMajorBreakerAtStart(t *testing.T) { 183 query := []byte(`search &abcDEF`) 184 res, err := spl.Parse("", query) 185 assert.Nil(t, res) 186 assert.NotNil(t, err) 187 } 188 189 func Test_searchUnquotedStringMajorBreakerInMiddle(t *testing.T) { 190 query := []byte(`search abc(DEF`) 191 res, err := spl.Parse("", query) 192 assert.Nil(t, res) 193 assert.NotNil(t, err) 194 } 195 196 func Test_searchUnquotedStringMajorBreakerAtEnd(t *testing.T) { 197 query := []byte(`search &abcDEF%26`) 198 res, err := spl.Parse("", query) 199 assert.Nil(t, res) 200 assert.NotNil(t, err) 201 } 202 203 func Test_searchFieldEqualToQuotedString(t *testing.T) { 204 query := []byte(`search status="ok"`) 205 res, err := spl.Parse("", query) 206 assert.Nil(t, err) 207 filterNode := res.(ast.QueryStruct).SearchFilter 208 209 assert.NotNil(t, filterNode) 210 assert.Equal(t, "=", filterNode.Comparison.Op) 211 assert.Equal(t, "status", filterNode.Comparison.Field) 212 assert.Equal(t, `"ok"`, filterNode.Comparison.Values) 213 214 expressionFilter := extractExpressionFilter(t, filterNode) 215 assert.Equal(t, "status", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 216 assert.Equal(t, utils.Equals, expressionFilter.FilterOperator) 217 assert.Equal(t, "ok", expressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal) 218 } 219 220 func Test_searchFieldNotEqualToQuotedString(t *testing.T) { 221 query := []byte(`search status!="ok"`) 222 res, err := spl.Parse("", query) 223 assert.Nil(t, err) 224 filterNode := res.(ast.QueryStruct).SearchFilter 225 226 assert.NotNil(t, filterNode) 227 assert.Equal(t, "!=", filterNode.Comparison.Op) 228 assert.Equal(t, "status", filterNode.Comparison.Field) 229 assert.Equal(t, `"ok"`, filterNode.Comparison.Values) 230 231 expressionFilter := extractExpressionFilter(t, filterNode) 232 assert.Equal(t, "status", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 233 assert.Equal(t, utils.NotEquals, expressionFilter.FilterOperator) 234 assert.Equal(t, "ok", expressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal) 235 } 236 237 func Test_searchFieldLessThanQuotedString(t *testing.T) { 238 query := []byte(`search status<"ok"`) 239 res, err := spl.Parse("", query) 240 assert.Nil(t, res) 241 assert.NotNil(t, err) 242 } 243 244 func Test_searchFieldLessThanOrEqualToQuotedString(t *testing.T) { 245 query := []byte(`search status<="ok"`) 246 res, err := spl.Parse("", query) 247 assert.Nil(t, res) 248 assert.NotNil(t, err) 249 } 250 251 func Test_searchFieldGreaterThanThanQuotedString(t *testing.T) { 252 query := []byte(`search status>"ok"`) 253 res, err := spl.Parse("", query) 254 assert.Nil(t, res) 255 assert.NotNil(t, err) 256 } 257 258 func Test_searchFieldGreaterThanOrEqualToQuotedString(t *testing.T) { 259 query := []byte(`search status>="ok"`) 260 res, err := spl.Parse("", query) 261 assert.Nil(t, res) 262 assert.NotNil(t, err) 263 } 264 265 func Test_searchFieldEqualToBooleanTrue(t *testing.T) { 266 query := []byte(`search status=true`) 267 res, err := spl.Parse("", query) 268 assert.Nil(t, err) 269 filterNode := res.(ast.QueryStruct).SearchFilter 270 271 assert.NotNil(t, filterNode) 272 assert.Equal(t, "=", filterNode.Comparison.Op) 273 assert.Equal(t, "status", filterNode.Comparison.Field) 274 assert.Equal(t, true, filterNode.Comparison.Values) 275 276 expressionFilter := extractExpressionFilter(t, filterNode) 277 assert.Equal(t, "status", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 278 assert.Equal(t, utils.Equals, expressionFilter.FilterOperator) 279 assert.Equal(t, uint8(1), expressionFilter.RightInput.Expression.LeftInput.ColumnValue.BoolVal) 280 } 281 282 func Test_searchFieldEqualToBooleanFalse(t *testing.T) { 283 query := []byte(`search status=false`) 284 res, err := spl.Parse("", query) 285 assert.Nil(t, err) 286 filterNode := res.(ast.QueryStruct).SearchFilter 287 288 assert.NotNil(t, filterNode) 289 assert.Equal(t, "=", filterNode.Comparison.Op) 290 assert.Equal(t, "status", filterNode.Comparison.Field) 291 assert.Equal(t, false, filterNode.Comparison.Values) 292 293 expressionFilter := extractExpressionFilter(t, filterNode) 294 assert.Equal(t, "status", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 295 assert.Equal(t, utils.Equals, expressionFilter.FilterOperator) 296 assert.Equal(t, uint8(0), expressionFilter.RightInput.Expression.LeftInput.ColumnValue.BoolVal) 297 } 298 299 func Test_searchFieldEqualToUnquotedString(t *testing.T) { 300 query := []byte(`search status=ok`) 301 res, err := spl.Parse("", query) 302 assert.Nil(t, err) 303 filterNode := res.(ast.QueryStruct).SearchFilter 304 305 assert.NotNil(t, filterNode) 306 assert.Equal(t, "=", filterNode.Comparison.Op) 307 assert.Equal(t, "status", filterNode.Comparison.Field) 308 assert.Equal(t, `"ok"`, filterNode.Comparison.Values) 309 310 expressionFilter := extractExpressionFilter(t, filterNode) 311 assert.Equal(t, "status", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 312 assert.Equal(t, utils.Equals, expressionFilter.FilterOperator) 313 assert.Equal(t, "ok", expressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal) 314 } 315 316 func Test_searchFieldNotEqualToUnquotedString(t *testing.T) { 317 query := []byte(`search status!=ok`) 318 res, err := spl.Parse("", query) 319 assert.Nil(t, err) 320 filterNode := res.(ast.QueryStruct).SearchFilter 321 322 assert.NotNil(t, filterNode) 323 assert.Equal(t, "!=", filterNode.Comparison.Op) 324 assert.Equal(t, "status", filterNode.Comparison.Field) 325 assert.Equal(t, `"ok"`, filterNode.Comparison.Values) 326 327 expressionFilter := extractExpressionFilter(t, filterNode) 328 assert.Equal(t, "status", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 329 assert.Equal(t, utils.NotEquals, expressionFilter.FilterOperator) 330 assert.Equal(t, "ok", expressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal) 331 } 332 333 func Test_searchFieldLessThanUnquotedString(t *testing.T) { 334 query := []byte(`search status<ok`) 335 res, err := spl.Parse("", query) 336 assert.Nil(t, res) 337 assert.NotNil(t, err) 338 } 339 340 func Test_searchFieldLessThanOrEqualToUnquotedString(t *testing.T) { 341 query := []byte(`search status<=ok`) 342 res, err := spl.Parse("", query) 343 assert.Nil(t, res) 344 assert.NotNil(t, err) 345 } 346 347 func Test_searchFieldGreaterThanThanUnquotedString(t *testing.T) { 348 query := []byte(`search status>ok`) 349 res, err := spl.Parse("", query) 350 assert.Nil(t, res) 351 assert.NotNil(t, err) 352 } 353 354 func Test_searchFieldGreaterThanOrEqualToUnquotedString(t *testing.T) { 355 query := []byte(`search status>=ok`) 356 res, err := spl.Parse("", query) 357 assert.Nil(t, res) 358 assert.NotNil(t, err) 359 } 360 361 func Test_searchInteger(t *testing.T) { 362 query := []byte(`search 123`) 363 res, err := spl.Parse("", query) 364 assert.Nil(t, err) 365 filterNode := res.(ast.QueryStruct).SearchFilter 366 367 assert.NotNil(t, filterNode) 368 assert.Equal(t, "=", filterNode.Comparison.Op) 369 assert.Equal(t, "*", filterNode.Comparison.Field) 370 assert.Equal(t, json.Number("123"), filterNode.Comparison.Values) 371 372 expressionFilter := extractExpressionFilter(t, filterNode) 373 assert.Equal(t, "*", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 374 assert.Equal(t, utils.Equals, expressionFilter.FilterOperator) 375 dtype, err := utils.CreateDtypeEnclosure(json.Number("123"), 0 /* qid */) 376 assert.Nil(t, err) 377 assert.Equal(t, dtype, expressionFilter.RightInput.Expression.LeftInput.ColumnValue) 378 } 379 380 func Test_searchIntegerLeadingZeros(t *testing.T) { 381 query := []byte(`search 00123`) 382 res, err := spl.Parse("", query) 383 assert.Nil(t, err) 384 filterNode := res.(ast.QueryStruct).SearchFilter 385 386 assert.NotNil(t, filterNode) 387 assert.Equal(t, "=", filterNode.Comparison.Op) 388 assert.Equal(t, "*", filterNode.Comparison.Field) 389 assert.Equal(t, json.Number("00123"), filterNode.Comparison.Values) 390 391 expressionFilter := extractExpressionFilter(t, filterNode) 392 assert.Equal(t, "*", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 393 assert.Equal(t, utils.Equals, expressionFilter.FilterOperator) 394 dtype, err := utils.CreateDtypeEnclosure(json.Number("00123"), 0 /* qid */) 395 assert.Nil(t, err) 396 assert.Equal(t, dtype, expressionFilter.RightInput.Expression.LeftInput.ColumnValue) 397 } 398 399 func Test_searchIntegerLeadingPlusSign(t *testing.T) { 400 query := []byte(`search +123`) 401 res, err := spl.Parse("", query) 402 assert.Nil(t, err) 403 filterNode := res.(ast.QueryStruct).SearchFilter 404 405 assert.NotNil(t, filterNode) 406 assert.Equal(t, "=", filterNode.Comparison.Op) 407 assert.Equal(t, "*", filterNode.Comparison.Field) 408 assert.Equal(t, json.Number("+123"), filterNode.Comparison.Values) 409 410 expressionFilter := extractExpressionFilter(t, filterNode) 411 assert.Equal(t, "*", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 412 assert.Equal(t, utils.Equals, expressionFilter.FilterOperator) 413 dtype, err := utils.CreateDtypeEnclosure(json.Number("+123"), 0 /* qid */) 414 assert.Nil(t, err) 415 assert.Equal(t, dtype, expressionFilter.RightInput.Expression.LeftInput.ColumnValue) 416 } 417 418 func Test_searchNegativeInteger(t *testing.T) { 419 query := []byte(`search -123`) 420 res, err := spl.Parse("", query) 421 assert.Nil(t, err) 422 filterNode := res.(ast.QueryStruct).SearchFilter 423 424 assert.NotNil(t, filterNode) 425 assert.Equal(t, "=", filterNode.Comparison.Op) 426 assert.Equal(t, "*", filterNode.Comparison.Field) 427 assert.Equal(t, json.Number("-123"), filterNode.Comparison.Values) 428 429 expressionFilter := extractExpressionFilter(t, filterNode) 430 assert.Equal(t, "*", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 431 assert.Equal(t, utils.Equals, expressionFilter.FilterOperator) 432 dtype, err := utils.CreateDtypeEnclosure(json.Number("-123"), 0 /* qid */) 433 assert.Nil(t, err) 434 assert.Equal(t, dtype, expressionFilter.RightInput.Expression.LeftInput.ColumnValue) 435 } 436 437 func Test_searchFloat(t *testing.T) { 438 query := []byte(`search 123.5`) 439 res, err := spl.Parse("", query) 440 assert.Nil(t, err) 441 filterNode := res.(ast.QueryStruct).SearchFilter 442 443 assert.NotNil(t, filterNode) 444 assert.Equal(t, "=", filterNode.Comparison.Op) 445 assert.Equal(t, "*", filterNode.Comparison.Field) 446 assert.Equal(t, json.Number("123.5"), filterNode.Comparison.Values) 447 448 expressionFilter := extractExpressionFilter(t, filterNode) 449 assert.Equal(t, "*", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 450 assert.Equal(t, utils.Equals, expressionFilter.FilterOperator) 451 dtype, err := utils.CreateDtypeEnclosure(json.Number("123.5"), 0 /* qid */) 452 assert.Nil(t, err) 453 assert.Equal(t, dtype, expressionFilter.RightInput.Expression.LeftInput.ColumnValue) 454 } 455 456 func Test_searchFloatLeadingDecimal(t *testing.T) { 457 query := []byte(`search .375`) 458 res, err := spl.Parse("", query) 459 assert.Nil(t, err) 460 filterNode := res.(ast.QueryStruct).SearchFilter 461 462 assert.NotNil(t, filterNode) 463 assert.Equal(t, "=", filterNode.Comparison.Op) 464 assert.Equal(t, "*", filterNode.Comparison.Field) 465 assert.Equal(t, json.Number(".375"), filterNode.Comparison.Values) 466 467 expressionFilter := extractExpressionFilter(t, filterNode) 468 assert.Equal(t, "*", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 469 assert.Equal(t, utils.Equals, expressionFilter.FilterOperator) 470 dtype, err := utils.CreateDtypeEnclosure(json.Number(".375"), 0 /* qid */) 471 assert.Nil(t, err) 472 assert.Equal(t, dtype, expressionFilter.RightInput.Expression.LeftInput.ColumnValue) 473 } 474 475 func Test_searchFloatLeadingPlusSign(t *testing.T) { 476 query := []byte(`search +0.375`) 477 res, err := spl.Parse("", query) 478 assert.Nil(t, err) 479 filterNode := res.(ast.QueryStruct).SearchFilter 480 481 assert.NotNil(t, filterNode) 482 assert.Equal(t, "=", filterNode.Comparison.Op) 483 assert.Equal(t, "*", filterNode.Comparison.Field) 484 assert.Equal(t, json.Number("+0.375"), filterNode.Comparison.Values) 485 486 expressionFilter := extractExpressionFilter(t, filterNode) 487 assert.Equal(t, "*", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 488 assert.Equal(t, utils.Equals, expressionFilter.FilterOperator) 489 dtype, err := utils.CreateDtypeEnclosure(json.Number("+0.375"), 0 /* qid */) 490 assert.Nil(t, err) 491 assert.Equal(t, dtype, expressionFilter.RightInput.Expression.LeftInput.ColumnValue) 492 } 493 494 func Test_searchFieldEqualToNumber(t *testing.T) { 495 query := []byte(`search status=400`) 496 res, err := spl.Parse("", query) 497 assert.Nil(t, err) 498 filterNode := res.(ast.QueryStruct).SearchFilter 499 500 assert.NotNil(t, filterNode) 501 assert.Equal(t, "=", filterNode.Comparison.Op) 502 assert.Equal(t, "status", filterNode.Comparison.Field) 503 assert.Equal(t, json.Number("400"), filterNode.Comparison.Values) 504 505 expressionFilter := extractExpressionFilter(t, filterNode) 506 assert.Equal(t, "status", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 507 assert.Equal(t, utils.Equals, expressionFilter.FilterOperator) 508 dtype, err := utils.CreateDtypeEnclosure(json.Number("400"), 0 /* qid */) 509 assert.Nil(t, err) 510 assert.Equal(t, dtype, expressionFilter.RightInput.Expression.LeftInput.ColumnValue) 511 } 512 513 func Test_searchFieldNotEqualToNumber(t *testing.T) { 514 query := []byte(`search status!=400`) 515 res, err := spl.Parse("", query) 516 assert.Nil(t, err) 517 filterNode := res.(ast.QueryStruct).SearchFilter 518 519 assert.NotNil(t, filterNode) 520 assert.Equal(t, "!=", filterNode.Comparison.Op) 521 assert.Equal(t, "status", filterNode.Comparison.Field) 522 assert.Equal(t, json.Number("400"), filterNode.Comparison.Values) 523 524 expressionFilter := extractExpressionFilter(t, filterNode) 525 assert.Equal(t, "status", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 526 assert.Equal(t, utils.NotEquals, expressionFilter.FilterOperator) 527 dtype, err := utils.CreateDtypeEnclosure(json.Number("400"), 0 /* qid */) 528 assert.Nil(t, err) 529 assert.Equal(t, dtype, expressionFilter.RightInput.Expression.LeftInput.ColumnValue) 530 } 531 532 func Test_searchFieldLessThanNumber(t *testing.T) { 533 query := []byte(`search latency<1000`) 534 res, err := spl.Parse("", query) 535 assert.Nil(t, err) 536 filterNode := res.(ast.QueryStruct).SearchFilter 537 538 assert.NotNil(t, filterNode) 539 assert.Equal(t, "<", filterNode.Comparison.Op) 540 assert.Equal(t, "latency", filterNode.Comparison.Field) 541 assert.Equal(t, json.Number("1000"), filterNode.Comparison.Values) 542 543 expressionFilter := extractExpressionFilter(t, filterNode) 544 assert.Equal(t, "latency", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 545 assert.Equal(t, utils.LessThan, expressionFilter.FilterOperator) 546 dtype, err := utils.CreateDtypeEnclosure(json.Number("1000"), 0 /* qid */) 547 assert.Nil(t, err) 548 assert.Equal(t, dtype, expressionFilter.RightInput.Expression.LeftInput.ColumnValue) 549 } 550 551 func Test_searchFieldLessThanOrEqualToNumber(t *testing.T) { 552 query := []byte(`search latency<=0.5`) 553 res, err := spl.Parse("", query) 554 assert.Nil(t, err) 555 filterNode := res.(ast.QueryStruct).SearchFilter 556 557 assert.NotNil(t, filterNode) 558 assert.Equal(t, "<=", filterNode.Comparison.Op) 559 assert.Equal(t, "latency", filterNode.Comparison.Field) 560 assert.Equal(t, json.Number("0.5"), filterNode.Comparison.Values) 561 562 expressionFilter := extractExpressionFilter(t, filterNode) 563 assert.Equal(t, "latency", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 564 assert.Equal(t, utils.LessThanOrEqualTo, expressionFilter.FilterOperator) 565 dtype, err := utils.CreateDtypeEnclosure(json.Number("0.5"), 0 /* qid */) 566 assert.Nil(t, err) 567 assert.Equal(t, dtype, expressionFilter.RightInput.Expression.LeftInput.ColumnValue) 568 } 569 570 func Test_searchFieldGreaterThanNumber(t *testing.T) { 571 query := []byte(`search latency>3.175`) 572 res, err := spl.Parse("", query) 573 assert.Nil(t, err) 574 filterNode := res.(ast.QueryStruct).SearchFilter 575 576 assert.NotNil(t, filterNode) 577 assert.Equal(t, ">", filterNode.Comparison.Op) 578 assert.Equal(t, "latency", filterNode.Comparison.Field) 579 assert.Equal(t, json.Number("3.175"), filterNode.Comparison.Values) 580 581 expressionFilter := extractExpressionFilter(t, filterNode) 582 assert.Equal(t, "latency", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 583 assert.Equal(t, utils.GreaterThan, expressionFilter.FilterOperator) 584 dtype, err := utils.CreateDtypeEnclosure(json.Number("3.175"), 0 /* qid */) 585 assert.Nil(t, err) 586 assert.Equal(t, dtype, expressionFilter.RightInput.Expression.LeftInput.ColumnValue) 587 } 588 589 func Test_searchFieldGreaterThanOrEqualToNumber(t *testing.T) { 590 query := []byte(`search latency>=1200`) 591 res, err := spl.Parse("", query) 592 assert.Nil(t, err) 593 filterNode := res.(ast.QueryStruct).SearchFilter 594 595 assert.NotNil(t, filterNode) 596 assert.Equal(t, ">=", filterNode.Comparison.Op) 597 assert.Equal(t, "latency", filterNode.Comparison.Field) 598 assert.Equal(t, json.Number("1200"), filterNode.Comparison.Values) 599 600 expressionFilter := extractExpressionFilter(t, filterNode) 601 assert.Equal(t, "latency", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 602 assert.Equal(t, utils.GreaterThanOrEqualTo, expressionFilter.FilterOperator) 603 dtype, err := utils.CreateDtypeEnclosure(json.Number("1200"), 0 /* qid */) 604 assert.Nil(t, err) 605 assert.Equal(t, dtype, expressionFilter.RightInput.Expression.LeftInput.ColumnValue) 606 } 607 608 func Test_searchSimpleAND(t *testing.T) { 609 query := []byte(`search status=ok AND latency<1000`) 610 res, err := spl.Parse("", query) 611 assert.Nil(t, err) 612 filterNode := res.(ast.QueryStruct).SearchFilter 613 614 assert.NotNil(t, filterNode) 615 assert.Equal(t, filterNode.NodeType, ast.NodeAnd) 616 617 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 618 assert.Equal(t, filterNode.Left.Comparison.Field, "status") 619 assert.Equal(t, filterNode.Left.Comparison.Op, "=") 620 assert.Equal(t, filterNode.Left.Comparison.Values, `"ok"`) 621 622 assert.Equal(t, filterNode.Right.NodeType, ast.NodeTerminal) 623 assert.Equal(t, filterNode.Right.Comparison.Field, "latency") 624 assert.Equal(t, filterNode.Right.Comparison.Op, "<") 625 assert.Equal(t, filterNode.Right.Comparison.Values, json.Number("1000")) 626 627 astNode := &structs.ASTNode{} 628 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 629 assert.Nil(t, err) 630 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 631 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 2) 632 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "status") 633 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 634 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "ok") 635 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "latency") 636 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.LessThan) 637 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1000)) 638 } 639 640 func Test_searchChainedAND(t *testing.T) { 641 query := []byte(`search A=1 AND B=2 AND C=3`) 642 res, err := spl.Parse("", query) 643 assert.Nil(t, err) 644 filterNode := res.(ast.QueryStruct).SearchFilter 645 646 assert.NotNil(t, filterNode) 647 assert.Equal(t, ast.NodeAnd, filterNode.NodeType) 648 assert.Equal(t, ast.NodeAnd, filterNode.Left.NodeType) 649 650 assert.Equal(t, filterNode.Left.Left.NodeType, ast.NodeTerminal) 651 assert.Equal(t, filterNode.Left.Left.Comparison.Field, "A") 652 assert.Equal(t, filterNode.Left.Left.Comparison.Op, "=") 653 assert.Equal(t, filterNode.Left.Left.Comparison.Values, json.Number("1")) 654 655 assert.Equal(t, filterNode.Left.Right.NodeType, ast.NodeTerminal) 656 assert.Equal(t, filterNode.Left.Right.Comparison.Field, "B") 657 assert.Equal(t, filterNode.Left.Right.Comparison.Op, "=") 658 assert.Equal(t, filterNode.Left.Right.Comparison.Values, json.Number("2")) 659 660 assert.Equal(t, filterNode.Right.NodeType, ast.NodeTerminal) 661 assert.Equal(t, filterNode.Right.Comparison.Field, "C") 662 assert.Equal(t, filterNode.Right.Comparison.Op, "=") 663 assert.Equal(t, filterNode.Right.Comparison.Values, json.Number("3")) 664 665 astNode := &structs.ASTNode{} 666 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 667 assert.Nil(t, err) 668 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 669 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 670 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "C") 671 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 672 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(3)) 673 assert.Len(t, astNode.AndFilterCondition.NestedNodes, 1) 674 assert.Len(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria, 2) 675 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 676 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 677 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 678 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "B") 679 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 680 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(2)) 681 } 682 683 func Test_searchSimpleOR(t *testing.T) { 684 query := []byte(`search status=ok OR latency<1000`) 685 res, err := spl.Parse("", query) 686 assert.Nil(t, err) 687 filterNode := res.(ast.QueryStruct).SearchFilter 688 689 assert.NotNil(t, filterNode) 690 assert.Equal(t, filterNode.NodeType, ast.NodeOr) 691 692 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 693 assert.Equal(t, filterNode.Left.Comparison.Field, "status") 694 assert.Equal(t, filterNode.Left.Comparison.Op, "=") 695 assert.Equal(t, filterNode.Left.Comparison.Values, `"ok"`) 696 697 assert.Equal(t, filterNode.Right.NodeType, ast.NodeTerminal) 698 assert.Equal(t, filterNode.Right.Comparison.Field, "latency") 699 assert.Equal(t, filterNode.Right.Comparison.Op, "<") 700 assert.Equal(t, filterNode.Right.Comparison.Values, json.Number("1000")) 701 702 astNode := &structs.ASTNode{} 703 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 704 assert.Nil(t, err) 705 assert.NotNil(t, astNode.OrFilterCondition.FilterCriteria) 706 assert.Len(t, astNode.OrFilterCondition.FilterCriteria, 2) 707 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "status") 708 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 709 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "ok") 710 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "latency") 711 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.LessThan) 712 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1000)) 713 } 714 715 func Test_searchChainedOR(t *testing.T) { 716 query := []byte(`search A=1 OR B=2 OR C=3`) 717 res, err := spl.Parse("", query) 718 assert.Nil(t, err) 719 filterNode := res.(ast.QueryStruct).SearchFilter 720 721 assert.NotNil(t, filterNode) 722 assert.Equal(t, ast.NodeOr, filterNode.NodeType) 723 assert.Equal(t, ast.NodeOr, filterNode.Left.NodeType) 724 725 assert.Equal(t, filterNode.Left.Left.NodeType, ast.NodeTerminal) 726 assert.Equal(t, filterNode.Left.Left.Comparison.Field, "A") 727 assert.Equal(t, filterNode.Left.Left.Comparison.Op, "=") 728 assert.Equal(t, filterNode.Left.Left.Comparison.Values, json.Number("1")) 729 730 assert.Equal(t, filterNode.Left.Right.NodeType, ast.NodeTerminal) 731 assert.Equal(t, filterNode.Left.Right.Comparison.Field, "B") 732 assert.Equal(t, filterNode.Left.Right.Comparison.Op, "=") 733 assert.Equal(t, filterNode.Left.Right.Comparison.Values, json.Number("2")) 734 735 assert.Equal(t, filterNode.Right.NodeType, ast.NodeTerminal) 736 assert.Equal(t, filterNode.Right.Comparison.Field, "C") 737 assert.Equal(t, filterNode.Right.Comparison.Op, "=") 738 assert.Equal(t, filterNode.Right.Comparison.Values, json.Number("3")) 739 740 astNode := &structs.ASTNode{} 741 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 742 assert.Nil(t, err) 743 assert.NotNil(t, astNode.OrFilterCondition.FilterCriteria) 744 assert.Len(t, astNode.OrFilterCondition.FilterCriteria, 1) 745 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "C") 746 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 747 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(3)) 748 assert.Len(t, astNode.OrFilterCondition.NestedNodes, 1) 749 assert.Len(t, astNode.OrFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria, 2) 750 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 751 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 752 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 753 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "B") 754 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 755 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(2)) 756 } 757 758 func Test_searchANDThenOR(t *testing.T) { 759 // This should be parsed as `A=1 AND (B=2 OR C=3)`. 760 query := []byte(`search A=1 AND B=2 OR C=3`) 761 res, err := spl.Parse("", query) 762 assert.Nil(t, err) 763 filterNode := res.(ast.QueryStruct).SearchFilter 764 765 assert.NotNil(t, filterNode) 766 assert.Equal(t, filterNode.NodeType, ast.NodeAnd) 767 assert.Equal(t, filterNode.Right.NodeType, ast.NodeOr) 768 769 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 770 assert.Equal(t, filterNode.Left.Comparison.Field, "A") 771 assert.Equal(t, filterNode.Left.Comparison.Op, "=") 772 assert.Equal(t, filterNode.Left.Comparison.Values, json.Number("1")) 773 774 assert.Equal(t, filterNode.Right.Left.NodeType, ast.NodeTerminal) 775 assert.Equal(t, filterNode.Right.Left.Comparison.Field, "B") 776 assert.Equal(t, filterNode.Right.Left.Comparison.Op, "=") 777 assert.Equal(t, filterNode.Right.Left.Comparison.Values, json.Number("2")) 778 779 assert.Equal(t, filterNode.Right.Right.NodeType, ast.NodeTerminal) 780 assert.Equal(t, filterNode.Right.Right.Comparison.Field, "C") 781 assert.Equal(t, filterNode.Right.Right.Comparison.Op, "=") 782 assert.Equal(t, filterNode.Right.Right.Comparison.Values, json.Number("3")) 783 784 astNode := &structs.ASTNode{} 785 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 786 assert.Nil(t, err) 787 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 788 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 789 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 790 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 791 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 792 assert.Len(t, astNode.AndFilterCondition.NestedNodes, 1) 793 assert.Len(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria, 2) 794 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "B") 795 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 796 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(2)) 797 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "C") 798 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 799 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(3)) 800 } 801 802 func Test_searchORThenAND(t *testing.T) { 803 // This should be parsed as `(A=1 OR B=2) AND C=3`. 804 query := []byte(`search A=1 OR B=2 AND C=3`) 805 res, err := spl.Parse("", query) 806 assert.Nil(t, err) 807 filterNode := res.(ast.QueryStruct).SearchFilter 808 809 assert.NotNil(t, filterNode) 810 assert.Equal(t, filterNode.NodeType, ast.NodeAnd) 811 assert.Equal(t, filterNode.Left.NodeType, ast.NodeOr) 812 813 assert.Equal(t, filterNode.Left.Left.NodeType, ast.NodeTerminal) 814 assert.Equal(t, filterNode.Left.Left.Comparison.Field, "A") 815 assert.Equal(t, filterNode.Left.Left.Comparison.Op, "=") 816 assert.Equal(t, filterNode.Left.Left.Comparison.Values, json.Number("1")) 817 818 assert.Equal(t, filterNode.Left.Right.NodeType, ast.NodeTerminal) 819 assert.Equal(t, filterNode.Left.Right.Comparison.Field, "B") 820 assert.Equal(t, filterNode.Left.Right.Comparison.Op, "=") 821 assert.Equal(t, filterNode.Left.Right.Comparison.Values, json.Number("2")) 822 823 assert.Equal(t, filterNode.Right.NodeType, ast.NodeTerminal) 824 assert.Equal(t, filterNode.Right.Comparison.Field, "C") 825 assert.Equal(t, filterNode.Right.Comparison.Op, "=") 826 assert.Equal(t, filterNode.Right.Comparison.Values, json.Number("3")) 827 828 astNode := &structs.ASTNode{} 829 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 830 assert.Nil(t, err) 831 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 832 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 833 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "C") 834 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 835 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(3)) 836 assert.Len(t, astNode.AndFilterCondition.NestedNodes, 1) 837 assert.Len(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria, 2) 838 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 839 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 840 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 841 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "B") 842 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 843 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(2)) 844 } 845 846 func Test_SimpleParentheses(t *testing.T) { 847 query := []byte(`search (status="ok")`) 848 res, err := spl.Parse("", query) 849 assert.Nil(t, err) 850 filterNode := res.(ast.QueryStruct).SearchFilter 851 852 assert.NotNil(t, filterNode) 853 assert.Equal(t, "=", filterNode.Comparison.Op) 854 assert.Equal(t, "status", filterNode.Comparison.Field) 855 assert.Equal(t, `"ok"`, filterNode.Comparison.Values) 856 857 expressionFilter := extractExpressionFilter(t, filterNode) 858 assert.Equal(t, "status", expressionFilter.LeftInput.Expression.LeftInput.ColumnName) 859 assert.Equal(t, utils.Equals, expressionFilter.FilterOperator) 860 assert.Equal(t, "ok", expressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal) 861 } 862 863 func Test_searchParenthesesToChangePrecedence(t *testing.T) { 864 query := []byte(`search A=1 OR (B=2 AND C=3)`) 865 res, err := spl.Parse("", query) 866 assert.Nil(t, err) 867 filterNode := res.(ast.QueryStruct).SearchFilter 868 869 assert.NotNil(t, filterNode) 870 assert.Equal(t, filterNode.NodeType, ast.NodeOr) 871 assert.Equal(t, filterNode.Right.NodeType, ast.NodeAnd) 872 873 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 874 assert.Equal(t, filterNode.Left.Comparison.Field, "A") 875 assert.Equal(t, filterNode.Left.Comparison.Op, "=") 876 assert.Equal(t, filterNode.Left.Comparison.Values, json.Number("1")) 877 878 assert.Equal(t, filterNode.Right.Left.NodeType, ast.NodeTerminal) 879 assert.Equal(t, filterNode.Right.Left.Comparison.Field, "B") 880 assert.Equal(t, filterNode.Right.Left.Comparison.Op, "=") 881 assert.Equal(t, filterNode.Right.Left.Comparison.Values, json.Number("2")) 882 883 assert.Equal(t, filterNode.Right.Right.NodeType, ast.NodeTerminal) 884 assert.Equal(t, filterNode.Right.Right.Comparison.Field, "C") 885 assert.Equal(t, filterNode.Right.Right.Comparison.Op, "=") 886 assert.Equal(t, filterNode.Right.Right.Comparison.Values, json.Number("3")) 887 888 astNode := &structs.ASTNode{} 889 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 890 assert.Nil(t, err) 891 assert.NotNil(t, astNode.OrFilterCondition.FilterCriteria) 892 assert.Len(t, astNode.OrFilterCondition.FilterCriteria, 1) 893 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 894 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 895 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 896 assert.Len(t, astNode.OrFilterCondition.NestedNodes, 1) 897 assert.Len(t, astNode.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria, 2) 898 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "B") 899 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 900 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(2)) 901 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "C") 902 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 903 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(3)) 904 } 905 906 func Test_searchImplicitAND(t *testing.T) { 907 query := []byte(`search status=ok latency<1000`) 908 res, err := spl.Parse("", query) 909 assert.Nil(t, err) 910 filterNode := res.(ast.QueryStruct).SearchFilter 911 912 assert.NotNil(t, filterNode) 913 assert.Equal(t, filterNode.NodeType, ast.NodeAnd) 914 915 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 916 assert.Equal(t, filterNode.Left.Comparison.Field, "status") 917 assert.Equal(t, filterNode.Left.Comparison.Op, "=") 918 assert.Equal(t, filterNode.Left.Comparison.Values, `"ok"`) 919 920 assert.Equal(t, filterNode.Right.NodeType, ast.NodeTerminal) 921 assert.Equal(t, filterNode.Right.Comparison.Field, "latency") 922 assert.Equal(t, filterNode.Right.Comparison.Op, "<") 923 assert.Equal(t, filterNode.Right.Comparison.Values, json.Number("1000")) 924 925 astNode := &structs.ASTNode{} 926 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 927 assert.Nil(t, err) 928 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 929 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 2) 930 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "status") 931 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 932 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "ok") 933 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "latency") 934 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.LessThan) 935 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1000)) 936 } 937 938 func Test_searchChainedImplicitAND(t *testing.T) { 939 query := []byte(`search A=1 B=2 C=3`) 940 res, err := spl.Parse("", query) 941 assert.Nil(t, err) 942 filterNode := res.(ast.QueryStruct).SearchFilter 943 944 assert.NotNil(t, filterNode) 945 assert.Equal(t, ast.NodeAnd, filterNode.NodeType) 946 assert.Equal(t, ast.NodeAnd, filterNode.Left.NodeType) 947 948 assert.Equal(t, filterNode.Left.Left.NodeType, ast.NodeTerminal) 949 assert.Equal(t, filterNode.Left.Left.Comparison.Field, "A") 950 assert.Equal(t, filterNode.Left.Left.Comparison.Op, "=") 951 assert.Equal(t, filterNode.Left.Left.Comparison.Values, json.Number("1")) 952 953 assert.Equal(t, filterNode.Left.Right.NodeType, ast.NodeTerminal) 954 assert.Equal(t, filterNode.Left.Right.Comparison.Field, "B") 955 assert.Equal(t, filterNode.Left.Right.Comparison.Op, "=") 956 assert.Equal(t, filterNode.Left.Right.Comparison.Values, json.Number("2")) 957 958 assert.Equal(t, filterNode.Right.NodeType, ast.NodeTerminal) 959 assert.Equal(t, filterNode.Right.Comparison.Field, "C") 960 assert.Equal(t, filterNode.Right.Comparison.Op, "=") 961 assert.Equal(t, filterNode.Right.Comparison.Values, json.Number("3")) 962 963 astNode := &structs.ASTNode{} 964 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 965 assert.Nil(t, err) 966 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 967 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 968 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "C") 969 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 970 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(3)) 971 assert.Len(t, astNode.AndFilterCondition.NestedNodes, 1) 972 assert.Len(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria, 2) 973 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 974 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 975 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 976 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "B") 977 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 978 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(2)) 979 } 980 981 func Test_searchMixedImplicitAndExplicitAND(t *testing.T) { 982 query := []byte(`search A=1 AND B=2 C=3`) 983 res, err := spl.Parse("", query) 984 assert.Nil(t, err) 985 filterNode := res.(ast.QueryStruct).SearchFilter 986 987 assert.NotNil(t, filterNode) 988 assert.Equal(t, ast.NodeAnd, filterNode.NodeType) 989 assert.Equal(t, ast.NodeAnd, filterNode.Left.NodeType) 990 991 assert.Equal(t, filterNode.Left.Left.NodeType, ast.NodeTerminal) 992 assert.Equal(t, filterNode.Left.Left.Comparison.Field, "A") 993 assert.Equal(t, filterNode.Left.Left.Comparison.Op, "=") 994 assert.Equal(t, filterNode.Left.Left.Comparison.Values, json.Number("1")) 995 996 assert.Equal(t, filterNode.Left.Right.NodeType, ast.NodeTerminal) 997 assert.Equal(t, filterNode.Left.Right.Comparison.Field, "B") 998 assert.Equal(t, filterNode.Left.Right.Comparison.Op, "=") 999 assert.Equal(t, filterNode.Left.Right.Comparison.Values, json.Number("2")) 1000 1001 assert.Equal(t, filterNode.Right.NodeType, ast.NodeTerminal) 1002 assert.Equal(t, filterNode.Right.Comparison.Field, "C") 1003 assert.Equal(t, filterNode.Right.Comparison.Op, "=") 1004 assert.Equal(t, filterNode.Right.Comparison.Values, json.Number("3")) 1005 1006 astNode := &structs.ASTNode{} 1007 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1008 assert.Nil(t, err) 1009 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1010 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1011 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "C") 1012 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1013 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(3)) 1014 assert.Len(t, astNode.AndFilterCondition.NestedNodes, 1) 1015 assert.Len(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria, 2) 1016 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1017 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1018 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1019 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "B") 1020 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 1021 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(2)) 1022 } 1023 1024 func Test_searchSimpleNOTEquals(t *testing.T) { 1025 query := []byte(`search NOT status=200`) 1026 res, err := spl.Parse("", query) 1027 assert.Nil(t, err) 1028 filterNode := res.(ast.QueryStruct).SearchFilter 1029 1030 assert.NotNil(t, filterNode) 1031 1032 // NOT is handled internally with De Morgan's law. 1033 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1034 assert.Equal(t, filterNode.Comparison.Field, "status") 1035 assert.Equal(t, filterNode.Comparison.Op, "!=") 1036 assert.Equal(t, filterNode.Comparison.Values, json.Number("200")) 1037 1038 astNode := &structs.ASTNode{} 1039 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1040 assert.Nil(t, err) 1041 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1042 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1043 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "status") 1044 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.NotEquals) 1045 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(200)) 1046 } 1047 1048 func Test_searchSimpleNOTNotEquals(t *testing.T) { 1049 query := []byte(`search NOT status!=200`) 1050 res, err := spl.Parse("", query) 1051 assert.Nil(t, err) 1052 filterNode := res.(ast.QueryStruct).SearchFilter 1053 1054 assert.NotNil(t, filterNode) 1055 1056 // NOT is handled internally with De Morgan's law. 1057 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1058 assert.Equal(t, filterNode.Comparison.Field, "status") 1059 assert.Equal(t, filterNode.Comparison.Op, "=") 1060 assert.Equal(t, filterNode.Comparison.Values, json.Number("200")) 1061 1062 astNode := &structs.ASTNode{} 1063 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1064 assert.Nil(t, err) 1065 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1066 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1067 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "status") 1068 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1069 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(200)) 1070 } 1071 1072 func Test_searchSimpleNOTLessThan(t *testing.T) { 1073 query := []byte(`search NOT status<200`) 1074 res, err := spl.Parse("", query) 1075 assert.Nil(t, err) 1076 filterNode := res.(ast.QueryStruct).SearchFilter 1077 1078 assert.NotNil(t, filterNode) 1079 1080 // NOT is handled internally with De Morgan's law. 1081 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1082 assert.Equal(t, filterNode.Comparison.Field, "status") 1083 assert.Equal(t, filterNode.Comparison.Op, ">=") 1084 assert.Equal(t, filterNode.Comparison.Values, json.Number("200")) 1085 1086 astNode := &structs.ASTNode{} 1087 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1088 assert.Nil(t, err) 1089 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1090 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1091 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "status") 1092 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.GreaterThanOrEqualTo) 1093 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(200)) 1094 } 1095 1096 func Test_searchSimpleNOTGreaterThan(t *testing.T) { 1097 query := []byte(`search NOT status>200`) 1098 res, err := spl.Parse("", query) 1099 assert.Nil(t, err) 1100 filterNode := res.(ast.QueryStruct).SearchFilter 1101 1102 assert.NotNil(t, filterNode) 1103 1104 // NOT is handled internally with De Morgan's law. 1105 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1106 assert.Equal(t, filterNode.Comparison.Field, "status") 1107 assert.Equal(t, filterNode.Comparison.Op, "<=") 1108 assert.Equal(t, filterNode.Comparison.Values, json.Number("200")) 1109 1110 astNode := &structs.ASTNode{} 1111 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1112 assert.Nil(t, err) 1113 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1114 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1115 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "status") 1116 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.LessThanOrEqualTo) 1117 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(200)) 1118 } 1119 1120 func Test_searchSimpleNOTLessThanOrEqual(t *testing.T) { 1121 query := []byte(`search NOT status<=200`) 1122 res, err := spl.Parse("", query) 1123 assert.Nil(t, err) 1124 filterNode := res.(ast.QueryStruct).SearchFilter 1125 1126 assert.NotNil(t, filterNode) 1127 1128 // NOT is handled internally with De Morgan's law. 1129 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1130 assert.Equal(t, filterNode.Comparison.Field, "status") 1131 assert.Equal(t, filterNode.Comparison.Op, ">") 1132 assert.Equal(t, filterNode.Comparison.Values, json.Number("200")) 1133 1134 astNode := &structs.ASTNode{} 1135 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1136 assert.Nil(t, err) 1137 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1138 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1139 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "status") 1140 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.GreaterThan) 1141 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(200)) 1142 } 1143 1144 func Test_searchSimpleNOTGreaterThanOrEqual(t *testing.T) { 1145 query := []byte(`search NOT status>=200`) 1146 res, err := spl.Parse("", query) 1147 assert.Nil(t, err) 1148 filterNode := res.(ast.QueryStruct).SearchFilter 1149 1150 assert.NotNil(t, filterNode) 1151 1152 // NOT is handled internally with De Morgan's law. 1153 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1154 assert.Equal(t, filterNode.Comparison.Field, "status") 1155 assert.Equal(t, filterNode.Comparison.Op, "<") 1156 assert.Equal(t, filterNode.Comparison.Values, json.Number("200")) 1157 1158 astNode := &structs.ASTNode{} 1159 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1160 assert.Nil(t, err) 1161 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1162 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1163 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "status") 1164 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.LessThan) 1165 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(200)) 1166 } 1167 1168 func Test_searchCancelingNots(t *testing.T) { 1169 query := []byte(`search NOT NOT (NOT (NOT status=200))`) 1170 res, err := spl.Parse("", query) 1171 assert.Nil(t, err) 1172 filterNode := res.(ast.QueryStruct).SearchFilter 1173 1174 assert.NotNil(t, filterNode) 1175 1176 // NOT is handled internally with De Morgan's law. 1177 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1178 assert.Equal(t, filterNode.Comparison.Field, "status") 1179 assert.Equal(t, filterNode.Comparison.Op, "=") 1180 assert.Equal(t, filterNode.Comparison.Values, json.Number("200")) 1181 1182 astNode := &structs.ASTNode{} 1183 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1184 assert.Nil(t, err) 1185 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1186 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1187 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "status") 1188 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1189 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(200)) 1190 } 1191 1192 func Test_searchCompoundNOT(t *testing.T) { 1193 query := []byte(`search NOT (status=ok OR (A>1 AND NOT A>=10))`) 1194 res, err := spl.Parse("", query) 1195 assert.Nil(t, err) 1196 filterNode := res.(ast.QueryStruct).SearchFilter 1197 1198 assert.NotNil(t, filterNode) 1199 // NOT is handled internally with De Morgan's law. 1200 assert.Equal(t, filterNode.NodeType, ast.NodeAnd) 1201 assert.Equal(t, filterNode.Right.NodeType, ast.NodeOr) 1202 1203 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 1204 assert.Equal(t, filterNode.Left.Comparison.Field, "status") 1205 assert.Equal(t, filterNode.Left.Comparison.Op, "!=") 1206 assert.Equal(t, filterNode.Left.Comparison.Values, `"ok"`) 1207 1208 assert.Equal(t, filterNode.Right.Left.NodeType, ast.NodeTerminal) 1209 assert.Equal(t, filterNode.Right.Left.Comparison.Field, "A") 1210 assert.Equal(t, filterNode.Right.Left.Comparison.Op, "<=") 1211 assert.Equal(t, filterNode.Right.Left.Comparison.Values, json.Number("1")) 1212 1213 assert.Equal(t, filterNode.Right.Right.NodeType, ast.NodeTerminal) 1214 assert.Equal(t, filterNode.Right.Right.Comparison.Field, "A") 1215 assert.Equal(t, filterNode.Right.Right.Comparison.Op, ">=") 1216 assert.Equal(t, filterNode.Right.Right.Comparison.Values, json.Number("10")) 1217 1218 astNode := &structs.ASTNode{} 1219 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1220 assert.Nil(t, err) 1221 assert.Len(t, astNode.AndFilterCondition.NestedNodes, 1) 1222 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1223 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "status") 1224 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.NotEquals) 1225 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "ok") 1226 assert.Len(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria, 2) 1227 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1228 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.LessThanOrEqualTo) 1229 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1230 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1231 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.GreaterThanOrEqualTo) 1232 assert.Equal(t, astNode.AndFilterCondition.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(10)) 1233 } 1234 1235 func Test_searchQuotedWildcard(t *testing.T) { 1236 query := []byte(`search day="T*day"`) 1237 res, err := spl.Parse("", query) 1238 assert.Nil(t, err) 1239 filterNode := res.(ast.QueryStruct).SearchFilter 1240 1241 assert.NotNil(t, filterNode) 1242 1243 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1244 assert.Equal(t, filterNode.Comparison.Field, "day") 1245 assert.Equal(t, filterNode.Comparison.Op, "=") 1246 assert.Equal(t, filterNode.Comparison.Values, `"T*day"`) 1247 1248 astNode := &structs.ASTNode{} 1249 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1250 assert.Nil(t, err) 1251 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1252 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1253 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "day") 1254 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1255 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "T*day") 1256 } 1257 1258 func Test_searchUnquotedWildcard(t *testing.T) { 1259 query := []byte(`search day=T*day`) 1260 res, err := spl.Parse("", query) 1261 assert.Nil(t, err) 1262 filterNode := res.(ast.QueryStruct).SearchFilter 1263 1264 assert.NotNil(t, filterNode) 1265 1266 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1267 assert.Equal(t, filterNode.Comparison.Field, "day") 1268 assert.Equal(t, filterNode.Comparison.Op, "=") 1269 assert.Equal(t, filterNode.Comparison.Values, `"T*day"`) 1270 1271 astNode := &structs.ASTNode{} 1272 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1273 assert.Nil(t, err) 1274 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1275 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1276 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "day") 1277 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1278 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "T*day") 1279 } 1280 1281 func Test_searchNumberedWildcardBecomesString(t *testing.T) { 1282 query := []byte(`search status_code=50*`) 1283 res, err := spl.Parse("", query) 1284 assert.Nil(t, err) 1285 filterNode := res.(ast.QueryStruct).SearchFilter 1286 1287 assert.NotNil(t, filterNode) 1288 1289 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1290 assert.Equal(t, filterNode.Comparison.Field, "status_code") 1291 assert.Equal(t, filterNode.Comparison.Op, "=") 1292 assert.Equal(t, filterNode.Comparison.Values, `"50*"`) 1293 1294 astNode := &structs.ASTNode{} 1295 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1296 assert.Nil(t, err) 1297 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1298 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1299 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "status_code") 1300 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1301 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "50*") 1302 } 1303 1304 func Test_chainedSearch(t *testing.T) { 1305 // This should be equivalent to `search A=1 AND B=2` 1306 query := []byte(`A=1 | search B=2`) 1307 res, err := spl.Parse("", query) 1308 assert.Nil(t, err) 1309 filterNode := res.(ast.QueryStruct).SearchFilter 1310 1311 assert.NotNil(t, filterNode) 1312 assert.Equal(t, ast.NodeAnd, filterNode.NodeType) 1313 1314 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 1315 assert.Equal(t, filterNode.Left.Comparison.Field, "A") 1316 assert.Equal(t, filterNode.Left.Comparison.Op, "=") 1317 assert.Equal(t, filterNode.Left.Comparison.Values, json.Number("1")) 1318 1319 assert.Equal(t, filterNode.Right.NodeType, ast.NodeTerminal) 1320 assert.Equal(t, filterNode.Right.Comparison.Field, "B") 1321 assert.Equal(t, filterNode.Right.Comparison.Op, "=") 1322 assert.Equal(t, filterNode.Right.Comparison.Values, json.Number("2")) 1323 1324 astNode := &structs.ASTNode{} 1325 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1326 assert.Nil(t, err) 1327 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1328 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 2) 1329 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1330 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1331 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1332 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "B") 1333 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 1334 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(2)) 1335 } 1336 1337 func Test_manyChainedSearch(t *testing.T) { 1338 // This should be equivalent to `search A=1 AND (B=2 AND (C=3 AND D=4))` 1339 query := []byte(`search A=1 | search B=2 | search C=3 | search D=4`) 1340 res, err := spl.Parse("", query) 1341 assert.Nil(t, err) 1342 filterNode := res.(ast.QueryStruct).SearchFilter 1343 1344 assert.NotNil(t, filterNode) 1345 assert.Equal(t, ast.NodeAnd, filterNode.NodeType) 1346 assert.Equal(t, ast.NodeAnd, filterNode.Right.NodeType) 1347 assert.Equal(t, ast.NodeAnd, filterNode.Right.Right.NodeType) 1348 1349 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 1350 assert.Equal(t, filterNode.Left.Comparison.Field, "A") 1351 assert.Equal(t, filterNode.Left.Comparison.Op, "=") 1352 assert.Equal(t, filterNode.Left.Comparison.Values, json.Number("1")) 1353 1354 assert.Equal(t, filterNode.Right.Left.NodeType, ast.NodeTerminal) 1355 assert.Equal(t, filterNode.Right.Left.Comparison.Field, "B") 1356 assert.Equal(t, filterNode.Right.Left.Comparison.Op, "=") 1357 assert.Equal(t, filterNode.Right.Left.Comparison.Values, json.Number("2")) 1358 1359 assert.Equal(t, filterNode.Right.Right.Left.NodeType, ast.NodeTerminal) 1360 assert.Equal(t, filterNode.Right.Right.Left.Comparison.Field, "C") 1361 assert.Equal(t, filterNode.Right.Right.Left.Comparison.Op, "=") 1362 assert.Equal(t, filterNode.Right.Right.Left.Comparison.Values, json.Number("3")) 1363 1364 assert.Equal(t, filterNode.Right.Right.Right.NodeType, ast.NodeTerminal) 1365 assert.Equal(t, filterNode.Right.Right.Right.Comparison.Field, "D") 1366 assert.Equal(t, filterNode.Right.Right.Right.Comparison.Op, "=") 1367 assert.Equal(t, filterNode.Right.Right.Right.Comparison.Values, json.Number("4")) 1368 1369 astNode := &structs.ASTNode{} 1370 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1371 assert.Nil(t, err) 1372 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1373 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1374 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1375 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1376 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1377 1378 assert.Len(t, astNode.AndFilterCondition.NestedNodes, 1) 1379 andFilter := astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition 1380 assert.Len(t, andFilter.FilterCriteria, 1) 1381 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "B") 1382 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1383 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(2)) 1384 1385 assert.Len(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.NestedNodes, 1) 1386 andFilter = astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.NestedNodes[0].AndFilterCondition 1387 assert.Len(t, andFilter.FilterCriteria, 2) 1388 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "C") 1389 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1390 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(3)) 1391 assert.Equal(t, andFilter.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "D") 1392 assert.Equal(t, andFilter.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 1393 assert.Equal(t, andFilter.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(4)) 1394 } 1395 1396 func Test_manyChainedSearchOptionalPipeSpacing(t *testing.T) { 1397 // This should be equivalent to `search A=1 AND (B=2 AND (C=3 AND D=4))` 1398 query := []byte(`search A=1| search B=apple|search C=3 |search D=4`) 1399 res, err := spl.Parse("", query) 1400 assert.Nil(t, err) 1401 filterNode := res.(ast.QueryStruct).SearchFilter 1402 1403 assert.NotNil(t, filterNode) 1404 assert.Equal(t, ast.NodeAnd, filterNode.NodeType) 1405 assert.Equal(t, ast.NodeAnd, filterNode.Right.NodeType) 1406 assert.Equal(t, ast.NodeAnd, filterNode.Right.Right.NodeType) 1407 1408 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 1409 assert.Equal(t, filterNode.Left.Comparison.Field, "A") 1410 assert.Equal(t, filterNode.Left.Comparison.Op, "=") 1411 assert.Equal(t, filterNode.Left.Comparison.Values, json.Number("1")) 1412 1413 assert.Equal(t, filterNode.Right.Left.NodeType, ast.NodeTerminal) 1414 assert.Equal(t, filterNode.Right.Left.Comparison.Field, "B") 1415 assert.Equal(t, filterNode.Right.Left.Comparison.Op, "=") 1416 assert.Equal(t, filterNode.Right.Left.Comparison.Values, `"apple"`) 1417 1418 assert.Equal(t, filterNode.Right.Right.Left.NodeType, ast.NodeTerminal) 1419 assert.Equal(t, filterNode.Right.Right.Left.Comparison.Field, "C") 1420 assert.Equal(t, filterNode.Right.Right.Left.Comparison.Op, "=") 1421 assert.Equal(t, filterNode.Right.Right.Left.Comparison.Values, json.Number("3")) 1422 1423 assert.Equal(t, filterNode.Right.Right.Right.NodeType, ast.NodeTerminal) 1424 assert.Equal(t, filterNode.Right.Right.Right.Comparison.Field, "D") 1425 assert.Equal(t, filterNode.Right.Right.Right.Comparison.Op, "=") 1426 assert.Equal(t, filterNode.Right.Right.Right.Comparison.Values, json.Number("4")) 1427 1428 astNode := &structs.ASTNode{} 1429 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1430 assert.Nil(t, err) 1431 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1432 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1433 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1434 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1435 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1436 1437 assert.Len(t, astNode.AndFilterCondition.NestedNodes, 1) 1438 andFilter := astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition 1439 assert.Len(t, andFilter.FilterCriteria, 1) 1440 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "B") 1441 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1442 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "apple") 1443 1444 assert.Len(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.NestedNodes, 1) 1445 andFilter = astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.NestedNodes[0].AndFilterCondition 1446 assert.Len(t, andFilter.FilterCriteria, 2) 1447 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "C") 1448 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1449 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(3)) 1450 assert.Equal(t, andFilter.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "D") 1451 assert.Equal(t, andFilter.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 1452 assert.Equal(t, andFilter.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(4)) 1453 } 1454 1455 func Test_manyChainedCompoundSearch(t *testing.T) { 1456 // This should be equivalent to `search A=1 AND ((B=2 AND C=3) AND ((D=4 OR E=5) AND F=6))` 1457 query := []byte(`search A=1 | search B=2 C=3 | search D=4 OR E=5 | search F=6`) 1458 res, err := spl.Parse("", query) 1459 assert.Nil(t, err) 1460 filterNode := res.(ast.QueryStruct).SearchFilter 1461 1462 assert.NotNil(t, filterNode) 1463 assert.Equal(t, ast.NodeAnd, filterNode.NodeType) 1464 assert.Equal(t, ast.NodeAnd, filterNode.Right.NodeType) 1465 assert.Equal(t, ast.NodeAnd, filterNode.Right.Left.NodeType) 1466 assert.Equal(t, ast.NodeAnd, filterNode.Right.Right.NodeType) 1467 assert.Equal(t, ast.NodeOr, filterNode.Right.Right.Left.NodeType) 1468 1469 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 1470 assert.Equal(t, filterNode.Left.Comparison.Field, "A") 1471 assert.Equal(t, filterNode.Left.Comparison.Op, "=") 1472 assert.Equal(t, filterNode.Left.Comparison.Values, json.Number("1")) 1473 1474 assert.Equal(t, filterNode.Right.Left.Left.NodeType, ast.NodeTerminal) 1475 assert.Equal(t, filterNode.Right.Left.Left.Comparison.Field, "B") 1476 assert.Equal(t, filterNode.Right.Left.Left.Comparison.Op, "=") 1477 assert.Equal(t, filterNode.Right.Left.Left.Comparison.Values, json.Number("2")) 1478 1479 assert.Equal(t, filterNode.Right.Left.Right.NodeType, ast.NodeTerminal) 1480 assert.Equal(t, filterNode.Right.Left.Right.Comparison.Field, "C") 1481 assert.Equal(t, filterNode.Right.Left.Right.Comparison.Op, "=") 1482 assert.Equal(t, filterNode.Right.Left.Right.Comparison.Values, json.Number("3")) 1483 1484 assert.Equal(t, filterNode.Right.Right.Left.Left.NodeType, ast.NodeTerminal) 1485 assert.Equal(t, filterNode.Right.Right.Left.Left.Comparison.Field, "D") 1486 assert.Equal(t, filterNode.Right.Right.Left.Left.Comparison.Op, "=") 1487 assert.Equal(t, filterNode.Right.Right.Left.Left.Comparison.Values, json.Number("4")) 1488 1489 assert.Equal(t, filterNode.Right.Right.Left.Right.NodeType, ast.NodeTerminal) 1490 assert.Equal(t, filterNode.Right.Right.Left.Right.Comparison.Field, "E") 1491 assert.Equal(t, filterNode.Right.Right.Left.Right.Comparison.Op, "=") 1492 assert.Equal(t, filterNode.Right.Right.Left.Right.Comparison.Values, json.Number("5")) 1493 1494 assert.Equal(t, filterNode.Right.Right.Right.NodeType, ast.NodeTerminal) 1495 assert.Equal(t, filterNode.Right.Right.Right.Comparison.Field, "F") 1496 assert.Equal(t, filterNode.Right.Right.Right.Comparison.Op, "=") 1497 assert.Equal(t, filterNode.Right.Right.Right.Comparison.Values, json.Number("6")) 1498 1499 astNode := &structs.ASTNode{} 1500 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1501 assert.Nil(t, err) 1502 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1503 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1504 andFilter := astNode.AndFilterCondition 1505 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1506 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1507 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1508 1509 assert.Len(t, astNode.AndFilterCondition.NestedNodes, 1) 1510 assert.Len(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.NestedNodes, 2) 1511 andFilter = astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.NestedNodes[0].AndFilterCondition 1512 assert.Len(t, andFilter.FilterCriteria, 2) 1513 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "B") 1514 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1515 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(2)) 1516 assert.Equal(t, andFilter.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "C") 1517 assert.Equal(t, andFilter.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 1518 assert.Equal(t, andFilter.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(3)) 1519 1520 andFilter = astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.NestedNodes[1].AndFilterCondition 1521 assert.Len(t, andFilter.NestedNodes, 1) 1522 assert.Equal(t, andFilter.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "D") 1523 assert.Equal(t, andFilter.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1524 assert.Equal(t, andFilter.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(4)) 1525 assert.Equal(t, andFilter.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "E") 1526 assert.Equal(t, andFilter.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 1527 assert.Equal(t, andFilter.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(5)) 1528 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "F") 1529 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1530 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(6)) 1531 } 1532 1533 func Test_searchBlockWithoutUsingSearchKeyword(t *testing.T) { 1534 // This should be equivalent to `search A=1 AND ((B=2 AND C=3) AND ((D=4 OR E=5) AND F=6))` 1535 query := []byte(`search A=1 | B=2 C=3 | search D=4 OR E=5 | F=6`) 1536 res, err := spl.Parse("", query) 1537 assert.Nil(t, err) 1538 filterNode := res.(ast.QueryStruct).SearchFilter 1539 1540 assert.NotNil(t, filterNode) 1541 assert.Equal(t, ast.NodeAnd, filterNode.NodeType) 1542 assert.Equal(t, ast.NodeAnd, filterNode.Right.NodeType) 1543 assert.Equal(t, ast.NodeAnd, filterNode.Right.Left.NodeType) 1544 assert.Equal(t, ast.NodeAnd, filterNode.Right.Right.NodeType) 1545 assert.Equal(t, ast.NodeOr, filterNode.Right.Right.Left.NodeType) 1546 1547 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 1548 assert.Equal(t, filterNode.Left.Comparison.Field, "A") 1549 assert.Equal(t, filterNode.Left.Comparison.Op, "=") 1550 assert.Equal(t, filterNode.Left.Comparison.Values, json.Number("1")) 1551 1552 assert.Equal(t, filterNode.Right.Left.Left.NodeType, ast.NodeTerminal) 1553 assert.Equal(t, filterNode.Right.Left.Left.Comparison.Field, "B") 1554 assert.Equal(t, filterNode.Right.Left.Left.Comparison.Op, "=") 1555 assert.Equal(t, filterNode.Right.Left.Left.Comparison.Values, json.Number("2")) 1556 1557 assert.Equal(t, filterNode.Right.Left.Right.NodeType, ast.NodeTerminal) 1558 assert.Equal(t, filterNode.Right.Left.Right.Comparison.Field, "C") 1559 assert.Equal(t, filterNode.Right.Left.Right.Comparison.Op, "=") 1560 assert.Equal(t, filterNode.Right.Left.Right.Comparison.Values, json.Number("3")) 1561 1562 assert.Equal(t, filterNode.Right.Right.Left.Left.NodeType, ast.NodeTerminal) 1563 assert.Equal(t, filterNode.Right.Right.Left.Left.Comparison.Field, "D") 1564 assert.Equal(t, filterNode.Right.Right.Left.Left.Comparison.Op, "=") 1565 assert.Equal(t, filterNode.Right.Right.Left.Left.Comparison.Values, json.Number("4")) 1566 1567 assert.Equal(t, filterNode.Right.Right.Left.Right.NodeType, ast.NodeTerminal) 1568 assert.Equal(t, filterNode.Right.Right.Left.Right.Comparison.Field, "E") 1569 assert.Equal(t, filterNode.Right.Right.Left.Right.Comparison.Op, "=") 1570 assert.Equal(t, filterNode.Right.Right.Left.Right.Comparison.Values, json.Number("5")) 1571 1572 assert.Equal(t, filterNode.Right.Right.Right.NodeType, ast.NodeTerminal) 1573 assert.Equal(t, filterNode.Right.Right.Right.Comparison.Field, "F") 1574 assert.Equal(t, filterNode.Right.Right.Right.Comparison.Op, "=") 1575 assert.Equal(t, filterNode.Right.Right.Right.Comparison.Values, json.Number("6")) 1576 1577 astNode := &structs.ASTNode{} 1578 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1579 assert.Nil(t, err) 1580 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1581 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1582 andFilter := astNode.AndFilterCondition 1583 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1584 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1585 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1586 1587 assert.Len(t, astNode.AndFilterCondition.NestedNodes, 1) 1588 assert.Len(t, astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.NestedNodes, 2) 1589 andFilter = astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.NestedNodes[0].AndFilterCondition 1590 assert.Len(t, andFilter.FilterCriteria, 2) 1591 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "B") 1592 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1593 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(2)) 1594 assert.Equal(t, andFilter.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "C") 1595 assert.Equal(t, andFilter.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 1596 assert.Equal(t, andFilter.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(3)) 1597 1598 andFilter = astNode.AndFilterCondition.NestedNodes[0].AndFilterCondition.NestedNodes[1].AndFilterCondition 1599 assert.Len(t, andFilter.NestedNodes, 1) 1600 assert.Equal(t, andFilter.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "D") 1601 assert.Equal(t, andFilter.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1602 assert.Equal(t, andFilter.NestedNodes[0].OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(4)) 1603 assert.Equal(t, andFilter.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "E") 1604 assert.Equal(t, andFilter.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 1605 assert.Equal(t, andFilter.NestedNodes[0].OrFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(5)) 1606 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "F") 1607 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1608 assert.Equal(t, andFilter.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(6)) 1609 } 1610 1611 func Test_regexSingleColumnEquals(t *testing.T) { 1612 query := []byte(`A=1 | regex B="^\d$"`) 1613 res, err := spl.Parse("", query) 1614 assert.Nil(t, err) 1615 filterNode := res.(ast.QueryStruct).SearchFilter 1616 1617 assert.NotNil(t, filterNode) 1618 assert.Equal(t, ast.NodeAnd, filterNode.NodeType) 1619 1620 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 1621 assert.Equal(t, filterNode.Left.Comparison.Field, "A") 1622 assert.Equal(t, filterNode.Left.Comparison.Op, "=") 1623 assert.Equal(t, filterNode.Left.Comparison.Values, json.Number("1")) 1624 1625 assert.Equal(t, filterNode.Right.NodeType, ast.NodeTerminal) 1626 assert.Equal(t, filterNode.Right.Comparison.Field, "B") 1627 assert.Equal(t, filterNode.Right.Comparison.Op, "=") 1628 assert.Equal(t, filterNode.Right.Comparison.Values, `^\d$`) 1629 assert.Equal(t, filterNode.Right.Comparison.ValueIsRegex, true) 1630 1631 astNode := &structs.ASTNode{} 1632 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1633 assert.Nil(t, err) 1634 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1635 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 2) 1636 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1637 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1638 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1639 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "B") 1640 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 1641 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, `^\d$`) 1642 1643 compiledRegex, err := regexp.Compile(`^\d$`) 1644 assert.Nil(t, err) 1645 assert.NotNil(t, compiledRegex) 1646 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.GetRegexp(), compiledRegex) 1647 } 1648 1649 func Test_regexSingleColumnNotEquals(t *testing.T) { 1650 query := []byte(`A=1 | regex B!="^\d$"`) 1651 res, err := spl.Parse("", query) 1652 assert.Nil(t, err) 1653 filterNode := res.(ast.QueryStruct).SearchFilter 1654 1655 assert.NotNil(t, filterNode) 1656 assert.Equal(t, ast.NodeAnd, filterNode.NodeType) 1657 1658 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 1659 assert.Equal(t, filterNode.Left.Comparison.Field, "A") 1660 assert.Equal(t, filterNode.Left.Comparison.Op, "=") 1661 assert.Equal(t, filterNode.Left.Comparison.Values, json.Number("1")) 1662 1663 assert.Equal(t, filterNode.Right.NodeType, ast.NodeTerminal) 1664 assert.Equal(t, filterNode.Right.Comparison.Field, "B") 1665 assert.Equal(t, filterNode.Right.Comparison.Op, "!=") 1666 assert.Equal(t, filterNode.Right.Comparison.Values, `^\d$`) 1667 assert.Equal(t, filterNode.Right.Comparison.ValueIsRegex, true) 1668 1669 astNode := &structs.ASTNode{} 1670 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1671 assert.Nil(t, err) 1672 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1673 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 2) 1674 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1675 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1676 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1677 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "B") 1678 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.NotEquals) 1679 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, `^\d$`) 1680 1681 compiledRegex, err := regexp.Compile(`^\d$`) 1682 assert.Nil(t, err) 1683 assert.NotNil(t, compiledRegex) 1684 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.GetRegexp(), compiledRegex) 1685 } 1686 1687 func Test_regexRequiresQuotes(t *testing.T) { 1688 query := []byte(`A=1 | regex B=^\d$`) 1689 res, err := spl.Parse("", query) 1690 assert.NotNil(t, err) 1691 assert.Nil(t, res) 1692 } 1693 1694 func Test_regexAnyColumn(t *testing.T) { 1695 query := []byte(`A=1 | regex "^\d$"`) 1696 res, err := spl.Parse("", query) 1697 assert.Nil(t, err) 1698 filterNode := res.(ast.QueryStruct).SearchFilter 1699 1700 assert.NotNil(t, filterNode) 1701 assert.Equal(t, ast.NodeAnd, filterNode.NodeType) 1702 1703 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 1704 assert.Equal(t, filterNode.Left.Comparison.Field, "A") 1705 assert.Equal(t, filterNode.Left.Comparison.Op, "=") 1706 assert.Equal(t, filterNode.Left.Comparison.Values, json.Number("1")) 1707 1708 assert.Equal(t, filterNode.Right.NodeType, ast.NodeTerminal) 1709 assert.Equal(t, filterNode.Right.Comparison.Field, "*") 1710 assert.Equal(t, filterNode.Right.Comparison.Op, "=") 1711 assert.Equal(t, filterNode.Right.Comparison.Values, `^\d$`) 1712 assert.Equal(t, filterNode.Right.Comparison.ValueIsRegex, true) 1713 1714 astNode := &structs.ASTNode{} 1715 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 1716 assert.Nil(t, err) 1717 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 1718 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 2) 1719 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1720 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1721 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1722 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "*") 1723 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 1724 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, `^\d$`) 1725 1726 compiledRegex, err := regexp.Compile(`^\d$`) 1727 assert.Nil(t, err) 1728 assert.NotNil(t, compiledRegex) 1729 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.GetRegexp(), compiledRegex) 1730 } 1731 1732 func Test_aggCountWithField(t *testing.T) { 1733 query := []byte(`search A=1 | stats count(city)`) 1734 res, err := spl.Parse("", query) 1735 assert.Nil(t, err) 1736 filterNode := res.(ast.QueryStruct).SearchFilter 1737 assert.NotNil(t, filterNode) 1738 1739 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1740 assert.Equal(t, filterNode.Comparison.Field, "A") 1741 assert.Equal(t, filterNode.Comparison.Op, "=") 1742 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 1743 1744 pipeCommands := res.(ast.QueryStruct).PipeCommands 1745 assert.NotNil(t, pipeCommands) 1746 assert.Equal(t, pipeCommands.PipeCommandType, structs.MeasureAggsType) 1747 assert.Len(t, pipeCommands.MeasureOperations, 1) 1748 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureCol, "city") 1749 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureFunc, utils.Count) 1750 1751 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 1752 assert.Nil(t, err) 1753 assert.NotNil(t, astNode) 1754 assert.NotNil(t, aggregator) 1755 1756 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1757 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1758 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1759 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1760 1761 assert.Equal(t, aggregator.PipeCommandType, structs.MeasureAggsType) 1762 assert.Len(t, aggregator.MeasureOperations, 1) 1763 assert.Equal(t, aggregator.MeasureOperations[0].MeasureCol, "city") 1764 assert.Equal(t, aggregator.MeasureOperations[0].MeasureFunc, utils.Count) 1765 } 1766 1767 func Test_aggCountWithoutField(t *testing.T) { 1768 query := []byte(`search A=1 | stats count`) 1769 res, err := spl.Parse("", query) 1770 assert.Nil(t, err) 1771 filterNode := res.(ast.QueryStruct).SearchFilter 1772 assert.NotNil(t, filterNode) 1773 1774 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1775 assert.Equal(t, filterNode.Comparison.Field, "A") 1776 assert.Equal(t, filterNode.Comparison.Op, "=") 1777 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 1778 1779 pipeCommands := res.(ast.QueryStruct).PipeCommands 1780 assert.NotNil(t, pipeCommands) 1781 assert.Equal(t, pipeCommands.PipeCommandType, structs.MeasureAggsType) 1782 assert.Len(t, pipeCommands.MeasureOperations, 1) 1783 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureCol, "*") 1784 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureFunc, utils.Count) 1785 1786 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 1787 assert.Nil(t, err) 1788 assert.NotNil(t, astNode) 1789 assert.NotNil(t, aggregator) 1790 1791 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1792 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1793 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1794 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1795 1796 assert.Equal(t, aggregator.PipeCommandType, structs.MeasureAggsType) 1797 assert.Len(t, aggregator.MeasureOperations, 1) 1798 assert.Equal(t, aggregator.MeasureOperations[0].MeasureCol, "*") 1799 assert.Equal(t, aggregator.MeasureOperations[0].MeasureFunc, utils.Count) 1800 } 1801 1802 func Test_aggCountAlias(t *testing.T) { 1803 query := []byte(`search A=1 | stats c(city)`) 1804 res, err := spl.Parse("", query) 1805 assert.Nil(t, err) 1806 filterNode := res.(ast.QueryStruct).SearchFilter 1807 assert.NotNil(t, filterNode) 1808 1809 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1810 assert.Equal(t, filterNode.Comparison.Field, "A") 1811 assert.Equal(t, filterNode.Comparison.Op, "=") 1812 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 1813 1814 pipeCommands := res.(ast.QueryStruct).PipeCommands 1815 assert.NotNil(t, pipeCommands) 1816 assert.Equal(t, pipeCommands.PipeCommandType, structs.MeasureAggsType) 1817 assert.Len(t, pipeCommands.MeasureOperations, 1) 1818 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureCol, "city") 1819 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureFunc, utils.Count) 1820 1821 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 1822 assert.Nil(t, err) 1823 assert.NotNil(t, astNode) 1824 assert.NotNil(t, aggregator) 1825 1826 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1827 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1828 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1829 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1830 1831 assert.Equal(t, aggregator.PipeCommandType, structs.MeasureAggsType) 1832 assert.Len(t, aggregator.MeasureOperations, 1) 1833 assert.Equal(t, aggregator.MeasureOperations[0].MeasureCol, "city") 1834 assert.Equal(t, aggregator.MeasureOperations[0].MeasureFunc, utils.Count) 1835 } 1836 1837 func Test_aggDistinctCount(t *testing.T) { 1838 query := []byte(`search A=1 | stats distinct_count(city)`) 1839 res, err := spl.Parse("", query) 1840 assert.Nil(t, err) 1841 filterNode := res.(ast.QueryStruct).SearchFilter 1842 assert.NotNil(t, filterNode) 1843 1844 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1845 assert.Equal(t, filterNode.Comparison.Field, "A") 1846 assert.Equal(t, filterNode.Comparison.Op, "=") 1847 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 1848 1849 pipeCommands := res.(ast.QueryStruct).PipeCommands 1850 assert.NotNil(t, pipeCommands) 1851 assert.Equal(t, pipeCommands.PipeCommandType, structs.MeasureAggsType) 1852 assert.Len(t, pipeCommands.MeasureOperations, 1) 1853 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureCol, "city") 1854 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureFunc, utils.Cardinality) 1855 1856 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 1857 assert.Nil(t, err) 1858 assert.NotNil(t, astNode) 1859 assert.NotNil(t, aggregator) 1860 1861 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1862 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1863 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1864 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1865 1866 assert.Equal(t, aggregator.PipeCommandType, structs.MeasureAggsType) 1867 assert.Len(t, aggregator.MeasureOperations, 1) 1868 assert.Equal(t, aggregator.MeasureOperations[0].MeasureCol, "city") 1869 assert.Equal(t, aggregator.MeasureOperations[0].MeasureFunc, utils.Cardinality) 1870 } 1871 1872 func Test_aggDistinctCountAlias(t *testing.T) { 1873 query := []byte(`search A=1 | stats dc(city)`) 1874 res, err := spl.Parse("", query) 1875 assert.Nil(t, err) 1876 filterNode := res.(ast.QueryStruct).SearchFilter 1877 assert.NotNil(t, filterNode) 1878 1879 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1880 assert.Equal(t, filterNode.Comparison.Field, "A") 1881 assert.Equal(t, filterNode.Comparison.Op, "=") 1882 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 1883 1884 pipeCommands := res.(ast.QueryStruct).PipeCommands 1885 assert.NotNil(t, pipeCommands) 1886 assert.Equal(t, pipeCommands.PipeCommandType, structs.MeasureAggsType) 1887 assert.Len(t, pipeCommands.MeasureOperations, 1) 1888 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureCol, "city") 1889 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureFunc, utils.Cardinality) 1890 1891 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 1892 assert.Nil(t, err) 1893 assert.NotNil(t, astNode) 1894 assert.NotNil(t, aggregator) 1895 1896 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1897 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1898 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1899 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1900 1901 assert.Equal(t, aggregator.PipeCommandType, structs.MeasureAggsType) 1902 assert.Len(t, aggregator.MeasureOperations, 1) 1903 assert.Equal(t, aggregator.MeasureOperations[0].MeasureCol, "city") 1904 assert.Equal(t, aggregator.MeasureOperations[0].MeasureFunc, utils.Cardinality) 1905 } 1906 1907 func Test_aggAvg(t *testing.T) { 1908 query := []byte(`search A=1 | stats avg(latency)`) 1909 res, err := spl.Parse("", query) 1910 assert.Nil(t, err) 1911 filterNode := res.(ast.QueryStruct).SearchFilter 1912 assert.NotNil(t, filterNode) 1913 1914 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1915 assert.Equal(t, filterNode.Comparison.Field, "A") 1916 assert.Equal(t, filterNode.Comparison.Op, "=") 1917 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 1918 1919 pipeCommands := res.(ast.QueryStruct).PipeCommands 1920 assert.NotNil(t, pipeCommands) 1921 assert.Equal(t, pipeCommands.PipeCommandType, structs.MeasureAggsType) 1922 assert.Len(t, pipeCommands.MeasureOperations, 1) 1923 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureCol, "latency") 1924 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureFunc, utils.Avg) 1925 1926 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 1927 assert.Nil(t, err) 1928 assert.NotNil(t, astNode) 1929 assert.NotNil(t, aggregator) 1930 1931 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1932 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1933 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1934 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1935 1936 assert.Equal(t, aggregator.PipeCommandType, structs.MeasureAggsType) 1937 assert.Len(t, aggregator.MeasureOperations, 1) 1938 assert.Equal(t, aggregator.MeasureOperations[0].MeasureCol, "latency") 1939 assert.Equal(t, aggregator.MeasureOperations[0].MeasureFunc, utils.Avg) 1940 } 1941 1942 func Test_aggMin(t *testing.T) { 1943 query := []byte(`search A=1 | stats min(latency)`) 1944 res, err := spl.Parse("", query) 1945 assert.Nil(t, err) 1946 filterNode := res.(ast.QueryStruct).SearchFilter 1947 assert.NotNil(t, filterNode) 1948 1949 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1950 assert.Equal(t, filterNode.Comparison.Field, "A") 1951 assert.Equal(t, filterNode.Comparison.Op, "=") 1952 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 1953 1954 pipeCommands := res.(ast.QueryStruct).PipeCommands 1955 assert.NotNil(t, pipeCommands) 1956 assert.Equal(t, pipeCommands.PipeCommandType, structs.MeasureAggsType) 1957 assert.Len(t, pipeCommands.MeasureOperations, 1) 1958 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureCol, "latency") 1959 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureFunc, utils.Min) 1960 1961 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 1962 assert.Nil(t, err) 1963 assert.NotNil(t, astNode) 1964 assert.NotNil(t, aggregator) 1965 1966 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 1967 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 1968 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 1969 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 1970 1971 assert.Equal(t, aggregator.PipeCommandType, structs.MeasureAggsType) 1972 assert.Len(t, aggregator.MeasureOperations, 1) 1973 assert.Equal(t, aggregator.MeasureOperations[0].MeasureCol, "latency") 1974 assert.Equal(t, aggregator.MeasureOperations[0].MeasureFunc, utils.Min) 1975 } 1976 1977 func Test_aggMax(t *testing.T) { 1978 query := []byte(`search A=1 | stats max(latency)`) 1979 res, err := spl.Parse("", query) 1980 assert.Nil(t, err) 1981 filterNode := res.(ast.QueryStruct).SearchFilter 1982 assert.NotNil(t, filterNode) 1983 1984 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 1985 assert.Equal(t, filterNode.Comparison.Field, "A") 1986 assert.Equal(t, filterNode.Comparison.Op, "=") 1987 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 1988 1989 pipeCommands := res.(ast.QueryStruct).PipeCommands 1990 assert.NotNil(t, pipeCommands) 1991 assert.Equal(t, pipeCommands.PipeCommandType, structs.MeasureAggsType) 1992 assert.Len(t, pipeCommands.MeasureOperations, 1) 1993 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureCol, "latency") 1994 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureFunc, utils.Max) 1995 1996 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 1997 assert.Nil(t, err) 1998 assert.NotNil(t, astNode) 1999 assert.NotNil(t, aggregator) 2000 2001 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2002 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2003 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2004 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2005 2006 assert.Equal(t, aggregator.PipeCommandType, structs.MeasureAggsType) 2007 assert.Len(t, aggregator.MeasureOperations, 1) 2008 assert.Equal(t, aggregator.MeasureOperations[0].MeasureCol, "latency") 2009 assert.Equal(t, aggregator.MeasureOperations[0].MeasureFunc, utils.Max) 2010 } 2011 2012 func Test_aggRange(t *testing.T) { 2013 query := []byte(`search A=1 | stats range(latency)`) 2014 res, err := spl.Parse("", query) 2015 assert.Nil(t, err) 2016 filterNode := res.(ast.QueryStruct).SearchFilter 2017 assert.NotNil(t, filterNode) 2018 2019 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2020 assert.Equal(t, filterNode.Comparison.Field, "A") 2021 assert.Equal(t, filterNode.Comparison.Op, "=") 2022 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2023 2024 pipeCommands := res.(ast.QueryStruct).PipeCommands 2025 assert.NotNil(t, pipeCommands) 2026 assert.Equal(t, pipeCommands.PipeCommandType, structs.MeasureAggsType) 2027 assert.Len(t, pipeCommands.MeasureOperations, 1) 2028 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureCol, "latency") 2029 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureFunc, utils.Range) 2030 2031 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2032 assert.Nil(t, err) 2033 assert.NotNil(t, astNode) 2034 assert.NotNil(t, aggregator) 2035 2036 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2037 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2038 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2039 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2040 2041 assert.Equal(t, aggregator.PipeCommandType, structs.MeasureAggsType) 2042 assert.Len(t, aggregator.MeasureOperations, 1) 2043 assert.Equal(t, aggregator.MeasureOperations[0].MeasureCol, "latency") 2044 assert.Equal(t, aggregator.MeasureOperations[0].MeasureFunc, utils.Range) 2045 } 2046 2047 func Test_aggValues(t *testing.T) { 2048 query := []byte(`search A=1 | stats values(latency)`) 2049 res, err := spl.Parse("", query) 2050 assert.Nil(t, err) 2051 filterNode := res.(ast.QueryStruct).SearchFilter 2052 assert.NotNil(t, filterNode) 2053 2054 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2055 assert.Equal(t, filterNode.Comparison.Field, "A") 2056 assert.Equal(t, filterNode.Comparison.Op, "=") 2057 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2058 2059 pipeCommands := res.(ast.QueryStruct).PipeCommands 2060 assert.NotNil(t, pipeCommands) 2061 assert.Equal(t, pipeCommands.PipeCommandType, structs.MeasureAggsType) 2062 assert.Len(t, pipeCommands.MeasureOperations, 1) 2063 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureCol, "latency") 2064 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureFunc, utils.Values) 2065 2066 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2067 assert.Nil(t, err) 2068 assert.NotNil(t, astNode) 2069 assert.NotNil(t, aggregator) 2070 2071 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2072 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2073 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2074 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2075 2076 assert.Equal(t, aggregator.PipeCommandType, structs.MeasureAggsType) 2077 assert.Len(t, aggregator.MeasureOperations, 1) 2078 assert.Equal(t, aggregator.MeasureOperations[0].MeasureCol, "latency") 2079 assert.Equal(t, aggregator.MeasureOperations[0].MeasureFunc, utils.Values) 2080 } 2081 2082 func Test_aggSum(t *testing.T) { 2083 query := []byte(`search A=1 | stats sum(latency)`) 2084 res, err := spl.Parse("", query) 2085 assert.Nil(t, err) 2086 filterNode := res.(ast.QueryStruct).SearchFilter 2087 assert.NotNil(t, filterNode) 2088 2089 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2090 assert.Equal(t, filterNode.Comparison.Field, "A") 2091 assert.Equal(t, filterNode.Comparison.Op, "=") 2092 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2093 2094 pipeCommands := res.(ast.QueryStruct).PipeCommands 2095 assert.NotNil(t, pipeCommands) 2096 assert.Equal(t, pipeCommands.PipeCommandType, structs.MeasureAggsType) 2097 assert.Len(t, pipeCommands.MeasureOperations, 1) 2098 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureCol, "latency") 2099 assert.Equal(t, pipeCommands.MeasureOperations[0].MeasureFunc, utils.Sum) 2100 2101 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2102 assert.Nil(t, err) 2103 assert.NotNil(t, astNode) 2104 assert.NotNil(t, aggregator) 2105 2106 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2107 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2108 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2109 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2110 2111 assert.Equal(t, aggregator.PipeCommandType, structs.MeasureAggsType) 2112 assert.Len(t, aggregator.MeasureOperations, 1) 2113 assert.Equal(t, aggregator.MeasureOperations[0].MeasureCol, "latency") 2114 assert.Equal(t, aggregator.MeasureOperations[0].MeasureFunc, utils.Sum) 2115 } 2116 2117 func Test_groupbyOneField(t *testing.T) { 2118 query := []byte(`search A=1 | stats avg(latency) BY http_status`) 2119 res, err := spl.Parse("", query) 2120 assert.Nil(t, err) 2121 filterNode := res.(ast.QueryStruct).SearchFilter 2122 assert.NotNil(t, filterNode) 2123 2124 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2125 assert.Equal(t, filterNode.Comparison.Field, "A") 2126 assert.Equal(t, filterNode.Comparison.Op, "=") 2127 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2128 2129 pipeCommands := res.(ast.QueryStruct).PipeCommands 2130 assert.NotNil(t, pipeCommands) 2131 assert.Equal(t, pipeCommands.PipeCommandType, structs.GroupByType) 2132 assert.Len(t, pipeCommands.GroupByRequest.MeasureOperations, 1) 2133 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[0].MeasureCol, "latency") 2134 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[0].MeasureFunc, utils.Avg) 2135 assert.Len(t, pipeCommands.GroupByRequest.GroupByColumns, 1) 2136 assert.Equal(t, pipeCommands.GroupByRequest.GroupByColumns[0], "http_status") 2137 assert.Equal(t, pipeCommands.BucketLimit, segquery.MAX_GRP_BUCKS) 2138 2139 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2140 assert.Nil(t, err) 2141 assert.NotNil(t, astNode) 2142 assert.NotNil(t, aggregator) 2143 2144 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2145 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2146 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2147 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2148 2149 assert.Equal(t, aggregator.PipeCommandType, structs.GroupByType) 2150 assert.Len(t, aggregator.GroupByRequest.MeasureOperations, 1) 2151 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[0].MeasureCol, "latency") 2152 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[0].MeasureFunc, utils.Avg) 2153 assert.Len(t, aggregator.GroupByRequest.GroupByColumns, 1) 2154 assert.Equal(t, aggregator.GroupByRequest.GroupByColumns[0], "http_status") 2155 assert.Equal(t, aggregator.BucketLimit, segquery.MAX_GRP_BUCKS) 2156 } 2157 2158 func Test_groupbyManyFields(t *testing.T) { 2159 query := []byte(`search A=1 | stats avg(latency) BY http_status, weekday, city`) 2160 res, err := spl.Parse("", query) 2161 assert.Nil(t, err) 2162 filterNode := res.(ast.QueryStruct).SearchFilter 2163 assert.NotNil(t, filterNode) 2164 2165 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2166 assert.Equal(t, filterNode.Comparison.Field, "A") 2167 assert.Equal(t, filterNode.Comparison.Op, "=") 2168 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2169 2170 pipeCommands := res.(ast.QueryStruct).PipeCommands 2171 assert.NotNil(t, pipeCommands) 2172 assert.Equal(t, pipeCommands.PipeCommandType, structs.GroupByType) 2173 assert.Len(t, pipeCommands.GroupByRequest.MeasureOperations, 1) 2174 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[0].MeasureCol, "latency") 2175 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[0].MeasureFunc, utils.Avg) 2176 assert.Len(t, pipeCommands.GroupByRequest.GroupByColumns, 3) 2177 assert.Equal(t, pipeCommands.GroupByRequest.GroupByColumns[0], "http_status") 2178 assert.Equal(t, pipeCommands.GroupByRequest.GroupByColumns[1], "weekday") 2179 assert.Equal(t, pipeCommands.GroupByRequest.GroupByColumns[2], "city") 2180 assert.Equal(t, pipeCommands.BucketLimit, segquery.MAX_GRP_BUCKS) 2181 2182 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2183 assert.Nil(t, err) 2184 assert.NotNil(t, astNode) 2185 assert.NotNil(t, aggregator) 2186 2187 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2188 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2189 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2190 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2191 2192 assert.Equal(t, aggregator.PipeCommandType, structs.GroupByType) 2193 assert.Len(t, aggregator.GroupByRequest.MeasureOperations, 1) 2194 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[0].MeasureCol, "latency") 2195 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[0].MeasureFunc, utils.Avg) 2196 assert.Len(t, aggregator.GroupByRequest.GroupByColumns, 3) 2197 assert.Equal(t, aggregator.GroupByRequest.GroupByColumns[0], "http_status") 2198 assert.Equal(t, aggregator.GroupByRequest.GroupByColumns[1], "weekday") 2199 assert.Equal(t, aggregator.GroupByRequest.GroupByColumns[2], "city") 2200 assert.Equal(t, aggregator.BucketLimit, segquery.MAX_GRP_BUCKS) 2201 } 2202 2203 func Test_timechartHasGroupby(t *testing.T) { 2204 queries := []string{ 2205 `search A=1 | timechart span=1d avg(latency), sum(latitude) BY http_status limit=bottom2`, 2206 `search A=1 | timechart avg(latency), sum(latitude) BY http_status span=1d limit=bottom2`, 2207 } 2208 2209 for _, queryStr := range queries { 2210 query := []byte(queryStr) 2211 res, err := spl.Parse("", query) 2212 assert.Nil(t, err) 2213 filterNode := res.(ast.QueryStruct).SearchFilter 2214 assert.NotNil(t, filterNode) 2215 2216 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2217 assert.Equal(t, filterNode.Comparison.Field, "A") 2218 assert.Equal(t, filterNode.Comparison.Op, "=") 2219 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2220 2221 pipeCommands := res.(ast.QueryStruct).PipeCommands 2222 assert.NotNil(t, pipeCommands) 2223 assert.Equal(t, pipeCommands.PipeCommandType, structs.GroupByType) 2224 assert.Len(t, pipeCommands.GroupByRequest.MeasureOperations, 2) 2225 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[0].MeasureCol, "latency") 2226 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[0].MeasureFunc, utils.Avg) 2227 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[1].MeasureCol, "latitude") 2228 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[1].MeasureFunc, utils.Sum) 2229 assert.Len(t, pipeCommands.GroupByRequest.GroupByColumns, 1) 2230 assert.Equal(t, pipeCommands.GroupByRequest.GroupByColumns[0], "timestamp") 2231 assert.Equal(t, pipeCommands.BucketLimit, segquery.MAX_GRP_BUCKS) 2232 // Timechart 2233 assert.NotNil(t, pipeCommands.TimeHistogram) 2234 assert.NotNil(t, pipeCommands.TimeHistogram.Timechart) 2235 assert.Equal(t, uint64(86_400_000), pipeCommands.TimeHistogram.IntervalMillis) 2236 assert.Equal(t, "http_status", pipeCommands.TimeHistogram.Timechart.ByField) 2237 assert.NotNil(t, pipeCommands.TimeHistogram.Timechart.LimitExpr) 2238 assert.False(t, pipeCommands.TimeHistogram.Timechart.LimitExpr.IsTop) 2239 assert.Equal(t, 2, pipeCommands.TimeHistogram.Timechart.LimitExpr.Num) 2240 assert.Equal(t, structs.LSMByFreq, int(pipeCommands.TimeHistogram.Timechart.LimitExpr.LimitScoreMode)) 2241 2242 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2243 assert.Nil(t, err) 2244 assert.NotNil(t, astNode) 2245 assert.NotNil(t, aggregator) 2246 2247 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2248 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2249 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2250 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2251 2252 assert.Equal(t, aggregator.PipeCommandType, structs.GroupByType) 2253 assert.Len(t, aggregator.GroupByRequest.MeasureOperations, 2) 2254 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[0].MeasureCol, "latency") 2255 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[0].MeasureFunc, utils.Avg) 2256 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[1].MeasureCol, "latitude") 2257 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[1].MeasureFunc, utils.Sum) 2258 assert.Len(t, aggregator.GroupByRequest.GroupByColumns, 1) 2259 assert.Equal(t, aggregator.GroupByRequest.GroupByColumns[0], "timestamp") 2260 assert.Equal(t, aggregator.BucketLimit, segquery.MAX_GRP_BUCKS) 2261 // Timechart 2262 assert.NotNil(t, aggregator.TimeHistogram) 2263 assert.NotNil(t, aggregator.TimeHistogram.Timechart) 2264 assert.Equal(t, uint64(86_400_000), aggregator.TimeHistogram.IntervalMillis) 2265 assert.Equal(t, "http_status", aggregator.TimeHistogram.Timechart.ByField) 2266 assert.NotNil(t, aggregator.TimeHistogram.Timechart.LimitExpr) 2267 assert.False(t, aggregator.TimeHistogram.Timechart.LimitExpr.IsTop) 2268 assert.Equal(t, 2, aggregator.TimeHistogram.Timechart.LimitExpr.Num) 2269 assert.Equal(t, structs.LSMByFreq, int(aggregator.TimeHistogram.Timechart.LimitExpr.LimitScoreMode)) 2270 } 2271 } 2272 2273 func Test_timechartWithoutGroupby(t *testing.T) { 2274 queries := []string{ 2275 `search A=1 | timechart span=1hr min(latency), range(longitude)`, 2276 `search A=1 | timechart min(latency), range(longitude) span=1hr`, 2277 } 2278 2279 for _, queryStr := range queries { 2280 query := []byte(queryStr) 2281 res, err := spl.Parse("", query) 2282 assert.Nil(t, err) 2283 filterNode := res.(ast.QueryStruct).SearchFilter 2284 assert.NotNil(t, filterNode) 2285 2286 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2287 assert.Equal(t, filterNode.Comparison.Field, "A") 2288 assert.Equal(t, filterNode.Comparison.Op, "=") 2289 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2290 2291 pipeCommands := res.(ast.QueryStruct).PipeCommands 2292 assert.NotNil(t, pipeCommands) 2293 assert.Equal(t, pipeCommands.PipeCommandType, structs.GroupByType) 2294 assert.Len(t, pipeCommands.GroupByRequest.MeasureOperations, 2) 2295 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[0].MeasureCol, "latency") 2296 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[0].MeasureFunc, utils.Min) 2297 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[1].MeasureCol, "longitude") 2298 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[1].MeasureFunc, utils.Range) 2299 assert.Len(t, pipeCommands.GroupByRequest.GroupByColumns, 1) 2300 assert.Equal(t, pipeCommands.GroupByRequest.GroupByColumns[0], "timestamp") 2301 assert.Equal(t, pipeCommands.BucketLimit, segquery.MAX_GRP_BUCKS) 2302 // Timechart 2303 assert.NotNil(t, pipeCommands.TimeHistogram) 2304 assert.NotNil(t, pipeCommands.TimeHistogram.Timechart) 2305 assert.Equal(t, uint64(3_600_000), pipeCommands.TimeHistogram.IntervalMillis) 2306 assert.Equal(t, "", pipeCommands.TimeHistogram.Timechart.ByField) 2307 assert.Nil(t, pipeCommands.TimeHistogram.Timechart.LimitExpr) 2308 2309 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2310 assert.Nil(t, err) 2311 assert.NotNil(t, astNode) 2312 assert.NotNil(t, aggregator) 2313 2314 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2315 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2316 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2317 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2318 2319 assert.Equal(t, aggregator.PipeCommandType, structs.GroupByType) 2320 assert.Len(t, aggregator.GroupByRequest.MeasureOperations, 2) 2321 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[0].MeasureCol, "latency") 2322 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[0].MeasureFunc, utils.Min) 2323 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[1].MeasureCol, "longitude") 2324 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[1].MeasureFunc, utils.Range) 2325 assert.Len(t, aggregator.GroupByRequest.GroupByColumns, 1) 2326 assert.Equal(t, aggregator.GroupByRequest.GroupByColumns[0], "timestamp") 2327 assert.Equal(t, aggregator.BucketLimit, segquery.MAX_GRP_BUCKS) 2328 // Timechart 2329 assert.NotNil(t, aggregator.TimeHistogram) 2330 assert.NotNil(t, aggregator.TimeHistogram.Timechart) 2331 assert.Equal(t, uint64(3_600_000), aggregator.TimeHistogram.IntervalMillis) 2332 assert.Equal(t, "", aggregator.TimeHistogram.Timechart.ByField) 2333 assert.Nil(t, aggregator.TimeHistogram.Timechart.LimitExpr) 2334 } 2335 } 2336 2337 func Test_timechartWithoutGroupBy(t *testing.T) { 2338 queries := []string{ 2339 `search A=1 | timechart span=1d avg(latency), sum(latitude) BY http_status`, 2340 `search A=1 | timechart avg(latency), sum(latitude) BY http_status span=1d`, 2341 } 2342 for _, queryStr := range queries { 2343 query := []byte(queryStr) 2344 res, err := spl.Parse("", query) 2345 assert.Nil(t, err) 2346 filterNode := res.(ast.QueryStruct).SearchFilter 2347 assert.NotNil(t, filterNode) 2348 2349 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2350 assert.Equal(t, filterNode.Comparison.Field, "A") 2351 assert.Equal(t, filterNode.Comparison.Op, "=") 2352 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2353 2354 pipeCommands := res.(ast.QueryStruct).PipeCommands 2355 assert.NotNil(t, pipeCommands) 2356 assert.Equal(t, pipeCommands.PipeCommandType, structs.GroupByType) 2357 assert.Len(t, pipeCommands.GroupByRequest.MeasureOperations, 2) 2358 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[0].MeasureCol, "latency") 2359 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[0].MeasureFunc, utils.Avg) 2360 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[1].MeasureCol, "latitude") 2361 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[1].MeasureFunc, utils.Sum) 2362 assert.Len(t, pipeCommands.GroupByRequest.GroupByColumns, 1) 2363 assert.Equal(t, pipeCommands.GroupByRequest.GroupByColumns[0], "timestamp") 2364 assert.Equal(t, pipeCommands.BucketLimit, segquery.MAX_GRP_BUCKS) 2365 // Timechart 2366 assert.NotNil(t, pipeCommands.TimeHistogram) 2367 assert.NotNil(t, pipeCommands.TimeHistogram.Timechart) 2368 assert.Equal(t, "http_status", pipeCommands.TimeHistogram.Timechart.ByField) 2369 2370 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2371 assert.Nil(t, err) 2372 assert.NotNil(t, astNode) 2373 assert.NotNil(t, aggregator) 2374 2375 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2376 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2377 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2378 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2379 2380 assert.Equal(t, aggregator.PipeCommandType, structs.GroupByType) 2381 assert.Len(t, aggregator.GroupByRequest.MeasureOperations, 2) 2382 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[0].MeasureCol, "latency") 2383 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[0].MeasureFunc, utils.Avg) 2384 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[1].MeasureCol, "latitude") 2385 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[1].MeasureFunc, utils.Sum) 2386 assert.Len(t, aggregator.GroupByRequest.GroupByColumns, 1) 2387 assert.Equal(t, aggregator.GroupByRequest.GroupByColumns[0], "timestamp") 2388 assert.Equal(t, aggregator.BucketLimit, segquery.MAX_GRP_BUCKS) 2389 // Timechart 2390 assert.NotNil(t, aggregator.TimeHistogram) 2391 assert.NotNil(t, aggregator.TimeHistogram.Timechart) 2392 assert.Equal(t, "http_status", pipeCommands.TimeHistogram.Timechart.ByField) 2393 } 2394 } 2395 2396 func Test_TimechartSpanArgWithoutGroupBy(t *testing.T) { 2397 queries := []string{ 2398 `search A=1 | timechart span=1m avg(latency)`, 2399 `search A=1 | timechart avg(latency) span=1m`, 2400 } 2401 2402 for _, queryStr := range queries { 2403 query := []byte(queryStr) 2404 res, err := spl.Parse("", query) 2405 assert.Nil(t, err) 2406 2407 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2408 2409 assert.Nil(t, err) 2410 assert.NotNil(t, astNode) 2411 assert.NotNil(t, aggregator) 2412 2413 assert.Equal(t, uint64(60_000), aggregator.TimeHistogram.IntervalMillis) 2414 2415 pipeCommands := res.(ast.QueryStruct).PipeCommands 2416 assert.NotNil(t, pipeCommands) 2417 assert.Equal(t, pipeCommands.PipeCommandType, structs.GroupByType) 2418 assert.Len(t, pipeCommands.GroupByRequest.MeasureOperations, 1) 2419 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[0].MeasureCol, "latency") 2420 assert.Equal(t, pipeCommands.GroupByRequest.MeasureOperations[0].MeasureFunc, utils.Avg) 2421 assert.Len(t, pipeCommands.GroupByRequest.GroupByColumns, 1) 2422 assert.Equal(t, pipeCommands.GroupByRequest.GroupByColumns[0], "timestamp") 2423 assert.Equal(t, pipeCommands.BucketLimit, segquery.MAX_GRP_BUCKS) 2424 } 2425 } 2426 2427 func Test_aggHasEvalFuncWithoutGroupBy(t *testing.T) { 2428 query := []byte(`city=Boston | stats max(latitude), range(eval(latitude >= 0))`) 2429 res, err := spl.Parse("", query) 2430 assert.Nil(t, err) 2431 filterNode := res.(ast.QueryStruct).SearchFilter 2432 assert.NotNil(t, filterNode) 2433 2434 assert.Equal(t, ast.NodeTerminal, filterNode.NodeType) 2435 assert.Equal(t, "city", filterNode.Comparison.Field) 2436 assert.Equal(t, "=", filterNode.Comparison.Op) 2437 assert.Equal(t, "\"Boston\"", filterNode.Comparison.Values) 2438 2439 pipeCommands := res.(ast.QueryStruct).PipeCommands 2440 assert.NotNil(t, pipeCommands) 2441 assert.Equal(t, pipeCommands.PipeCommandType, structs.MeasureAggsType) 2442 assert.Len(t, pipeCommands.MeasureOperations, 2) 2443 assert.Equal(t, "latitude", pipeCommands.MeasureOperations[0].MeasureCol) 2444 assert.Equal(t, utils.Max, pipeCommands.MeasureOperations[0].MeasureFunc) 2445 2446 assert.Equal(t, "range(eval(latitude >= 0))", pipeCommands.MeasureOperations[1].StrEnc) 2447 assert.Equal(t, utils.Range, pipeCommands.MeasureOperations[1].MeasureFunc) 2448 assert.NotNil(t, pipeCommands.MeasureOperations[1].ValueColRequest) 2449 assert.Equal(t, structs.VEMBooleanExpr, int(pipeCommands.MeasureOperations[1].ValueColRequest.ValueExprMode)) 2450 assert.NotNil(t, pipeCommands.MeasureOperations[1].ValueColRequest.BooleanExpr) 2451 assert.NotNil(t, pipeCommands.MeasureOperations[1].ValueColRequest.BooleanExpr.LeftValue) 2452 assert.NotNil(t, pipeCommands.MeasureOperations[1].ValueColRequest.BooleanExpr.RightValue) 2453 assert.NotNil(t, pipeCommands.MeasureOperations[1].ValueColRequest.BooleanExpr.LeftValue.NumericExpr) 2454 assert.NotNil(t, pipeCommands.MeasureOperations[1].ValueColRequest.BooleanExpr.RightValue.NumericExpr) 2455 assert.Equal(t, "latitude", pipeCommands.MeasureOperations[1].ValueColRequest.BooleanExpr.LeftValue.NumericExpr.Value) 2456 assert.Equal(t, "0", pipeCommands.MeasureOperations[1].ValueColRequest.BooleanExpr.RightValue.NumericExpr.Value) 2457 } 2458 2459 func Test_aggHasEvalFuncWithGroupBy(t *testing.T) { 2460 query := []byte(`* | stats count(eval(http_status >= 100)), values(eval(if(len(state) > 5, job_title, city))) BY state`) 2461 res, err := spl.Parse("", query) 2462 assert.Nil(t, err) 2463 filterNode := res.(ast.QueryStruct).SearchFilter 2464 assert.NotNil(t, filterNode) 2465 2466 assert.Equal(t, ast.NodeTerminal, filterNode.NodeType) 2467 assert.Equal(t, "*", filterNode.Comparison.Field) 2468 assert.Equal(t, "=", filterNode.Comparison.Op) 2469 assert.Equal(t, "\"*\"", filterNode.Comparison.Values) 2470 2471 pipeCommands := res.(ast.QueryStruct).PipeCommands 2472 assert.NotNil(t, pipeCommands) 2473 assert.Equal(t, pipeCommands.PipeCommandType, structs.GroupByType) 2474 assert.NotNil(t, pipeCommands.GroupByRequest) 2475 assert.Len(t, pipeCommands.GroupByRequest.MeasureOperations, 2) 2476 2477 assert.Equal(t, "count(eval(http_status >= 100))", pipeCommands.GroupByRequest.MeasureOperations[0].StrEnc) 2478 assert.Equal(t, utils.Count, pipeCommands.GroupByRequest.MeasureOperations[0].MeasureFunc) 2479 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[0].ValueColRequest) 2480 assert.Equal(t, structs.VEMBooleanExpr, int(pipeCommands.GroupByRequest.MeasureOperations[0].ValueColRequest.ValueExprMode)) 2481 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[0].ValueColRequest.BooleanExpr) 2482 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[0].ValueColRequest.BooleanExpr.LeftValue) 2483 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[0].ValueColRequest.BooleanExpr.RightValue) 2484 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[0].ValueColRequest.BooleanExpr.LeftValue.NumericExpr) 2485 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[0].ValueColRequest.BooleanExpr.RightValue.NumericExpr) 2486 assert.Equal(t, "http_status", pipeCommands.GroupByRequest.MeasureOperations[0].ValueColRequest.BooleanExpr.LeftValue.NumericExpr.Value) 2487 assert.Equal(t, "100", pipeCommands.GroupByRequest.MeasureOperations[0].ValueColRequest.BooleanExpr.RightValue.NumericExpr.Value) 2488 2489 assert.Equal(t, "values(eval(if(len(state) > 5, job_title, city)))", pipeCommands.GroupByRequest.MeasureOperations[1].StrEnc) 2490 assert.Equal(t, utils.Values, pipeCommands.GroupByRequest.MeasureOperations[1].MeasureFunc) 2491 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest) 2492 assert.Equal(t, structs.VEMConditionExpr, int(pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ValueExprMode)) 2493 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ConditionExpr) 2494 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ConditionExpr.BoolExpr) 2495 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ConditionExpr.BoolExpr.LeftValue) 2496 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ConditionExpr.BoolExpr.RightValue) 2497 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr) 2498 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ConditionExpr.BoolExpr.RightValue.NumericExpr) 2499 assert.Equal(t, "len", pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.Op) 2500 assert.Equal(t, "state", pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.Left.Value) 2501 assert.Equal(t, "5", pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ConditionExpr.BoolExpr.RightValue.NumericExpr.Value) 2502 2503 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ConditionExpr.TrueValue) 2504 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ConditionExpr.FalseValue) 2505 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ConditionExpr.TrueValue.NumericExpr) 2506 assert.NotNil(t, pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ConditionExpr.FalseValue.NumericExpr) 2507 assert.Equal(t, "job_title", pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ConditionExpr.TrueValue.NumericExpr.Value) 2508 assert.Equal(t, "city", pipeCommands.GroupByRequest.MeasureOperations[1].ValueColRequest.ConditionExpr.FalseValue.NumericExpr.Value) 2509 } 2510 2511 func Test_groupbyFieldWithWildcard(t *testing.T) { 2512 query := []byte(`search A=1 | stats avg(latency) BY http*`) 2513 _, err := spl.Parse("", query) 2514 assert.NotNil(t, err) 2515 } 2516 2517 func Test_fieldSelectImplicitPlus(t *testing.T) { 2518 query := []byte(`search A=1 | fields weekday`) 2519 res, err := spl.Parse("", query) 2520 assert.Nil(t, err) 2521 filterNode := res.(ast.QueryStruct).SearchFilter 2522 assert.NotNil(t, filterNode) 2523 2524 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2525 assert.Equal(t, filterNode.Comparison.Field, "A") 2526 assert.Equal(t, filterNode.Comparison.Op, "=") 2527 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2528 2529 pipeCommands := res.(ast.QueryStruct).PipeCommands 2530 assert.NotNil(t, pipeCommands) 2531 assert.Equal(t, pipeCommands.PipeCommandType, structs.OutputTransformType) 2532 assert.Len(t, pipeCommands.OutputTransforms.OutputColumns.ExcludeColumns, 0) 2533 assert.Len(t, pipeCommands.OutputTransforms.OutputColumns.IncludeColumns, 1) 2534 assert.Equal(t, pipeCommands.OutputTransforms.OutputColumns.IncludeColumns[0], "weekday") 2535 2536 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2537 assert.Nil(t, err) 2538 assert.NotNil(t, astNode) 2539 assert.NotNil(t, aggregator) 2540 2541 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2542 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2543 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2544 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2545 2546 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 2547 assert.Len(t, aggregator.OutputTransforms.OutputColumns.ExcludeColumns, 0) 2548 assert.Len(t, aggregator.OutputTransforms.OutputColumns.IncludeColumns, 1) 2549 assert.Equal(t, aggregator.OutputTransforms.OutputColumns.IncludeColumns[0], "weekday") 2550 } 2551 2552 func Test_fieldSelectExplicitPlus(t *testing.T) { 2553 query := []byte(`search A=1 | fields + weekday`) 2554 res, err := spl.Parse("", query) 2555 assert.Nil(t, err) 2556 filterNode := res.(ast.QueryStruct).SearchFilter 2557 assert.NotNil(t, filterNode) 2558 2559 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2560 assert.Equal(t, filterNode.Comparison.Field, "A") 2561 assert.Equal(t, filterNode.Comparison.Op, "=") 2562 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2563 2564 pipeCommands := res.(ast.QueryStruct).PipeCommands 2565 assert.NotNil(t, pipeCommands) 2566 assert.Equal(t, pipeCommands.PipeCommandType, structs.OutputTransformType) 2567 assert.Len(t, pipeCommands.OutputTransforms.OutputColumns.ExcludeColumns, 0) 2568 assert.Len(t, pipeCommands.OutputTransforms.OutputColumns.IncludeColumns, 1) 2569 assert.Equal(t, pipeCommands.OutputTransforms.OutputColumns.IncludeColumns[0], "weekday") 2570 2571 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2572 assert.Nil(t, err) 2573 assert.NotNil(t, astNode) 2574 assert.NotNil(t, aggregator) 2575 2576 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2577 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2578 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2579 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2580 2581 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 2582 assert.Len(t, aggregator.OutputTransforms.OutputColumns.ExcludeColumns, 0) 2583 assert.Len(t, aggregator.OutputTransforms.OutputColumns.IncludeColumns, 1) 2584 assert.Equal(t, aggregator.OutputTransforms.OutputColumns.IncludeColumns[0], "weekday") 2585 } 2586 2587 func Test_fieldSelectMinus(t *testing.T) { 2588 query := []byte(`search A=1 | fields - weekday`) 2589 res, err := spl.Parse("", query) 2590 assert.Nil(t, err) 2591 filterNode := res.(ast.QueryStruct).SearchFilter 2592 assert.NotNil(t, filterNode) 2593 2594 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2595 assert.Equal(t, filterNode.Comparison.Field, "A") 2596 assert.Equal(t, filterNode.Comparison.Op, "=") 2597 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2598 2599 pipeCommands := res.(ast.QueryStruct).PipeCommands 2600 assert.NotNil(t, pipeCommands) 2601 assert.Equal(t, pipeCommands.PipeCommandType, structs.OutputTransformType) 2602 assert.Len(t, pipeCommands.OutputTransforms.OutputColumns.IncludeColumns, 0) 2603 assert.Len(t, pipeCommands.OutputTransforms.OutputColumns.ExcludeColumns, 1) 2604 assert.Equal(t, pipeCommands.OutputTransforms.OutputColumns.ExcludeColumns[0], "weekday") 2605 2606 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2607 assert.Nil(t, err) 2608 assert.NotNil(t, astNode) 2609 assert.NotNil(t, aggregator) 2610 2611 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2612 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2613 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2614 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2615 2616 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 2617 assert.Len(t, aggregator.OutputTransforms.OutputColumns.IncludeColumns, 0) 2618 assert.Len(t, aggregator.OutputTransforms.OutputColumns.ExcludeColumns, 1) 2619 assert.Equal(t, aggregator.OutputTransforms.OutputColumns.ExcludeColumns[0], "weekday") 2620 } 2621 2622 func Test_fieldSelectManyFields(t *testing.T) { 2623 query := []byte(`search A=1 | fields weekday, latency, city`) 2624 res, err := spl.Parse("", query) 2625 assert.Nil(t, err) 2626 filterNode := res.(ast.QueryStruct).SearchFilter 2627 assert.NotNil(t, filterNode) 2628 2629 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2630 assert.Equal(t, filterNode.Comparison.Field, "A") 2631 assert.Equal(t, filterNode.Comparison.Op, "=") 2632 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2633 2634 pipeCommands := res.(ast.QueryStruct).PipeCommands 2635 assert.NotNil(t, pipeCommands) 2636 assert.Equal(t, pipeCommands.PipeCommandType, structs.OutputTransformType) 2637 assert.Len(t, pipeCommands.OutputTransforms.OutputColumns.ExcludeColumns, 0) 2638 assert.Len(t, pipeCommands.OutputTransforms.OutputColumns.IncludeColumns, 3) 2639 assert.Equal(t, pipeCommands.OutputTransforms.OutputColumns.IncludeColumns[0], "weekday") 2640 assert.Equal(t, pipeCommands.OutputTransforms.OutputColumns.IncludeColumns[1], "latency") 2641 assert.Equal(t, pipeCommands.OutputTransforms.OutputColumns.IncludeColumns[2], "city") 2642 2643 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2644 assert.Nil(t, err) 2645 assert.NotNil(t, astNode) 2646 assert.NotNil(t, aggregator) 2647 2648 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2649 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2650 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2651 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2652 2653 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 2654 assert.Len(t, aggregator.OutputTransforms.OutputColumns.ExcludeColumns, 0) 2655 assert.Len(t, aggregator.OutputTransforms.OutputColumns.IncludeColumns, 3) 2656 assert.Equal(t, aggregator.OutputTransforms.OutputColumns.IncludeColumns[0], "weekday") 2657 assert.Equal(t, aggregator.OutputTransforms.OutputColumns.IncludeColumns[1], "latency") 2658 assert.Equal(t, aggregator.OutputTransforms.OutputColumns.IncludeColumns[2], "city") 2659 } 2660 2661 func Test_commentAtStart(t *testing.T) { 2662 query := []byte("```Hello, world!``` A=1") 2663 res, err := spl.Parse("", query) 2664 assert.Nil(t, err) 2665 filterNode := res.(ast.QueryStruct).SearchFilter 2666 2667 assert.NotNil(t, filterNode) 2668 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2669 assert.Equal(t, filterNode.Comparison.Field, "A") 2670 assert.Equal(t, filterNode.Comparison.Op, "=") 2671 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2672 2673 astNode := &structs.ASTNode{} 2674 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 2675 assert.Nil(t, err) 2676 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 2677 assert.Len(t, astNode.AndFilterCondition.NestedNodes, 0) 2678 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2679 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2680 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2681 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2682 } 2683 2684 func Test_commentInMiddle(t *testing.T) { 2685 query := []byte("search A=1 ```Hello, world!``` OR C=3") 2686 res, err := spl.Parse("", query) 2687 assert.Nil(t, err) 2688 filterNode := res.(ast.QueryStruct).SearchFilter 2689 2690 assert.NotNil(t, filterNode) 2691 assert.Equal(t, ast.NodeOr, filterNode.NodeType) 2692 2693 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 2694 assert.Equal(t, filterNode.Left.Comparison.Field, "A") 2695 assert.Equal(t, filterNode.Left.Comparison.Op, "=") 2696 assert.Equal(t, filterNode.Left.Comparison.Values, json.Number("1")) 2697 2698 assert.Equal(t, filterNode.Right.NodeType, ast.NodeTerminal) 2699 assert.Equal(t, filterNode.Right.Comparison.Field, "C") 2700 assert.Equal(t, filterNode.Right.Comparison.Op, "=") 2701 assert.Equal(t, filterNode.Right.Comparison.Values, json.Number("3")) 2702 2703 astNode := &structs.ASTNode{} 2704 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 2705 assert.Nil(t, err) 2706 assert.NotNil(t, astNode.OrFilterCondition.FilterCriteria) 2707 assert.Len(t, astNode.OrFilterCondition.NestedNodes, 0) 2708 assert.Len(t, astNode.OrFilterCondition.FilterCriteria, 2) 2709 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2710 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2711 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2712 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "C") 2713 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 2714 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(3)) 2715 } 2716 2717 func Test_commentAtEnd(t *testing.T) { 2718 query := []byte("A=1 ```| search B=2```") 2719 res, err := spl.Parse("", query) 2720 assert.Nil(t, err) 2721 filterNode := res.(ast.QueryStruct).SearchFilter 2722 2723 assert.NotNil(t, filterNode) 2724 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2725 assert.Equal(t, filterNode.Comparison.Field, "A") 2726 assert.Equal(t, filterNode.Comparison.Op, "=") 2727 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2728 2729 astNode := &structs.ASTNode{} 2730 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 2731 assert.Nil(t, err) 2732 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 2733 assert.Len(t, astNode.AndFilterCondition.NestedNodes, 0) 2734 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2735 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2736 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2737 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2738 } 2739 2740 func Test_commentContainingQuotes(t *testing.T) { 2741 query := []byte("A=1 ```| search B=\"2\"```") 2742 res, err := spl.Parse("", query) 2743 assert.Nil(t, err) 2744 filterNode := res.(ast.QueryStruct).SearchFilter 2745 2746 assert.NotNil(t, filterNode) 2747 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2748 assert.Equal(t, filterNode.Comparison.Field, "A") 2749 assert.Equal(t, filterNode.Comparison.Op, "=") 2750 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2751 2752 astNode := &structs.ASTNode{} 2753 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 2754 assert.Nil(t, err) 2755 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 2756 assert.Len(t, astNode.AndFilterCondition.NestedNodes, 0) 2757 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2758 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2759 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2760 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2761 } 2762 2763 func Test_commentContainingBackticks(t *testing.T) { 2764 query := []byte("A=1 ```one ` and two `` still inside comment```") 2765 res, err := spl.Parse("", query) 2766 assert.Nil(t, err) 2767 filterNode := res.(ast.QueryStruct).SearchFilter 2768 2769 assert.NotNil(t, filterNode) 2770 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2771 assert.Equal(t, filterNode.Comparison.Field, "A") 2772 assert.Equal(t, filterNode.Comparison.Op, "=") 2773 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2774 2775 astNode := &structs.ASTNode{} 2776 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 2777 assert.Nil(t, err) 2778 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 2779 assert.Len(t, astNode.AndFilterCondition.NestedNodes, 0) 2780 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2781 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2782 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2783 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2784 } 2785 2786 func Test_commentInsideQuotes(t *testing.T) { 2787 query := []byte("A=\"Hello, ```this is not commented out``` world!\"") 2788 res, err := spl.Parse("", query) 2789 assert.Nil(t, err) 2790 filterNode := res.(ast.QueryStruct).SearchFilter 2791 2792 assert.NotNil(t, filterNode) 2793 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2794 assert.Equal(t, filterNode.Comparison.Field, "A") 2795 assert.Equal(t, filterNode.Comparison.Op, "=") 2796 assert.Equal(t, filterNode.Comparison.Values, "\"Hello, ```this is not commented out``` world!\"") 2797 2798 astNode := &structs.ASTNode{} 2799 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 2800 assert.Nil(t, err) 2801 assert.NotNil(t, astNode.AndFilterCondition.FilterCriteria) 2802 assert.Len(t, astNode.AndFilterCondition.NestedNodes, 0) 2803 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2804 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2805 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2806 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.StringVal, "Hello, ```this is not commented out``` world!") 2807 } 2808 2809 func Test_renameOneAggField(t *testing.T) { 2810 query := []byte(`search A=1 | stats avg(latency) AS Average`) 2811 res, err := spl.Parse("", query) 2812 assert.Nil(t, err) 2813 filterNode := res.(ast.QueryStruct).SearchFilter 2814 assert.NotNil(t, filterNode) 2815 2816 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2817 assert.Equal(t, filterNode.Comparison.Field, "A") 2818 assert.Equal(t, filterNode.Comparison.Op, "=") 2819 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2820 2821 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2822 assert.Nil(t, err) 2823 assert.NotNil(t, astNode) 2824 assert.NotNil(t, aggregator) 2825 2826 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2827 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2828 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2829 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2830 2831 assert.Equal(t, aggregator.PipeCommandType, structs.MeasureAggsType) 2832 assert.Len(t, aggregator.MeasureOperations, 1) 2833 assert.Equal(t, aggregator.MeasureOperations[0].MeasureCol, "latency") 2834 assert.Equal(t, aggregator.MeasureOperations[0].MeasureFunc, utils.Avg) 2835 2836 renameAgg := aggregator.Next 2837 assert.NotNil(t, renameAgg) 2838 assert.Equal(t, renameAgg.PipeCommandType, structs.OutputTransformType) 2839 assert.NotNil(t, renameAgg.OutputTransforms) 2840 assert.NotNil(t, renameAgg.OutputTransforms.OutputColumns) 2841 assert.Len(t, renameAgg.OutputTransforms.OutputColumns.RenameColumns, 0) 2842 assert.Len(t, renameAgg.OutputTransforms.OutputColumns.RenameAggregationColumns, 1) 2843 assert.Equal(t, renameAgg.OutputTransforms.OutputColumns.RenameAggregationColumns["avg(latency)"], "Average") 2844 } 2845 2846 func Test_renameManyAggFields(t *testing.T) { 2847 query := []byte(`search A=1 | stats avg(latency) AS Average, count AS Count, min(latency)`) 2848 res, err := spl.Parse("", query) 2849 assert.Nil(t, err) 2850 filterNode := res.(ast.QueryStruct).SearchFilter 2851 assert.NotNil(t, filterNode) 2852 2853 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2854 assert.Equal(t, filterNode.Comparison.Field, "A") 2855 assert.Equal(t, filterNode.Comparison.Op, "=") 2856 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2857 2858 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2859 assert.Nil(t, err) 2860 assert.NotNil(t, astNode) 2861 assert.NotNil(t, aggregator) 2862 2863 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2864 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2865 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2866 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2867 2868 assert.Equal(t, aggregator.PipeCommandType, structs.MeasureAggsType) 2869 assert.Len(t, aggregator.MeasureOperations, 3) 2870 assert.Equal(t, aggregator.MeasureOperations[0].MeasureCol, "latency") 2871 assert.Equal(t, aggregator.MeasureOperations[0].MeasureFunc, utils.Avg) 2872 assert.Equal(t, aggregator.MeasureOperations[1].MeasureCol, "*") 2873 assert.Equal(t, aggregator.MeasureOperations[1].MeasureFunc, utils.Count) 2874 assert.Equal(t, aggregator.MeasureOperations[2].MeasureCol, "latency") 2875 assert.Equal(t, aggregator.MeasureOperations[2].MeasureFunc, utils.Min) 2876 2877 renameAgg := aggregator.Next 2878 assert.NotNil(t, renameAgg) 2879 assert.Equal(t, renameAgg.PipeCommandType, structs.OutputTransformType) 2880 assert.Len(t, renameAgg.OutputTransforms.OutputColumns.RenameColumns, 0) 2881 assert.Len(t, renameAgg.OutputTransforms.OutputColumns.RenameAggregationColumns, 2) 2882 assert.Equal(t, renameAgg.OutputTransforms.OutputColumns.RenameAggregationColumns["avg(latency)"], "Average") 2883 assert.Equal(t, renameAgg.OutputTransforms.OutputColumns.RenameAggregationColumns["count(*)"], "Count") 2884 } 2885 2886 func Test_renameFieldsWithGroupby(t *testing.T) { 2887 query := []byte(`search A=1 | stats avg(latency) AS Average, count BY weekday, city`) 2888 res, err := spl.Parse("", query) 2889 assert.Nil(t, err) 2890 filterNode := res.(ast.QueryStruct).SearchFilter 2891 assert.NotNil(t, filterNode) 2892 2893 assert.Equal(t, filterNode.NodeType, ast.NodeTerminal) 2894 assert.Equal(t, filterNode.Comparison.Field, "A") 2895 assert.Equal(t, filterNode.Comparison.Op, "=") 2896 assert.Equal(t, filterNode.Comparison.Values, json.Number("1")) 2897 2898 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2899 assert.Nil(t, err) 2900 assert.NotNil(t, astNode) 2901 assert.NotNil(t, aggregator) 2902 2903 assert.Len(t, astNode.AndFilterCondition.FilterCriteria, 1) 2904 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 2905 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 2906 assert.Equal(t, astNode.AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 2907 2908 assert.Equal(t, aggregator.PipeCommandType, structs.GroupByType) 2909 assert.Len(t, aggregator.GroupByRequest.MeasureOperations, 2) 2910 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[0].MeasureCol, "latency") 2911 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[0].MeasureFunc, utils.Avg) 2912 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[1].MeasureCol, "*") 2913 assert.Equal(t, aggregator.GroupByRequest.MeasureOperations[1].MeasureFunc, utils.Count) 2914 assert.Len(t, aggregator.GroupByRequest.GroupByColumns, 2) 2915 assert.Equal(t, aggregator.GroupByRequest.GroupByColumns[0], "weekday") 2916 assert.Equal(t, aggregator.GroupByRequest.GroupByColumns[1], "city") 2917 assert.Equal(t, aggregator.BucketLimit, segquery.MAX_GRP_BUCKS) 2918 2919 renameAgg := aggregator.Next 2920 assert.NotNil(t, renameAgg) 2921 assert.Equal(t, renameAgg.PipeCommandType, structs.OutputTransformType) 2922 assert.Len(t, renameAgg.OutputTransforms.OutputColumns.RenameColumns, 0) 2923 assert.Len(t, renameAgg.OutputTransforms.OutputColumns.RenameAggregationColumns, 1) 2924 assert.Equal(t, renameAgg.OutputTransforms.OutputColumns.RenameAggregationColumns["avg(latency)"], "Average") 2925 } 2926 2927 func Test_rexBlockNewFieldWithoutGroupBy(t *testing.T) { 2928 query := []byte(`city=Boston | rex field=app_version "(?<first>\d+)\.(?<second>\d+)\.(?<third>\d+)"`) 2929 res, err := spl.Parse("", query) 2930 assert.Nil(t, err) 2931 filterNode := res.(ast.QueryStruct).SearchFilter 2932 assert.NotNil(t, filterNode) 2933 2934 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2935 assert.Nil(t, err) 2936 assert.NotNil(t, astNode) 2937 assert.NotNil(t, aggregator) 2938 assert.Nil(t, aggregator.Next) 2939 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 2940 assert.NotNil(t, aggregator.OutputTransforms.LetColumns) 2941 assert.NotNil(t, aggregator.OutputTransforms.LetColumns.RexColRequest) 2942 assert.Equal(t, aggregator.OutputTransforms.LetColumns.RexColRequest.Pattern, "(?P<first>\\d+)\\.(?P<second>\\d+)\\.(?P<third>\\d+)") 2943 assert.Equal(t, aggregator.OutputTransforms.LetColumns.RexColRequest.FieldName, "app_version") 2944 assert.Equal(t, aggregator.OutputTransforms.LetColumns.RexColRequest.RexColNames, []string{"first", "second", "third"}) 2945 } 2946 2947 func Test_rexBlockOverideExistingFieldWithoutGroupBy(t *testing.T) { 2948 query := []byte(`city=Boston | rex field=app_version "(?<app_version>\d+)\.(?<city>\d+)\.(?<third>\d+)"`) 2949 res, err := spl.Parse("", query) 2950 assert.Nil(t, err) 2951 filterNode := res.(ast.QueryStruct).SearchFilter 2952 assert.NotNil(t, filterNode) 2953 2954 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2955 assert.Nil(t, err) 2956 assert.NotNil(t, astNode) 2957 assert.NotNil(t, aggregator) 2958 assert.Nil(t, aggregator.Next) 2959 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 2960 assert.NotNil(t, aggregator.OutputTransforms.LetColumns) 2961 assert.NotNil(t, aggregator.OutputTransforms.LetColumns.RexColRequest) 2962 assert.Equal(t, aggregator.OutputTransforms.LetColumns.RexColRequest.Pattern, "(?P<app_version>\\d+)\\.(?P<city>\\d+)\\.(?P<third>\\d+)") 2963 assert.Equal(t, aggregator.OutputTransforms.LetColumns.RexColRequest.FieldName, "app_version") 2964 assert.Equal(t, aggregator.OutputTransforms.LetColumns.RexColRequest.RexColNames, []string{"app_version", "city", "third"}) 2965 } 2966 2967 func Test_rexBlockNewFieldWithGroupBy(t *testing.T) { 2968 query := []byte(`city=Boston | stats count AS Count BY user_email | rex field=user_email "(?<name>.+)@(?<provider>.+)"`) 2969 res, err := spl.Parse("", query) 2970 assert.Nil(t, err) 2971 filterNode := res.(ast.QueryStruct).SearchFilter 2972 assert.NotNil(t, filterNode) 2973 2974 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2975 assert.Nil(t, err) 2976 assert.NotNil(t, astNode) 2977 assert.NotNil(t, aggregator) 2978 assert.NotNil(t, aggregator.GroupByRequest) 2979 assert.Equal(t, aggregator.GroupByRequest.GroupByColumns, []string{"user_email"}) 2980 assert.NotNil(t, aggregator.Next) 2981 assert.NotNil(t, aggregator.Next.Next) 2982 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 2983 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.RexColRequest) 2984 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.RexColRequest.Pattern, "(?P<name>.+)@(?P<provider>.+)") 2985 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.RexColRequest.FieldName, "user_email") 2986 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.RexColRequest.RexColNames, []string{"name", "provider"}) 2987 } 2988 2989 func Test_rexBlockOverideExistingFieldWithGroupBy(t *testing.T) { 2990 query := []byte(`city=Boston | stats count AS Count BY http_status, weekday | rex field=http_status "(?<http_status>\d)(?<weekday>\d)(?<third>\d)"`) 2991 res, err := spl.Parse("", query) 2992 assert.Nil(t, err) 2993 filterNode := res.(ast.QueryStruct).SearchFilter 2994 assert.NotNil(t, filterNode) 2995 2996 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 2997 assert.Nil(t, err) 2998 assert.NotNil(t, astNode) 2999 assert.NotNil(t, aggregator) 3000 assert.NotNil(t, aggregator.GroupByRequest) 3001 assert.Equal(t, aggregator.GroupByRequest.GroupByColumns, []string{"http_status", "weekday"}) 3002 assert.NotNil(t, aggregator.Next) 3003 assert.NotNil(t, aggregator.Next.Next) 3004 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3005 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.RexColRequest) 3006 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.RexColRequest.Pattern, "(?P<http_status>\\d)(?P<weekday>\\d)(?P<third>\\d)") 3007 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.RexColRequest.FieldName, "http_status") 3008 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.RexColRequest.RexColNames, []string{"http_status", "weekday", "third"}) 3009 } 3010 3011 func Test_statisticBlockWithoutStatsGroupBy(t *testing.T) { 3012 query := []byte(`city=Boston | rare 3 http_method, gender by country, http_status useother=true otherstr=testOther percentfield=http_method countfield=gender showperc=false`) 3013 res, err := spl.Parse("", query) 3014 assert.Nil(t, err) 3015 filterNode := res.(ast.QueryStruct).SearchFilter 3016 assert.NotNil(t, filterNode) 3017 3018 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3019 assert.Nil(t, err) 3020 assert.NotNil(t, astNode) 3021 assert.NotNil(t, aggregator) 3022 assert.NotNil(t, aggregator.GroupByRequest) 3023 assert.Equal(t, []string{"http_method", "gender", "country", "http_status"}, aggregator.GroupByRequest.GroupByColumns) 3024 assert.NotNil(t, aggregator.Next) 3025 assert.Equal(t, structs.OutputTransformType, aggregator.Next.PipeCommandType) 3026 assert.NotNil(t, aggregator.Next.OutputTransforms) 3027 assert.NotNil(t, aggregator.Next.OutputTransforms.LetColumns) 3028 assert.NotNil(t, aggregator.Next.OutputTransforms.LetColumns.StatisticColRequest) 3029 assert.Equal(t, structs.SFMRare, int(aggregator.Next.OutputTransforms.LetColumns.StatisticColRequest.StatisticFunctionMode)) 3030 3031 assert.Equal(t, "3", aggregator.Next.OutputTransforms.LetColumns.StatisticColRequest.Limit) 3032 assert.Equal(t, "gender", aggregator.Next.OutputTransforms.LetColumns.StatisticColRequest.StatisticOptions.CountField) 3033 assert.Equal(t, "testOther", aggregator.Next.OutputTransforms.LetColumns.StatisticColRequest.StatisticOptions.OtherStr) 3034 assert.Equal(t, "http_method", aggregator.Next.OutputTransforms.LetColumns.StatisticColRequest.StatisticOptions.PercentField) 3035 assert.Equal(t, true, aggregator.Next.OutputTransforms.LetColumns.StatisticColRequest.StatisticOptions.ShowCount) 3036 assert.Equal(t, false, aggregator.Next.OutputTransforms.LetColumns.StatisticColRequest.StatisticOptions.ShowPerc) 3037 assert.Equal(t, true, aggregator.Next.OutputTransforms.LetColumns.StatisticColRequest.StatisticOptions.UseOther) 3038 3039 assert.Equal(t, []string{"http_method", "gender"}, aggregator.Next.OutputTransforms.LetColumns.StatisticColRequest.FieldList) 3040 assert.Equal(t, []string{"country", "http_status"}, aggregator.Next.OutputTransforms.LetColumns.StatisticColRequest.ByClause) 3041 } 3042 3043 func Test_statisticBlockWithStatsGroupBy(t *testing.T) { 3044 query := []byte(`city=Boston | stats count AS gg BY http_status, weekday, gender, state | top 2 gg, state, http_status useother=true countfield=true percentfield=weekday`) 3045 res, err := spl.Parse("", query) 3046 assert.Nil(t, err) 3047 filterNode := res.(ast.QueryStruct).SearchFilter 3048 assert.NotNil(t, filterNode) 3049 3050 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3051 assert.Nil(t, err) 3052 assert.NotNil(t, astNode) 3053 assert.NotNil(t, aggregator) 3054 assert.Equal(t, structs.GroupByType, aggregator.PipeCommandType) 3055 assert.NotNil(t, aggregator.GroupByRequest) 3056 assert.Equal(t, []string{"http_status", "weekday", "gender", "state"}, aggregator.GroupByRequest.GroupByColumns) 3057 assert.NotNil(t, aggregator.Next) 3058 assert.NotNil(t, aggregator.Next.Next) 3059 assert.NotNil(t, aggregator.Next.Next.Next) 3060 assert.NotNil(t, aggregator.Next.Next.GroupByRequest) 3061 assert.Equal(t, structs.GroupByType, aggregator.Next.Next.PipeCommandType) 3062 assert.Equal(t, []string{"gg", "state", "http_status"}, aggregator.Next.Next.GroupByRequest.GroupByColumns) 3063 assert.Equal(t, structs.OutputTransformType, aggregator.Next.Next.Next.PipeCommandType) 3064 assert.NotNil(t, aggregator.Next.Next.Next.OutputTransforms) 3065 assert.NotNil(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns) 3066 3067 assert.NotNil(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.StatisticColRequest) 3068 assert.Equal(t, structs.SFMTop, int(aggregator.Next.Next.Next.OutputTransforms.LetColumns.StatisticColRequest.StatisticFunctionMode)) 3069 assert.Equal(t, "2", aggregator.Next.Next.Next.OutputTransforms.LetColumns.StatisticColRequest.Limit) 3070 assert.Equal(t, "true", aggregator.Next.Next.Next.OutputTransforms.LetColumns.StatisticColRequest.StatisticOptions.CountField) 3071 assert.Equal(t, "other", aggregator.Next.Next.Next.OutputTransforms.LetColumns.StatisticColRequest.StatisticOptions.OtherStr) 3072 assert.Equal(t, "weekday", aggregator.Next.Next.Next.OutputTransforms.LetColumns.StatisticColRequest.StatisticOptions.PercentField) 3073 assert.Equal(t, true, aggregator.Next.Next.Next.OutputTransforms.LetColumns.StatisticColRequest.StatisticOptions.ShowCount) 3074 assert.Equal(t, true, aggregator.Next.Next.Next.OutputTransforms.LetColumns.StatisticColRequest.StatisticOptions.ShowPerc) 3075 assert.Equal(t, true, aggregator.Next.Next.Next.OutputTransforms.LetColumns.StatisticColRequest.StatisticOptions.UseOther) 3076 3077 assert.Equal(t, []string{"gg", "state", "http_status"}, aggregator.Next.Next.Next.OutputTransforms.LetColumns.StatisticColRequest.FieldList) 3078 assert.Equal(t, []string(nil), aggregator.Next.Next.Next.OutputTransforms.LetColumns.StatisticColRequest.ByClause) 3079 } 3080 3081 func Test_renameBlockPhrase(t *testing.T) { 3082 query := []byte(`city=Boston | fields city, country | rename city AS "test"`) 3083 res, err := spl.Parse("", query) 3084 assert.Nil(t, err) 3085 filterNode := res.(ast.QueryStruct).SearchFilter 3086 assert.NotNil(t, filterNode) 3087 3088 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3089 assert.Nil(t, err) 3090 assert.NotNil(t, astNode) 3091 assert.NotNil(t, aggregator) 3092 assert.NotNil(t, aggregator.Next) 3093 assert.Equal(t, aggregator.Next.PipeCommandType, structs.OutputTransformType) 3094 assert.NotNil(t, aggregator.Next.OutputTransforms.LetColumns) 3095 assert.NotNil(t, aggregator.Next.OutputTransforms.LetColumns.RenameColRequest) 3096 assert.Equal(t, structs.REMPhrase, int(aggregator.Next.OutputTransforms.LetColumns.RenameColRequest.RenameExprMode)) 3097 assert.Equal(t, "city", aggregator.Next.OutputTransforms.LetColumns.RenameColRequest.OriginalPattern) 3098 assert.Equal(t, "test", aggregator.Next.OutputTransforms.LetColumns.RenameColRequest.NewPattern) 3099 } 3100 3101 func Test_renameBlockRegex(t *testing.T) { 3102 query := []byte(`city=Boston | stats count AS Count BY http_status, http_method | rename ht*_* AS start*mid*end`) 3103 res, err := spl.Parse("", query) 3104 assert.Nil(t, err) 3105 filterNode := res.(ast.QueryStruct).SearchFilter 3106 assert.NotNil(t, filterNode) 3107 3108 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3109 assert.Nil(t, err) 3110 assert.NotNil(t, astNode) 3111 assert.NotNil(t, aggregator) 3112 assert.NotNil(t, aggregator.Next) 3113 assert.NotNil(t, aggregator.Next.Next) 3114 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3115 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3116 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.RenameColRequest) 3117 assert.Equal(t, structs.REMRegex, int(aggregator.Next.Next.OutputTransforms.LetColumns.RenameColRequest.RenameExprMode)) 3118 assert.Equal(t, "ht*_*", aggregator.Next.Next.OutputTransforms.LetColumns.RenameColRequest.OriginalPattern) 3119 assert.Equal(t, "start*mid*end", aggregator.Next.Next.OutputTransforms.LetColumns.RenameColRequest.NewPattern) 3120 } 3121 3122 func Test_renameOverrideExistingField(t *testing.T) { 3123 query := []byte(`city=Boston | stats count AS Count BY http_status, http_method | rename http_status AS Count`) 3124 res, err := spl.Parse("", query) 3125 assert.Nil(t, err) 3126 filterNode := res.(ast.QueryStruct).SearchFilter 3127 assert.NotNil(t, filterNode) 3128 3129 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3130 assert.Nil(t, err) 3131 assert.NotNil(t, astNode) 3132 assert.NotNil(t, aggregator) 3133 assert.NotNil(t, aggregator.Next) 3134 assert.NotNil(t, aggregator.Next.Next) 3135 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3136 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3137 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.RenameColRequest) 3138 assert.Equal(t, structs.REMOverride, int(aggregator.Next.Next.OutputTransforms.LetColumns.RenameColRequest.RenameExprMode)) 3139 assert.Equal(t, "http_status", aggregator.Next.Next.OutputTransforms.LetColumns.RenameColRequest.OriginalPattern) 3140 assert.Equal(t, "Count", aggregator.Next.Next.OutputTransforms.LetColumns.RenameColRequest.NewPattern) 3141 } 3142 3143 func Test_evalNewField(t *testing.T) { 3144 query := []byte(`search A=1 | stats max(latency) AS Max | eval MaxSeconds=Max . " seconds"`) 3145 res, err := spl.Parse("", query) 3146 assert.Nil(t, err) 3147 filterNode := res.(ast.QueryStruct).SearchFilter 3148 assert.NotNil(t, filterNode) 3149 3150 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3151 assert.Nil(t, err) 3152 assert.NotNil(t, astNode) 3153 assert.NotNil(t, aggregator) 3154 assert.NotNil(t, aggregator.Next) 3155 3156 // Second agg is for renaming max(latency) to Max, the third is for eval. 3157 assert.NotNil(t, aggregator.Next.Next) 3158 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3159 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3160 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "MaxSeconds") 3161 assert.Len(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms, 2) 3162 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].IsField, true) 3163 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].Value, "Max") 3164 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].IsField, false) 3165 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].Value, " seconds") 3166 } 3167 3168 func Test_evalReplaceField(t *testing.T) { 3169 query := []byte(`search A=1 | stats max(latency) AS Max | eval Max=Max . " seconds"`) 3170 res, err := spl.Parse("", query) 3171 assert.Nil(t, err) 3172 filterNode := res.(ast.QueryStruct).SearchFilter 3173 assert.NotNil(t, filterNode) 3174 3175 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3176 assert.Nil(t, err) 3177 assert.NotNil(t, astNode) 3178 assert.NotNil(t, aggregator) 3179 assert.NotNil(t, aggregator.Next) 3180 3181 // Second agg is for renaming max(latency) to Max, the third is for eval. 3182 assert.NotNil(t, aggregator.Next.Next) 3183 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3184 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3185 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "Max") 3186 assert.Len(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms, 2) 3187 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].IsField, true) 3188 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].Value, "Max") 3189 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].IsField, false) 3190 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].Value, " seconds") 3191 } 3192 3193 func Test_evalAfterGroupBy(t *testing.T) { 3194 query := []byte(`search A=1 | stats max(latency) AS Max BY weekday | eval Max=Max . " seconds on " . weekday`) 3195 res, err := spl.Parse("", query) 3196 assert.Nil(t, err) 3197 filterNode := res.(ast.QueryStruct).SearchFilter 3198 assert.NotNil(t, filterNode) 3199 3200 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3201 assert.Nil(t, err) 3202 assert.NotNil(t, astNode) 3203 assert.NotNil(t, aggregator) 3204 assert.NotNil(t, aggregator.Next) 3205 3206 // Second agg is for renaming max(latency) to Max, the third is for eval. 3207 assert.NotNil(t, aggregator.Next.Next) 3208 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3209 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3210 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "Max") 3211 assert.Len(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms, 3) 3212 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].IsField, true) 3213 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].Value, "Max") 3214 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].IsField, false) 3215 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].Value, " seconds on ") 3216 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[2].IsField, true) 3217 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[2].Value, "weekday") 3218 } 3219 3220 func Test_evalReplaceGroupByCol(t *testing.T) { 3221 query := []byte(`search A=1 | stats max(latency) AS Max BY weekday | eval weekday=weekday . ": " . Max . " seconds"`) 3222 res, err := spl.Parse("", query) 3223 assert.Nil(t, err) 3224 filterNode := res.(ast.QueryStruct).SearchFilter 3225 assert.NotNil(t, filterNode) 3226 3227 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3228 assert.Nil(t, err) 3229 assert.NotNil(t, astNode) 3230 assert.NotNil(t, aggregator) 3231 assert.NotNil(t, aggregator.Next) 3232 3233 // Second agg is for renaming max(latency) to Max, the third is for eval. 3234 assert.NotNil(t, aggregator.Next.Next) 3235 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3236 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3237 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "weekday") 3238 assert.Len(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms, 4) 3239 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].IsField, true) 3240 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].Value, "weekday") 3241 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].IsField, false) 3242 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].Value, ": ") 3243 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[2].IsField, true) 3244 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[2].Value, "Max") 3245 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[3].IsField, false) 3246 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[3].Value, " seconds") 3247 } 3248 3249 func Test_evalFunctionsToNumber(t *testing.T) { 3250 query := []byte(`city=Boston | stats count AS Count BY state | eval result=tonumber("0A4",16)`) 3251 res, err := spl.Parse("", query) 3252 assert.Nil(t, err) 3253 filterNode := res.(ast.QueryStruct).SearchFilter 3254 assert.NotNil(t, filterNode) 3255 3256 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3257 assert.Nil(t, err) 3258 assert.NotNil(t, astNode) 3259 assert.NotNil(t, aggregator) 3260 assert.NotNil(t, aggregator.Next) 3261 assert.NotNil(t, aggregator.Next.Next) 3262 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3263 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3264 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 3265 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3266 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMNumericExpr) 3267 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.NumericExprMode), structs.NEMNumericExpr) 3268 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.IsTerminal, false) 3269 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Op, "tonumber") 3270 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right) 3271 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.NumericExprMode), structs.NEMNumber) 3272 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.IsTerminal, true) 3273 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.ValueIsField, false) 3274 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.Value, "16") 3275 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Val) 3276 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Val.StringExprMode), structs.SEMRawString) 3277 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Val.RawString, "0A4") 3278 3279 } 3280 3281 func Test_evalFunctionsAbs(t *testing.T) { 3282 query := []byte(`city=Boston | stats count AS Count BY http_status | eval myField=abs(http_status - 100)`) 3283 res, err := spl.Parse("", query) 3284 assert.Nil(t, err) 3285 filterNode := res.(ast.QueryStruct).SearchFilter 3286 assert.NotNil(t, filterNode) 3287 3288 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3289 assert.Nil(t, err) 3290 assert.NotNil(t, astNode) 3291 assert.NotNil(t, aggregator) 3292 assert.NotNil(t, aggregator.Next) 3293 assert.NotNil(t, aggregator.Next.Next) 3294 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3295 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3296 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "myField") 3297 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.IsTerminal, false) 3298 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Op, "abs") 3299 assert.Nil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right, err) 3300 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Op, "-") 3301 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.IsTerminal, true) 3302 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.ValueIsField, true) 3303 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.Value, "http_status") 3304 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.ValueIsField, false) 3305 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.IsTerminal, true) 3306 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Value, "100") 3307 } 3308 3309 func Test_evalFunctionsCeil(t *testing.T) { 3310 query := []byte(`city=Boston | stats count AS Count BY weekday | eval ceil=ceil(Count + 0.2)`) 3311 res, err := spl.Parse("", query) 3312 assert.Nil(t, err) 3313 filterNode := res.(ast.QueryStruct).SearchFilter 3314 assert.NotNil(t, filterNode) 3315 3316 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3317 assert.Nil(t, err) 3318 assert.NotNil(t, astNode) 3319 assert.NotNil(t, aggregator) 3320 assert.NotNil(t, aggregator.Next) 3321 assert.NotNil(t, aggregator.Next.Next) 3322 assert.Equal(t, aggregator.GroupByRequest.GroupByColumns[0], "weekday") 3323 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3324 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Op, "ceil") 3325 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.IsTerminal, false) 3326 assert.Nil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right, err) 3327 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Op, "+") 3328 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.ValueIsField, true) 3329 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.IsTerminal, true) 3330 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.Value, "Count") 3331 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.IsTerminal, true) 3332 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Value, "0.2") 3333 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.ValueIsField, false) 3334 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "ceil") 3335 } 3336 3337 func Test_evalFunctionsRound(t *testing.T) { 3338 query := []byte(`city=Detroit | stats count AS Count BY latitude | where latitude > 89.6 | eval round=round(latitude)`) 3339 res, err := spl.Parse("", query) 3340 assert.Nil(t, err) 3341 filterNode := res.(ast.QueryStruct).SearchFilter 3342 assert.NotNil(t, filterNode) 3343 3344 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3345 assert.Nil(t, err) 3346 assert.NotNil(t, astNode) 3347 assert.NotNil(t, aggregator) 3348 assert.NotNil(t, aggregator.Next) 3349 assert.NotNil(t, aggregator.Next.Next) 3350 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3351 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.LeftValue.NumericExpr.Value, "latitude") 3352 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.LeftValue.NumericExpr.ValueIsField, true) 3353 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.RightValue.NumericExpr.Value, "89.6") 3354 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.RightValue.NumericExpr.ValueIsField, false) 3355 3356 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.IsTerminal, false) 3357 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Op, "round") 3358 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Value, "latitude") 3359 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.ValueIsField, true) 3360 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.IsTerminal, true) 3361 assert.Nil(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right) 3362 } 3363 3364 func Test_evalFunctionsRoundPrecision(t *testing.T) { 3365 query := []byte(`city=Detroit | stats count AS Count BY latitude | where latitude > 89.6 | eval round=round(latitude, 3)`) 3366 res, err := spl.Parse("", query) 3367 assert.Nil(t, err) 3368 filterNode := res.(ast.QueryStruct).SearchFilter 3369 assert.NotNil(t, filterNode) 3370 3371 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3372 assert.Nil(t, err) 3373 assert.NotNil(t, astNode) 3374 assert.NotNil(t, aggregator) 3375 assert.NotNil(t, aggregator.Next) 3376 assert.NotNil(t, aggregator.Next.Next) 3377 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3378 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.LeftValue.NumericExpr.Value, "latitude") 3379 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.LeftValue.NumericExpr.ValueIsField, true) 3380 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.RightValue.NumericExpr.Value, "89.6") 3381 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.RightValue.NumericExpr.ValueIsField, false) 3382 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.IsTerminal, false) 3383 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Op, "round") 3384 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Value, "latitude") 3385 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.ValueIsField, true) 3386 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.IsTerminal, true) 3387 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.Value, "3") 3388 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.ValueIsField, false) 3389 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.IsTerminal, true) 3390 } 3391 3392 func Test_evalFunctionsSqrt(t *testing.T) { 3393 query := []byte(`city=Columbus | stats count AS Count BY http_status | eval sqrt=sqrt(http_status + 200)`) 3394 res, err := spl.Parse("", query) 3395 assert.Nil(t, err) 3396 filterNode := res.(ast.QueryStruct).SearchFilter 3397 assert.NotNil(t, filterNode) 3398 3399 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3400 assert.Nil(t, err) 3401 assert.NotNil(t, astNode) 3402 assert.NotNil(t, aggregator) 3403 assert.NotNil(t, aggregator.Next) 3404 assert.NotNil(t, aggregator.Next.Next) 3405 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3406 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3407 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "sqrt") 3408 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.IsTerminal, false) 3409 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Op, "sqrt") 3410 assert.Nil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right, err) 3411 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Op, "+") 3412 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.Value, "http_status") 3413 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.ValueIsField, true) 3414 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Value, "200") 3415 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.ValueIsField, false) 3416 } 3417 3418 func Test_evalFunctionsLen(t *testing.T) { 3419 query := []byte(`city=Boston | stats count AS Count BY app_name | eval len=len(app_name) | where len > 22`) 3420 res, err := spl.Parse("", query) 3421 assert.Nil(t, err) 3422 filterNode := res.(ast.QueryStruct).SearchFilter 3423 assert.NotNil(t, filterNode) 3424 3425 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3426 assert.Nil(t, err) 3427 assert.NotNil(t, astNode) 3428 assert.NotNil(t, aggregator) 3429 assert.NotNil(t, aggregator.Next) 3430 assert.NotNil(t, aggregator.Next.Next) 3431 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3432 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3433 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "len") 3434 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3435 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr) 3436 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.IsTerminal, false) 3437 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Op, "len") 3438 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.NumericExprMode), structs.NEMLenField) 3439 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.IsTerminal, true) 3440 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.ValueIsField, true) 3441 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Value, "app_name") 3442 assert.Nil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right) 3443 assert.Nil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left) 3444 assert.Nil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right) 3445 } 3446 3447 func Test_evalFunctionsLower(t *testing.T) { 3448 query := []byte(`city=Boston | stats count AS Count BY state | eval myField="Test concat:" . lower(state) . " end"`) 3449 res, err := spl.Parse("", query) 3450 assert.Nil(t, err) 3451 filterNode := res.(ast.QueryStruct).SearchFilter 3452 assert.NotNil(t, filterNode) 3453 3454 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3455 assert.Nil(t, err) 3456 assert.NotNil(t, astNode) 3457 assert.NotNil(t, aggregator) 3458 assert.NotNil(t, aggregator.Next) 3459 assert.NotNil(t, aggregator.Next.Next) 3460 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3461 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3462 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "myField") 3463 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3464 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMStringExpr) 3465 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr) 3466 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr) 3467 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].Value, "Test concat:") 3468 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].IsField, false) 3469 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].TextExpr.Op, "lower") 3470 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].TextExpr.Value.StringExprMode), structs.SEMField) 3471 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].TextExpr.Value.FieldName, "state") 3472 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].IsField, false) 3473 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[2].Value, " end") 3474 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[2].IsField, false) 3475 } 3476 3477 func Test_evalFunctionsLtrim(t *testing.T) { 3478 query := []byte(`city=Boston | stats count AS Count BY state | eval myField=ltrim(state, "Ma") . " test end"`) 3479 res, err := spl.Parse("", query) 3480 assert.Nil(t, err) 3481 filterNode := res.(ast.QueryStruct).SearchFilter 3482 assert.NotNil(t, filterNode) 3483 3484 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3485 assert.Nil(t, err) 3486 assert.NotNil(t, astNode) 3487 assert.NotNil(t, aggregator) 3488 assert.NotNil(t, aggregator.Next) 3489 assert.NotNil(t, aggregator.Next.Next) 3490 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3491 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3492 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "myField") 3493 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3494 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMStringExpr) 3495 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr) 3496 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr) 3497 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.Op, "ltrim") 3498 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.StrToRemove, "Ma") 3499 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.Value.FieldName, "state") 3500 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.Value.StringExprMode), structs.SEMField) 3501 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].IsField, false) 3502 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].Value, " test end") 3503 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].IsField, false) 3504 } 3505 3506 func Test_evalFunctionsRtrim(t *testing.T) { 3507 query := []byte(`city=Boston | stats count AS Count BY state | eval myField=state . " start:" . rtrim(state, "nd")`) 3508 res, err := spl.Parse("", query) 3509 assert.Nil(t, err) 3510 filterNode := res.(ast.QueryStruct).SearchFilter 3511 assert.NotNil(t, filterNode) 3512 3513 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3514 assert.Nil(t, err) 3515 assert.NotNil(t, astNode) 3516 assert.NotNil(t, aggregator) 3517 assert.NotNil(t, aggregator.Next) 3518 assert.NotNil(t, aggregator.Next.Next) 3519 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3520 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3521 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "myField") 3522 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3523 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMStringExpr) 3524 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr) 3525 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr) 3526 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].Value, "state") 3527 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].IsField, true) 3528 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].Value, " start:") 3529 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].IsField, false) 3530 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[2].TextExpr.Op, "rtrim") 3531 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[2].TextExpr.Value.FieldName, "state") 3532 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[2].TextExpr.Value.StringExprMode), structs.SEMField) 3533 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[2].TextExpr.StrToRemove, "nd") 3534 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[2].IsField, false) 3535 } 3536 3537 func Test_evalFunctionsIf(t *testing.T) { 3538 query := []byte(`city=Boston | stats count AS Count BY http_status | eval myField=if(http_status > 400, http_status, "Error")`) 3539 res, err := spl.Parse("", query) 3540 assert.Nil(t, err) 3541 filterNode := res.(ast.QueryStruct).SearchFilter 3542 assert.NotNil(t, filterNode) 3543 3544 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3545 assert.Nil(t, err) 3546 assert.NotNil(t, astNode) 3547 assert.NotNil(t, aggregator) 3548 assert.NotNil(t, aggregator.Next) 3549 assert.NotNil(t, aggregator.Next.Next) 3550 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3551 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3552 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "myField") 3553 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3554 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMConditionExpr) 3555 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr) 3556 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.Op, "if") 3557 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr) 3558 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.IsTerminal, true) 3559 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.IsTerminal, true) 3560 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.ValueIsField, true) 3561 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.Value, "http_status") 3562 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.RightValue.NumericExpr.IsTerminal, true) 3563 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.RightValue.NumericExpr.ValueIsField, false) 3564 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.RightValue.NumericExpr.Value, "400") 3565 3566 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.TrueValue.NumericExpr.IsTerminal, true) 3567 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.TrueValue.NumericExpr.ValueIsField, true) 3568 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.TrueValue.NumericExpr.Value, "http_status") 3569 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.FalseValue.StringExpr.RawString, "Error") 3570 } 3571 3572 func Test_evalFunctionsIn(t *testing.T) { 3573 query := []byte(`city=Boston | stats count AS Count BY http_status | where http_status in(404, 301, "abc")`) 3574 res, err := spl.Parse("", query) 3575 assert.Nil(t, err) 3576 filterNode := res.(ast.QueryStruct).SearchFilter 3577 assert.NotNil(t, filterNode) 3578 3579 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3580 assert.Nil(t, err) 3581 assert.NotNil(t, astNode) 3582 assert.NotNil(t, aggregator) 3583 assert.NotNil(t, aggregator.Next) 3584 assert.NotNil(t, aggregator.Next.Next) 3585 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3586 assert.Nil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3587 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.FilterRows) 3588 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.IsTerminal, true) 3589 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.FilterRows.LeftValue) 3590 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.FilterRows.LeftValue.NumericExpr) 3591 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.LeftValue.NumericExpr.IsTerminal, true) 3592 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.LeftValue.NumericExpr.ValueIsField, true) 3593 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.FilterRows.LeftValue.NumericExpr.NumericExprMode), structs.NEMNumberField) 3594 assert.Nil(t, aggregator.Next.Next.OutputTransforms.FilterRows.RightValue) 3595 3596 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.ValueOp, "in") 3597 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.FilterRows.ValueList) 3598 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.ValueList[0].NumericExpr.IsTerminal, true) 3599 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.ValueList[0].NumericExpr.ValueIsField, false) 3600 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.ValueList[0].NumericExpr.Value, "404") 3601 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.ValueList[1].NumericExpr.IsTerminal, true) 3602 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.ValueList[1].NumericExpr.ValueIsField, false) 3603 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.ValueList[1].NumericExpr.Value, "301") 3604 assert.Equal(t, aggregator.Next.Next.OutputTransforms.FilterRows.ValueList[2].StringExpr.RawString, "abc") 3605 } 3606 3607 func Test_evalFunctionsIfAndIn(t *testing.T) { 3608 query := []byte(`city=Boston | stats count AS Count BY state | eval myField=if(in(state, "Mary" . "land", "Hawaii", 99 + 1), state, "Error")`) 3609 res, err := spl.Parse("", query) 3610 assert.Nil(t, err) 3611 filterNode := res.(ast.QueryStruct).SearchFilter 3612 assert.NotNil(t, filterNode) 3613 3614 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3615 assert.Nil(t, err) 3616 assert.NotNil(t, astNode) 3617 assert.NotNil(t, aggregator) 3618 assert.NotNil(t, aggregator.Next) 3619 assert.NotNil(t, aggregator.Next.Next) 3620 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3621 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3622 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "myField") 3623 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3624 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMConditionExpr) 3625 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr) 3626 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.Op, "if") 3627 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr) 3628 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueOp, "in") 3629 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.IsTerminal, true) 3630 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.IsTerminal, true) 3631 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.ValueIsField, true) 3632 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.Value, "state") 3633 assert.Nil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.RightValue) 3634 3635 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueList[0].StringExpr.ConcatExpr.Atoms[0].IsField, false) 3636 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueList[0].StringExpr.ConcatExpr.Atoms[0].Value, "Mary") 3637 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueList[0].StringExpr.ConcatExpr.Atoms[1].IsField, false) 3638 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueList[0].StringExpr.ConcatExpr.Atoms[1].Value, "land") 3639 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueList[1].StringExpr.RawString, "Hawaii") 3640 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueList[2].NumericExpr.Op, "+") 3641 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueList[2].NumericExpr.Left.IsTerminal, true) 3642 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueList[2].NumericExpr.Left.ValueIsField, false) 3643 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueList[2].NumericExpr.Left.Value, "99") 3644 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueList[2].NumericExpr.Right.IsTerminal, true) 3645 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueList[2].NumericExpr.Right.ValueIsField, false) 3646 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueList[2].NumericExpr.Right.Value, "1") 3647 3648 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.TrueValue.NumericExpr.IsTerminal, true) 3649 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.TrueValue.NumericExpr.ValueIsField, true) 3650 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.TrueValue.NumericExpr.Value, "state") 3651 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.FalseValue.StringExpr.RawString, "Error") 3652 } 3653 3654 func Test_evalFunctionsCidrmatch(t *testing.T) { 3655 query := []byte(`city=Boston | stats count AS Count BY http_status | eval result=if(cidrmatch("192.0.2.0/24", "192.0.2.5"), "local", "not local")`) 3656 res, err := spl.Parse("", query) 3657 assert.Nil(t, err) 3658 filterNode := res.(ast.QueryStruct).SearchFilter 3659 assert.NotNil(t, filterNode) 3660 3661 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3662 assert.Nil(t, err) 3663 assert.NotNil(t, astNode) 3664 assert.NotNil(t, aggregator) 3665 assert.NotNil(t, aggregator.Next) 3666 assert.NotNil(t, aggregator.Next.Next) 3667 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3668 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3669 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 3670 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3671 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMConditionExpr) 3672 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr) 3673 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.Op, "if") 3674 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr) 3675 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueOp, "cidrmatch") 3676 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.IsTerminal, true) 3677 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.StringExpr.RawString, "192.0.2.0/24") 3678 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.RightValue.StringExpr.RawString, "192.0.2.5") 3679 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.TrueValue.StringExpr.RawString, "local") 3680 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.FalseValue.StringExpr.RawString, "not local") 3681 3682 } 3683 func Test_evalFunctionsIfAndIsString(t *testing.T) { 3684 query := []byte(`city=Boston | stats count AS Count BY country | eval result=if(isstr(country), "This is a string", "This is not a string")`) 3685 res, err := spl.Parse("", query) 3686 assert.Nil(t, err) 3687 filterNode := res.(ast.QueryStruct).SearchFilter 3688 assert.NotNil(t, filterNode) 3689 3690 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3691 assert.Nil(t, err) 3692 assert.NotNil(t, astNode) 3693 assert.NotNil(t, aggregator) 3694 assert.NotNil(t, aggregator.Next) 3695 assert.NotNil(t, aggregator.Next.Next) 3696 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3697 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3698 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 3699 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3700 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMConditionExpr) 3701 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr) 3702 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.Op, "if") 3703 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr) 3704 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueOp, "isstr") 3705 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.IsTerminal, true) 3706 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.IsTerminal, true) 3707 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.ValueIsField, true) 3708 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.Value, "country") 3709 assert.Nil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.RightValue) 3710 3711 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.TrueValue.StringExpr.RawString, "This is a string") 3712 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.FalseValue.StringExpr.RawString, "This is not a string") 3713 3714 } 3715 3716 func Test_evalFunctionsIfAndIsInt(t *testing.T) { 3717 query := []byte(`city=Boston | stats count AS Count BY http_status | eval result=if(isint(http_status), "This is an integer", "This is not an integer")`) 3718 res, err := spl.Parse("", query) 3719 assert.Nil(t, err) 3720 filterNode := res.(ast.QueryStruct).SearchFilter 3721 assert.NotNil(t, filterNode) 3722 3723 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3724 assert.Nil(t, err) 3725 assert.NotNil(t, astNode) 3726 assert.NotNil(t, aggregator) 3727 assert.NotNil(t, aggregator.Next) 3728 assert.NotNil(t, aggregator.Next.Next) 3729 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3730 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3731 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 3732 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3733 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMConditionExpr) 3734 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr) 3735 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.Op, "if") 3736 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr) 3737 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueOp, "isint") 3738 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.IsTerminal, true) 3739 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.IsTerminal, true) 3740 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.ValueIsField, true) 3741 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.Value, "http_status") 3742 assert.Nil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.RightValue) 3743 3744 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.TrueValue.StringExpr.RawString, "This is an integer") 3745 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.FalseValue.StringExpr.RawString, "This is not an integer") 3746 3747 } 3748 func Test_evalFunctionsIfAndIsBool(t *testing.T) { 3749 query := []byte(`city=Boston | stats count AS Count BY city | eval result=if(isbool(city), "This is a boolean value", "This is not a boolean value")`) 3750 res, err := spl.Parse("", query) 3751 assert.Nil(t, err) 3752 filterNode := res.(ast.QueryStruct).SearchFilter 3753 assert.NotNil(t, filterNode) 3754 3755 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3756 assert.Nil(t, err) 3757 assert.NotNil(t, astNode) 3758 assert.NotNil(t, aggregator) 3759 assert.NotNil(t, aggregator.Next) 3760 assert.NotNil(t, aggregator.Next.Next) 3761 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3762 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3763 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 3764 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3765 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMConditionExpr) 3766 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr) 3767 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.Op, "if") 3768 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr) 3769 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueOp, "isbool") 3770 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.IsTerminal, true) 3771 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.IsTerminal, true) 3772 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.ValueIsField, true) 3773 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.Value, "city") 3774 assert.Nil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.RightValue) 3775 3776 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.TrueValue.StringExpr.RawString, "This is a boolean value") 3777 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.FalseValue.StringExpr.RawString, "This is not a boolean value") 3778 3779 } 3780 3781 func Test_evalFunctionsIfAndIsNull(t *testing.T) { 3782 query := []byte(`city=Boston | stats count AS Count BY state | eval result=if(isnull(state), "This is a null value", "This is not a null value")`) 3783 res, err := spl.Parse("", query) 3784 assert.Nil(t, err) 3785 filterNode := res.(ast.QueryStruct).SearchFilter 3786 assert.NotNil(t, filterNode) 3787 3788 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3789 assert.Nil(t, err) 3790 assert.NotNil(t, astNode) 3791 assert.NotNil(t, aggregator) 3792 assert.NotNil(t, aggregator.Next) 3793 assert.NotNil(t, aggregator.Next.Next) 3794 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3795 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3796 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 3797 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3798 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMConditionExpr) 3799 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr) 3800 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.Op, "if") 3801 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr) 3802 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueOp, "isnull") 3803 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.IsTerminal, true) 3804 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.IsTerminal, true) 3805 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.ValueIsField, true) 3806 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.Value, "state") 3807 assert.Nil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.RightValue) 3808 3809 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.TrueValue.StringExpr.RawString, "This is a null value") 3810 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.FalseValue.StringExpr.RawString, "This is not a null value") 3811 3812 } 3813 3814 func Test_evalFunctionsLike(t *testing.T) { 3815 query := []byte(`city=Boston | stats count AS Count BY http_status | eval result=if(like(http_status, "4%"), "True", "False")`) 3816 res, err := spl.Parse("", query) 3817 assert.Nil(t, err) 3818 filterNode := res.(ast.QueryStruct).SearchFilter 3819 assert.NotNil(t, filterNode) 3820 3821 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3822 assert.Nil(t, err) 3823 assert.NotNil(t, astNode) 3824 assert.NotNil(t, aggregator) 3825 assert.NotNil(t, aggregator.Next) 3826 assert.NotNil(t, aggregator.Next.Next) 3827 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3828 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3829 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 3830 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3831 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMConditionExpr) 3832 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr) 3833 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.Op, "if") 3834 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr) 3835 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueOp, "like") 3836 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.IsTerminal, true) 3837 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.ValueIsField, true) 3838 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.Value, "http_status") 3839 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.RightValue.StringExpr.RawString, "4%") 3840 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.TrueValue.StringExpr.RawString, "True") 3841 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.FalseValue.StringExpr.RawString, "False") 3842 3843 } 3844 3845 func Test_evalFunctionsMatch(t *testing.T) { 3846 query := []byte(`city=Boston | stats count AS Count BY country | eval result=if(match(country, "^Sa"), "yes", "no")`) 3847 res, err := spl.Parse("", query) 3848 assert.Nil(t, err) 3849 filterNode := res.(ast.QueryStruct).SearchFilter 3850 assert.NotNil(t, filterNode) 3851 3852 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3853 assert.Nil(t, err) 3854 assert.NotNil(t, astNode) 3855 assert.NotNil(t, aggregator) 3856 assert.NotNil(t, aggregator.Next) 3857 assert.NotNil(t, aggregator.Next.Next) 3858 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3859 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3860 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 3861 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3862 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMConditionExpr) 3863 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr) 3864 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.Op, "if") 3865 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr) 3866 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.ValueOp, "match") 3867 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.IsTerminal, true) 3868 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.ValueIsField, true) 3869 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.LeftValue.NumericExpr.Value, "country") 3870 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.BoolExpr.RightValue.StringExpr.RawString, "^Sa") 3871 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.TrueValue.StringExpr.RawString, "yes") 3872 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ConditionExpr.FalseValue.StringExpr.RawString, "no") 3873 3874 } 3875 3876 func Test_evalFunctionsUrldecode(t *testing.T) { 3877 query := []byte(`city=Boston | stats count AS Count BY http_status | eval result=urldecode("http%3A%2F%2Fwww.splunk.com%2Fdownload%3Fr%3Dheader")`) 3878 res, err := spl.Parse("", query) 3879 assert.Nil(t, err) 3880 filterNode := res.(ast.QueryStruct).SearchFilter 3881 assert.NotNil(t, filterNode) 3882 3883 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3884 assert.Nil(t, err) 3885 assert.NotNil(t, astNode) 3886 assert.NotNil(t, aggregator) 3887 assert.NotNil(t, aggregator.Next) 3888 assert.NotNil(t, aggregator.Next.Next) 3889 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3890 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3891 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 3892 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3893 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMStringExpr) 3894 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr) 3895 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr) 3896 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Op, "urldecode") 3897 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Value) 3898 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Value.RawString, "http%3A%2F%2Fwww.splunk.com%2Fdownload%3Fr%3Dheader") 3899 3900 } 3901 3902 func Test_evalFunctionsSplit(t *testing.T) { 3903 query := []byte(`city=Boston | stats count AS Count BY ident | eval result=split(ident,"-")`) 3904 res, err := spl.Parse("", query) 3905 assert.Nil(t, err) 3906 filterNode := res.(ast.QueryStruct).SearchFilter 3907 assert.NotNil(t, filterNode) 3908 3909 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3910 assert.Nil(t, err) 3911 assert.NotNil(t, astNode) 3912 assert.NotNil(t, aggregator) 3913 assert.NotNil(t, aggregator.Next) 3914 assert.NotNil(t, aggregator.Next.Next) 3915 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3916 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3917 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 3918 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3919 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMStringExpr) 3920 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Op, "split") 3921 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Value) 3922 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Value.StringExprMode), structs.SEMField) 3923 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Value.FieldName, "ident") 3924 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Delimiter) 3925 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Delimiter.RawString, "-") 3926 3927 } 3928 3929 func Test_evalFunctionsNow(t *testing.T) { 3930 query := []byte(`city=Boston | stats count AS Count BY ident | eval result=now()`) 3931 res, err := spl.Parse("", query) 3932 assert.Nil(t, err) 3933 filterNode := res.(ast.QueryStruct).SearchFilter 3934 assert.NotNil(t, filterNode) 3935 3936 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3937 assert.Nil(t, err) 3938 assert.NotNil(t, astNode) 3939 assert.NotNil(t, aggregator) 3940 assert.NotNil(t, aggregator.Next) 3941 assert.NotNil(t, aggregator.Next.Next) 3942 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3943 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3944 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 3945 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3946 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMNumericExpr) 3947 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr) 3948 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.NumericExprMode), structs.NEMNumber) 3949 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.IsTerminal, true) 3950 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Op, "now") 3951 3952 } 3953 3954 func Test_evalFunctionsMax(t *testing.T) { 3955 query := []byte(`city=Boston | stats count AS Count BY http_status | eval result=max(1, 3, 450, http_status)`) 3956 res, err := spl.Parse("", query) 3957 assert.Nil(t, err) 3958 filterNode := res.(ast.QueryStruct).SearchFilter 3959 assert.NotNil(t, filterNode) 3960 3961 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3962 assert.Nil(t, err) 3963 assert.NotNil(t, astNode) 3964 assert.NotNil(t, aggregator) 3965 assert.NotNil(t, aggregator.Next) 3966 assert.NotNil(t, aggregator.Next.Next) 3967 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3968 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3969 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 3970 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3971 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMStringExpr) 3972 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Op, "max") 3973 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues) 3974 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues[0].ConcatExpr.Atoms[0].IsField, false) 3975 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues[0].ConcatExpr.Atoms[0].Value, "1") 3976 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues[1].ConcatExpr.Atoms[0].IsField, false) 3977 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues[1].ConcatExpr.Atoms[0].Value, "3") 3978 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues[2].ConcatExpr.Atoms[0].IsField, false) 3979 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues[2].ConcatExpr.Atoms[0].Value, "450") 3980 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues[3].FieldName, "http_status") 3981 } 3982 func Test_evalFunctionsMin(t *testing.T) { 3983 query := []byte(`city=Boston | stats count AS Count BY http_status | eval result=min(1, 3, 450, http_status)`) 3984 res, err := spl.Parse("", query) 3985 assert.Nil(t, err) 3986 filterNode := res.(ast.QueryStruct).SearchFilter 3987 assert.NotNil(t, filterNode) 3988 3989 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 3990 assert.Nil(t, err) 3991 assert.NotNil(t, astNode) 3992 assert.NotNil(t, aggregator) 3993 assert.NotNil(t, aggregator.Next) 3994 assert.NotNil(t, aggregator.Next.Next) 3995 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 3996 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 3997 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 3998 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 3999 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMStringExpr) 4000 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Op, "min") 4001 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues) 4002 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues[0].ConcatExpr.Atoms[0].IsField, false) 4003 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues[0].ConcatExpr.Atoms[0].Value, "1") 4004 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues[1].ConcatExpr.Atoms[0].IsField, false) 4005 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues[1].ConcatExpr.Atoms[0].Value, "3") 4006 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues[2].ConcatExpr.Atoms[0].IsField, false) 4007 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues[2].ConcatExpr.Atoms[0].Value, "450") 4008 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.MaxMinValues[3].FieldName, "http_status") 4009 } 4010 4011 func Test_evalFunctionsSubstr(t *testing.T) { 4012 query := []byte(`city=Boston | stats count AS Count BY state | eval result=substr("splendid", 1, 3) . substr("chunk", -3)`) 4013 res, err := spl.Parse("", query) 4014 assert.Nil(t, err) 4015 filterNode := res.(ast.QueryStruct).SearchFilter 4016 assert.NotNil(t, filterNode) 4017 4018 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4019 assert.Nil(t, err) 4020 assert.NotNil(t, astNode) 4021 assert.NotNil(t, aggregator) 4022 assert.NotNil(t, aggregator.Next) 4023 assert.NotNil(t, aggregator.Next.Next) 4024 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4025 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 4026 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 4027 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 4028 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMStringExpr) 4029 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr) 4030 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr) 4031 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr) 4032 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].IsField, false) 4033 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.IsTerminal, false) 4034 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.Op, "substr") 4035 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.Value) 4036 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.Value.StringExprMode), structs.SEMRawString) 4037 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.Value.RawString, "splendid") 4038 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.StartIndex) 4039 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.StartIndex.NumericExprMode), structs.NEMNumber) 4040 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.StartIndex.IsTerminal, true) 4041 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.StartIndex.ValueIsField, false) 4042 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.StartIndex.Value, "1") 4043 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.LengthExpr) 4044 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.LengthExpr.NumericExprMode), structs.NEMNumber) 4045 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.LengthExpr.IsTerminal, true) 4046 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.LengthExpr.ValueIsField, false) 4047 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].TextExpr.LengthExpr.Value, "3") 4048 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].IsField, false) 4049 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].TextExpr.IsTerminal, false) 4050 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].TextExpr.Op, "substr") 4051 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].TextExpr.Value) 4052 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].TextExpr.Value.StringExprMode), structs.SEMRawString) 4053 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].TextExpr.Value.RawString, "chunk") 4054 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].TextExpr.StartIndex) 4055 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].TextExpr.StartIndex.NumericExprMode), structs.NEMNumber) 4056 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].TextExpr.StartIndex.IsTerminal, true) 4057 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].TextExpr.StartIndex.ValueIsField, false) 4058 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].TextExpr.StartIndex.Value, "-3") 4059 } 4060 4061 func Test_evalFunctionsToStringBooleanValue(t *testing.T) { 4062 query := []byte(`city=Boston | stats count AS Count BY state | eval result=tostring((2 > 1))`) 4063 res, err := spl.Parse("", query) 4064 assert.Nil(t, err) 4065 filterNode := res.(ast.QueryStruct).SearchFilter 4066 assert.NotNil(t, filterNode) 4067 4068 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4069 assert.Nil(t, err) 4070 assert.NotNil(t, astNode) 4071 assert.NotNil(t, aggregator) 4072 assert.NotNil(t, aggregator.Next) 4073 assert.NotNil(t, aggregator.Next.Next) 4074 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4075 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 4076 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 4077 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 4078 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMStringExpr) 4079 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Op, "tostring") 4080 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val) 4081 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.ValueExprMode), structs.VEMBooleanExpr) 4082 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.BooleanExpr.ValueOp, ">") 4083 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.BooleanExpr.IsTerminal, true) 4084 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.BooleanExpr.LeftValue.NumericExpr.IsTerminal, true) 4085 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.BooleanExpr.LeftValue.NumericExpr.ValueIsField, false) 4086 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.BooleanExpr.LeftValue.NumericExpr.Value, "2") 4087 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.BooleanExpr.RightValue.NumericExpr.IsTerminal, true) 4088 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.BooleanExpr.RightValue.NumericExpr.ValueIsField, false) 4089 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.BooleanExpr.RightValue.NumericExpr.Value, "1") 4090 } 4091 4092 func Test_evalFunctionsToStringHex(t *testing.T) { 4093 query := []byte(`city=Boston | stats count AS Count BY state | eval result=tostring(15,"hex")`) 4094 res, err := spl.Parse("", query) 4095 assert.Nil(t, err) 4096 filterNode := res.(ast.QueryStruct).SearchFilter 4097 assert.NotNil(t, filterNode) 4098 4099 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4100 assert.Nil(t, err) 4101 assert.NotNil(t, astNode) 4102 assert.NotNil(t, aggregator) 4103 assert.NotNil(t, aggregator.Next) 4104 assert.NotNil(t, aggregator.Next.Next) 4105 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4106 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 4107 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 4108 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 4109 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMStringExpr) 4110 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Op, "tostring") 4111 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val) 4112 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.ValueExprMode), structs.VEMNumericExpr) 4113 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.NumericExpr.IsTerminal, true) 4114 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.NumericExpr.ValueIsField, false) 4115 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.NumericExpr.Value, "15") 4116 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Format.StringExprMode), structs.SEMRawString) 4117 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Format.RawString, "hex") 4118 } 4119 4120 func Test_evalFunctionsToStringCommas(t *testing.T) { 4121 query := []byte(`city=Boston | stats count AS Count BY state | eval result=tostring(12345.6789,"commas")`) 4122 res, err := spl.Parse("", query) 4123 assert.Nil(t, err) 4124 filterNode := res.(ast.QueryStruct).SearchFilter 4125 assert.NotNil(t, filterNode) 4126 4127 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4128 assert.Nil(t, err) 4129 assert.NotNil(t, astNode) 4130 assert.NotNil(t, aggregator) 4131 assert.NotNil(t, aggregator.Next) 4132 assert.NotNil(t, aggregator.Next.Next) 4133 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4134 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 4135 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 4136 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 4137 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMStringExpr) 4138 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Op, "tostring") 4139 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val) 4140 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.ValueExprMode), structs.VEMNumericExpr) 4141 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.NumericExpr.IsTerminal, true) 4142 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.NumericExpr.ValueIsField, false) 4143 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.NumericExpr.Value, "12345.6789") 4144 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Format.StringExprMode), structs.SEMRawString) 4145 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Format.RawString, "commas") 4146 } 4147 4148 func Test_evalFunctionsToStringDuration(t *testing.T) { 4149 query := []byte(`city=Boston | stats count AS Count BY state | eval result=tostring(615,"duration")`) 4150 res, err := spl.Parse("", query) 4151 assert.Nil(t, err) 4152 filterNode := res.(ast.QueryStruct).SearchFilter 4153 assert.NotNil(t, filterNode) 4154 4155 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4156 assert.Nil(t, err) 4157 assert.NotNil(t, astNode) 4158 assert.NotNil(t, aggregator) 4159 assert.NotNil(t, aggregator.Next) 4160 assert.NotNil(t, aggregator.Next.Next) 4161 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4162 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 4163 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 4164 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest) 4165 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.ValueExprMode), structs.VEMStringExpr) 4166 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Op, "tostring") 4167 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val) 4168 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.ValueExprMode), structs.VEMNumericExpr) 4169 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.NumericExpr.IsTerminal, true) 4170 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.NumericExpr.ValueIsField, false) 4171 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Val.NumericExpr.Value, "615") 4172 assert.Equal(t, int(aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Format.StringExprMode), structs.SEMRawString) 4173 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.TextExpr.Format.RawString, "duration") 4174 } 4175 4176 func Test_evalFunctionsExact(t *testing.T) { 4177 query := []byte(`city=Boston | stats count AS Count BY http_status | eval result=exact(3.14 * http_status)`) 4178 res, err := spl.Parse("", query) 4179 assert.Nil(t, err) 4180 filterNode := res.(ast.QueryStruct).SearchFilter 4181 assert.NotNil(t, filterNode) 4182 4183 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4184 assert.Nil(t, err) 4185 assert.NotNil(t, astNode) 4186 assert.NotNil(t, aggregator) 4187 assert.NotNil(t, aggregator.Next) 4188 assert.NotNil(t, aggregator.Next.Next) 4189 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4190 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 4191 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 4192 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.IsTerminal, false) 4193 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Op, "exact") 4194 assert.Nil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right, err) 4195 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Op, "*") 4196 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.IsTerminal, true) 4197 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.ValueIsField, false) 4198 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.Value, "3.14") 4199 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.ValueIsField, true) 4200 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.IsTerminal, true) 4201 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Value, "http_status") 4202 } 4203 4204 func Test_evalFunctionsExp(t *testing.T) { 4205 query := []byte(`city=Boston | stats count AS Count BY http_status | eval result=exp(3)`) 4206 res, err := spl.Parse("", query) 4207 assert.Nil(t, err) 4208 filterNode := res.(ast.QueryStruct).SearchFilter 4209 assert.NotNil(t, filterNode) 4210 4211 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4212 assert.Nil(t, err) 4213 assert.NotNil(t, astNode) 4214 assert.NotNil(t, aggregator) 4215 assert.NotNil(t, aggregator.Next) 4216 assert.NotNil(t, aggregator.Next.Next) 4217 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4218 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 4219 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "result") 4220 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.IsTerminal, false) 4221 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Op, "exp") 4222 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.IsTerminal, true) 4223 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.ValueIsField, false) 4224 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Value, "3") 4225 } 4226 4227 func Test_ChainedEval(t *testing.T) { 4228 query := []byte(`search A=1 | stats max(latency) AS Max | eval Max=Max . " seconds" | eval Max="Max Latency: " . Max`) 4229 res, err := spl.Parse("", query) 4230 assert.Nil(t, err) 4231 filterNode := res.(ast.QueryStruct).SearchFilter 4232 assert.NotNil(t, filterNode) 4233 4234 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4235 assert.Nil(t, err) 4236 assert.NotNil(t, astNode) 4237 assert.NotNil(t, aggregator) 4238 assert.NotNil(t, aggregator.Next) 4239 4240 // Second agg is for renaming max(latency) to Max, the third is for the first eval. 4241 assert.NotNil(t, aggregator.Next.Next) 4242 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4243 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 4244 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "Max") 4245 assert.Len(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms, 2) 4246 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].IsField, true) 4247 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].Value, "Max") 4248 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].IsField, false) 4249 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].Value, " seconds") 4250 4251 // The fourth agg is for the second eval. 4252 assert.NotNil(t, aggregator.Next.Next.Next) 4253 assert.Equal(t, aggregator.Next.Next.Next.PipeCommandType, structs.OutputTransformType) 4254 assert.NotNil(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns) 4255 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.NewColName, "Max") 4256 assert.Len(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms, 2) 4257 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].IsField, false) 4258 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].Value, "Max Latency: ") 4259 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].IsField, true) 4260 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].Value, "Max") 4261 } 4262 4263 func Test_evalWithMultipleElements(t *testing.T) { 4264 query := []byte(`search A=1 | stats max(latency) AS Max | eval Max=Max . " seconds", Max="Max Latency: " . Max`) 4265 res, err := spl.Parse("", query) 4266 assert.Nil(t, err) 4267 filterNode := res.(ast.QueryStruct).SearchFilter 4268 assert.NotNil(t, filterNode) 4269 4270 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4271 assert.Nil(t, err) 4272 assert.NotNil(t, astNode) 4273 assert.NotNil(t, aggregator) 4274 assert.NotNil(t, aggregator.Next) 4275 4276 // Second agg is for renaming max(latency) to Max, the third is for the first statement in eval. 4277 assert.NotNil(t, aggregator.Next.Next) 4278 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4279 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 4280 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "Max") 4281 assert.Len(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms, 2) 4282 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].IsField, true) 4283 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].Value, "Max") 4284 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].IsField, false) 4285 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].Value, " seconds") 4286 4287 // The fourth agg is for the second statement in eval. 4288 assert.NotNil(t, aggregator.Next.Next.Next) 4289 assert.Equal(t, aggregator.Next.Next.Next.PipeCommandType, structs.OutputTransformType) 4290 assert.NotNil(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns) 4291 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.NewColName, "Max") 4292 assert.Len(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms, 2) 4293 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].IsField, false) 4294 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].Value, "Max Latency: ") 4295 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].IsField, true) 4296 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].Value, "Max") 4297 } 4298 4299 func Test_evalWithMultipleSpaces(t *testing.T) { 4300 query := []byte(`search A = 1 | stats max( latency ) AS Max | eval Max = Max . " seconds", Max="Max Latency: " . Max`) 4301 res, err := spl.Parse("", query) 4302 assert.Nil(t, err) 4303 filterNode := res.(ast.QueryStruct).SearchFilter 4304 assert.NotNil(t, filterNode) 4305 4306 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4307 assert.Nil(t, err) 4308 assert.NotNil(t, astNode) 4309 assert.NotNil(t, aggregator) 4310 assert.NotNil(t, aggregator.Next) 4311 4312 // Second agg is for renaming max(latency) to Max, the third is for the first statement in eval. 4313 assert.NotNil(t, aggregator.Next.Next) 4314 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4315 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 4316 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "Max") 4317 assert.Len(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms, 2) 4318 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].IsField, true) 4319 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].Value, "Max") 4320 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].IsField, false) 4321 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].Value, " seconds") 4322 4323 // The fourth agg is for the second statement in eval. 4324 assert.NotNil(t, aggregator.Next.Next.Next) 4325 assert.Equal(t, aggregator.Next.Next.Next.PipeCommandType, structs.OutputTransformType) 4326 assert.NotNil(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns) 4327 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.NewColName, "Max") 4328 assert.Len(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms, 2) 4329 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].IsField, false) 4330 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[0].Value, "Max Latency: ") 4331 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].IsField, true) 4332 assert.Equal(t, aggregator.Next.Next.Next.OutputTransforms.LetColumns.ValueColRequest.StringExpr.ConcatExpr.Atoms[1].Value, "Max") 4333 } 4334 4335 func Test_evalWithMultipleSpaces2(t *testing.T) { 4336 query := []byte(`search A = 1 OR ( B = 2 AND C = 3)`) 4337 res, err := spl.Parse("", query) 4338 assert.Nil(t, err) 4339 filterNode := res.(ast.QueryStruct).SearchFilter 4340 4341 assert.NotNil(t, filterNode) 4342 assert.Equal(t, filterNode.NodeType, ast.NodeOr) 4343 assert.Equal(t, filterNode.Right.NodeType, ast.NodeAnd) 4344 4345 assert.Equal(t, filterNode.Left.NodeType, ast.NodeTerminal) 4346 assert.Equal(t, filterNode.Left.Comparison.Field, "A") 4347 assert.Equal(t, filterNode.Left.Comparison.Op, "=") 4348 assert.Equal(t, filterNode.Left.Comparison.Values, json.Number("1")) 4349 4350 assert.Equal(t, filterNode.Right.Left.NodeType, ast.NodeTerminal) 4351 assert.Equal(t, filterNode.Right.Left.Comparison.Field, "B") 4352 assert.Equal(t, filterNode.Right.Left.Comparison.Op, "=") 4353 assert.Equal(t, filterNode.Right.Left.Comparison.Values, json.Number("2")) 4354 4355 assert.Equal(t, filterNode.Right.Right.NodeType, ast.NodeTerminal) 4356 assert.Equal(t, filterNode.Right.Right.Comparison.Field, "C") 4357 assert.Equal(t, filterNode.Right.Right.Comparison.Op, "=") 4358 assert.Equal(t, filterNode.Right.Right.Comparison.Values, json.Number("3")) 4359 4360 astNode := &structs.ASTNode{} 4361 err = pipesearch.SearchQueryToASTnode(filterNode, astNode, 0) 4362 assert.Nil(t, err) 4363 assert.NotNil(t, astNode.OrFilterCondition.FilterCriteria) 4364 assert.Len(t, astNode.OrFilterCondition.FilterCriteria, 1) 4365 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "A") 4366 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 4367 assert.Equal(t, astNode.OrFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(1)) 4368 assert.Len(t, astNode.OrFilterCondition.NestedNodes, 1) 4369 assert.Len(t, astNode.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria, 2) 4370 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "B") 4371 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.FilterOperator, utils.Equals) 4372 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[0].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(2)) 4373 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.LeftInput.Expression.LeftInput.ColumnName, "C") 4374 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.FilterOperator, utils.Equals) 4375 assert.Equal(t, astNode.OrFilterCondition.NestedNodes[0].AndFilterCondition.FilterCriteria[1].ExpressionFilter.RightInput.Expression.LeftInput.ColumnValue.UnsignedVal, uint64(3)) 4376 } 4377 4378 func Test_SimpleNumericEval(t *testing.T) { 4379 query := []byte(`search A=1 | stats count AS Count | eval Thousands=Count / 1000`) 4380 res, err := spl.Parse("", query) 4381 assert.Nil(t, err) 4382 filterNode := res.(ast.QueryStruct).SearchFilter 4383 assert.NotNil(t, filterNode) 4384 4385 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4386 assert.Nil(t, err) 4387 assert.NotNil(t, astNode) 4388 assert.NotNil(t, aggregator) 4389 assert.NotNil(t, aggregator.Next) 4390 4391 // Second agg is for renaming count(*) to Count, the third is for eval. 4392 assert.NotNil(t, aggregator.Next.Next) 4393 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4394 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 4395 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "Thousands") 4396 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr) 4397 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.IsTerminal, false) 4398 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Op, "/") 4399 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.IsTerminal, true) 4400 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.ValueIsField, true) 4401 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Value, "Count") 4402 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.IsTerminal, true) 4403 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.ValueIsField, false) 4404 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.Value, "1000") 4405 } 4406 4407 func Test_NumericEvalLeftAssociative(t *testing.T) { 4408 query := []byte(`search A=1 | stats count AS Count | eval Custom=100 - Count - 40.5`) 4409 res, err := spl.Parse("", query) 4410 assert.Nil(t, err) 4411 filterNode := res.(ast.QueryStruct).SearchFilter 4412 assert.NotNil(t, filterNode) 4413 4414 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4415 assert.Nil(t, err) 4416 assert.NotNil(t, astNode) 4417 assert.NotNil(t, aggregator) 4418 assert.NotNil(t, aggregator.Next) 4419 4420 // Second agg is for renaming count(*) to Count, the third is for eval. 4421 // The node structure should be: 4422 // Minus 4423 // / \ 4424 // Minus 40.5 4425 // / \ 4426 // 100 Count 4427 assert.NotNil(t, aggregator.Next.Next) 4428 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4429 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 4430 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "Custom") 4431 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr) 4432 4433 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.IsTerminal, false) 4434 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Op, "-") 4435 4436 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.IsTerminal, false) 4437 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Op, "-") 4438 4439 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.IsTerminal, true) 4440 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.ValueIsField, false) 4441 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.Value, "100") 4442 4443 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.IsTerminal, true) 4444 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.ValueIsField, true) 4445 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Value, "Count") 4446 4447 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.IsTerminal, true) 4448 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.ValueIsField, false) 4449 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.Value, "40.5") 4450 } 4451 4452 func Test_NumericEvalOrderOfOperations(t *testing.T) { 4453 query := []byte(`search A=1 | stats count AS Count | eval Custom=100 - 17 * 22 / 5 + 11`) 4454 res, err := spl.Parse("", query) 4455 assert.Nil(t, err) 4456 filterNode := res.(ast.QueryStruct).SearchFilter 4457 assert.NotNil(t, filterNode) 4458 4459 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4460 assert.Nil(t, err) 4461 assert.NotNil(t, astNode) 4462 assert.NotNil(t, aggregator) 4463 assert.NotNil(t, aggregator.Next) 4464 4465 // Second agg is for renaming count(*) to Count, the third is for eval. 4466 // The eval should be parsed as (100 - ((17 * 22) / 5)) + 11, which is: 4467 // Plus 4468 // / \ 4469 // Minus 11 4470 // / \ 4471 // 100 Divide 4472 // / \ 4473 // Times 5 4474 // / \ 4475 // 17 22 4476 assert.NotNil(t, aggregator.Next.Next) 4477 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4478 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 4479 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "Custom") 4480 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr) 4481 4482 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.IsTerminal, false) 4483 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Op, "+") 4484 4485 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.IsTerminal, false) 4486 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Op, "-") 4487 4488 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.IsTerminal, true) 4489 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.ValueIsField, false) 4490 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Left.Value, "100") 4491 4492 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.IsTerminal, false) 4493 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Op, "/") 4494 4495 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Left.IsTerminal, false) 4496 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Left.Op, "*") 4497 4498 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Left.Left.IsTerminal, true) 4499 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Left.Left.ValueIsField, false) 4500 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Left.Left.Value, "17") 4501 4502 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Left.Right.IsTerminal, true) 4503 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Left.Right.ValueIsField, false) 4504 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Left.Right.Value, "22") 4505 4506 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Right.IsTerminal, true) 4507 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Right.ValueIsField, false) 4508 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Right.Right.Value, "5") 4509 4510 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.IsTerminal, true) 4511 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.ValueIsField, false) 4512 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.Value, "11") 4513 } 4514 4515 func Test_NumericEvalParentheses(t *testing.T) { 4516 query := []byte(`search A=1 | stats count AS Count | eval Custom=22 * (100 - 17)`) 4517 res, err := spl.Parse("", query) 4518 assert.Nil(t, err) 4519 filterNode := res.(ast.QueryStruct).SearchFilter 4520 assert.NotNil(t, filterNode) 4521 4522 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4523 assert.Nil(t, err) 4524 assert.NotNil(t, astNode) 4525 assert.NotNil(t, aggregator) 4526 assert.NotNil(t, aggregator.Next) 4527 4528 // Second agg is for renaming count(*) to Count, the third is for eval. 4529 // The node structure should be: 4530 // Times 4531 // / \ 4532 // 22 Minus 4533 // / \ 4534 // 100 17 4535 assert.NotNil(t, aggregator.Next.Next) 4536 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4537 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns) 4538 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.NewColName, "Custom") 4539 assert.NotNil(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr) 4540 4541 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.IsTerminal, false) 4542 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Op, "*") 4543 4544 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.IsTerminal, true) 4545 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.ValueIsField, false) 4546 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Left.Value, "22") 4547 4548 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.IsTerminal, false) 4549 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.Op, "-") 4550 4551 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.Left.IsTerminal, true) 4552 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.Left.ValueIsField, false) 4553 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.Left.Value, "100") 4554 4555 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.Right.IsTerminal, true) 4556 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.Right.ValueIsField, false) 4557 assert.Equal(t, aggregator.Next.Next.OutputTransforms.LetColumns.ValueColRequest.NumericExpr.Right.Right.Value, "17") 4558 } 4559 4560 func Test_WhereNumeric(t *testing.T) { 4561 query := []byte(`search A=1 | stats count AS Count | where 22 * (100 - 17) >= Count / 50`) 4562 res, err := spl.Parse("", query) 4563 assert.Nil(t, err) 4564 filterNode := res.(ast.QueryStruct).SearchFilter 4565 assert.NotNil(t, filterNode) 4566 4567 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4568 assert.Nil(t, err) 4569 assert.NotNil(t, astNode) 4570 assert.NotNil(t, aggregator) 4571 assert.NotNil(t, aggregator.Next) 4572 4573 // Second agg is for renaming count(*) to Count, the third is for eval. 4574 // The node structure should be: 4575 // BoolExpr 4576 // / | \ 4577 // ValueExpr >= ValueExpr 4578 // | | 4579 // Times Div 4580 // / \ / \ 4581 // 22 Minus Count 50 4582 // / \ 4583 // 100 17 4584 assert.NotNil(t, aggregator.Next.Next) 4585 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4586 4587 filterRows := aggregator.Next.Next.OutputTransforms.FilterRows 4588 assert.NotNil(t, filterRows) 4589 assert.Equal(t, filterRows.IsTerminal, true) 4590 assert.Equal(t, filterRows.ValueOp, ">=") 4591 4592 assert.Equal(t, int(filterRows.LeftValue.ValueExprMode), structs.VEMNumericExpr) 4593 assert.NotNil(t, filterRows.LeftValue.NumericExpr) 4594 4595 assert.Equal(t, filterRows.LeftValue.NumericExpr.IsTerminal, false) 4596 assert.Equal(t, filterRows.LeftValue.NumericExpr.Op, "*") 4597 4598 assert.Equal(t, filterRows.LeftValue.NumericExpr.Left.IsTerminal, true) 4599 assert.Equal(t, filterRows.LeftValue.NumericExpr.Left.ValueIsField, false) 4600 assert.Equal(t, filterRows.LeftValue.NumericExpr.Left.Value, "22") 4601 4602 assert.Equal(t, filterRows.LeftValue.NumericExpr.Right.IsTerminal, false) 4603 assert.Equal(t, filterRows.LeftValue.NumericExpr.Right.Op, "-") 4604 4605 assert.Equal(t, filterRows.LeftValue.NumericExpr.Right.Left.IsTerminal, true) 4606 assert.Equal(t, filterRows.LeftValue.NumericExpr.Right.Left.ValueIsField, false) 4607 assert.Equal(t, filterRows.LeftValue.NumericExpr.Right.Left.Value, "100") 4608 4609 assert.Equal(t, filterRows.LeftValue.NumericExpr.Right.Right.IsTerminal, true) 4610 assert.Equal(t, filterRows.LeftValue.NumericExpr.Right.Right.ValueIsField, false) 4611 assert.Equal(t, filterRows.LeftValue.NumericExpr.Right.Right.Value, "17") 4612 4613 assert.Equal(t, int(filterRows.RightValue.ValueExprMode), structs.VEMNumericExpr) 4614 assert.NotNil(t, filterRows.RightValue.NumericExpr) 4615 4616 assert.Equal(t, filterRows.RightValue.NumericExpr.IsTerminal, false) 4617 assert.Equal(t, filterRows.RightValue.NumericExpr.Op, "/") 4618 4619 assert.Equal(t, filterRows.RightValue.NumericExpr.Left.IsTerminal, true) 4620 assert.Equal(t, filterRows.RightValue.NumericExpr.Left.ValueIsField, true) 4621 assert.Equal(t, filterRows.RightValue.NumericExpr.Left.Value, "Count") 4622 4623 assert.Equal(t, filterRows.RightValue.NumericExpr.Right.IsTerminal, true) 4624 assert.Equal(t, filterRows.RightValue.NumericExpr.Right.ValueIsField, false) 4625 assert.Equal(t, filterRows.RightValue.NumericExpr.Right.Value, "50") 4626 } 4627 4628 func Test_WhereConcat(t *testing.T) { 4629 query := []byte(`search A=1 | stats count AS Count BY weekday | where Count = 10 . " items"`) 4630 res, err := spl.Parse("", query) 4631 assert.Nil(t, err) 4632 filterNode := res.(ast.QueryStruct).SearchFilter 4633 assert.NotNil(t, filterNode) 4634 4635 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4636 assert.Nil(t, err) 4637 assert.NotNil(t, astNode) 4638 assert.NotNil(t, aggregator) 4639 assert.NotNil(t, aggregator.Next) 4640 4641 // Second agg is for renaming count(*) to Count, the third is for eval. 4642 // The node structure should be: 4643 // BoolExpr 4644 // / | \ 4645 // ValueExpr = ValueExpr 4646 // | | 4647 // Count ConcatExpr 4648 // / \ 4649 // 10 " items" 4650 assert.NotNil(t, aggregator.Next.Next) 4651 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4652 4653 filterRows := aggregator.Next.Next.OutputTransforms.FilterRows 4654 assert.NotNil(t, filterRows) 4655 assert.Equal(t, filterRows.IsTerminal, true) 4656 assert.Equal(t, filterRows.ValueOp, "=") 4657 4658 assert.Equal(t, int(filterRows.LeftValue.ValueExprMode), structs.VEMNumericExpr) 4659 assert.Equal(t, filterRows.LeftValue.NumericExpr.Value, "Count") 4660 assert.Equal(t, filterRows.LeftValue.NumericExpr.ValueIsField, true) 4661 4662 assert.Equal(t, int(filterRows.RightValue.ValueExprMode), structs.VEMStringExpr) 4663 assert.NotNil(t, filterRows.RightValue.StringExpr.ConcatExpr) 4664 4665 assert.Len(t, filterRows.RightValue.StringExpr.ConcatExpr.Atoms, 2) 4666 assert.Equal(t, filterRows.RightValue.StringExpr.ConcatExpr.Atoms[0].IsField, false) 4667 assert.Equal(t, filterRows.RightValue.StringExpr.ConcatExpr.Atoms[0].Value, "10") 4668 assert.Equal(t, filterRows.RightValue.StringExpr.ConcatExpr.Atoms[1].IsField, false) 4669 assert.Equal(t, filterRows.RightValue.StringExpr.ConcatExpr.Atoms[1].Value, " items") 4670 } 4671 4672 func Test_WhereBooleanOrderOfOperations(t *testing.T) { 4673 query := []byte(`search A=1 | stats count AS Count | where Count > 1 OR Count > 2 AND NOT (Count > 3) OR Count > 4`) 4674 res, err := spl.Parse("", query) 4675 assert.Nil(t, err) 4676 filterNode := res.(ast.QueryStruct).SearchFilter 4677 assert.NotNil(t, filterNode) 4678 4679 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4680 assert.Nil(t, err) 4681 assert.NotNil(t, astNode) 4682 assert.NotNil(t, aggregator) 4683 assert.NotNil(t, aggregator.Next) 4684 4685 // Second agg is for renaming count(*) to Count, the third is for eval. 4686 // This should be parsed as: (Count > 1 OR (Count > 2 AND NOT (Count > 3))) OR Count > 4 4687 // The node structure should be: 4688 // BoolExpr 4689 // / | \ 4690 // BoolExpr OR BoolExpr 4691 // / | \ / | \ 4692 // BoolExpr OR BoolExpr Count > 4 4693 // / | \ / | \ 4694 // Count > 1 BoolExpr AND BoolExpr 4695 // / | \ / | 4696 // Count > 2 BoolExp Not 4697 // / | \ 4698 // Count > 3 4699 4700 assert.NotNil(t, aggregator.Next.Next) 4701 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4702 4703 filterRows := aggregator.Next.Next.OutputTransforms.FilterRows 4704 assert.NotNil(t, filterRows) 4705 assert.Equal(t, filterRows.IsTerminal, false) 4706 assert.Equal(t, filterRows.BoolOp, structs.BoolOpOr) 4707 4708 assert.Equal(t, filterRows.LeftBool.IsTerminal, false) 4709 assert.Equal(t, filterRows.LeftBool.BoolOp, structs.BoolOpOr) 4710 4711 assert.Equal(t, filterRows.LeftBool.LeftBool.IsTerminal, true) 4712 assert.Equal(t, filterRows.LeftBool.LeftBool.RightValue.NumericExpr.Value, "1") 4713 assert.Equal(t, filterRows.LeftBool.LeftBool.RightValue.NumericExpr.ValueIsField, false) 4714 4715 assert.Equal(t, filterRows.LeftBool.RightBool.IsTerminal, false) 4716 assert.Equal(t, filterRows.LeftBool.RightBool.BoolOp, structs.BoolOpAnd) 4717 4718 assert.Equal(t, filterRows.LeftBool.RightBool.LeftBool.IsTerminal, true) 4719 assert.Equal(t, filterRows.LeftBool.RightBool.LeftBool.RightValue.NumericExpr.Value, "2") 4720 assert.Equal(t, filterRows.LeftBool.RightBool.LeftBool.RightValue.NumericExpr.ValueIsField, false) 4721 4722 assert.Equal(t, filterRows.LeftBool.RightBool.RightBool.IsTerminal, false) 4723 assert.Equal(t, filterRows.LeftBool.RightBool.RightBool.BoolOp, structs.BoolOpNot) 4724 4725 assert.Equal(t, filterRows.LeftBool.RightBool.RightBool.LeftBool.IsTerminal, true) 4726 assert.Equal(t, filterRows.LeftBool.RightBool.RightBool.LeftBool.RightValue.NumericExpr.Value, "3") 4727 assert.Equal(t, filterRows.LeftBool.RightBool.RightBool.LeftBool.RightValue.NumericExpr.ValueIsField, false) 4728 4729 assert.Equal(t, filterRows.RightBool.IsTerminal, true) 4730 assert.Equal(t, filterRows.RightBool.RightValue.NumericExpr.Value, "4") 4731 assert.Equal(t, filterRows.RightBool.RightValue.NumericExpr.ValueIsField, false) 4732 4733 } 4734 4735 func Test_WhereBoolean(t *testing.T) { 4736 query := []byte(`search A=1 | stats count AS Count, min(latency) AS Min, max(latency) AS Max | where Count > 100 OR (Max > 1000 AND NOT ((Max - Min) / 2 <= 600))`) 4737 res, err := spl.Parse("", query) 4738 assert.Nil(t, err) 4739 filterNode := res.(ast.QueryStruct).SearchFilter 4740 assert.NotNil(t, filterNode) 4741 4742 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4743 assert.Nil(t, err) 4744 assert.NotNil(t, astNode) 4745 assert.NotNil(t, aggregator) 4746 assert.NotNil(t, aggregator.Next) 4747 4748 // Second agg is for renaming, the third is for eval. 4749 // The node structure should be: 4750 // BoolExpr 4751 // / | \ 4752 // BoolExpr OR BoolExpr 4753 // / | \ / | \ 4754 // Count > 100 BoolExpr And BoolExpr 4755 // / | \ / | 4756 // Max > 1000 BoolExpr Not 4757 // / | \ 4758 // ValueExpr <= ValueExpr 4759 // | | 4760 // NumericExpr 600 4761 // | 4762 // Div 4763 // / \ 4764 // Minus 2 4765 // / \ 4766 // Max Min 4767 4768 assert.NotNil(t, aggregator.Next.Next) 4769 assert.Equal(t, aggregator.Next.Next.PipeCommandType, structs.OutputTransformType) 4770 4771 filterRows := aggregator.Next.Next.OutputTransforms.FilterRows 4772 assert.NotNil(t, filterRows) 4773 assert.Equal(t, filterRows.IsTerminal, false) 4774 assert.Equal(t, filterRows.BoolOp, structs.BoolOpOr) 4775 4776 assert.Equal(t, filterRows.LeftBool.IsTerminal, true) 4777 assert.Equal(t, int(filterRows.LeftBool.LeftValue.ValueExprMode), structs.VEMNumericExpr) 4778 assert.Equal(t, filterRows.LeftBool.LeftValue.NumericExpr.Value, "Count") 4779 assert.Equal(t, filterRows.LeftBool.LeftValue.NumericExpr.ValueIsField, true) 4780 4781 assert.Equal(t, filterRows.LeftBool.ValueOp, ">") 4782 assert.Equal(t, int(filterRows.LeftBool.RightValue.ValueExprMode), structs.VEMNumericExpr) 4783 assert.NotNil(t, filterRows.LeftBool.RightValue.NumericExpr) 4784 assert.Equal(t, filterRows.LeftBool.RightValue.NumericExpr.IsTerminal, true) 4785 assert.Equal(t, filterRows.LeftBool.RightValue.NumericExpr.Value, "100") 4786 assert.Equal(t, filterRows.LeftBool.RightValue.NumericExpr.ValueIsField, false) 4787 4788 assert.Equal(t, filterRows.RightBool.IsTerminal, false) 4789 assert.Equal(t, filterRows.RightBool.BoolOp, structs.BoolOpAnd) 4790 4791 assert.Equal(t, filterRows.RightBool.LeftBool.IsTerminal, true) 4792 assert.Equal(t, int(filterRows.RightBool.LeftBool.LeftValue.ValueExprMode), structs.VEMNumericExpr) 4793 assert.Equal(t, filterRows.RightBool.LeftBool.LeftValue.NumericExpr.Value, "Max") 4794 assert.Equal(t, filterRows.RightBool.LeftBool.LeftValue.NumericExpr.ValueIsField, true) 4795 4796 assert.Equal(t, filterRows.RightBool.LeftBool.ValueOp, ">") 4797 assert.Equal(t, int(filterRows.RightBool.LeftBool.RightValue.ValueExprMode), structs.VEMNumericExpr) 4798 assert.NotNil(t, filterRows.RightBool.LeftBool.RightValue.NumericExpr) 4799 assert.Equal(t, filterRows.RightBool.LeftBool.RightValue.NumericExpr.IsTerminal, true) 4800 assert.Equal(t, filterRows.RightBool.LeftBool.RightValue.NumericExpr.Value, "1000") 4801 assert.Equal(t, filterRows.RightBool.LeftBool.RightValue.NumericExpr.ValueIsField, false) 4802 4803 assert.Equal(t, filterRows.RightBool.RightBool.IsTerminal, false) 4804 assert.Equal(t, filterRows.RightBool.RightBool.BoolOp, structs.BoolOpNot) 4805 assert.Nil(t, filterRows.RightBool.RightBool.RightBool) 4806 4807 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.IsTerminal, true) 4808 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.ValueOp, "<=") 4809 4810 assert.Equal(t, int(filterRows.RightBool.RightBool.LeftBool.LeftValue.ValueExprMode), structs.VEMNumericExpr) 4811 assert.NotNil(t, filterRows.RightBool.RightBool.LeftBool.LeftValue.NumericExpr) 4812 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.LeftValue.NumericExpr.IsTerminal, false) 4813 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.LeftValue.NumericExpr.Op, "/") 4814 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.LeftValue.NumericExpr.Left.IsTerminal, false) 4815 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.LeftValue.NumericExpr.Left.Op, "-") 4816 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.LeftValue.NumericExpr.Left.Left.IsTerminal, true) 4817 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.LeftValue.NumericExpr.Left.Left.Value, "Max") 4818 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.LeftValue.NumericExpr.Left.Left.ValueIsField, true) 4819 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.LeftValue.NumericExpr.Left.Right.Value, "Min") 4820 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.LeftValue.NumericExpr.Left.Right.ValueIsField, true) 4821 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.LeftValue.NumericExpr.Right.IsTerminal, true) 4822 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.LeftValue.NumericExpr.Right.Value, "2") 4823 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.LeftValue.NumericExpr.Right.ValueIsField, false) 4824 4825 assert.Equal(t, int(filterRows.RightBool.RightBool.LeftBool.RightValue.ValueExprMode), structs.VEMNumericExpr) 4826 assert.NotNil(t, filterRows.RightBool.RightBool.LeftBool.RightValue.NumericExpr) 4827 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.RightValue.NumericExpr.IsTerminal, true) 4828 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.RightValue.NumericExpr.Value, "600") 4829 assert.Equal(t, filterRows.RightBool.RightBool.LeftBool.RightValue.NumericExpr.ValueIsField, false) 4830 } 4831 4832 func Test_head(t *testing.T) { 4833 query := []byte(`A=1 | head`) 4834 res, err := spl.Parse("", query) 4835 assert.Nil(t, err) 4836 filterNode := res.(ast.QueryStruct).SearchFilter 4837 assert.NotNil(t, filterNode) 4838 4839 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4840 assert.Nil(t, err) 4841 assert.NotNil(t, astNode) 4842 assert.NotNil(t, aggregator) 4843 assert.Nil(t, aggregator.Next) 4844 4845 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 4846 assert.Equal(t, aggregator.OutputTransforms.MaxRows, uint64(10)) // This is the SPL default when no value is given. 4847 } 4848 4849 func Test_headWithNumber(t *testing.T) { 4850 query := []byte(`A=1 | head 22`) 4851 res, err := spl.Parse("", query) 4852 assert.Nil(t, err) 4853 filterNode := res.(ast.QueryStruct).SearchFilter 4854 assert.NotNil(t, filterNode) 4855 4856 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4857 assert.Nil(t, err) 4858 assert.NotNil(t, astNode) 4859 assert.NotNil(t, aggregator) 4860 assert.Nil(t, aggregator.Next) 4861 4862 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 4863 assert.Equal(t, aggregator.OutputTransforms.MaxRows, uint64(22)) 4864 } 4865 4866 // SPL allows "limit=" right before the number. 4867 func Test_headWithLimitKeyword(t *testing.T) { 4868 query := []byte(`A=1 | head limit=15`) 4869 res, err := spl.Parse("", query) 4870 assert.Nil(t, err) 4871 filterNode := res.(ast.QueryStruct).SearchFilter 4872 assert.NotNil(t, filterNode) 4873 4874 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4875 assert.Nil(t, err) 4876 assert.NotNil(t, astNode) 4877 assert.NotNil(t, aggregator) 4878 assert.Nil(t, aggregator.Next) 4879 4880 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 4881 assert.Equal(t, aggregator.OutputTransforms.MaxRows, uint64(15)) 4882 } 4883 4884 func Test_dedupOneField(t *testing.T) { 4885 query := []byte(`A=1 | dedup state`) 4886 res, err := spl.Parse("", query) 4887 assert.Nil(t, err) 4888 filterNode := res.(ast.QueryStruct).SearchFilter 4889 assert.NotNil(t, filterNode) 4890 4891 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4892 assert.Nil(t, err) 4893 assert.NotNil(t, astNode) 4894 assert.NotNil(t, aggregator) 4895 assert.Nil(t, aggregator.Next) 4896 4897 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 4898 assert.NotNil(t, aggregator.OutputTransforms.LetColumns) 4899 assert.NotNil(t, aggregator.OutputTransforms.LetColumns.DedupColRequest) 4900 4901 dedupExpr := aggregator.OutputTransforms.LetColumns.DedupColRequest 4902 assert.Equal(t, dedupExpr.Limit, uint64(1)) 4903 assert.Equal(t, dedupExpr.FieldList, []string{"state"}) 4904 assert.NotNil(t, dedupExpr.DedupOptions) 4905 assert.Equal(t, dedupExpr.DedupOptions.Consecutive, false) 4906 assert.Equal(t, dedupExpr.DedupOptions.KeepEmpty, false) 4907 assert.Equal(t, dedupExpr.DedupOptions.KeepEvents, false) 4908 assert.Len(t, dedupExpr.DedupSortEles, 0) 4909 } 4910 4911 func Test_dedupMultipleFields(t *testing.T) { 4912 query := []byte(`A=1 | dedup state weekday http_status`) 4913 res, err := spl.Parse("", query) 4914 assert.Nil(t, err) 4915 filterNode := res.(ast.QueryStruct).SearchFilter 4916 assert.NotNil(t, filterNode) 4917 4918 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4919 assert.Nil(t, err) 4920 assert.NotNil(t, astNode) 4921 assert.NotNil(t, aggregator) 4922 assert.Nil(t, aggregator.Next) 4923 4924 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 4925 assert.NotNil(t, aggregator.OutputTransforms.LetColumns) 4926 assert.NotNil(t, aggregator.OutputTransforms.LetColumns.DedupColRequest) 4927 4928 dedupExpr := aggregator.OutputTransforms.LetColumns.DedupColRequest 4929 assert.Equal(t, dedupExpr.Limit, uint64(1)) 4930 assert.Equal(t, dedupExpr.FieldList, []string{"state", "weekday", "http_status"}) 4931 assert.NotNil(t, dedupExpr.DedupOptions) 4932 assert.Equal(t, dedupExpr.DedupOptions.Consecutive, false) 4933 assert.Equal(t, dedupExpr.DedupOptions.KeepEmpty, false) 4934 assert.Equal(t, dedupExpr.DedupOptions.KeepEvents, false) 4935 assert.Len(t, dedupExpr.DedupSortEles, 0) 4936 } 4937 4938 func Test_dedupWithLimit(t *testing.T) { 4939 query := []byte(`A=1 | dedup 4 state weekday http_status`) 4940 res, err := spl.Parse("", query) 4941 assert.Nil(t, err) 4942 filterNode := res.(ast.QueryStruct).SearchFilter 4943 assert.NotNil(t, filterNode) 4944 4945 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4946 assert.Nil(t, err) 4947 assert.NotNil(t, astNode) 4948 assert.NotNil(t, aggregator) 4949 assert.Nil(t, aggregator.Next) 4950 4951 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 4952 assert.NotNil(t, aggregator.OutputTransforms.LetColumns) 4953 assert.NotNil(t, aggregator.OutputTransforms.LetColumns.DedupColRequest) 4954 4955 dedupExpr := aggregator.OutputTransforms.LetColumns.DedupColRequest 4956 assert.Equal(t, dedupExpr.Limit, uint64(4)) 4957 assert.Equal(t, dedupExpr.FieldList, []string{"state", "weekday", "http_status"}) 4958 assert.NotNil(t, dedupExpr.DedupOptions) 4959 assert.Equal(t, dedupExpr.DedupOptions.Consecutive, false) 4960 assert.Equal(t, dedupExpr.DedupOptions.KeepEmpty, false) 4961 assert.Equal(t, dedupExpr.DedupOptions.KeepEvents, false) 4962 assert.Len(t, dedupExpr.DedupSortEles, 0) 4963 } 4964 4965 func Test_dedupWithOptionsBeforeFieldList(t *testing.T) { 4966 query := []byte(`A=1 | dedup keepevents=true keepempty=false consecutive=true state weekday http_status `) 4967 res, err := spl.Parse("", query) 4968 assert.Nil(t, err) 4969 filterNode := res.(ast.QueryStruct).SearchFilter 4970 assert.NotNil(t, filterNode) 4971 4972 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 4973 assert.Nil(t, err) 4974 assert.NotNil(t, astNode) 4975 assert.NotNil(t, aggregator) 4976 assert.Nil(t, aggregator.Next) 4977 4978 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 4979 assert.NotNil(t, aggregator.OutputTransforms.LetColumns) 4980 assert.NotNil(t, aggregator.OutputTransforms.LetColumns.DedupColRequest) 4981 4982 dedupExpr := aggregator.OutputTransforms.LetColumns.DedupColRequest 4983 assert.Equal(t, dedupExpr.Limit, uint64(1)) 4984 assert.Equal(t, dedupExpr.FieldList, []string{"state", "weekday", "http_status"}) 4985 assert.NotNil(t, dedupExpr.DedupOptions) 4986 assert.Equal(t, dedupExpr.DedupOptions.Consecutive, true) 4987 assert.Equal(t, dedupExpr.DedupOptions.KeepEmpty, false) 4988 assert.Equal(t, dedupExpr.DedupOptions.KeepEvents, true) 4989 assert.Len(t, dedupExpr.DedupSortEles, 0) 4990 } 4991 4992 func Test_dedupWithOptionsAfterFieldList(t *testing.T) { 4993 query := []byte(`A=1 | dedup state weekday http_status keepevents=true keepempty=true consecutive=false`) 4994 res, err := spl.Parse("", query) 4995 assert.Nil(t, err) 4996 filterNode := res.(ast.QueryStruct).SearchFilter 4997 assert.NotNil(t, filterNode) 4998 4999 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 5000 assert.Nil(t, err) 5001 assert.NotNil(t, astNode) 5002 assert.NotNil(t, aggregator) 5003 assert.Nil(t, aggregator.Next) 5004 5005 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 5006 assert.NotNil(t, aggregator.OutputTransforms.LetColumns) 5007 assert.NotNil(t, aggregator.OutputTransforms.LetColumns.DedupColRequest) 5008 5009 dedupExpr := aggregator.OutputTransforms.LetColumns.DedupColRequest 5010 assert.Equal(t, dedupExpr.Limit, uint64(1)) 5011 assert.Equal(t, dedupExpr.FieldList, []string{"state", "weekday", "http_status"}) 5012 assert.NotNil(t, dedupExpr.DedupOptions) 5013 assert.Equal(t, dedupExpr.DedupOptions.Consecutive, false) 5014 assert.Equal(t, dedupExpr.DedupOptions.KeepEmpty, true) 5015 assert.Equal(t, dedupExpr.DedupOptions.KeepEvents, true) 5016 assert.Len(t, dedupExpr.DedupSortEles, 0) 5017 } 5018 5019 func Test_dedupWithSortBy(t *testing.T) { 5020 query := []byte(`A=1 | dedup state weekday http_status sortby +weekday -state`) 5021 res, err := spl.Parse("", query) 5022 assert.Nil(t, err) 5023 filterNode := res.(ast.QueryStruct).SearchFilter 5024 assert.NotNil(t, filterNode) 5025 5026 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 5027 assert.Nil(t, err) 5028 assert.NotNil(t, astNode) 5029 assert.NotNil(t, aggregator) 5030 assert.Nil(t, aggregator.Next) 5031 5032 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 5033 assert.NotNil(t, aggregator.OutputTransforms.LetColumns) 5034 assert.NotNil(t, aggregator.OutputTransforms.LetColumns.DedupColRequest) 5035 5036 dedupExpr := aggregator.OutputTransforms.LetColumns.DedupColRequest 5037 assert.Equal(t, dedupExpr.Limit, uint64(1)) 5038 assert.Equal(t, dedupExpr.FieldList, []string{"state", "weekday", "http_status"}) 5039 assert.NotNil(t, dedupExpr.DedupOptions) 5040 assert.Equal(t, dedupExpr.DedupOptions.Consecutive, false) 5041 assert.Equal(t, dedupExpr.DedupOptions.KeepEmpty, false) 5042 assert.Equal(t, dedupExpr.DedupOptions.KeepEvents, false) 5043 assert.Len(t, dedupExpr.DedupSortEles, 2) 5044 assert.Equal(t, dedupExpr.DedupSortEles[0].SortByAsc, true) 5045 assert.Equal(t, dedupExpr.DedupSortEles[0].Op, "") 5046 assert.Equal(t, dedupExpr.DedupSortEles[0].Field, "weekday") 5047 assert.Equal(t, dedupExpr.DedupSortEles[1].SortByAsc, false) 5048 assert.Equal(t, dedupExpr.DedupSortEles[1].Op, "") 5049 assert.Equal(t, dedupExpr.DedupSortEles[1].Field, "state") 5050 } 5051 5052 func Test_sortWithOneField(t *testing.T) { 5053 query := []byte(`A=1 | sort auto(city)`) 5054 res, err := spl.Parse("", query) 5055 assert.Nil(t, err) 5056 filterNode := res.(ast.QueryStruct).SearchFilter 5057 assert.NotNil(t, filterNode) 5058 5059 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 5060 assert.Nil(t, err) 5061 assert.NotNil(t, astNode) 5062 assert.NotNil(t, aggregator) 5063 assert.Nil(t, aggregator.Next) 5064 5065 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 5066 assert.NotNil(t, aggregator.OutputTransforms.LetColumns) 5067 assert.NotNil(t, aggregator.OutputTransforms.LetColumns.SortColRequest) 5068 5069 sortExpr := aggregator.OutputTransforms.LetColumns.SortColRequest 5070 assert.Len(t, sortExpr.SortEles, 1) 5071 assert.Equal(t, []int{1}, sortExpr.SortAscending) 5072 assert.Equal(t, "city", sortExpr.SortEles[0].Field) 5073 assert.Equal(t, "auto", sortExpr.SortEles[0].Op) 5074 assert.Equal(t, true, sortExpr.SortEles[0].SortByAsc) 5075 } 5076 5077 func Test_sortWithMultipleFields(t *testing.T) { 5078 query := []byte(`A=1 | sort str(app_name), -city, num(latency)`) 5079 res, err := spl.Parse("", query) 5080 assert.Nil(t, err) 5081 filterNode := res.(ast.QueryStruct).SearchFilter 5082 assert.NotNil(t, filterNode) 5083 5084 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 5085 assert.Nil(t, err) 5086 assert.NotNil(t, astNode) 5087 assert.NotNil(t, aggregator) 5088 assert.Nil(t, aggregator.Next) 5089 5090 assert.Equal(t, aggregator.PipeCommandType, structs.OutputTransformType) 5091 assert.NotNil(t, aggregator.OutputTransforms.LetColumns) 5092 assert.NotNil(t, aggregator.OutputTransforms.LetColumns.SortColRequest) 5093 5094 sortExpr := aggregator.OutputTransforms.LetColumns.SortColRequest 5095 assert.Len(t, sortExpr.SortEles, 3) 5096 assert.Equal(t, []int{1, -1, 1}, sortExpr.SortAscending) 5097 assert.Equal(t, "app_name", sortExpr.SortEles[0].Field) 5098 assert.Equal(t, "str", sortExpr.SortEles[0].Op) 5099 assert.Equal(t, true, sortExpr.SortEles[0].SortByAsc) 5100 5101 assert.Equal(t, "city", sortExpr.SortEles[1].Field) 5102 assert.Equal(t, "", sortExpr.SortEles[1].Op) 5103 assert.Equal(t, false, sortExpr.SortEles[1].SortByAsc) 5104 5105 assert.Equal(t, "latency", sortExpr.SortEles[2].Field) 5106 assert.Equal(t, "num", sortExpr.SortEles[2].Op) 5107 assert.Equal(t, true, sortExpr.SortEles[2].SortByAsc) 5108 } 5109 5110 // SPL Transaction command. 5111 func Test_TransactionRequestWithFields(t *testing.T) { 5112 query := []byte(`A=1 | transaction A`) 5113 res, err := spl.Parse("", query) 5114 assert.Nil(t, err) 5115 filterNode := res.(ast.QueryStruct).SearchFilter 5116 assert.NotNil(t, filterNode) 5117 5118 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 5119 assert.Nil(t, err) 5120 assert.NotNil(t, astNode) 5121 assert.NotNil(t, aggregator) 5122 assert.NotNil(t, aggregator.TransactionArguments) 5123 5124 transactionRequest := aggregator.TransactionArguments 5125 assert.Equal(t, aggregator.PipeCommandType, structs.TransactionType) 5126 assert.Equal(t, transactionRequest.Fields, []string{"A"}) 5127 5128 query = []byte(`A=1 | transaction A B C`) 5129 res, err = spl.Parse("", query) 5130 assert.Nil(t, err) 5131 filterNode = res.(ast.QueryStruct).SearchFilter 5132 assert.NotNil(t, filterNode) 5133 5134 astNode, aggregator, err = pipesearch.ParseQuery(string(query), 0, "Splunk QL") 5135 assert.Nil(t, err) 5136 assert.NotNil(t, astNode) 5137 assert.NotNil(t, aggregator) 5138 assert.NotNil(t, aggregator.TransactionArguments) 5139 5140 transactionRequest = aggregator.TransactionArguments 5141 assert.Equal(t, aggregator.PipeCommandType, structs.TransactionType) 5142 assert.Equal(t, transactionRequest.Fields, []string{"A", "B", "C"}) 5143 } 5144 5145 func Test_TransactionRequestWithStartsAndEndsWith(t *testing.T) { 5146 query1 := []byte(`A=1 | transaction A B C startswith="foo" endswith="bar"`) 5147 query1Res := &structs.TransactionArguments{ 5148 Fields: []string{"A", "B", "C"}, 5149 StartsWith: &structs.FilterStringExpr{StringValue: "foo"}, 5150 EndsWith: &structs.FilterStringExpr{StringValue: "bar"}, 5151 } 5152 5153 query2 := []byte(`A=1 | transaction endswith="bar" startswith="foo"`) 5154 query2Res := &structs.TransactionArguments{ 5155 Fields: []string(nil), 5156 StartsWith: &structs.FilterStringExpr{StringValue: "foo"}, 5157 EndsWith: &structs.FilterStringExpr{StringValue: "bar"}, 5158 } 5159 5160 query3 := []byte(`A=1 | transaction startswith="foo" endswith="bar"`) 5161 query3Res := &structs.TransactionArguments{ 5162 Fields: []string(nil), 5163 StartsWith: &structs.FilterStringExpr{StringValue: "foo"}, 5164 EndsWith: &structs.FilterStringExpr{StringValue: "bar"}, 5165 } 5166 5167 query4 := []byte(`A=1 | transaction endswith="bar"`) 5168 query4Res := &structs.TransactionArguments{ 5169 Fields: []string(nil), 5170 StartsWith: nil, 5171 EndsWith: &structs.FilterStringExpr{StringValue: "bar"}, 5172 } 5173 5174 query5 := []byte(`A=1 | transaction startswith="foo"`) 5175 query5Res := &structs.TransactionArguments{ 5176 Fields: []string(nil), 5177 StartsWith: &structs.FilterStringExpr{StringValue: "foo"}, 5178 EndsWith: nil, 5179 } 5180 5181 query6 := []byte(`A=1 | transaction startswith="foo" endswith="bar" A B C`) 5182 query6Res := &structs.TransactionArguments{ 5183 Fields: []string{"A", "B", "C"}, 5184 StartsWith: &structs.FilterStringExpr{StringValue: "foo"}, 5185 EndsWith: &structs.FilterStringExpr{StringValue: "bar"}, 5186 } 5187 5188 queries := [][]byte{query1, query2, query3, query4, query5, query6} 5189 results := []*structs.TransactionArguments{query1Res, query2Res, query3Res, query4Res, query5Res, query6Res} 5190 5191 for ind, query := range queries { 5192 res, err := spl.Parse("", query) 5193 assert.Nil(t, err) 5194 filterNode := res.(ast.QueryStruct).SearchFilter 5195 assert.NotNil(t, filterNode) 5196 5197 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 5198 assert.Nil(t, err) 5199 assert.NotNil(t, astNode) 5200 assert.NotNil(t, aggregator) 5201 assert.NotNil(t, aggregator.TransactionArguments) 5202 5203 transactionRequest := aggregator.TransactionArguments 5204 assert.Equal(t, aggregator.PipeCommandType, structs.TransactionType) 5205 assert.Equal(t, transactionRequest.Fields, results[ind].Fields) 5206 assert.Equal(t, transactionRequest.StartsWith, results[ind].StartsWith) 5207 assert.Equal(t, transactionRequest.EndsWith, results[ind].EndsWith) 5208 } 5209 } 5210 5211 func Test_TransactionRequestWithFilterStringExpr(t *testing.T) { 5212 // CASE 1: Fields + StartsWith is Eval + EndsWith is TransactionQueryString With only OR 5213 query1 := []byte(`A=1 | transaction A B C startswith=eval(duration > 10) endswith=("foo" OR "bar2")`) 5214 query1Res := &structs.TransactionArguments{ 5215 Fields: []string{"A", "B", "C"}, 5216 StartsWith: &structs.FilterStringExpr{ 5217 EvalBoolExpr: &structs.BoolExpr{ 5218 IsTerminal: true, 5219 LeftValue: &structs.ValueExpr{ 5220 NumericExpr: &structs.NumericExpr{ 5221 IsTerminal: true, 5222 NumericExprMode: structs.NEMNumberField, 5223 ValueIsField: true, 5224 Value: "duration", 5225 }, 5226 }, 5227 RightValue: &structs.ValueExpr{ 5228 NumericExpr: &structs.NumericExpr{ 5229 IsTerminal: true, 5230 NumericExprMode: structs.NEMNumber, 5231 ValueIsField: false, 5232 Value: "10", 5233 }, 5234 }, 5235 ValueOp: ">", 5236 }, 5237 }, 5238 EndsWith: &structs.FilterStringExpr{ 5239 SearchNode: &structs.ASTNode{ 5240 OrFilterCondition: &structs.Condition{ 5241 FilterCriteria: []*structs.FilterCriteria{ 5242 { 5243 MatchFilter: &structs.MatchFilter{ 5244 MatchColumn: "*", 5245 MatchWords: [][]byte{ 5246 []byte("foo"), 5247 }, 5248 MatchOperator: utils.And, 5249 MatchPhrase: []byte("foo"), 5250 MatchType: structs.MATCH_PHRASE, 5251 }, 5252 }, 5253 { 5254 MatchFilter: &structs.MatchFilter{ 5255 MatchColumn: "*", 5256 MatchWords: [][]byte{ 5257 []byte("bar2"), 5258 }, 5259 MatchOperator: utils.And, 5260 MatchPhrase: []byte("bar2"), 5261 MatchType: structs.MATCH_PHRASE, 5262 }, 5263 }, 5264 }, 5265 }, 5266 }, 5267 }, 5268 } 5269 5270 // CASE 2: Fields + StartsWith is searchTerm (String) + EndsWith is TransactionQueryString With OR & AND 5271 query2 := []byte(`A=1 | transaction A B C startswith=status="ok" endswith=("foo" OR "foo1" AND "bar")`) 5272 query2Res := &structs.TransactionArguments{ 5273 Fields: []string{"A", "B", "C"}, 5274 StartsWith: &structs.FilterStringExpr{ 5275 SearchNode: &structs.ASTNode{ 5276 AndFilterCondition: &structs.Condition{ 5277 FilterCriteria: []*structs.FilterCriteria{ 5278 { 5279 ExpressionFilter: &structs.ExpressionFilter{ 5280 LeftInput: &structs.FilterInput{ 5281 Expression: &structs.Expression{ 5282 LeftInput: &structs.ExpressionInput{ 5283 ColumnValue: nil, 5284 ColumnName: "status", 5285 }, 5286 ExpressionOp: utils.Add, 5287 RightInput: nil, 5288 }, 5289 }, 5290 FilterOperator: utils.Equals, 5291 RightInput: &structs.FilterInput{ 5292 Expression: &structs.Expression{ 5293 LeftInput: &structs.ExpressionInput{ 5294 ColumnValue: &utils.DtypeEnclosure{ 5295 Dtype: utils.SS_DT_STRING, 5296 StringVal: "ok", 5297 }, 5298 }, 5299 }, 5300 }, 5301 }, 5302 }, 5303 }, 5304 }, 5305 }, 5306 }, 5307 EndsWith: &structs.FilterStringExpr{ 5308 SearchNode: &structs.ASTNode{ 5309 AndFilterCondition: &structs.Condition{ 5310 FilterCriteria: []*structs.FilterCriteria{ 5311 { 5312 MatchFilter: &structs.MatchFilter{ 5313 MatchColumn: "*", 5314 MatchWords: [][]byte{ 5315 []byte("bar"), 5316 }, 5317 MatchOperator: utils.And, 5318 MatchPhrase: []byte("bar"), 5319 MatchType: structs.MATCH_PHRASE, 5320 }, 5321 }, 5322 }, 5323 NestedNodes: []*structs.ASTNode{ 5324 { 5325 OrFilterCondition: &structs.Condition{ 5326 FilterCriteria: []*structs.FilterCriteria{ 5327 { 5328 MatchFilter: &structs.MatchFilter{ 5329 MatchColumn: "*", 5330 MatchWords: [][]byte{ 5331 []byte("foo"), 5332 }, 5333 MatchOperator: utils.And, 5334 MatchPhrase: []byte("foo"), 5335 MatchType: structs.MATCH_PHRASE, 5336 }, 5337 }, 5338 { 5339 MatchFilter: &structs.MatchFilter{ 5340 MatchColumn: "*", 5341 MatchWords: [][]byte{ 5342 []byte("foo1"), 5343 }, 5344 MatchOperator: utils.And, 5345 MatchPhrase: []byte("foo1"), 5346 MatchType: structs.MATCH_PHRASE, 5347 }, 5348 }, 5349 }, 5350 }, 5351 }, 5352 }, 5353 }, 5354 }, 5355 }, 5356 } 5357 5358 // CASE 3: Fields + StartWith is searchTerm (Number) + endswith is Eval 5359 query3 := []byte(`A=1 | transaction A B C startswith=duration>10 endswith=eval(status<400)`) 5360 query3Res := &structs.TransactionArguments{ 5361 Fields: []string{"A", "B", "C"}, 5362 StartsWith: &structs.FilterStringExpr{ 5363 SearchNode: &structs.ASTNode{ 5364 AndFilterCondition: &structs.Condition{ 5365 FilterCriteria: []*structs.FilterCriteria{ 5366 { 5367 ExpressionFilter: &structs.ExpressionFilter{ 5368 LeftInput: &structs.FilterInput{ 5369 Expression: &structs.Expression{ 5370 LeftInput: &structs.ExpressionInput{ 5371 ColumnValue: nil, 5372 ColumnName: "duration", 5373 }, 5374 ExpressionOp: utils.Add, 5375 RightInput: nil, 5376 }, 5377 }, 5378 FilterOperator: utils.GreaterThan, 5379 RightInput: &structs.FilterInput{ 5380 Expression: &structs.Expression{ 5381 LeftInput: &structs.ExpressionInput{ 5382 ColumnValue: &utils.DtypeEnclosure{ 5383 Dtype: utils.SS_DT_UNSIGNED_NUM, 5384 UnsignedVal: uint64(10), 5385 SignedVal: int64(10), 5386 FloatVal: float64(10), 5387 StringVal: "10", 5388 }, 5389 }, 5390 }, 5391 }, 5392 }, 5393 }, 5394 }, 5395 }, 5396 }, 5397 }, 5398 EndsWith: &structs.FilterStringExpr{ 5399 EvalBoolExpr: &structs.BoolExpr{ 5400 IsTerminal: true, 5401 LeftValue: &structs.ValueExpr{ 5402 NumericExpr: &structs.NumericExpr{ 5403 IsTerminal: true, 5404 NumericExprMode: structs.NEMNumberField, 5405 ValueIsField: true, 5406 Value: "status", 5407 }, 5408 }, 5409 RightValue: &structs.ValueExpr{ 5410 NumericExpr: &structs.NumericExpr{ 5411 IsTerminal: true, 5412 NumericExprMode: structs.NEMNumber, 5413 ValueIsField: false, 5414 Value: "400", 5415 }, 5416 }, 5417 ValueOp: "<", 5418 }, 5419 }, 5420 } 5421 5422 // CASE 4: Fields + StartWith is searchTerm (String) + endswith is String Value 5423 query4 := []byte(`A=1 | transaction A B C startswith=status="Ok" endswith="foo"`) 5424 query4Res := &structs.TransactionArguments{ 5425 Fields: []string{"A", "B", "C"}, 5426 StartsWith: &structs.FilterStringExpr{ 5427 SearchNode: &structs.ASTNode{ 5428 AndFilterCondition: &structs.Condition{ 5429 FilterCriteria: []*structs.FilterCriteria{ 5430 { 5431 ExpressionFilter: &structs.ExpressionFilter{ 5432 LeftInput: &structs.FilterInput{ 5433 Expression: &structs.Expression{ 5434 LeftInput: &structs.ExpressionInput{ 5435 ColumnValue: nil, 5436 ColumnName: "status", 5437 }, 5438 ExpressionOp: utils.Add, 5439 RightInput: nil, 5440 }, 5441 }, 5442 FilterOperator: utils.Equals, 5443 RightInput: &structs.FilterInput{ 5444 Expression: &structs.Expression{ 5445 LeftInput: &structs.ExpressionInput{ 5446 ColumnValue: &utils.DtypeEnclosure{ 5447 Dtype: utils.SS_DT_STRING, 5448 StringVal: "Ok", 5449 }, 5450 }, 5451 }, 5452 }, 5453 }, 5454 }, 5455 }, 5456 }, 5457 }, 5458 }, 5459 EndsWith: &structs.FilterStringExpr{ 5460 StringValue: "foo", 5461 }, 5462 } 5463 5464 // CASE 5: Fields + StartWith is String Search Expression + endswith is String Value 5465 query5 := []byte(`A=1 | transaction A B C startswith="status=300 OR status=bar" endswith="bar"`) 5466 query5Res := &structs.TransactionArguments{ 5467 Fields: []string{"A", "B", "C"}, 5468 StartsWith: &structs.FilterStringExpr{ 5469 SearchNode: &structs.ASTNode{ 5470 OrFilterCondition: &structs.Condition{ 5471 FilterCriteria: []*structs.FilterCriteria{ 5472 { 5473 ExpressionFilter: &structs.ExpressionFilter{ 5474 LeftInput: &structs.FilterInput{ 5475 Expression: &structs.Expression{ 5476 LeftInput: &structs.ExpressionInput{ 5477 ColumnValue: nil, 5478 ColumnName: "status", 5479 }, 5480 ExpressionOp: utils.Add, 5481 RightInput: nil, 5482 }, 5483 }, 5484 RightInput: &structs.FilterInput{ 5485 Expression: &structs.Expression{ 5486 LeftInput: &structs.ExpressionInput{ 5487 ColumnValue: &utils.DtypeEnclosure{ 5488 Dtype: utils.SS_DT_UNSIGNED_NUM, 5489 StringVal: "300", 5490 UnsignedVal: uint64(300), 5491 SignedVal: int64(300), 5492 FloatVal: float64(300), 5493 }, 5494 ColumnName: "", 5495 }, 5496 ExpressionOp: utils.Add, 5497 RightInput: nil, 5498 }, 5499 }, 5500 FilterOperator: utils.Equals, 5501 }, 5502 }, 5503 { 5504 ExpressionFilter: &structs.ExpressionFilter{ 5505 LeftInput: &structs.FilterInput{ 5506 Expression: &structs.Expression{ 5507 LeftInput: &structs.ExpressionInput{ 5508 ColumnValue: nil, 5509 ColumnName: "status", 5510 }, 5511 ExpressionOp: utils.Add, 5512 RightInput: nil, 5513 }, 5514 }, 5515 RightInput: &structs.FilterInput{ 5516 Expression: &structs.Expression{ 5517 LeftInput: &structs.ExpressionInput{ 5518 ColumnValue: &utils.DtypeEnclosure{ 5519 Dtype: utils.SS_DT_STRING, 5520 StringVal: "bar", 5521 }, 5522 ColumnName: "", 5523 }, 5524 ExpressionOp: utils.Add, 5525 RightInput: nil, 5526 }, 5527 }, 5528 FilterOperator: utils.Equals, 5529 }, 5530 }, 5531 }, 5532 NestedNodes: nil, 5533 }, 5534 }, 5535 }, 5536 EndsWith: &structs.FilterStringExpr{ 5537 StringValue: "bar", 5538 }, 5539 } 5540 5541 // CASE 6: Fields + StartWith is String Search Expression + endswith is Eval 5542 query6 := []byte(`A=1 | transaction A B C startswith="status=foo OR status=bar AND action=login" endswith=eval(status<400)`) 5543 query6Res := &structs.TransactionArguments{ 5544 Fields: []string{"A", "B", "C"}, 5545 StartsWith: &structs.FilterStringExpr{ 5546 SearchNode: &structs.ASTNode{ 5547 AndFilterCondition: &structs.Condition{ 5548 FilterCriteria: []*structs.FilterCriteria{ 5549 { 5550 ExpressionFilter: &structs.ExpressionFilter{ 5551 LeftInput: &structs.FilterInput{ 5552 Expression: &structs.Expression{ 5553 LeftInput: &structs.ExpressionInput{ 5554 ColumnValue: nil, 5555 ColumnName: "action", 5556 }, 5557 ExpressionOp: utils.Add, 5558 RightInput: nil, 5559 }, 5560 }, 5561 RightInput: &structs.FilterInput{ 5562 Expression: &structs.Expression{ 5563 LeftInput: &structs.ExpressionInput{ 5564 ColumnValue: &utils.DtypeEnclosure{ 5565 Dtype: utils.SS_DT_STRING, 5566 StringVal: "login", 5567 }, 5568 ColumnName: "", 5569 }, 5570 ExpressionOp: utils.Add, 5571 RightInput: nil, 5572 }, 5573 }, 5574 FilterOperator: utils.Equals, 5575 }, 5576 }, 5577 }, 5578 NestedNodes: []*structs.ASTNode{ 5579 { 5580 OrFilterCondition: &structs.Condition{ 5581 FilterCriteria: []*structs.FilterCriteria{ 5582 { 5583 ExpressionFilter: &structs.ExpressionFilter{ 5584 LeftInput: &structs.FilterInput{ 5585 Expression: &structs.Expression{ 5586 LeftInput: &structs.ExpressionInput{ 5587 ColumnValue: nil, 5588 ColumnName: "status", 5589 }, 5590 ExpressionOp: utils.Add, 5591 RightInput: nil, 5592 }, 5593 }, 5594 RightInput: &structs.FilterInput{ 5595 Expression: &structs.Expression{ 5596 LeftInput: &structs.ExpressionInput{ 5597 ColumnValue: &utils.DtypeEnclosure{ 5598 Dtype: utils.SS_DT_STRING, 5599 StringVal: "foo", 5600 }, 5601 ColumnName: "", 5602 }, 5603 ExpressionOp: utils.Add, 5604 RightInput: nil, 5605 }, 5606 }, 5607 FilterOperator: utils.Equals, 5608 }, 5609 }, 5610 { 5611 ExpressionFilter: &structs.ExpressionFilter{ 5612 LeftInput: &structs.FilterInput{ 5613 Expression: &structs.Expression{ 5614 LeftInput: &structs.ExpressionInput{ 5615 ColumnValue: nil, 5616 ColumnName: "status", 5617 }, 5618 ExpressionOp: utils.Add, 5619 RightInput: nil, 5620 }, 5621 }, 5622 RightInput: &structs.FilterInput{ 5623 Expression: &structs.Expression{ 5624 LeftInput: &structs.ExpressionInput{ 5625 ColumnValue: &utils.DtypeEnclosure{ 5626 Dtype: utils.SS_DT_STRING, 5627 StringVal: "bar", 5628 }, 5629 ColumnName: "", 5630 }, 5631 ExpressionOp: utils.Add, 5632 RightInput: nil, 5633 }, 5634 }, 5635 FilterOperator: utils.Equals, 5636 }, 5637 }, 5638 }, 5639 NestedNodes: nil, 5640 }, 5641 }, 5642 }, 5643 }, 5644 }, 5645 }, 5646 EndsWith: &structs.FilterStringExpr{ 5647 EvalBoolExpr: &structs.BoolExpr{ 5648 IsTerminal: true, 5649 LeftValue: &structs.ValueExpr{ 5650 NumericExpr: &structs.NumericExpr{ 5651 IsTerminal: true, 5652 NumericExprMode: structs.NEMNumberField, 5653 ValueIsField: true, 5654 Value: "status", 5655 }, 5656 }, 5657 RightValue: &structs.ValueExpr{ 5658 NumericExpr: &structs.NumericExpr{ 5659 IsTerminal: true, 5660 NumericExprMode: structs.NEMNumber, 5661 ValueIsField: false, 5662 Value: "400", 5663 }, 5664 }, 5665 ValueOp: "<", 5666 }, 5667 }, 5668 } 5669 5670 // CASE 7: Fileds + StartWith is Search Term (With Number) + endsWith is String Search Expression 5671 query7 := []byte(`A=1 | transaction A B C startswith=(status>300 OR status=201) endswith="status=foo OR status=bar AND action=login"`) 5672 query7Res := &structs.TransactionArguments{ 5673 Fields: []string{"A", "B", "C"}, 5674 StartsWith: &structs.FilterStringExpr{ 5675 SearchNode: &structs.ASTNode{ 5676 OrFilterCondition: &structs.Condition{ 5677 FilterCriteria: []*structs.FilterCriteria{ 5678 { 5679 ExpressionFilter: &structs.ExpressionFilter{ 5680 LeftInput: &structs.FilterInput{ 5681 Expression: &structs.Expression{ 5682 LeftInput: &structs.ExpressionInput{ 5683 ColumnValue: nil, 5684 ColumnName: "status", 5685 }, 5686 ExpressionOp: utils.Add, 5687 RightInput: nil, 5688 }, 5689 }, 5690 FilterOperator: utils.GreaterThan, 5691 RightInput: &structs.FilterInput{ 5692 Expression: &structs.Expression{ 5693 LeftInput: &structs.ExpressionInput{ 5694 ColumnValue: &utils.DtypeEnclosure{ 5695 Dtype: utils.SS_DT_UNSIGNED_NUM, 5696 UnsignedVal: uint64(300), 5697 SignedVal: int64(300), 5698 FloatVal: float64(300), 5699 StringVal: "300", 5700 }, 5701 }, 5702 }, 5703 }, 5704 }, 5705 }, 5706 { 5707 ExpressionFilter: &structs.ExpressionFilter{ 5708 LeftInput: &structs.FilterInput{ 5709 Expression: &structs.Expression{ 5710 LeftInput: &structs.ExpressionInput{ 5711 ColumnValue: nil, 5712 ColumnName: "status", 5713 }, 5714 ExpressionOp: utils.Add, 5715 RightInput: nil, 5716 }, 5717 }, 5718 FilterOperator: utils.Equals, 5719 RightInput: &structs.FilterInput{ 5720 Expression: &structs.Expression{ 5721 LeftInput: &structs.ExpressionInput{ 5722 ColumnValue: &utils.DtypeEnclosure{ 5723 Dtype: utils.SS_DT_UNSIGNED_NUM, 5724 UnsignedVal: uint64(201), 5725 SignedVal: int64(201), 5726 FloatVal: float64(201), 5727 StringVal: "201", 5728 }, 5729 }, 5730 }, 5731 }, 5732 }, 5733 }, 5734 }, 5735 }, 5736 }, 5737 }, 5738 EndsWith: &structs.FilterStringExpr{ 5739 SearchNode: &structs.ASTNode{ 5740 AndFilterCondition: &structs.Condition{ 5741 FilterCriteria: []*structs.FilterCriteria{ 5742 { 5743 ExpressionFilter: &structs.ExpressionFilter{ 5744 LeftInput: &structs.FilterInput{ 5745 Expression: &structs.Expression{ 5746 LeftInput: &structs.ExpressionInput{ 5747 ColumnValue: nil, 5748 ColumnName: "action", 5749 }, 5750 ExpressionOp: utils.Add, 5751 RightInput: nil, 5752 }, 5753 }, 5754 RightInput: &structs.FilterInput{ 5755 Expression: &structs.Expression{ 5756 LeftInput: &structs.ExpressionInput{ 5757 ColumnValue: &utils.DtypeEnclosure{ 5758 Dtype: utils.SS_DT_STRING, 5759 StringVal: "login", 5760 }, 5761 ColumnName: "", 5762 }, 5763 ExpressionOp: utils.Add, 5764 RightInput: nil, 5765 }, 5766 }, 5767 FilterOperator: utils.Equals, 5768 }, 5769 }, 5770 }, 5771 NestedNodes: []*structs.ASTNode{ 5772 { 5773 OrFilterCondition: &structs.Condition{ 5774 FilterCriteria: []*structs.FilterCriteria{ 5775 { 5776 ExpressionFilter: &structs.ExpressionFilter{ 5777 LeftInput: &structs.FilterInput{ 5778 Expression: &structs.Expression{ 5779 LeftInput: &structs.ExpressionInput{ 5780 ColumnValue: nil, 5781 ColumnName: "status", 5782 }, 5783 ExpressionOp: utils.Add, 5784 RightInput: nil, 5785 }, 5786 }, 5787 RightInput: &structs.FilterInput{ 5788 Expression: &structs.Expression{ 5789 LeftInput: &structs.ExpressionInput{ 5790 ColumnValue: &utils.DtypeEnclosure{ 5791 Dtype: utils.SS_DT_STRING, 5792 StringVal: "foo", 5793 }, 5794 ColumnName: "", 5795 }, 5796 ExpressionOp: utils.Add, 5797 RightInput: nil, 5798 }, 5799 }, 5800 FilterOperator: utils.Equals, 5801 }, 5802 }, 5803 { 5804 ExpressionFilter: &structs.ExpressionFilter{ 5805 LeftInput: &structs.FilterInput{ 5806 Expression: &structs.Expression{ 5807 LeftInput: &structs.ExpressionInput{ 5808 ColumnValue: nil, 5809 ColumnName: "status", 5810 }, 5811 ExpressionOp: utils.Add, 5812 RightInput: nil, 5813 }, 5814 }, 5815 RightInput: &structs.FilterInput{ 5816 Expression: &structs.Expression{ 5817 LeftInput: &structs.ExpressionInput{ 5818 ColumnValue: &utils.DtypeEnclosure{ 5819 Dtype: utils.SS_DT_STRING, 5820 StringVal: "bar", 5821 }, 5822 ColumnName: "", 5823 }, 5824 ExpressionOp: utils.Add, 5825 RightInput: nil, 5826 }, 5827 }, 5828 FilterOperator: utils.Equals, 5829 }, 5830 }, 5831 }, 5832 NestedNodes: nil, 5833 }, 5834 }, 5835 }, 5836 }, 5837 }, 5838 }, 5839 } 5840 5841 // CASE 8: Fields + StartsWith=OR String Clauses + EndsWith=OR Clauses 5842 query8 := []byte(`A=1 | transaction A B C startswith=("GET" OR "POST1") endswith=("DELETE" OR "POST2")`) 5843 query8Res := &structs.TransactionArguments{ 5844 Fields: []string{"A", "B", "C"}, 5845 StartsWith: &structs.FilterStringExpr{ 5846 SearchNode: &structs.ASTNode{ 5847 OrFilterCondition: &structs.Condition{ 5848 FilterCriteria: []*structs.FilterCriteria{ 5849 { 5850 MatchFilter: &structs.MatchFilter{ 5851 MatchColumn: "*", 5852 MatchWords: [][]byte{ 5853 []byte("GET"), 5854 }, 5855 MatchOperator: utils.And, 5856 MatchPhrase: []byte("GET"), 5857 MatchType: structs.MATCH_PHRASE, 5858 }, 5859 }, 5860 { 5861 MatchFilter: &structs.MatchFilter{ 5862 MatchColumn: "*", 5863 MatchWords: [][]byte{ 5864 []byte("POST1"), 5865 }, 5866 MatchOperator: utils.And, 5867 MatchPhrase: []byte("POST1"), 5868 MatchType: structs.MATCH_PHRASE, 5869 }, 5870 }, 5871 }, 5872 }, 5873 }, 5874 }, 5875 EndsWith: &structs.FilterStringExpr{ 5876 SearchNode: &structs.ASTNode{ 5877 OrFilterCondition: &structs.Condition{ 5878 FilterCriteria: []*structs.FilterCriteria{ 5879 { 5880 MatchFilter: &structs.MatchFilter{ 5881 MatchColumn: "*", 5882 MatchWords: [][]byte{ 5883 []byte("DELETE"), 5884 }, 5885 MatchOperator: utils.And, 5886 MatchPhrase: []byte("DELETE"), 5887 MatchType: structs.MATCH_PHRASE, 5888 }, 5889 }, 5890 { 5891 MatchFilter: &structs.MatchFilter{ 5892 MatchColumn: "*", 5893 MatchWords: [][]byte{ 5894 []byte("POST2"), 5895 }, 5896 MatchOperator: utils.And, 5897 MatchPhrase: []byte("POST2"), 5898 MatchType: structs.MATCH_PHRASE, 5899 }, 5900 }, 5901 }, 5902 }, 5903 }, 5904 }, 5905 } 5906 5907 // CASE 9: Fields + StartsWith=AND String Clauses + EndsWith=Single String Clause 5908 query9 := []byte(`A=1 | transaction A B C startswith=("GET" AND "POST1") endswith=("DELETE")`) 5909 query9Res := &structs.TransactionArguments{ 5910 Fields: []string{"A", "B", "C"}, 5911 StartsWith: &structs.FilterStringExpr{ 5912 SearchNode: &structs.ASTNode{ 5913 AndFilterCondition: &structs.Condition{ 5914 FilterCriteria: []*structs.FilterCriteria{ 5915 { 5916 MatchFilter: &structs.MatchFilter{ 5917 MatchColumn: "*", 5918 MatchWords: [][]byte{ 5919 []byte("GET"), 5920 }, 5921 MatchOperator: utils.And, 5922 MatchPhrase: []byte("GET"), 5923 MatchType: structs.MATCH_PHRASE, 5924 }, 5925 }, 5926 { 5927 MatchFilter: &structs.MatchFilter{ 5928 MatchColumn: "*", 5929 MatchWords: [][]byte{ 5930 []byte("POST1"), 5931 }, 5932 MatchOperator: utils.And, 5933 MatchPhrase: []byte("POST1"), 5934 MatchType: structs.MATCH_PHRASE, 5935 }, 5936 }, 5937 }, 5938 }, 5939 }, 5940 }, 5941 EndsWith: &structs.FilterStringExpr{ 5942 SearchNode: &structs.ASTNode{ 5943 AndFilterCondition: &structs.Condition{ 5944 FilterCriteria: []*structs.FilterCriteria{ 5945 { 5946 MatchFilter: &structs.MatchFilter{ 5947 MatchColumn: "*", 5948 MatchWords: [][]byte{ 5949 []byte("DELETE"), 5950 }, 5951 MatchOperator: utils.And, 5952 MatchPhrase: []byte("DELETE"), 5953 MatchType: structs.MATCH_PHRASE, 5954 }, 5955 }, 5956 }, 5957 }, 5958 }, 5959 }, 5960 } 5961 5962 queries := [][]byte{query1, query2, query3, query4, query5, query6, query7, query8, query9} 5963 results := []*structs.TransactionArguments{query1Res, query2Res, query3Res, query4Res, query5Res, query6Res, query7Res, query8Res, query9Res} 5964 5965 for ind, query := range queries { 5966 res, err := spl.Parse("", query) 5967 assert.Nil(t, err) 5968 filterNode := res.(ast.QueryStruct).SearchFilter 5969 assert.NotNil(t, filterNode) 5970 5971 astNode, aggregator, err := pipesearch.ParseQuery(string(query), 0, "Splunk QL") 5972 assert.Nil(t, err) 5973 assert.NotNil(t, astNode) 5974 assert.NotNil(t, aggregator) 5975 assert.NotNil(t, aggregator.TransactionArguments) 5976 5977 transactionRequest := aggregator.TransactionArguments 5978 assert.Equal(t, structs.TransactionType, aggregator.PipeCommandType) 5979 assert.Equal(t, results[ind].Fields, transactionRequest.Fields) 5980 assert.Equal(t, results[ind].StartsWith, transactionRequest.StartsWith) 5981 assert.Equal(t, results[ind].EndsWith, transactionRequest.EndsWith) 5982 } 5983 }