bool Expr::applyFunctionWithPeeling()

in velox/expression/Expr.cpp [944:1067]


bool Expr::applyFunctionWithPeeling(
    const SelectivityVector& rows,
    const SelectivityVector& applyRows,
    EvalCtx* context,
    VectorPtr* result) {
  if (context->wrapEncoding() == VectorEncoding::Simple::CONSTANT) {
    return false;
  }
  int numLevels = 0;
  bool peeled;
  int32_t numConstant = 0;
  auto numArgs = inputValues_.size();
  // Holds the outermost wrapper. This may be the last reference after
  // peeling for a temporary dictionary, hence use a shared_ptr.
  VectorPtr firstWrapper = nullptr;
  std::vector<bool> constantArgs;
  do {
    peeled = true;
    BufferPtr firstIndices;
    BufferPtr firstLengths;
    std::vector<VectorPtr> maybePeeled;
    for (auto i = 0; i < inputValues_.size(); ++i) {
      auto leaf = inputValues_[i];
      if (!constantArgs.empty() && constantArgs[i]) {
        setPeeledArg(leaf, i, numArgs, maybePeeled);
        continue;
      }
      if ((numLevels == 0 && leaf->isConstant(rows)) ||
          leaf->isConstantEncoding()) {
        if (leaf->isConstantEncoding()) {
          setPeeledArg(leaf, i, numArgs, maybePeeled);
        } else {
          setPeeledArg(
              BaseVector::wrapInConstant(leaf->size(), rows.begin(), leaf),
              i,
              numArgs,
              maybePeeled);
        }
        constantArgs.resize(numArgs);
        constantArgs.at(i) = true;
        ++numConstant;
        continue;
      }
      auto encoding = leaf->encoding();
      if (encoding == VectorEncoding::Simple::DICTIONARY) {
        if (firstLengths) {
          // having a mix of dictionary and sequence encoded fields
          peeled = false;
          break;
        }
        if (!vectorFunction_->isDefaultNullBehavior() && leaf->rawNulls()) {
          // A dictionary that adds nulls over an Expr that is not null for a
          // null argument cannot be peeled.
          peeled = false;
          break;
        }
        BufferPtr indices = leaf->wrapInfo();
        if (!firstIndices) {
          firstIndices = std::move(indices);
        } else if (indices != firstIndices) {
          // different fields use different dictionaries
          peeled = false;
          break;
        }
        if (!firstWrapper) {
          firstWrapper = leaf;
        }
        setPeeledArg(leaf->valueVector(), i, numArgs, maybePeeled);
      } else if (encoding == VectorEncoding::Simple::SEQUENCE) {
        if (firstIndices) {
          // having a mix of dictionary and sequence encoded fields
          peeled = false;
          break;
        }
        BufferPtr lengths = leaf->wrapInfo();
        if (!firstLengths) {
          firstLengths = std::move(lengths);
        } else if (lengths != firstLengths) {
          // different fields use different sequences
          peeled = false;
          break;
        }
        if (!firstWrapper) {
          firstWrapper = leaf;
        }
        setPeeledArg(leaf->valueVector(), i, numArgs, maybePeeled);
      } else {
        // Non-peelable encoding.
        peeled = false;
        break;
      }
    }
    if (peeled) {
      ++numLevels;
      inputValues_ = std::move(maybePeeled);
    }
  } while (peeled && numConstant != numArgs);
  if (!numLevels) {
    return false;
  }
  LocalSelectivityVector newRowsHolder(context);
  ContextSaver saver;
  // We peel off the wrappers and make a new selection.
  SelectivityVector* newRows;
  LocalDecodedVector localDecoded(context);
  if (numConstant == numArgs) {
    // All the fields are constant across the rows of interest.
    newRows = singleRow(newRowsHolder, rows.begin());

    context->saveAndReset(&saver, rows);
    context->setConstantWrap(rows.begin());
  } else {
    auto decoded = localDecoded.get();
    decoded->makeIndices(*firstWrapper, applyRows, numLevels);
    newRows = translateToInnerRows(applyRows, *decoded, newRowsHolder);
    context->saveAndReset(&saver, rows);
    setDictionaryWrapping(*decoded, rows, *firstWrapper, context);
  }

  VectorPtr peeledResult;
  applyFunction(*newRows, context, &peeledResult);
  context->setWrapped(this, peeledResult, rows, result);
  return true;
}