github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/segment/writer/segstream.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 writer 18 19 import ( 20 "github.com/siglens/siglens/pkg/config" 21 "github.com/siglens/siglens/pkg/segment/structs" 22 "github.com/siglens/siglens/pkg/segment/utils" 23 log "github.com/sirupsen/logrus" 24 ) 25 26 /* 27 Main function exported to check colWips against persistent queries during ingest 28 29 Internally, updates the bitset with recNum for all queries that matched 30 */ 31 func applyStreamingSearchToRecord(wipBlock WipBlock, psNode map[string]*structs.SearchNode, 32 recNum uint16) { 33 34 holderDte := &utils.DtypeEnclosure{} 35 tsKey := config.GetTimeStampKey() 36 for pqid, sNode := range psNode { 37 holderDte.Reset() 38 if applySearchSingleNode(wipBlock.colWips, sNode, holderDte, tsKey) { 39 wipBlock.addRecordToMatchedResults(recNum, pqid) 40 } 41 } 42 } 43 44 func applySearchSingleNode(colWips map[string]*ColWip, sNode *structs.SearchNode, holderDte *utils.DtypeEnclosure, tsKey string) bool { 45 retVal := false 46 if sNode.AndSearchConditions != nil { 47 andConditions := applySearchSingleCondition(colWips, sNode.AndSearchConditions, utils.And, holderDte, tsKey) 48 if !andConditions { 49 return false 50 } 51 retVal = true 52 } 53 54 // at least one must pass. If and conditions are defined, then this is a noop check 55 if sNode.OrSearchConditions != nil { 56 orConditions := applySearchSingleCondition(colWips, sNode.OrSearchConditions, utils.Or, holderDte, tsKey) 57 retVal = retVal || orConditions 58 } 59 60 if !retVal { 61 return retVal 62 } 63 // all must fail 64 if sNode.ExclusionSearchConditions != nil { 65 exclusionConditions := applySearchSingleCondition(colWips, sNode.ExclusionSearchConditions, utils.Exclusion, holderDte, tsKey) 66 if exclusionConditions { 67 return false 68 } 69 } 70 return true 71 } 72 73 func applySearchSingleCondition(colWips map[string]*ColWip, sCond *structs.SearchCondition, op utils.LogicalOperator, 74 holderDte *utils.DtypeEnclosure, tsKey string) bool { 75 orMatch := false 76 if sCond.SearchNode != nil { 77 for _, sNode := range sCond.SearchNode { 78 retVal := applySearchSingleNode(colWips, sNode, holderDte, tsKey) 79 if !retVal && op == utils.And { 80 return retVal 81 } else { 82 orMatch = orMatch || retVal 83 } 84 } 85 } 86 if sCond.SearchQueries != nil { 87 for _, query := range sCond.SearchQueries { 88 retVal := applySearchSingleQuery(colWips, query, op, holderDte, tsKey) 89 if !retVal && op == utils.And { 90 return retVal 91 } else { 92 orMatch = orMatch || retVal 93 } 94 } 95 } 96 97 if op == utils.And { 98 // previous false values would have returned already 99 return true 100 } 101 return orMatch 102 } 103 104 func applySearchSingleQuery(colWips map[string]*ColWip, sQuery *structs.SearchQuery, op utils.LogicalOperator, 105 holderDte *utils.DtypeEnclosure, tsKey string) bool { 106 switch sQuery.SearchType { 107 case structs.MatchAll: 108 return true 109 case structs.MatchWords: 110 rawVal, ok := colWips[sQuery.MatchFilter.MatchColumn] 111 if !ok { 112 return false 113 } 114 retVal, err := ApplySearchToMatchFilterRawCsg(sQuery.MatchFilter, rawVal.getLastRecord()) 115 if err != nil { 116 log.Errorf("applySearchSingleQuery: failed to apply match words search! error: %v", err) 117 return false 118 } 119 return retVal 120 case structs.MatchWordsAllColumns: 121 for cname, colVal := range colWips { 122 if cname == tsKey { 123 continue 124 } 125 retVal, _ := ApplySearchToMatchFilterRawCsg(sQuery.MatchFilter, colVal.getLastRecord()) 126 if retVal { 127 return true 128 } 129 } 130 return false 131 case structs.SimpleExpression: 132 rawVal, ok := colWips[sQuery.QueryInfo.ColName] 133 if !ok { 134 return false 135 } 136 retVal, err := ApplySearchToExpressionFilterSimpleCsg(sQuery.QueryInfo.QValDte, sQuery.ExpressionFilter.FilterOp, rawVal.getLastRecord(), false, holderDte) 137 if err != nil { 138 log.Errorf("applySearchSingleQuery: failed to apply simple expression search! error: %v", err) 139 return false 140 } 141 return retVal 142 case structs.RegexExpression: 143 rawVal, ok := colWips[sQuery.QueryInfo.ColName] 144 if !ok { 145 return false 146 } 147 retVal, err := ApplySearchToExpressionFilterSimpleCsg(sQuery.QueryInfo.QValDte, sQuery.ExpressionFilter.FilterOp, rawVal.getLastRecord(), true, holderDte) 148 if err != nil { 149 log.Errorf("applySearchSingleQuery: failed to apply wildcard expression search! error: %v", err) 150 return false 151 } 152 return retVal 153 case structs.RegexExpressionAllColumns: 154 for cname, colVal := range colWips { 155 if cname == tsKey { 156 continue 157 } 158 retVal, _ := ApplySearchToExpressionFilterSimpleCsg(sQuery.QueryInfo.QValDte, sQuery.ExpressionFilter.FilterOp, colVal.getLastRecord(), true, holderDte) 159 if retVal { 160 return true 161 } 162 } 163 return false 164 case structs.SimpleExpressionAllColumns: 165 for cname, colVal := range colWips { 166 if cname == tsKey { 167 continue 168 } 169 retVal, _ := ApplySearchToExpressionFilterSimpleCsg(sQuery.QueryInfo.QValDte, sQuery.ExpressionFilter.FilterOp, colVal.getLastRecord(), false, holderDte) 170 if retVal { 171 return true 172 } 173 } 174 return false 175 case structs.MatchDictArraySingleColumn: 176 rawVal, ok := colWips[sQuery.QueryInfo.ColName] 177 if !ok { 178 return false 179 } 180 retVal, err := ApplySearchToDictArrayFilter([]byte(sQuery.QueryInfo.ColName), sQuery.QueryInfo.QValDte, rawVal.getLastRecord(), sQuery.ExpressionFilter.FilterOp, true, holderDte) 181 if err != nil { 182 log.Errorf("ApplySearchToDictArrayFilter: failed to apply wildcard expression search! error: %v", err) 183 return false 184 } 185 return retVal 186 case structs.MatchDictArrayAllColumns: 187 for cname, colVal := range colWips { 188 if cname == tsKey { 189 continue 190 } 191 retVal, _ := ApplySearchToDictArrayFilter([]byte(sQuery.QueryInfo.ColName), sQuery.QueryInfo.QValDte, colVal.getLastRecord(), sQuery.ExpressionFilter.FilterOp, false, holderDte) 192 if retVal { 193 return true 194 } 195 } 196 return false 197 default: 198 log.Errorf("applySearchSingleQuery: unsupported query type! %+v", sQuery.SearchType) 199 return false 200 } 201 } 202 203 /* 204 Adds recNum as a matched record in the current bitset based on pqid 205 */ 206 func (wipBlock *WipBlock) addRecordToMatchedResults(recNum uint16, pqid string) { 207 pqMatch, ok := wipBlock.pqMatches[pqid] 208 if !ok { 209 log.Errorf("addRecordToMatchedResults: tried to match a record for a pqid that does not exist") 210 return 211 } 212 pqMatch.AddMatchedRecord(uint(recNum)) 213 } 214 215 func (colWip *ColWip) getLastRecord() []byte { 216 return colWip.cbuf[colWip.cstartidx:colWip.cbufidx] 217 }