/// <summary> /// Find the items containing *any word* starting with the word passed /// and add the union of all of them to the result set passed. /// </summary> /// <param name="prefix">Prefix to find</param> /// <param name="result">Result to which to add matches</param> public void WhereMatches(ByteBlock prefix, ShortSet result) { if (result == null) { throw new ArgumentNullException("result"); } // Split each word in the input value RangeSet prefixWords = _splitter.Split(prefix); // Shortcut: If only one word, add directly to result set if (prefixWords.Count == 1 && prefixWords.Ranges[0].Length == prefix.Length) { // Add matches for words starting with this prefix in every block foreach (WordIndexBlock block in _blocks) { block.WhereMatches(prefix, result); } } else { // We need to add (OR) the items which match all words (AND) in the split prefix ShortSet matchesForAllWords = null; ShortSet matchesForWord = new ShortSet(result.Capacity); // For each found word, add all matches for (int i = 0; i < prefixWords.Count; ++i) { Range word = prefixWords.Ranges[i]; ByteBlock wordBlock = new ByteBlock(prefix.Array, word.Index, word.Length); matchesForWord.Clear(); // Add matches for words starting with this prefix in every block foreach (WordIndexBlock block in _blocks) { block.WhereMatches(wordBlock, matchesForWord); } // AND matches for this word with each other word in the prefix if (matchesForAllWords == null) { matchesForAllWords = new ShortSet(result.Capacity); matchesForAllWords.Or(matchesForWord); } else { matchesForAllWords.And(matchesForWord); } } // OR matches for ALL words with the final result if (matchesForAllWords != null) { result.Or(matchesForAllWords); } } }
public void VerifyConsistency(IColumn column, VerificationLevel level, ExecutionDetails details) { if (_words.Count > WordCountLimit) { details.AddError(ExecutionDetails.WordIndexBlockTooFull, column.Name, _words.Count); } if (_words.Count != _sets.Count) { details.AddError(ExecutionDetails.WordIndexBlockSizesMismatch, column.Name, _words.Count, _sets.Count); } if (level == VerificationLevel.Full) { // Validate that all IDs in all sets are valid // NOTE: Replacing with a validating GetInSet would be more thorough; check for duplicate values, padding problems, etc. ShortSet allValidItems = new ShortSet(column.Count); allValidItems.Not(); ShortSet items = new ShortSet(ushort.MaxValue); for (ushort i = 0; i < _words.Count; ++i) { items.Clear(); GetInSet(i, items); items.AndNot(allValidItems); if (items.Count() > 0) { details.AddError(ExecutionDetails.WordIndexInvalidItemID, column.Name, _words[i], String.Join(", ", items.Values)); } } } // Ask the Sets and Words columns to self-verify _sets.VerifyConsistency(level, details); _words.VerifyConsistency(level, details); }