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