github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/ast/structs.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 ast
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"strings"
    23  
    24  	"github.com/siglens/siglens/pkg/segment/structs"
    25  	"github.com/siglens/siglens/pkg/segment/utils"
    26  )
    27  
    28  type QueryStruct struct {
    29  	SearchFilter *Node
    30  	PipeCommands *structs.QueryAggregators
    31  }
    32  
    33  // NodeType represents the type of a node in the parse tree
    34  type NodeType int
    35  
    36  // Node Types
    37  const (
    38  	_ NodeType = iota
    39  	NodeNot
    40  	NodeAnd
    41  	NodeOr
    42  	NodeTerminal
    43  )
    44  
    45  // Node is a node in the query parse tree
    46  type Node struct {
    47  	NodeType   NodeType
    48  	Comparison Comparison
    49  	Left       *Node
    50  	Right      *Node
    51  }
    52  
    53  // Comparison is an individual comparison operation on a terminal node
    54  type Comparison struct {
    55  	Op           string
    56  	Field        string
    57  	Values       interface{}
    58  	ValueIsRegex bool // True if Values is a regex string. False if Values is a wildcarded string or anything else.
    59  }
    60  
    61  type GrepValue struct {
    62  	Field string
    63  }
    64  
    65  // ParseError is the exported error type for parsing errors with detailed information as to where they occurred
    66  type ParseError struct {
    67  	Inner    error    `json:"inner"`
    68  	Line     int      `json:"line"`
    69  	Column   int      `json:"column"`
    70  	Offset   int      `json:"offset"`
    71  	Prefix   string   `json:"prefix"`
    72  	Expected []string `json:"expected"`
    73  }
    74  
    75  func MakeValue(val interface{}) (interface{}, error) {
    76  	return val, nil
    77  }
    78  
    79  func StringFromChars(chars interface{}) string {
    80  	str := ""
    81  	r := chars.([]interface{})
    82  	for _, i := range r {
    83  		j := i.([]uint8)
    84  		str += string(j[0])
    85  	}
    86  	return str
    87  }
    88  
    89  func (p *ParseError) Error() string {
    90  	return p.Prefix + ": " + p.Inner.Error()
    91  }
    92  
    93  func OpNameToString(label interface{}) (string, error) {
    94  	var sb strings.Builder
    95  	value := label.([]interface{})
    96  	for _, i := range value {
    97  		if i == nil {
    98  			continue
    99  		}
   100  		switch b := i.(type) {
   101  		case []byte:
   102  			sb.WriteByte(b[0])
   103  		case string:
   104  			sb.WriteString(b)
   105  		case []interface{}:
   106  			s, err := OpNameToString(i)
   107  			if err != nil {
   108  				return "", err
   109  			}
   110  			sb.WriteString(s)
   111  		default:
   112  			return "", fmt.Errorf("unexpected type [%T] found in label interfaces: %+v", i, i)
   113  		}
   114  	}
   115  	return sb.String(), nil
   116  }
   117  
   118  func toIfaceSlice(v interface{}) []interface{} {
   119  	if v == nil {
   120  		return nil
   121  	}
   122  	return v.([]interface{})
   123  }
   124  
   125  // helper method to get individual tokens from their rule index
   126  func GetTokens(first, rest interface{}, idx int) []string {
   127  	out := []string{first.(string)}
   128  	restSl := toIfaceSlice(rest)
   129  	for _, v := range restSl {
   130  		expr := toIfaceSlice(v)
   131  		out = append(out, expr[idx].(string))
   132  	}
   133  	return out
   134  }
   135  
   136  // helper method to get individual tokens from their rule index
   137  func GetMeasureAggsTokens(first, rest interface{}, idx int) *structs.QueryAggregators {
   138  	aggNode := &structs.QueryAggregators{}
   139  	aggNode.PipeCommandType = structs.MeasureAggsType
   140  	aggNode.MeasureOperations = make([]*structs.MeasureAggregator, 0)
   141  	aggNode.MeasureOperations = append(aggNode.MeasureOperations, first.(*structs.MeasureAggregator))
   142  
   143  	restSl := toIfaceSlice(rest)
   144  	for _, v := range restSl {
   145  		expr := toIfaceSlice(v)
   146  		aggNode.MeasureOperations = append(aggNode.MeasureOperations, expr[idx].(*structs.MeasureAggregator))
   147  	}
   148  	return aggNode
   149  }
   150  
   151  // helper method to get individual tokens from their rule index
   152  func GetGroupByTokens(cols, first, rest interface{}, idx int, limit int) *structs.QueryAggregators {
   153  	aggNode := &structs.QueryAggregators{}
   154  	aggNode.PipeCommandType = structs.GroupByType
   155  	aggNode.GroupByRequest = &structs.GroupByRequest{}
   156  	aggNode.GroupByRequest.MeasureOperations = make([]*structs.MeasureAggregator, 0)
   157  	aggNode.GroupByRequest.MeasureOperations = append(aggNode.GroupByRequest.MeasureOperations, first.(*structs.MeasureAggregator))
   158  	aggNode.BucketLimit = limit
   159  
   160  	if cols != nil {
   161  		aggNode.GroupByRequest.GroupByColumns = cols.([]string)
   162  	}
   163  	restSl := toIfaceSlice(rest)
   164  	for _, v := range restSl {
   165  		expr := toIfaceSlice(v)
   166  		aggNode.GroupByRequest.MeasureOperations = append(aggNode.GroupByRequest.MeasureOperations, expr[idx].(*structs.MeasureAggregator))
   167  	}
   168  	return aggNode
   169  }
   170  
   171  func AggTypeToAggregateFunction(aggType string) (utils.AggregateFunctions, error) {
   172  	var aggFunc utils.AggregateFunctions
   173  
   174  	if aggType == "avg" {
   175  		aggFunc = utils.Avg
   176  	} else if aggType == "min" {
   177  		aggFunc = utils.Min
   178  	} else if aggType == "max" {
   179  		aggFunc = utils.Max
   180  	} else if aggType == "sum" {
   181  		aggFunc = utils.Sum
   182  	} else if aggType == "count" {
   183  		aggFunc = utils.Count
   184  	} else if aggType == "cardinality" {
   185  		aggFunc = utils.Cardinality
   186  	} else {
   187  		return aggFunc, errors.New("unsupported statistic aggregation type")
   188  	}
   189  	return aggFunc, nil
   190  }