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); });
}
}