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