static std::unique_ptr build_expr()

in flex/engines/graph_db/runtime/utils/expr_impl.cc [553:751]


static std::unique_ptr<ExprBase> build_expr(
    const GraphInterface& graph, const Context& ctx,
    const std::map<std::string, std::string>& params,
    std::stack<common::ExprOpr>& opr_stack, VarType var_type) {
  while (!opr_stack.empty()) {
    auto opr = opr_stack.top();
    opr_stack.pop();
    switch (opr.item_case()) {
    case common::ExprOpr::kConst: {
      if (opr.const_().item_case() == common::Value::kStr) {
        const std::string& str = opr.const_().str();
        return std::make_unique<ConstExpr>(RTAny::from_string(str));
      }
      return std::make_unique<ConstExpr>(parse_const_value(opr.const_()));
    }
    case common::ExprOpr::kParam: {
      return std::make_unique<ConstExpr>(parse_param(opr.param(), params));
    }
    case common::ExprOpr::kVar: {
      return std::make_unique<VariableExpr>(graph, ctx, opr.var(), var_type);
    }
    case common::ExprOpr::kLogical: {
      if (opr.logical() == common::Logical::WITHIN) {
        auto lhs = opr_stack.top();
        opr_stack.pop();
        auto rhs = opr_stack.top();
        opr_stack.pop();
        assert(lhs.has_var());
        if (rhs.has_const_()) {
          auto key =
              std::make_unique<VariableExpr>(graph, ctx, lhs.var(), var_type);
          if (key->type() == RTAnyType::kI64Value) {
            return std::make_unique<WithInExpr<int64_t>>(ctx, std::move(key),
                                                         rhs.const_());
          } else if (key->type() == RTAnyType::kU64Value) {
            return std::make_unique<WithInExpr<uint64_t>>(ctx, std::move(key),
                                                          rhs.const_());
          } else if (key->type() == RTAnyType::kI32Value) {
            return std::make_unique<WithInExpr<int32_t>>(ctx, std::move(key),
                                                         rhs.const_());
          } else if (key->type() == RTAnyType::kStringValue) {
            return std::make_unique<WithInExpr<std::string>>(
                ctx, std::move(key), rhs.const_());
          } else {
            LOG(FATAL) << "not support";
          }
        } else if (rhs.has_var()) {
          auto key =
              std::make_unique<VariableExpr>(graph, ctx, lhs.var(), var_type);
          if (key->type() == RTAnyType::kVertex) {
            auto val =
                std::make_unique<VariableExpr>(graph, ctx, rhs.var(), var_type);
            if (val->type() == RTAnyType::kList) {
              return std::make_unique<VertexWithInListExpr>(ctx, std::move(key),
                                                            std::move(val));
            } else if (val->type() == RTAnyType::kSet) {
              return std::make_unique<VertexWithInSetExpr>(ctx, std::move(key),
                                                           std::move(val));
            } else {
              LOG(FATAL) << "not support";
            }
          }

        } else {
          LOG(FATAL) << "not support" << rhs.DebugString();
        }
      } else if (opr.logical() == common::Logical::NOT ||
                 opr.logical() == common::Logical::ISNULL) {
        auto lhs = build_expr(graph, ctx, params, opr_stack, var_type);
        return std::make_unique<UnaryLogicalExpr>(std::move(lhs),
                                                  opr.logical());
      } else {
        auto lhs = build_expr(graph, ctx, params, opr_stack, var_type);
        auto rhs = build_expr(graph, ctx, params, opr_stack, var_type);
        return std::make_unique<LogicalExpr>(std::move(lhs), std::move(rhs),
                                             opr.logical());
      }
      break;
    }
    case common::ExprOpr::kArith: {
      auto lhs = build_expr(graph, ctx, params, opr_stack, var_type);
      auto rhs = build_expr(graph, ctx, params, opr_stack, var_type);
      return std::make_unique<ArithExpr>(std::move(lhs), std::move(rhs),
                                         opr.arith());
    }
    case common::ExprOpr::kCase: {
      auto op = opr.case_();
      size_t len = op.when_then_expressions_size();
      std::vector<
          std::pair<std::unique_ptr<ExprBase>, std::unique_ptr<ExprBase>>>
          when_then_exprs;
      for (size_t i = 0; i < len; ++i) {
        auto when_expr = op.when_then_expressions(i).when_expression();
        auto then_expr = op.when_then_expressions(i).then_result_expression();
        when_then_exprs.emplace_back(
            parse_expression_impl(graph, ctx, params, when_expr, var_type),
            parse_expression_impl(graph, ctx, params, then_expr, var_type));
      }
      auto else_expr = parse_expression_impl(
          graph, ctx, params, op.else_result_expression(), var_type);
      return std::make_unique<CaseWhenExpr>(std::move(when_then_exprs),
                                            std::move(else_expr));
    }
    case common::ExprOpr::kExtract: {
      auto hs = build_expr(graph, ctx, params, opr_stack, var_type);
      if (hs->type() == RTAnyType::kI64Value) {
        return std::make_unique<ExtractExpr<int64_t>>(std::move(hs),
                                                      opr.extract());
      } else if (hs->type() == RTAnyType::kDate32) {
        return std::make_unique<ExtractExpr<Day>>(std::move(hs), opr.extract());
      } else if (hs->type() == RTAnyType::kTimestamp) {
        return std::make_unique<ExtractExpr<Date>>(std::move(hs),
                                                   opr.extract());
      } else {
        LOG(FATAL) << "not support" << static_cast<int>(hs->type());
      }
    }
    case common::ExprOpr::kVars: {
      auto op = opr.vars();

      if (op.keys_size() == 3) {
        std::array<std::unique_ptr<ExprBase>, 3> exprs;
        for (int i = 0; i < op.keys_size(); ++i) {
          exprs[i] =
              std::make_unique<VariableExpr>(graph, ctx, op.keys(i), var_type);
        }
        return TypedTupleBuilder<3, 3>().build_typed_tuple(std::move(exprs));
      } else if (op.keys_size() == 2) {
        std::array<std::unique_ptr<ExprBase>, 2> exprs;
        for (int i = 0; i < op.keys_size(); ++i) {
          exprs[i] =
              std::make_unique<VariableExpr>(graph, ctx, op.keys(i), var_type);
        }
        return TypedTupleBuilder<2, 2>().build_typed_tuple(std::move(exprs));
      }

      std::vector<std::unique_ptr<ExprBase>> exprs;
      for (int i = 0; i < op.keys_size(); ++i) {
        exprs.push_back(
            std::make_unique<VariableExpr>(graph, ctx, op.keys(i), var_type));
      }
      return std::make_unique<TupleExpr>(std::move(exprs));
    }
    case common::ExprOpr::kMap: {
      auto op = opr.map();
      std::vector<RTAny> keys_vec;
      std::vector<std::unique_ptr<ExprBase>> exprs;
      for (int i = 0; i < op.key_vals_size(); ++i) {
        auto key = op.key_vals(i).key();
        auto val = op.key_vals(i).val();
        auto any = parse_const_value(key);
        keys_vec.push_back(any);
        exprs.emplace_back(
            std::make_unique<VariableExpr>(graph, ctx, val,
                                           var_type));  // just for parse
      }
      if (exprs.size() > 0) {
        return std::make_unique<MapExpr>(std::move(keys_vec), std::move(exprs));
      }
      LOG(FATAL) << "not support" << opr.DebugString();
    }
    case common::ExprOpr::kUdfFunc: {
      auto op = opr.udf_func();
      std::string name = op.name();
      auto expr =
          parse_expression_impl(graph, ctx, params, op.parameters(0), var_type);
      if (name == "gs.function.relationships") {
        return std::make_unique<RelationshipsExpr>(std::move(expr));
      } else if (name == "gs.function.nodes") {
        return std::make_unique<NodesExpr>(std::move(expr));
      } else if (name == "gs.function.startNode") {
        return std::make_unique<StartNodeExpr>(std::move(expr));
      } else if (name == "gs.function.endNode") {
        return std::make_unique<EndNodeExpr>(std::move(expr));
      } else if (name == "gs.function.toFloat") {
        return std::make_unique<ToFloatExpr>(std::move(expr));
      } else if (name == "gs.function.concat") {
        auto expr2 = parse_expression_impl(graph, ctx, params, op.parameters(1),
                                           var_type);
        return std::make_unique<StrConcatExpr>(std::move(expr),
                                               std::move(expr2));
      } else if (name == "gs.function.listSize") {
        return std::make_unique<StrListSizeExpr>(std::move(expr));
      } else {
        LOG(FATAL) << "not support udf" << opr.DebugString();
      }
    }
    case common::ExprOpr::kDateTimeMinus: {
      auto lhs = build_expr(graph, ctx, params, opr_stack, var_type);
      auto rhs = build_expr(graph, ctx, params, opr_stack, var_type);
      return std::make_unique<DateMinusExpr>(std::move(lhs), std::move(rhs));
    }
    default:
      LOG(FATAL) << "not support" << opr.DebugString();
      break;
    }
  }
  return nullptr;
}