/** * @brief Take the intersection of this TupleIdSequence with another's * complement (i.e. set difference), modifying this TupleIdSequence * in-place. * @warning This TupleIdSequence must be the same length as the other, and * the set-difference only has semantic meaning if both * TupleIdSequences refer to tuples in the same block. * * @param other Another TupleIdSequence to intersect with the complement of. **/ inline void intersectWithComplement(const TupleIdSequence &other) { DEBUG_ASSERT(length() == other.length()); internal_bitvector_.unsetFrom(other.internal_bitvector_); }
TupleIdSequence* PatternMatchingUncheckedComparator<is_like_pattern, is_negation, left_nullable, right_nullable> ::compareValueAccessorAndStaticValue( ValueAccessor *accessor, const attribute_id value_accessor_attr_id, const TypedValue &static_value, const TupleIdSequence *filter) const { // Specialized implementation for matching a ValueAccessor of strings to a // single pattern. In this situation, the pattern will be compiled only once // in advance and then matched by each of the string in the ValueAccessor. return InvokeOnValueAccessorMaybeTupleIdSequenceAdapter( accessor, [&](auto *accessor) -> TupleIdSequence* { // NOLINT(build/c++11) #ifdef QUICKSTEP_ENABLE_VECTOR_PREDICATE_SHORT_CIRCUIT static constexpr bool short_circuit = true; #else static constexpr bool short_circuit = false; #endif TupleIdSequence *result = new TupleIdSequence(accessor->getEndPosition()); if (right_nullable && static_value.isNull()) { return result; } // Transform and compile pattern in advance before the loop. const char *pattern = static_cast<const char *>(static_value.getDataPtr()); std::string regex_pattern; re2::StringPiece pattern_piece; std::size_t orig_pattern_len = strnlen(pattern, right_length_); if (is_like_pattern) { regex_pattern = this->transformLikeToRegex(pattern, orig_pattern_len); pattern_piece.set(regex_pattern.c_str(), regex_pattern.size()); } else { pattern_piece.set(pattern, orig_pattern_len); } const re2::RE2 re2_pattern(pattern_piece); if (short_circuit && (filter != nullptr)) { DCHECK_EQ(filter->length(), result->length()); for (TupleIdSequence::const_iterator filter_it = filter->begin(); filter_it != filter->end(); ++filter_it) { const void *va_value = accessor->template getUntypedValueAtAbsolutePosition<left_nullable>(value_accessor_attr_id, *filter_it); result->set(*filter_it, this->matchDataPtrWithPattern(va_value, re2_pattern)); } } else { accessor->beginIteration(); if (accessor->isColumnAccessorSupported()) { // If ColumnAccessor is supported on the underlying accessor, we have a fast strided // column accessor available for the iteration on the underlying block. std::unique_ptr<const ColumnAccessor<left_nullable>> column_accessor (accessor->template getColumnAccessor<left_nullable>(value_accessor_attr_id)); DCHECK(column_accessor != nullptr); while (accessor->next()) { const void *va_value = column_accessor->getUntypedValue(); result->set(accessor->getCurrentPosition(), this->matchDataPtrWithPattern(va_value, re2_pattern)); } } else { while (accessor->next()) { const void *va_value = accessor->template getUntypedValue<left_nullable>(value_accessor_attr_id); result->set(accessor->getCurrentPosition(), this->matchDataPtrWithPattern(va_value, re2_pattern)); } } if (!short_circuit && (filter != nullptr)) { result->intersectWith(*filter); } } return result; }); }