Skip to content

Commit

Permalink
implemented the integration of cypher into the GQL ASTNode system, a…
Browse files Browse the repository at this point in the history
…nd fixed bugs in the GQL match feature (#533)

* add cypher test compare result

* implement query

* implement match query

* implement standalone call and create

* cpplint

* cpplint

* cpplint

* fix double format

* update

* update

* implement set

* implement gql set

* fix test case

* move dml

* cpplint

* cpplint

* remove ddl header

* fix compile error

* follow comment

* comments

* comments

* comments

* cpplint

* comments

* comments

* comments

* comments

* comments

* fix bug

* fix bug

* remove incorrect comments

* fix bug

* comments

---------

Co-authored-by: Shipeng Qi <[email protected]>
Co-authored-by: Ke Huang <[email protected]>
  • Loading branch information
3 people authored Jun 11, 2024
1 parent ae51027 commit 2c769ad
Show file tree
Hide file tree
Showing 96 changed files with 9,691 additions and 60 deletions.
9 changes: 9 additions & 0 deletions deps/geax-front-end/include/geax-front-end/ast/AstDumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,15 @@ class AstDumper : public AstNodeVisitor {
VISIT_PARAM_AND_CHECK_WITH_MSG(rig);
return GEAXErrorCode::GEAX_SUCCEED;
}
std::any visit(BSquare* node) override {
INDET_GUARD();
VARIABLE_GUARD_WITH_TYPE_NAME(BSquare);
auto lef = node->left();
auto rig = node->right();
VISIT_PARAM_AND_CHECK_WITH_MSG(lef);
VISIT_PARAM_AND_CHECK_WITH_MSG(rig);
return GEAXErrorCode::GEAX_SUCCEED;
}
std::any visit(BAnd* node) override {
INDET_GUARD();
VARIABLE_GUARD_WITH_TYPE_NAME(BAnd);
Expand Down
1 change: 1 addition & 0 deletions deps/geax-front-end/include/geax-front-end/ast/AstNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ using StrArray = std::array<const char* const, N>;
TYPE(BMul, kBMul, "BMul") \
TYPE(BDiv, kBDiv, "BDiv") \
TYPE(BMod, kBMod, "BMod") \
TYPE(BSquare, kBSquare, "BSquare") \
TYPE(BOr, kBOr, "BOr") \
TYPE(BXor, kBXor, "BXor") \
TYPE(BAnd, kBAnd, "BAnd") \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class BSub;
class BMod;
class BMul;
class BDiv;
class BSquare;
class BOr;
class BXor;
class BBitAnd;
Expand Down Expand Up @@ -252,6 +253,7 @@ class AstNodeVisitor {
virtual std::any visit(BDiv* node) = 0;
virtual std::any visit(BMul* node) = 0;
virtual std::any visit(BMod* node) = 0;
virtual std::any visit(BSquare* node) = 0;
virtual std::any visit(BAnd* node) = 0;
virtual std::any visit(BOr* node) = 0;
virtual std::any visit(BXor* node) = 0;
Expand Down Expand Up @@ -498,6 +500,7 @@ class AstExprNodeVisitorImpl : public AstNodeVisitor {
virtual std::any visit(BDiv* node) override = 0;
virtual std::any visit(BMul* node) override = 0;
virtual std::any visit(BMod* node) override = 0;
virtual std::any visit(BSquare* node) override = 0;
virtual std::any visit(BAnd* node) override = 0;
virtual std::any visit(BOr* node) override = 0;
virtual std::any visit(BXor* node) override = 0;
Expand Down Expand Up @@ -892,6 +895,9 @@ class AstLabelTreeNodeVisitorImpl : public AstNodeVisitor {
virtual std::any visit(BMod*) override {
return GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT;
}
virtual std::any visit(BSquare*) override {
return GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT;
}
virtual std::any visit(BAnd*) override {
return GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT;
}
Expand Down
34 changes: 34 additions & 0 deletions deps/geax-front-end/include/geax-front-end/ast/expr/BSquare.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Copyright 2023 AntGroup CO., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*/

#ifndef GEAXFRONTEND_AST_EXPR_BSQUARE_H_
#define GEAXFRONTEND_AST_EXPR_BSQUARE_H_

#include "geax-front-end/ast/expr/BinaryOp.h"

namespace geax {
namespace frontend {

class BSquare : public BinaryOp {
public:
BSquare() : BinaryOp(AstNodeType::kBSquare) {}
~BSquare() = default;

std::any accept(AstNodeVisitor& visitor) override { return visitor.visit(this); }
}; // class BSquare

} // namespace frontend
} // namespace geax

#endif // GEAXFRONTEND_AST_EXPR_BSQUARE_H_
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "geax-front-end/ast/expr/BLike.h"
#include "geax-front-end/ast/expr/BMod.h"
#include "geax-front-end/ast/expr/BMul.h"
#include "geax-front-end/ast/expr/BSquare.h"
#include "geax-front-end/ast/expr/BNotEqual.h"
#include "geax-front-end/ast/expr/BNotGreaterThan.h"
#include "geax-front-end/ast/expr/BNotSmallerThan.h"
Expand Down
3 changes: 3 additions & 0 deletions src/BuildCypherLib.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ set(LGRAPH_CYPHER_SRC # find cypher/ -name "*.cpp" | sort
cypher/execution_plan/ops/op_skip.cpp
cypher/execution_plan/ops/op_sort.cpp
cypher/execution_plan/ops/op_standalone_call.cpp
cypher/execution_plan/ops/op_gql_standalone_call.cpp
cypher/execution_plan/ops/op_union.cpp
cypher/execution_plan/ops/op_unwind.cpp
cypher/execution_plan/ops/op_var_len_expand.cpp
Expand All @@ -57,12 +58,14 @@ set(LGRAPH_CYPHER_SRC # find cypher/ -name "*.cpp" | sort
cypher/graph/relationship.cpp
cypher/grouping/group.cpp
cypher/parser/cypher_base_visitor.cpp
cypher/parser/cypher_base_visitor_v2.cpp
cypher/parser/cypher_error_listener.cpp
cypher/parser/symbol_table.cpp
cypher/parser/generated/LcypherLexer.cpp
cypher/parser/generated/LcypherParser.cpp
cypher/parser/generated/LcypherVisitor.cpp
cypher/procedure/procedure.cpp
cypher/procedure/procedure_v2.cpp
cypher/resultset/record.cpp
cypher/monitor/monitor_manager.cpp
cypher/execution_plan/optimization/rewrite/schema_rewrite.cpp
Expand Down
56 changes: 55 additions & 1 deletion src/cypher/arithmetic/arithmetic_expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@
#include <stack>
#include <string>
#include <vector>
#include <regex>
#include "cypher/cypher_exception.h"
#include "cypher/cypher_types.h"
#include "cypher/procedure/utils.h"
#include "cypher/parser/expression.h"
#include "cypher/parser/clause.h"
#include "cypher/parser/symbol_table.h"
#include "cypher/procedure/utils.h"
#include "cypher/arithmetic/arithmetic_expression.h"

#define CHECK_NODE(e) \
Expand Down Expand Up @@ -1233,6 +1234,59 @@ cypher::FieldData BuiltinFunction::PolygonWKT(RTContext *ctx, const Record &reco
}
}

cypher::FieldData BuiltinFunction::StartsWith(RTContext *ctx, const Record &record,
const std::vector<ArithExprNode> &args) {
if (args.size() != 3) CYPHER_ARGUMENT_ERROR();
auto prefix = args[1].Evaluate(ctx, record);
std::string prefix_str = prefix.constant.scalar.AsString();
auto variable = args[2].Evaluate(ctx, record);
std::string variable_str = variable.constant.scalar.AsString();
bool ret = variable_str.compare(0, prefix_str.size(), prefix_str) == 0;
return cypher::FieldData(lgraph_api::FieldData(ret));
}

cypher::FieldData BuiltinFunction::EndsWith(RTContext *ctx, const Record &record,
const std::vector<ArithExprNode> &args) {
if (args.size() != 3) CYPHER_ARGUMENT_ERROR();
auto postfix = args[1].Evaluate(ctx, record);
std::string postfix_str = postfix.constant.scalar.AsString();
auto variable = args[2].Evaluate(ctx, record);
std::string variable_str = variable.constant.scalar.AsString();
bool ret = variable_str.size() >= postfix_str.size() &&
variable_str.compare(variable_str.size() - postfix_str.size(),
postfix_str.size(), postfix_str) == 0;
return cypher::FieldData(lgraph_api::FieldData(ret));
}

cypher::FieldData BuiltinFunction::Contains(RTContext *ctx, const Record &record,
const std::vector<ArithExprNode> &args) {
if (args.size() != 3) CYPHER_ARGUMENT_ERROR();
auto substr = args[1].Evaluate(ctx, record);
std::string substr_str = substr.constant.scalar.AsString();
auto variable = args[2].Evaluate(ctx, record);
std::string variable_str = variable.constant.scalar.AsString();
bool ret = variable_str.find(substr_str) != std::string::npos;
return cypher::FieldData(lgraph_api::FieldData(ret));
}

cypher::FieldData BuiltinFunction::Regexp(RTContext *ctx, const Record &record,
const std::vector<ArithExprNode> &args) {
if (args.size() != 3) CYPHER_ARGUMENT_ERROR();
auto regexp = args[1].Evaluate(ctx, record);
std::string regexp_str = regexp.constant.scalar.AsString();
auto variable = args[2].Evaluate(ctx, record);
std::string variable_str = variable.constant.scalar.AsString();
bool ret = std::regex_match(variable_str, std::regex(regexp_str));
return cypher::FieldData(lgraph_api::FieldData(ret));
}

cypher::FieldData BuiltinFunction::Exists(RTContext *ctx, const Record &record,
const std::vector<ArithExprNode> &args) {
// TODO(lingsu): implement in future
CYPHER_TODO();
return cypher::FieldData();
}

cypher::FieldData BuiltinFunction::Bin(RTContext *ctx, const Record &record,
const std::vector<ArithExprNode> &args) {
if (args.size() != 2) CYPHER_ARGUMENT_ERROR();
Expand Down
21 changes: 21 additions & 0 deletions src/cypher/arithmetic/arithmetic_expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,22 @@ struct BuiltinFunction {
static cypher::FieldData PolygonWKT(RTContext *ctx, const Record &record,
const std::vector<ArithExprNode> &args);


static cypher::FieldData StartsWith(RTContext *ctx, const Record &record,
const std::vector<ArithExprNode> &args);

static cypher::FieldData EndsWith(RTContext *ctx, const Record &record,
const std::vector<ArithExprNode> &args);

static cypher::FieldData Contains(RTContext *ctx, const Record &record,
const std::vector<ArithExprNode> &args);

static cypher::FieldData Regexp(RTContext *ctx, const Record &record,
const std::vector<ArithExprNode> &args);

static cypher::FieldData Exists(RTContext *ctx, const Record &record,
const std::vector<ArithExprNode> &args);

/* binary function (open cypher extension) */
static cypher::FieldData Bin(RTContext *ctx, const Record &record,
const std::vector<ArithExprNode> &args);
Expand Down Expand Up @@ -550,6 +566,11 @@ struct ArithOpNode {
ae_registered_funcs.emplace("polygon", BuiltinFunction::Polygon);
ae_registered_funcs.emplace("polygonwkb", BuiltinFunction::PolygonWKB);
ae_registered_funcs.emplace("polygonwkt", BuiltinFunction::PolygonWKT);
ae_registered_funcs.emplace("startswith", BuiltinFunction::StartsWith);
ae_registered_funcs.emplace("endswith", BuiltinFunction::EndsWith);
ae_registered_funcs.emplace("contains", BuiltinFunction::Contains);
ae_registered_funcs.emplace("regexp", BuiltinFunction::Regexp);
ae_registered_funcs.emplace("exists", BuiltinFunction::Exists);

/* native API-like functions */
ae_registered_funcs.emplace("native.getedgefield", BuiltinFunction::NativeGetEdgeField);
Expand Down
69 changes: 64 additions & 5 deletions src/cypher/arithmetic/ast_expr_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,12 @@
#endif

cypher::FieldData doCallBuiltinFunc(const std::string& name, cypher::RTContext* ctx,
const cypher::Record& record,
const std::vector<cypher::ArithExprNode> &args) {
const cypher::Record& record,
const std::vector<cypher::ArithExprNode>& args) {
static std::unordered_map<std::string, cypher::BuiltinFunction::FUNC> ae_registered_funcs =
cypher::ArithOpNode::RegisterFuncs();
auto it = ae_registered_funcs.find(name);
if (it == ae_registered_funcs.end())
NOT_SUPPORT_AND_THROW();
if (it == ae_registered_funcs.end()) NOT_SUPPORT_AND_THROW();
cypher::BuiltinFunction::FUNC func = it->second;
auto data = func(ctx, record, args);
return data;
Expand Down Expand Up @@ -200,6 +199,8 @@ std::any cypher::AstExprEvaluator::visit(geax::frontend::BMul* node) { DO_BINARY

std::any cypher::AstExprEvaluator::visit(geax::frontend::BMod* node) { DO_BINARY_EXPR(Mod); }

std::any cypher::AstExprEvaluator::visit(geax::frontend::BSquare* node) { DO_BINARY_EXPR(Pow); }

std::any cypher::AstExprEvaluator::visit(geax::frontend::BAnd* node) { DO_BINARY_EXPR(And); }

std::any cypher::AstExprEvaluator::visit(geax::frontend::BOr* node) { DO_BINARY_EXPR(Or); }
Expand Down Expand Up @@ -328,7 +329,18 @@ std::any cypher::AstExprEvaluator::visit(geax::frontend::Windowing* node) {
NOT_SUPPORT_AND_THROW();
}

std::any cypher::AstExprEvaluator::visit(geax::frontend::MkList* node) { NOT_SUPPORT_AND_THROW(); }
std::any cypher::AstExprEvaluator::visit(geax::frontend::MkList* node) {
const auto& elems = node->elems();
std::vector<::lgraph::FieldData> fields;
fields.reserve(elems.size());
std::vector<::lgraph::FieldData> list;
for (auto& e : elems) {
auto entry = std::any_cast<Entry>(e->accept(*this));
if (!entry.IsScalar()) NOT_SUPPORT_AND_THROW();
list.emplace_back(entry.constant.scalar);
}
return Entry(cypher::FieldData(list));
}

std::any cypher::AstExprEvaluator::visit(geax::frontend::MkMap* node) { NOT_SUPPORT_AND_THROW(); }

Expand Down Expand Up @@ -376,6 +388,7 @@ std::any cypher::AstExprEvaluator::visit(geax::frontend::VNone* node) { NOT_SUPP

std::any cypher::AstExprEvaluator::visit(geax::frontend::Ref* node) {
auto it = sym_tab_->symbols.find(node->name());
if (it == sym_tab_->symbols.end()) NOT_SUPPORT_AND_THROW();
switch (it->second.type) {
case SymbolNode::NODE:
case SymbolNode::RELATIONSHIP:
Expand All @@ -400,6 +413,52 @@ std::any cypher::AstExprEvaluator::visit(geax::frontend::Ref* node) {

std::any cypher::AstExprEvaluator::visit(geax::frontend::Param* node) { NOT_SUPPORT_AND_THROW(); }

std::any cypher::AstExprEvaluator::visit(geax::frontend::SingleLabel* node) {
std::unordered_set<std::string> set;
set.insert(std::move(node->label()));
return set;
}

std::any cypher::AstExprEvaluator::visit(geax::frontend::LabelOr* node) {
std::unordered_set<std::string> left;
checkedAnyCast(node->left()->accept(*this), left);
std::unordered_set<std::string> right;
checkedAnyCast(node->left()->accept(*this), right);
left.insert(right.begin(), right.end());
return left;
}

std::any cypher::AstExprEvaluator::visit(geax::frontend::IsLabeled* node) {
Entry e;
checkedAnyCast(node->expr()->accept(*this), e);
CYPHER_THROW_ASSERT(e.IsNode() || e.IsRelationship());
auto alias = e.constant.scalar.AsString();
std::unordered_set<std::string> labels;
checkedAnyCast(node->labelTree()->accept(*this), labels);
bool exist = false;
std::string label;
if (e.IsNode()) {
auto n = e.node;
CYPHER_THROW_ASSERT(n && n->IsValidAfterMaterialize(ctx_));
label = n->ItRef()->GetLabel();
} else if (e.IsRelationship()) {
auto rel = e.relationship;
CYPHER_THROW_ASSERT(rel && rel->ItRef()->IsValid());
label = rel->ItRef()->GetLabel();
}
exist = labels.count(label);
return Entry(cypher::FieldData(lgraph::FieldData(exist)));
}

std::any cypher::AstExprEvaluator::visit(geax::frontend::IsNull* node) {
Entry e;
checkedAnyCast(node->expr()->accept(*this), e);
cypher::FieldData ret;
ret.type = FieldData::SCALAR;
ret.scalar = ::lgraph::FieldData(e.IsNull());
return Entry(ret);
}

std::any cypher::AstExprEvaluator::reportError() { return error_msg_; }

} // namespace cypher
19 changes: 18 additions & 1 deletion src/cypher/arithmetic/ast_expr_evaluator.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@

namespace cypher {

template <typename TargetType>
void checkedAnyCast(const std::any& s, TargetType& d) {
try {
d = std::any_cast<TargetType>(s);
} catch (...) {
// TODO(lingsu): remove in future
assert(false);
}
}

class AstExprEvaluator : public geax::frontend::AstExprNodeVisitorImpl {
public:
AstExprEvaluator() = delete;
Expand All @@ -54,7 +64,9 @@ class AstExprEvaluator : public geax::frontend::AstExprNodeVisitorImpl {
record_ = record;
agg_pos_ = 0;
visit_mode_ = VisitMode::EVALUATE;
return std::any_cast<Entry>(expr_->accept(*this));
Entry entry;
checkedAnyCast(expr_->accept(*this), entry);
return entry;
}

void Aggregate(RTContext* ctx, const Record* record) {
Expand Down Expand Up @@ -95,6 +107,7 @@ class AstExprEvaluator : public geax::frontend::AstExprNodeVisitorImpl {
std::any visit(geax::frontend::BDiv* node) override;
std::any visit(geax::frontend::BMul* node) override;
std::any visit(geax::frontend::BMod* node) override;
std::any visit(geax::frontend::BSquare* node) override;
std::any visit(geax::frontend::BAnd* node) override;
std::any visit(geax::frontend::BOr* node) override;
std::any visit(geax::frontend::BXor* node) override;
Expand Down Expand Up @@ -133,6 +146,10 @@ class AstExprEvaluator : public geax::frontend::AstExprNodeVisitorImpl {
std::any visit(geax::frontend::VNone* node) override;
std::any visit(geax::frontend::Ref* node) override;
std::any visit(geax::frontend::Param* node) override;
std::any visit(geax::frontend::SingleLabel* node) override;
std::any visit(geax::frontend::LabelOr* node) override;
std::any visit(geax::frontend::IsLabeled* node) override;
std::any visit(geax::frontend::IsNull* node) override;

std::any reportError() override;

Expand Down
Loading

0 comments on commit 2c769ad

Please sign in to comment.