virtual void apply()

in velox/experimental/codegen/vector_function/GeneratedVectorFunction-inl.h [171:293]


  virtual void apply(
      const SelectivityVector& rows,
      std::vector<VectorPtr>& args,
      const TypePtr& outputType,
      exec::EvalCtx* context,
      VectorPtr* result) const override {
    VELOX_CHECK(result != nullptr);
    VELOX_CHECK(rowType_ != nullptr);
    VELOX_CHECK(
        (*result == nullptr) or (result->get()->as<RowVector>() != nullptr));

    // all-constant expressions shouldn't be compiled
    VELOX_CHECK(args.size() > 0);

    BaseVector::ensureWritable(rows, rowType_, context->pool(), result);

    // TODO: We should probably move this loop inside ensureWritable
    for (size_t columnIndex = 0; columnIndex < rowType_->size();
         ++columnIndex) {
      BaseVector::ensureWritable(
          rows,
          rowType_->childAt(columnIndex),
          context->pool(),
          &(result->get()->as<RowVector>()->childAt(columnIndex)));
    }

    // Constuct nulls
    for (auto& child : result->get()->as<RowVector>()->children()) {
      child->setCodegenOutput();
      if constexpr (
          (GeneratedCodeConfig::isDefaultNull ||
           GeneratedCodeConfig::isDefaultNullStrict) &&
          !GeneratedCode::hasFilter) {
        // preset all with nulls, only if it's projection only
        child->addNulls(nullptr, rows);
      } else {
        // preset all not nulls
        child->mutableRawNulls();
      }
    }

    (*result)->setCodegenOutput();

    VELOX_CHECK(result->get()->as<RowVector>() != nullptr);

    // Shared string input buffer
    // TODO: write now we are sharing everything, this not ideal. We should do
    // a static analysis reachability pass and acquire shared buffers
    // accordingly to reduce memory lifetime.
    for (auto& arg : args) {
      if (arg->type()->kind() == TypeKind::VARCHAR) {
        for (size_t columnIndex = 0; columnIndex < rowType_->size();
             ++columnIndex) {
          // Ensures that the results vectors are nullables.
          if (result->get()
                  ->as<RowVector>()
                  ->childAt(columnIndex)
                  ->type()
                  ->kind() == TypeKind::VARCHAR) {
            result->get()
                ->as<RowVector>()
                ->childAt(columnIndex)
                ->template asFlatVector<StringView>()
                ->acquireSharedStringBuffers(arg.get());
          }
        }
      }
    }

    size_t resultSize;

    if constexpr (
        GeneratedCodeConfig::isDefaultNull ||
        GeneratedCodeConfig::isDefaultNullStrict) {
      // only proccess indices where all inputs are not nulls
      auto rowsNotNull = rows;

      auto deselectNull = [&rowsNotNull, &rows](const VectorPtr& arg) {
        if (arg->mayHaveNulls() && arg->getNullCount() != 0) {
          rowsNotNull.deselectNulls(
              arg->flatRawNulls(rows), rows.begin(), rows.end());
        }
      };

      if constexpr (GeneratedCode::hasFilter) {
        /// when it's filter default null, we only deselect null bits on filter
        /// attributes even if projection's also default null, because input
        /// index and output index don't match now.
        applyLambdaToVector(deselectNull, args, FilterInputIndices{});
      } else {
        for (const auto& arg : args) {
          deselectNull(arg);
        }
      }

      resultSize = apply(
          rowsNotNull,
          args,
          outputType,
          context,
          result->get()->as<RowVector>()->children());

    } else {
      resultSize = apply(
          rows,
          args,
          outputType,
          context,
          result->get()->as<RowVector>()->children());
    }

    // truncate result
    if (resultSize != args[0]->size()) {
      for (size_t columnIndex = 0; columnIndex < rowType_->size();
           ++columnIndex) {
        result->get()
            ->as<RowVector>()
            ->childAt(columnIndex)
            ->resize(resultSize);
      }
      result->get()->resize(resultSize);
    }
  }