void CastExpr::apply()

in velox/expression/CastExpr.cpp [498:625]


void CastExpr::apply(
    const SelectivityVector& rows,
    VectorPtr& input,
    exec::EvalCtx* context,
    const std::shared_ptr<const Type>& fromType,
    const std::shared_ptr<const Type>& toType,
    VectorPtr* result) {
  LocalSelectivityVector nonNullRows(context->execCtx(), rows.end());
  *nonNullRows = rows;
  if (input->mayHaveNulls()) {
    nonNullRows->deselectNulls(
        input->flatRawNulls(rows), rows.begin(), rows.end());
  }

  LocalSelectivityVector nullRows(context->execCtx(), rows.end());
  nullRows->clearAll();
  if (input->mayHaveNulls()) {
    *nullRows = rows;
    nullRows->deselectNonNulls(
        input->flatRawNulls(rows), rows.begin(), rows.end());
  }

  CastOperatorPtr castOperator;
  if ((castOperator = getCastOperator(toType->toString()))) {
    if (!castOperator->isSupportedType(fromType)) {
      VELOX_FAIL(
          "Cannot cast {} to {}.", fromType->toString(), toType->toString());
    }

    applyCustomTypeCast<true>(
        input,
        rows,
        *nonNullRows,
        castOperator,
        toType,
        fromType,
        context,
        nullOnFailure_,
        result);
  } else if ((castOperator = getCastOperator(fromType->toString()))) {
    if (!castOperator->isSupportedType(toType)) {
      VELOX_FAIL(
          "Cannot cast {} to {}.", fromType->toString(), toType->toString());
    }

    applyCustomTypeCast<false>(
        input,
        rows,
        *nonNullRows,
        castOperator,
        fromType,
        toType,
        context,
        nullOnFailure_,
        result);
  } else {
    LocalDecodedVector decoded(context, *input, rows);

    if (toType->isArray() || toType->isMap() || toType->isRow()) {
      LocalSelectivityVector translatedRows(
          context->execCtx(), decoded->base()->size());
      translatedRows->clearAll();
      nonNullRows->applyToSelected([&](auto row) {
        translatedRows->setValid(decoded->index(row), true);
      });
      translatedRows->updateBounds();

      VectorPtr localResult;

      switch (toType->kind()) {
        // Handle complex type conversions
        case TypeKind::MAP:
          localResult = applyMap(
              *translatedRows,
              decoded->base()->asUnchecked<MapVector>(),
              context,
              fromType->asMap(),
              toType->asMap());
          break;
        case TypeKind::ARRAY:
          localResult = applyArray(
              *translatedRows,
              decoded->base()->asUnchecked<ArrayVector>(),
              context,
              fromType->asArray(),
              toType->asArray());
          break;
        case TypeKind::ROW:
          localResult = applyRow(
              *translatedRows,
              decoded->base()->asUnchecked<RowVector>(),
              context,
              fromType->asRow(),
              toType->asRow());
          break;
        default: {
          VELOX_UNREACHABLE();
        }
      }

      if (!decoded->isIdentityMapping()) {
        localResult = decoded->wrap(localResult, *input, rows);
      }

      context->moveOrCopyResult(localResult, rows, result);
    } else {
      // Handling primitive type conversions
      BaseVector::ensureWritable(rows, toType, context->pool(), result);
      // Unwrapping toType pointer. VERY IMPORTANT: dynamic type pointer and
      // static type templates in each cast must match exactly
      VELOX_DYNAMIC_SCALAR_TYPE_DISPATCH(
          applyCast,
          toType->kind(),
          fromType->kind(),
          *nonNullRows,
          context,
          *decoded,
          result);
    }
  }

  // Copy nulls from "input".
  if (nullRows->hasSelections()) {
    auto targetNulls = (*result)->mutableRawNulls();
    nullRows->applyToSelected(
        [&](auto row) { bits::setNull(targetNulls, row, true); });
  }
}