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