in velox/expression/ExprCompiler.cpp [309:401]
ExprPtr compileExpression(
const TypedExprPtr& expr,
Scope* scope,
const core::QueryConfig& config,
memory::MemoryPool* pool,
bool enableConstantFolding) {
ExprPtr alreadyCompiled = getAlreadyCompiled(expr.get(), &scope->visited);
if (alreadyCompiled) {
if (!alreadyCompiled->isMultiplyReferenced()) {
scope->exprSet->addToReset(alreadyCompiled);
}
alreadyCompiled->setMultiplyReferenced();
return alreadyCompiled;
}
ExprPtr result;
auto resultType = expr->type();
auto compiledInputs =
compileInputs(expr, scope, config, pool, enableConstantFolding);
auto inputTypes = getTypes(compiledInputs);
if (auto concat = dynamic_cast<const core::ConcatTypedExpr*>(expr.get())) {
auto vectorFunction = getVectorFunction("row_constructor", inputTypes, {});
VELOX_CHECK(vectorFunction, "Vector function row_constructor is missing");
result = std::make_shared<Expr>(
resultType, std::move(compiledInputs), vectorFunction, "row");
} else if (auto cast = dynamic_cast<const core::CastTypedExpr*>(expr.get())) {
VELOX_CHECK(!compiledInputs.empty());
result = std::make_shared<CastExpr>(
resultType, std::move(compiledInputs[0]), cast->nullOnFailure());
} else if (auto call = dynamic_cast<const core::CallTypedExpr*>(expr.get())) {
if (auto specialForm = getSpecialForm(
call->name(), resultType, std::move(compiledInputs))) {
result = specialForm;
} else if (
auto simpleFunctionEntry =
SimpleFunctions().resolveFunction(call->name(), inputTypes)) {
auto metadata = simpleFunctionEntry->getMetadata();
VELOX_USER_CHECK(
resultType->kindEquals(metadata->returnType()),
"Found incompatible return types for '{}' ({} vs. {}) "
"for input types ({}).",
call->name(),
metadata->returnType(),
resultType,
folly::join(", ", inputTypes));
auto func = simpleFunctionEntry->createFunction()->createVectorFunction(
config, getConstantInputs(compiledInputs));
result = std::make_shared<Expr>(
resultType, std::move(compiledInputs), std::move(func), call->name());
} else if (
auto func = getVectorFunction(
call->name(), inputTypes, getConstantInputs(compiledInputs))) {
result = std::make_shared<Expr>(
resultType, std::move(compiledInputs), func, call->name());
} else {
VELOX_FAIL(
"Scalar function not registered: {} ({})",
call->name(),
folly::join(", ", inputTypes));
}
} else if (
auto access =
dynamic_cast<const core::FieldAccessTypedExpr*>(expr.get())) {
auto fieldReference = std::make_shared<FieldReference>(
expr->type(), move(compiledInputs), access->name());
captureFieldReference(fieldReference.get(), expr.get(), scope);
result = fieldReference;
} else if (auto row = dynamic_cast<const core::InputTypedExpr*>(expr.get())) {
VELOX_UNSUPPORTED("InputTypedExpr '{}' is not supported", row->toString());
} else if (
auto constant =
dynamic_cast<const core::ConstantTypedExpr*>(expr.get())) {
if (constant->hasValueVector()) {
result = std::make_shared<ConstantExpr>(constant->valueVector());
} else {
result = std::make_shared<ConstantExpr>(
BaseVector::createConstant(constant->value(), 1, pool));
}
} else if (
auto lambda = dynamic_cast<const core::LambdaTypedExpr*>(expr.get())) {
result = compileLambda(lambda, scope, config, pool, enableConstantFolding);
} else {
VELOX_UNSUPPORTED("Unknown typed expression");
}
result->computeMetadata();
auto folded =
enableConstantFolding ? tryFoldIfConstant(result, scope) : result;
scope->visited[expr.get()] = folded;
return folded;
}