ExprPtr compileExpression()

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