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 }