github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/segment/search/conditioncheck.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 search 18 19 import ( 20 "errors" 21 22 "github.com/siglens/siglens/pkg/segment/reader/segread" 23 . "github.com/siglens/siglens/pkg/segment/structs" 24 . "github.com/siglens/siglens/pkg/segment/utils" 25 "github.com/siglens/siglens/pkg/segment/writer" 26 log "github.com/sirupsen/logrus" 27 ) 28 29 // TODO: support for complex expressions 30 func ApplyColumnarSearchQuery(query *SearchQuery, multiColReader *segread.MultiColSegmentReader, 31 blockNum uint16, recordNum uint16, holderDte *DtypeEnclosure, qid uint64, 32 dictEncColNames map[string]bool, searchReq *SegmentSearchRequest, 33 cmiPassedCnames map[string]bool) (bool, error) { 34 35 switch query.SearchType { 36 case MatchAll: 37 // ts should have already been checked 38 return true, nil 39 case MatchWords: 40 rawColVal, err := multiColReader.ReadRawRecordFromColumnFile(query.QueryInfo.ColName, 41 blockNum, recordNum, qid) 42 if err != nil { 43 return false, err 44 } 45 return writer.ApplySearchToMatchFilterRawCsg(query.MatchFilter, rawColVal) 46 case MatchWordsAllColumns: 47 var atleastOneNonError bool 48 var finalErr error 49 for cname := range cmiPassedCnames { 50 51 // we skip rawsearching for columns that are dict encoded, 52 // since we already search for them in the prior call to applyColumnarSearchUsingDictEnc 53 _, ok := dictEncColNames[cname] 54 if ok { 55 continue 56 } 57 58 rawColVal, err := multiColReader.ReadRawRecordFromColumnFile(cname, blockNum, recordNum, qid) 59 if err != nil { 60 finalErr = err 61 continue 62 } else { 63 atleastOneNonError = true 64 } 65 retVal, _ := writer.ApplySearchToMatchFilterRawCsg(query.MatchFilter, rawColVal) 66 if retVal { 67 multiColReader.IncrementColumnUsage(cname) 68 return true, nil 69 } 70 } 71 if atleastOneNonError { 72 return false, nil 73 } else { 74 return false, finalErr 75 } 76 case SimpleExpression: 77 rawColVal, err := multiColReader.ReadRawRecordFromColumnFile(query.QueryInfo.ColName, blockNum, recordNum, qid) 78 if err != nil { 79 return false, err 80 } 81 return writer.ApplySearchToExpressionFilterSimpleCsg(query.QueryInfo.QValDte, query.ExpressionFilter.FilterOp, rawColVal, false, holderDte) 82 case RegexExpression: 83 rawColVal, err := multiColReader.ReadRawRecordFromColumnFile(query.QueryInfo.ColName, blockNum, recordNum, qid) 84 if err != nil { 85 return false, err 86 } 87 return writer.ApplySearchToExpressionFilterSimpleCsg(query.QueryInfo.QValDte, query.ExpressionFilter.FilterOp, rawColVal, true, holderDte) 88 case RegexExpressionAllColumns: 89 var atleastOneNonError bool 90 var finalErr error 91 for cname := range cmiPassedCnames { 92 93 // we skip rawsearching for columns that are dict encoded, 94 // since we already search for them in the prior call to applyColumnarSearchUsingDictEnc 95 _, ok := dictEncColNames[cname] 96 if ok { 97 continue 98 } 99 100 rawColVal, err := multiColReader.ReadRawRecordFromColumnFile(cname, blockNum, recordNum, qid) 101 if err != nil { 102 finalErr = err 103 continue 104 } else { 105 atleastOneNonError = true 106 } 107 retVal, _ := writer.ApplySearchToExpressionFilterSimpleCsg(query.QueryInfo.QValDte, query.ExpressionFilter.FilterOp, rawColVal, true, holderDte) 108 if retVal { 109 multiColReader.IncrementColumnUsage(cname) 110 return true, nil 111 } 112 } 113 if atleastOneNonError { 114 return false, nil 115 } else { 116 return false, finalErr 117 } 118 case SimpleExpressionAllColumns: 119 var atleastOneNonError bool 120 var finalErr error 121 for cname := range cmiPassedCnames { 122 123 // we skip rawsearching for columns that are dict encoded, 124 // since we already search for them in the prior call to applyColumnarSearchUsingDictEnc 125 _, ok := dictEncColNames[cname] 126 if ok { 127 continue 128 } 129 130 rawColVal, err := multiColReader.ReadRawRecordFromColumnFile(cname, blockNum, recordNum, qid) 131 if err != nil { 132 finalErr = err 133 continue 134 } else { 135 atleastOneNonError = true 136 } 137 retVal, _ := writer.ApplySearchToExpressionFilterSimpleCsg(query.QueryInfo.QValDte, query.ExpressionFilter.FilterOp, rawColVal, false, holderDte) 138 if retVal { 139 multiColReader.IncrementColumnUsage(cname) 140 return true, nil 141 } 142 } 143 if atleastOneNonError { 144 return false, nil 145 } else { 146 return false, finalErr 147 } 148 case MatchDictArraySingleColumn: 149 rawColVal, err := multiColReader.ReadRawRecordFromColumnFile(query.QueryInfo.ColName, blockNum, recordNum, qid) 150 if err != nil { 151 return false, err 152 } 153 return writer.ApplySearchToDictArrayFilter(query.QueryInfo.KValDte, query.QueryInfo.QValDte, rawColVal, Equals, true, holderDte) 154 case MatchDictArrayAllColumns: 155 var atleastOneNonError bool 156 var finalErr error 157 for _, colInfo := range multiColReader.AllColums { 158 159 // we skip rawsearching for columns that are dict encoded, 160 // since we already search for them in the prior call to applyColumnarSearchUsingDictEnc 161 _, ok := dictEncColNames[colInfo.ColumnName] 162 if ok { 163 continue 164 } 165 166 rawColVal, err := multiColReader.ReadRawRecordFromColumnFile(colInfo.ColumnName, blockNum, recordNum, qid) 167 if err != nil { 168 finalErr = err 169 continue 170 } else { 171 atleastOneNonError = true 172 } 173 retVal, _ := writer.ApplySearchToDictArrayFilter(query.QueryInfo.KValDte, query.QueryInfo.QValDte, rawColVal, query.ExpressionFilter.FilterOp, true, holderDte) 174 if retVal { 175 multiColReader.IncrementColumnUsage(colInfo.ColumnName) 176 return true, nil 177 } 178 } 179 if atleastOneNonError { 180 return false, nil 181 } else { 182 return false, finalErr 183 } 184 // case ComplexExpression: 185 // return // match complex exp 186 default: 187 log.Errorf("qid=%d, ApplySearchQuery: unsupported query type! %+v", qid, query.SearchType) 188 return false, errors.New("unsupported query type") 189 } 190 } 191 192 /* 193 returns doRecLevelSearch, error 194 if it determines that this query can be fully satisfied by looking at the dict encoded, then 195 will return doRecLevelSearch=false. 196 */ 197 func applyColumnarSearchUsingDictEnc(sq *SearchQuery, mcr *segread.MultiColSegmentReader, 198 blockNum uint16, qid uint64, bri *BlockRecordIterator, bsh *BlockSearchHelper, 199 searchReq *SegmentSearchRequest, cmiPassedCnames map[string]bool) (bool, map[string]bool, error) { 200 201 dictEncColNames := make(map[string]bool) 202 203 switch sq.SearchType { 204 case MatchAll: 205 for i := uint(0); i < uint(bri.AllRecLen); i++ { 206 bsh.AddMatchedRecord(i) 207 } 208 return false, dictEncColNames, nil 209 210 case MatchWords: 211 isDict, err := mcr.IsBlkDictEncoded(sq.QueryInfo.ColName, blockNum) 212 if err != nil { 213 return true, dictEncColNames, err 214 } 215 216 if !isDict { 217 return true, dictEncColNames, nil 218 } 219 220 found, err := mcr.ApplySearchToMatchFilterDictCsg(sq.MatchFilter, bsh, sq.QueryInfo.ColName) 221 if err != nil { 222 log.Errorf("applyColumnarSearchUsingDictEnc: matchwords dict search failed, err=%v", err) 223 return false, dictEncColNames, err 224 } 225 return found, dictEncColNames, err 226 227 case MatchWordsAllColumns: 228 for cname := range cmiPassedCnames { 229 230 isDict, err := mcr.IsBlkDictEncoded(cname, blockNum) 231 if err != nil { 232 continue 233 } 234 235 if !isDict { 236 continue 237 } 238 239 dictEncColNames[cname] = true 240 found, err := mcr.ApplySearchToMatchFilterDictCsg(sq.MatchFilter, bsh, cname) 241 if err != nil { 242 continue 243 } 244 if found { 245 mcr.IncrementColumnUsage(cname) 246 } 247 } 248 return true, dictEncColNames, nil 249 250 case SimpleExpression, RegexExpression: 251 252 isDict, err := mcr.IsBlkDictEncoded(sq.QueryInfo.ColName, blockNum) 253 if err != nil { 254 return true, dictEncColNames, err 255 } 256 257 if !isDict { 258 return true, dictEncColNames, nil 259 } 260 261 var regex bool 262 if sq.SearchType == RegexExpression { 263 regex = true 264 } 265 266 found, err := mcr.ApplySearchToExpressionFilterDictCsg(sq.QueryInfo.QValDte, 267 sq.ExpressionFilter.FilterOp, regex, bsh, sq.QueryInfo.ColName) 268 if err != nil { 269 log.Errorf("applyColumnarSearchUsingDictEnc: simpleexp/wildrexp dict search failed, err=%v", err) 270 return false, dictEncColNames, err 271 } 272 return found, dictEncColNames, err 273 274 case RegexExpressionAllColumns: 275 for cname := range cmiPassedCnames { 276 277 isDict, err := mcr.IsBlkDictEncoded(cname, blockNum) 278 if err != nil { 279 continue 280 } 281 282 if !isDict { 283 continue 284 } 285 286 dictEncColNames[cname] = true 287 found, err := mcr.ApplySearchToExpressionFilterDictCsg(sq.QueryInfo.QValDte, 288 sq.ExpressionFilter.FilterOp, true, bsh, cname) 289 if err != nil { 290 continue 291 } 292 if found { 293 mcr.IncrementColumnUsage(cname) 294 } 295 } 296 return true, dictEncColNames, nil 297 298 case SimpleExpressionAllColumns: 299 for cname := range cmiPassedCnames { 300 301 isDict, err := mcr.IsBlkDictEncoded(cname, blockNum) 302 if err != nil { 303 continue 304 } 305 306 if !isDict { 307 continue 308 } 309 310 dictEncColNames[cname] = true 311 found, err := mcr.ApplySearchToExpressionFilterDictCsg(sq.QueryInfo.QValDte, 312 sq.ExpressionFilter.FilterOp, false, bsh, cname) 313 if err != nil { 314 continue 315 } 316 if found { 317 mcr.IncrementColumnUsage(cname) 318 } 319 } 320 return true, dictEncColNames, nil 321 case MatchDictArraySingleColumn, MatchDictArrayAllColumns: 322 return true, dictEncColNames, nil 323 // case ComplexExpression: 324 // return // match complex exp 325 default: 326 log.Errorf("qid=%d, applyColumnarSearchUsingDictEnc: unsupported query type! %+v", qid, sq.SearchType) 327 return true, dictEncColNames, errors.New("unsupported query type") 328 } 329 }