github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/ast/pipesearch/searchQueryParser.go (about) 1 /* 2 Copyright 2023. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package pipesearch 18 19 import ( 20 "encoding/json" 21 "errors" 22 "fmt" 23 24 "github.com/siglens/siglens/pkg/ast" 25 "github.com/siglens/siglens/pkg/ast/logql" 26 "github.com/siglens/siglens/pkg/ast/spl" 27 "github.com/siglens/siglens/pkg/ast/sql" 28 "github.com/siglens/siglens/pkg/config" 29 "github.com/siglens/siglens/pkg/segment/aggregations" 30 "github.com/siglens/siglens/pkg/segment/query/metadata" 31 "github.com/siglens/siglens/pkg/segment/structs" 32 . "github.com/siglens/siglens/pkg/segment/structs" 33 34 segment "github.com/siglens/siglens/pkg/segment" 35 . "github.com/siglens/siglens/pkg/segment/utils" 36 log "github.com/sirupsen/logrus" 37 ) 38 39 func ParseRequest(searchText string, startEpoch, endEpoch uint64, qid uint64, queryLanguageType string, indexName string) (*ASTNode, *QueryAggregators, error) { 40 var parsingError error 41 var queryAggs *QueryAggregators 42 var boolNode *ASTNode 43 boolNode, queryAggs, parsingError = ParseQuery(searchText, qid, queryLanguageType) 44 if parsingError != nil { 45 return nil, nil, parsingError 46 } 47 48 if boolNode == nil && queryAggs == nil { 49 err := fmt.Errorf("qid=%d, ParseRequest: boolNode and queryAggs are nil for searchText: %v", qid, searchText) 50 log.Errorf(err.Error()) 51 return nil, nil, err 52 } 53 54 tRange, err := ast.ParseTimeRange(startEpoch, endEpoch, queryAggs, qid) 55 if err != nil { 56 log.Errorf("qid=%d, Search ParseRequest: parseTimeRange error: %v", qid, err) 57 return nil, nil, err 58 } 59 boolNode.TimeRange = tRange 60 61 //aggs 62 if queryAggs != nil { 63 // if groupby request or segment stats exist, dont early exist and no sort is needed 64 if queryAggs.GroupByRequest != nil { 65 queryAggs.GroupByRequest.BucketCount = 10_000 66 queryAggs.EarlyExit = false 67 queryAggs.Sort = nil 68 if len(queryAggs.GroupByRequest.GroupByColumns) == 1 && queryAggs.GroupByRequest.GroupByColumns[0] == "*" { 69 queryAggs.GroupByRequest.GroupByColumns = metadata.GetAllColNames([]string{indexName}) 70 } 71 if queryAggs.TimeHistogram != nil && queryAggs.TimeHistogram.Timechart != nil { 72 if queryAggs.TimeHistogram.Timechart.BinOptions != nil && 73 queryAggs.TimeHistogram.Timechart.BinOptions.SpanOptions != nil && 74 queryAggs.TimeHistogram.Timechart.BinOptions.SpanOptions.DefaultSettings { 75 spanOptions, err := ast.GetDefaultTimechartSpanOptions(startEpoch, endEpoch, qid) 76 if err != nil { 77 log.Errorf("qid=%d, Search ParseRequest: GetDefaultTimechartSpanOptions error: %v", qid, err) 78 return nil, nil, err 79 } 80 queryAggs.TimeHistogram.Timechart.BinOptions.SpanOptions = spanOptions 81 queryAggs.TimeHistogram.IntervalMillis = aggregations.GetIntervalInMillis(spanOptions.SpanLength.Num, spanOptions.SpanLength.TimeScalr) 82 } 83 queryAggs.TimeHistogram.StartTime = startEpoch 84 queryAggs.TimeHistogram.EndTime = endEpoch 85 } 86 } else if queryAggs.MeasureOperations != nil { 87 queryAggs.EarlyExit = false 88 queryAggs.Sort = nil 89 } else { 90 queryAggs.EarlyExit = true 91 if queryAggs.Sort == nil { 92 queryAggs.Sort = &SortRequest{ 93 ColName: config.GetTimeStampKey(), 94 Ascending: false, 95 } 96 } 97 } 98 } else { 99 queryAggs = structs.InitDefaultQueryAggregations() 100 } 101 102 segment.LogASTNode(queryLanguageType+"query parser", boolNode, qid) 103 segment.LogQueryAggsNode(queryLanguageType+"aggs parser", queryAggs, qid) 104 return boolNode, queryAggs, nil 105 } 106 107 func ParseQuery(searchText string, qid uint64, queryLanguageType string) (*ASTNode, *QueryAggregators, error) { 108 109 var boolNode *ASTNode 110 var aggNode *QueryAggregators 111 var err error 112 113 if queryLanguageType == "SQL" { 114 boolNode, aggNode, _, err = sql.ConvertToASTNodeSQL(searchText, qid) 115 } else { 116 boolNode, aggNode, err = parsePipeSearch(searchText, queryLanguageType, qid) 117 } 118 119 if err != nil { 120 log.Errorf("qid=%d, ParseQuery:ParsePipeSearch error: %v", qid, err) 121 return nil, nil, err 122 } 123 124 return boolNode, aggNode, nil 125 } 126 127 func createMatchAll(qid uint64) *ASTNode { 128 rootNode := &ASTNode{} 129 colName := "*" 130 colValue := "*" 131 criteria := ast.CreateTermFilterCriteria(colName, colValue, Equals, qid) 132 rootNode.AndFilterCondition = &Condition{FilterCriteria: []*FilterCriteria{criteria}} 133 return rootNode 134 } 135 136 func parsePipeSearch(searchText string, queryLanguage string, qid uint64) (*ASTNode, *QueryAggregators, error) { 137 var leafNode *ASTNode 138 var res interface{} 139 var err error 140 if searchText == "*" || searchText == "" { 141 leafNode = createMatchAll(qid) 142 return leafNode, nil, nil 143 } 144 //peg parsing to AST tree 145 switch queryLanguage { 146 case "Pipe QL": 147 res, err = Parse("", []byte(searchText)) 148 case "Log QL": 149 res, err = logql.Parse("", []byte(searchText)) 150 case "Splunk QL": 151 res, err = spl.Parse("", []byte(searchText)) 152 default: 153 log.Errorf("qid=%d, parsePipeSearch: Unknown queryLanguage: %v", qid, queryLanguage) 154 } 155 156 if err != nil { 157 log.Errorf("qid=%d, parsePipeSearch: PEG Parse error: %v:%v", qid, err, getParseError(err)) 158 return nil, nil, getParseError(err) 159 } 160 161 result, err := json.MarshalIndent(res, "", " ") 162 if err == nil { 163 log.Infof("qid=%d, parsePipeSearch output:\n%v\n", qid, string(result)) 164 } else { 165 log.Infof("qid=%d, parsePipeSearch output:\n%v\n", qid, res) 166 } 167 168 queryJson := res.(ast.QueryStruct).SearchFilter 169 pipeCommandsJson := res.(ast.QueryStruct).PipeCommands 170 boolNode := &ASTNode{} 171 if queryJson == nil { 172 boolNode = createMatchAll(qid) 173 } 174 err = SearchQueryToASTnode(queryJson, boolNode, qid) 175 if err != nil { 176 log.Errorf("qid=%d, parsePipeSearch: SearchQueryToASTnode error: %v", qid, err) 177 return nil, nil, err 178 } 179 if pipeCommandsJson == nil { 180 return boolNode, nil, nil 181 } 182 pipeCommands, err := searchPipeCommandsToASTnode(pipeCommandsJson, qid) 183 184 if err != nil { 185 log.Errorf("qid=%d, parsePipeSearch: SearchQueryToASTnode error: %v", qid, err) 186 return nil, nil, err 187 } 188 return boolNode, pipeCommands, nil 189 } 190 191 func SearchQueryToASTnode(node *ast.Node, boolNode *ASTNode, qid uint64) error { 192 var err error 193 if node == nil { 194 return nil 195 } 196 197 switch node.NodeType { 198 case ast.NodeOr: 199 err := parseORCondition(node.Left, boolNode, qid) 200 if err != nil { 201 log.Errorf("qid=%d, SearchQueryToASTnode : parseORCondition error: %v", qid, err) 202 return err 203 } 204 205 err = parseORCondition(node.Right, boolNode, qid) 206 if err != nil { 207 log.Errorf("qid=%d, SearchQueryToASTnode : parseORCondition error: %v", qid, err) 208 return err 209 } 210 211 case ast.NodeAnd: 212 err := parseANDCondition(node.Left, boolNode, qid) 213 if err != nil { 214 log.Errorf("qid=%d, SearchQueryToASTnode : parseANDCondition error: %v", qid, err) 215 return err 216 } 217 218 err = parseANDCondition(node.Right, boolNode, qid) 219 if err != nil { 220 log.Errorf("qid=%d, SearchQueryToASTnode : parseANDCondition error: %v", qid, err) 221 return err 222 } 223 224 case ast.NodeTerminal: 225 criteria, err := ast.ProcessSingleFilter(node.Comparison.Field, node.Comparison.Values, node.Comparison.Op, node.Comparison.ValueIsRegex, qid) 226 if err != nil { 227 log.Errorf("qid=%d, SearchQueryToASTnode : parseSingleTerm: processPipeSearchMap error: %v", qid, err) 228 return err 229 } 230 filtercond := &Condition{ 231 FilterCriteria: []*FilterCriteria(criteria), 232 } 233 if boolNode.AndFilterCondition == nil { 234 boolNode.AndFilterCondition = filtercond 235 } else { 236 boolNode.AndFilterCondition.JoinCondition(filtercond) 237 } 238 default: 239 log.Errorf("SearchQueryToASTnode : node type %d not supported", node.NodeType) 240 return errors.New("SearchQueryToASTnode : node type not supported") 241 } 242 return err 243 } 244 245 func searchPipeCommandsToASTnode(node *QueryAggregators, qid uint64) (*QueryAggregators, error) { 246 var err error 247 var pipeCommands *QueryAggregators 248 //todo return array of queryaggs 249 if node == nil { 250 log.Errorf("qid=%d, searchPipeCommandsToASTnode : search pipe command node can not be nil %v", qid, node) 251 return nil, errors.New("searchPipeCommandsToASTnode: search pipe command node is nil ") 252 } 253 switch node.PipeCommandType { 254 case OutputTransformType: 255 pipeCommands, err = parseColumnsCmd(node.OutputTransforms, qid) 256 if err != nil { 257 log.Errorf("qid=%d, searchPipeCommandsToASTnode : parseColumnsCmd error: %v", qid, err) 258 return nil, err 259 } 260 case MeasureAggsType: 261 pipeCommands, err = parseSegLevelStats(node.MeasureOperations, qid) 262 if err != nil { 263 log.Errorf("qid=%d, searchPipeCommandsToASTnode : parseSegLevelStats error: %v", qid, err) 264 return nil, err 265 } 266 case GroupByType: 267 pipeCommands, err = parseGroupBySegLevelStats(node.GroupByRequest, node.BucketLimit, qid) 268 if err != nil { 269 log.Errorf("qid=%d, searchPipeCommandsToASTnode : parseGroupBySegLevelStats error: %v", qid, err) 270 return nil, err 271 } 272 pipeCommands.TimeHistogram = node.TimeHistogram 273 case TransactionType: 274 pipeCommands, err = parseTransactionRequest(node.TransactionArguments, qid) 275 if err != nil { 276 log.Errorf("qid=%d, searchPipeCommandsToASTnode : parseTransactionRequest error: %v", qid, err) 277 return nil, err 278 } 279 default: 280 log.Errorf("searchPipeCommandsToASTnode : node type %d not supported", node.PipeCommandType) 281 return nil, errors.New("searchPipeCommandsToASTnode : node type not supported") 282 } 283 284 if node.Next != nil { 285 pipeCommands.Next, err = searchPipeCommandsToASTnode(node.Next, qid) 286 287 if err != nil { 288 log.Errorf("qid=%d, searchPipeCommandsToASTnode failed to parse child node: %v", qid, node.Next) 289 return nil, err 290 } 291 } 292 293 return pipeCommands, nil 294 } 295 296 func parseGroupBySegLevelStats(node *structs.GroupByRequest, bucketLimit int, qid uint64) (*QueryAggregators, error) { 297 aggNode := &QueryAggregators{} 298 aggNode.PipeCommandType = GroupByType 299 aggNode.GroupByRequest = &structs.GroupByRequest{} 300 aggNode.GroupByRequest.MeasureOperations = make([]*structs.MeasureAggregator, 0) 301 aggNode.BucketLimit = bucketLimit 302 for _, parsedMeasureAgg := range node.MeasureOperations { 303 var tempMeasureAgg = &MeasureAggregator{} 304 tempMeasureAgg.MeasureCol = parsedMeasureAgg.MeasureCol 305 tempMeasureAgg.MeasureFunc = parsedMeasureAgg.MeasureFunc 306 tempMeasureAgg.ValueColRequest = parsedMeasureAgg.ValueColRequest 307 tempMeasureAgg.StrEnc = parsedMeasureAgg.StrEnc 308 aggNode.GroupByRequest.MeasureOperations = append(aggNode.GroupByRequest.MeasureOperations, tempMeasureAgg) 309 } 310 if node.GroupByColumns != nil { 311 aggNode.GroupByRequest.GroupByColumns = node.GroupByColumns 312 } 313 aggNode.EarlyExit = false 314 return aggNode, nil 315 } 316 317 func parseSegLevelStats(node []*structs.MeasureAggregator, qid uint64) (*QueryAggregators, error) { 318 aggNode := &QueryAggregators{} 319 aggNode.PipeCommandType = MeasureAggsType 320 aggNode.MeasureOperations = make([]*structs.MeasureAggregator, 0) 321 for _, parsedMeasureAgg := range node { 322 var tempMeasureAgg = &MeasureAggregator{} 323 tempMeasureAgg.MeasureCol = parsedMeasureAgg.MeasureCol 324 tempMeasureAgg.MeasureFunc = parsedMeasureAgg.MeasureFunc 325 tempMeasureAgg.ValueColRequest = parsedMeasureAgg.ValueColRequest 326 tempMeasureAgg.StrEnc = parsedMeasureAgg.StrEnc 327 aggNode.MeasureOperations = append(aggNode.MeasureOperations, tempMeasureAgg) 328 } 329 return aggNode, nil 330 } 331 332 func parseTransactionRequest(node *structs.TransactionArguments, qid uint64) (*QueryAggregators, error) { 333 aggNode := &QueryAggregators{} 334 aggNode.PipeCommandType = TransactionType 335 aggNode.TransactionArguments = &TransactionArguments{} 336 aggNode.TransactionArguments.Fields = node.Fields 337 aggNode.TransactionArguments.StartsWith = node.StartsWith 338 aggNode.TransactionArguments.EndsWith = node.EndsWith 339 340 if node.StartsWith != nil { 341 if node.StartsWith.SearchNode != nil { 342 boolNode := &ASTNode{} 343 err := SearchQueryToASTnode(node.StartsWith.SearchNode.(*ast.Node), boolNode, qid) 344 if err != nil { 345 log.Errorf("qid=%d, parseTransactionRequest: SearchQueryToASTnode error: %v", qid, err) 346 return nil, err 347 } 348 aggNode.TransactionArguments.StartsWith.SearchNode = boolNode 349 } 350 } 351 352 if node.EndsWith != nil { 353 if node.EndsWith.SearchNode != nil { 354 boolNode := &ASTNode{} 355 err := SearchQueryToASTnode(node.EndsWith.SearchNode.(*ast.Node), boolNode, qid) 356 if err != nil { 357 log.Errorf("qid=%d, parseTransactionRequest: SearchQueryToASTnode error: %v", qid, err) 358 return nil, err 359 } 360 aggNode.TransactionArguments.EndsWith.SearchNode = boolNode 361 } 362 } 363 aggNode.EarlyExit = false 364 return aggNode, nil 365 } 366 367 func parseColumnsCmd(node *structs.OutputTransforms, qid uint64) (*QueryAggregators, error) { 368 aggNode := &QueryAggregators{} 369 aggNode.PipeCommandType = OutputTransformType 370 aggNode.OutputTransforms = &OutputTransforms{} 371 if node == nil { 372 return aggNode, nil 373 } 374 if node.OutputColumns != nil { 375 if node.OutputColumns.IncludeColumns != nil { 376 aggNode.OutputTransforms.OutputColumns = &ColumnsRequest{} 377 aggNode.OutputTransforms.OutputColumns.IncludeColumns = append(aggNode.OutputTransforms.OutputColumns.IncludeColumns, node.OutputColumns.IncludeColumns...) 378 } 379 if node.OutputColumns.ExcludeColumns != nil { 380 aggNode.OutputTransforms.OutputColumns = &ColumnsRequest{} 381 aggNode.OutputTransforms.OutputColumns.ExcludeColumns = append(aggNode.OutputTransforms.OutputColumns.ExcludeColumns, node.OutputColumns.ExcludeColumns...) 382 } 383 if node.OutputColumns.RenameColumns != nil { 384 if aggNode.OutputTransforms.OutputColumns == nil { 385 aggNode.OutputTransforms.OutputColumns = &ColumnsRequest{} 386 } 387 aggNode.OutputTransforms.OutputColumns.RenameColumns = make(map[string]string) 388 for k, v := range node.OutputColumns.RenameColumns { 389 aggNode.OutputTransforms.OutputColumns.RenameColumns[k] = v 390 } 391 } 392 if node.OutputColumns.RenameAggregationColumns != nil { 393 if aggNode.OutputTransforms.OutputColumns == nil { 394 aggNode.OutputTransforms.OutputColumns = &ColumnsRequest{} 395 } 396 aggNode.OutputTransforms.OutputColumns.RenameAggregationColumns = make(map[string]string) 397 for k, v := range node.OutputColumns.RenameAggregationColumns { 398 aggNode.OutputTransforms.OutputColumns.RenameAggregationColumns[k] = v 399 } 400 } 401 if node.OutputColumns.IncludeValues != nil { 402 if aggNode.OutputTransforms.OutputColumns == nil { 403 aggNode.OutputTransforms.OutputColumns = &ColumnsRequest{} 404 } 405 aggNode.OutputTransforms.OutputColumns.IncludeValues = node.OutputColumns.IncludeValues 406 } 407 } 408 if node.LetColumns != nil { 409 aggNode.OutputTransforms.LetColumns = &LetColumnsRequest{} 410 aggNode.OutputTransforms.LetColumns.NewColName = node.LetColumns.NewColName 411 412 if node.LetColumns.SingleColRequest != nil { 413 aggNode.OutputTransforms.LetColumns.SingleColRequest = &SingleColLetRequest{} 414 aggNode.OutputTransforms.LetColumns.SingleColRequest.CName = node.LetColumns.SingleColRequest.CName 415 aggNode.OutputTransforms.LetColumns.SingleColRequest.Oper = node.LetColumns.SingleColRequest.Oper 416 aggNode.OutputTransforms.LetColumns.SingleColRequest.Value = node.LetColumns.SingleColRequest.Value 417 } 418 if node.LetColumns.MultiColsRequest != nil { 419 aggNode.OutputTransforms.LetColumns.MultiColsRequest = &MultiColLetRequest{} 420 aggNode.OutputTransforms.LetColumns.MultiColsRequest.LeftCName = node.LetColumns.MultiColsRequest.LeftCName 421 aggNode.OutputTransforms.LetColumns.MultiColsRequest.Oper = node.LetColumns.MultiColsRequest.Oper 422 aggNode.OutputTransforms.LetColumns.MultiColsRequest.RightCName = node.LetColumns.MultiColsRequest.RightCName 423 } 424 if node.LetColumns.ValueColRequest != nil { 425 aggNode.OutputTransforms.LetColumns.ValueColRequest = node.LetColumns.ValueColRequest 426 } 427 if node.LetColumns.RexColRequest != nil { 428 aggNode.OutputTransforms.LetColumns.RexColRequest = node.LetColumns.RexColRequest 429 } 430 if node.LetColumns.StatisticColRequest != nil { 431 aggNode.OutputTransforms.LetColumns.StatisticColRequest = node.LetColumns.StatisticColRequest 432 } 433 if node.LetColumns.RenameColRequest != nil { 434 aggNode.OutputTransforms.LetColumns.RenameColRequest = node.LetColumns.RenameColRequest 435 } 436 if node.LetColumns.DedupColRequest != nil { 437 aggNode.OutputTransforms.LetColumns.DedupColRequest = node.LetColumns.DedupColRequest 438 } 439 if node.LetColumns.SortColRequest != nil { 440 aggNode.OutputTransforms.LetColumns.SortColRequest = node.LetColumns.SortColRequest 441 } 442 } 443 if node.FilterRows != nil { 444 aggNode.OutputTransforms.FilterRows = node.FilterRows 445 } 446 447 aggNode.OutputTransforms.MaxRows = node.MaxRows 448 449 if node.MaxRows > 0 { 450 aggNode.Limit = int(node.MaxRows) 451 } 452 453 return aggNode, nil 454 } 455 456 func parseORCondition(node *ast.Node, boolNode *ASTNode, qid uint64) error { 457 qsSubNode := &ASTNode{} 458 if boolNode.OrFilterCondition == nil { 459 boolNode.OrFilterCondition = &Condition{} 460 } 461 switch node.NodeType { 462 case ast.NodeOr: 463 err := SearchQueryToASTnode(node, qsSubNode, qid) 464 if err != nil { 465 log.Errorf("qid=%d, SearchQueryToASTnode : parseORCondition error: %v", qid, err) 466 return err 467 } 468 if boolNode.OrFilterCondition.NestedNodes == nil { 469 boolNode.OrFilterCondition.NestedNodes = []*ASTNode{qsSubNode} 470 } else { 471 boolNode.OrFilterCondition.NestedNodes = append(boolNode.OrFilterCondition.NestedNodes, qsSubNode) 472 } 473 return nil 474 case ast.NodeAnd: 475 err := SearchQueryToASTnode(node, qsSubNode, qid) 476 if err != nil { 477 log.Errorf("qid=%d, SearchQueryToASTnode : parseORCondition error: %v", qid, err) 478 return err 479 } 480 if boolNode.OrFilterCondition.NestedNodes == nil { 481 boolNode.OrFilterCondition.NestedNodes = []*ASTNode{qsSubNode} 482 } else { 483 boolNode.OrFilterCondition.NestedNodes = append(boolNode.OrFilterCondition.NestedNodes, qsSubNode) 484 } 485 return nil 486 case ast.NodeTerminal: 487 criteria, err := ast.ProcessSingleFilter(node.Comparison.Field, node.Comparison.Values, node.Comparison.Op, node.Comparison.ValueIsRegex, qid) 488 if err != nil { 489 log.Errorf("qid=%d, SearchQueryToASTnode : processPipeSearchMap error: %v", qid, err) 490 return err 491 } 492 filtercond := &Condition{ 493 FilterCriteria: []*FilterCriteria(criteria), 494 } 495 if boolNode.OrFilterCondition == nil { 496 boolNode.OrFilterCondition = filtercond 497 } else { 498 boolNode.OrFilterCondition.JoinCondition(filtercond) 499 } 500 return nil 501 default: 502 log.Errorf("parseORCondition : node type %d not supported", node.NodeType) 503 return errors.New("parseORCondition : node type not supported") 504 } 505 } 506 func parseANDCondition(node *ast.Node, boolNode *ASTNode, qid uint64) error { 507 qsSubNode := &ASTNode{} 508 if boolNode.AndFilterCondition == nil { 509 boolNode.AndFilterCondition = &Condition{} 510 } 511 switch node.NodeType { 512 case ast.NodeOr: 513 err := SearchQueryToASTnode(node, qsSubNode, qid) 514 if err != nil { 515 log.Errorf("qid=%d, SearchQueryToASTnode : parseANDCondition error: %v", qid, err) 516 return err 517 } 518 if boolNode.AndFilterCondition.NestedNodes == nil { 519 boolNode.AndFilterCondition.NestedNodes = []*ASTNode{qsSubNode} 520 } else { 521 boolNode.AndFilterCondition.NestedNodes = append(boolNode.AndFilterCondition.NestedNodes, qsSubNode) 522 } 523 return nil 524 case ast.NodeAnd: 525 err := SearchQueryToASTnode(node, qsSubNode, qid) 526 if err != nil { 527 log.Errorf("qid=%d, SearchQueryToASTnode : parseANDCondition error: %v", qid, err) 528 return err 529 } 530 if boolNode.AndFilterCondition.NestedNodes == nil { 531 boolNode.AndFilterCondition.NestedNodes = []*ASTNode{qsSubNode} 532 } else { 533 boolNode.AndFilterCondition.NestedNodes = append(boolNode.AndFilterCondition.NestedNodes, qsSubNode) 534 } 535 return nil 536 case ast.NodeTerminal: 537 criteria, err := ast.ProcessSingleFilter(node.Comparison.Field, node.Comparison.Values, node.Comparison.Op, node.Comparison.ValueIsRegex, qid) 538 if err != nil { 539 log.Errorf("qid=%d, SearchQueryToASTnode : processPipeSearchMap error: %v", qid, err) 540 return err 541 } 542 filtercond := &Condition{ 543 FilterCriteria: []*FilterCriteria(criteria), 544 } 545 if boolNode.AndFilterCondition == nil { 546 boolNode.AndFilterCondition = filtercond 547 } else { 548 boolNode.AndFilterCondition.JoinCondition(filtercond) 549 } 550 return nil 551 default: 552 log.Errorf("parseANDCondition : node type %d not supported", node.NodeType) 553 return errors.New("parseANDCondition : node type not supported") 554 } 555 }