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  }