std::unique_ptr BytesValues::mergeWith()

in velox/type/Filter.cpp [1053:1127]


std::unique_ptr<Filter> BytesValues::mergeWith(const Filter* other) const {
  switch (other->kind()) {
    case FilterKind::kAlwaysTrue:
    case FilterKind::kAlwaysFalse:
    case FilterKind::kIsNull:
    case FilterKind::kMultiRange:
      return other->mergeWith(this);
    case FilterKind::kIsNotNull:
      return this->clone(false);
    case FilterKind::kBytesValues: {
      bool bothNullAllowed = nullAllowed_ && other->testNull();
      auto otherBytesValues = static_cast<const BytesValues*>(other);

      if (this->upper_.compare(otherBytesValues->lower_) < 0 ||
          otherBytesValues->upper_.compare(this->lower_) < 0) {
        return nullOrFalse(bothNullAllowed);
      }
      const BytesValues* smallerFilter = this;
      const BytesValues* largerFilter = otherBytesValues;
      if (this->values().size() > otherBytesValues->values().size()) {
        smallerFilter = otherBytesValues;
        largerFilter = this;
      }

      std::vector<std::string> newValues;
      newValues.reserve(smallerFilter->values().size());

      for (const auto& value : smallerFilter->values()) {
        if (largerFilter->values_.contains(value)) {
          newValues.emplace_back(value);
        }
      }

      if (newValues.empty()) {
        return nullOrFalse(bothNullAllowed);
      }

      return std::make_unique<BytesValues>(
          std::move(newValues), bothNullAllowed);
    }
    case FilterKind::kBytesRange: {
      auto otherBytesRange = static_cast<const BytesRange*>(other);
      bool bothNullAllowed = nullAllowed_ && other->testNull();

      if (!testBytesRange(
              otherBytesRange->isLowerUnbounded()
                  ? std::nullopt
                  : std::optional(otherBytesRange->lower()),
              otherBytesRange->isUpperUnbounded()
                  ? std::nullopt
                  : std::optional(otherBytesRange->upper()),
              bothNullAllowed)) {
        return nullOrFalse(bothNullAllowed);
      }

      std::vector<std::string> newValues;
      newValues.reserve(this->values().size());
      for (const auto& value : this->values()) {
        if (otherBytesRange->testBytes(value.data(), value.length())) {
          newValues.emplace_back(value);
        }
      }

      if (newValues.empty()) {
        return nullOrFalse(bothNullAllowed);
      }

      return std::make_unique<BytesValues>(
          std::move(newValues), bothNullAllowed);
    }

    default:
      VELOX_UNREACHABLE();
  }
}