/**
  * @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_);
 }
Exemple #2
0
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;
  });
}