diff --git a/src/context/test/CMakeLists.txt b/src/context/test/CMakeLists.txt
index 3246fe025cfbfa273e467d70c6213bce59e1d86b..7d7aec6c5ca9716f0109ed6c8d8cf2d8a9b413f1 100644
--- a/src/context/test/CMakeLists.txt
+++ b/src/context/test/CMakeLists.txt
@@ -9,6 +9,7 @@ SET(CONTEXT_TEST_LIBS
$<TARGET_OBJECTS:common_encryption_obj>
$<TARGET_OBJECTS:common_expression_obj>
$<TARGET_OBJECTS:common_function_manager_obj>
+ $<TARGET_OBJECTS:common_agg_function_manager_obj>
$<TARGET_OBJECTS:common_fs_obj>
$<TARGET_OBJECTS:common_time_obj>
$<TARGET_OBJECTS:common_base_obj>
diff --git a/src/daemons/CMakeLists.txt b/src/daemons/CMakeLists.txt
index 972b90c6f5bd861112e7e19d03af698a445d55da..bf9eeeda9661ca9cc6fdda49fe92627e0233e0bd 100644
--- a/src/daemons/CMakeLists.txt
+++ b/src/daemons/CMakeLists.txt
@@ -55,6 +55,7 @@ nebula_add_executable(
$<TARGET_OBJECTS:common_charset_obj>
$<TARGET_OBJECTS:common_encryption_obj>
$<TARGET_OBJECTS:common_function_manager_obj>
+ $<TARGET_OBJECTS:common_agg_function_manager_obj>
$<TARGET_OBJECTS:common_conf_obj>
$<TARGET_OBJECTS:common_time_utils_obj>
$<TARGET_OBJECTS:common_graph_obj>
diff --git a/src/executor/test/CMakeLists.txt b/src/executor/test/CMakeLists.txt
index 789a5f7151de01d1a7bc6e6bc03a343aab5a403d..6c9ff1010397d9d0c21c3af9af4a219553ab5bcf 100644
--- a/src/executor/test/CMakeLists.txt
+++ b/src/executor/test/CMakeLists.txt
@@ -27,6 +27,7 @@ SET(EXEC_QUERY_TEST_OBJS
$<TARGET_OBJECTS:common_file_based_cluster_id_man_obj>
$<TARGET_OBJECTS:common_charset_obj>
$<TARGET_OBJECTS:common_function_manager_obj>
+ $<TARGET_OBJECTS:common_agg_function_manager_obj>
$<TARGET_OBJECTS:common_encryption_obj>
$<TARGET_OBJECTS:common_http_client_obj>
$<TARGET_OBJECTS:common_time_utils_obj>
diff --git a/src/optimizer/test/CMakeLists.txt b/src/optimizer/test/CMakeLists.txt
index c58b2da6ffd1921a49db356aa5752f2044dd3f7e..9dbd228d5fde414b9fe96faf0b8f0999a9971b3b 100644
--- a/src/optimizer/test/CMakeLists.txt
+++ b/src/optimizer/test/CMakeLists.txt
@@ -10,6 +10,7 @@ set(OPTIMIZER_TEST_LIB
$<TARGET_OBJECTS:common_datatypes_obj>
$<TARGET_OBJECTS:common_expression_obj>
$<TARGET_OBJECTS:common_function_manager_obj>
+ $<TARGET_OBJECTS:common_agg_function_manager_obj>
$<TARGET_OBJECTS:common_time_obj>
$<TARGET_OBJECTS:common_meta_thrift_obj>
$<TARGET_OBJECTS:common_meta_client_obj>
diff --git a/src/parser/parser.yy b/src/parser/parser.yy
index dd02a1c9e5935b0d02dbbe988b6e9f1dd1b91664..1235bea0ad0d82052b6ae852808dbbe28fffc1d2 100644
--- a/src/parser/parser.yy
+++ b/src/parser/parser.yy
@@ -26,6 +26,7 @@
#include "common/expression/PredicateExpression.h"
#include "common/expression/ListComprehensionExpression.h"
#include "common/expression/AggregateExpression.h"
+#include "common/function/FunctionManager.h"
#include "common/expression/ReduceExpression.h"
#include "util/ParserUtil.h"
@@ -158,7 +159,6 @@ static constexpr size_t MAX_ABS_INTEGER = 9223372036854775808ULL;
%token KW_ATOMIC_EDGE
%token KW_DROP KW_REMOVE KW_SPACES KW_INGEST KW_INDEX KW_INDEXES
%token KW_IF KW_NOT KW_EXISTS KW_WITH
-%token KW_COUNT KW_COUNT_DISTINCT KW_SUM KW_AVG KW_MAX KW_MIN KW_STD KW_BIT_AND KW_BIT_OR KW_BIT_XOR KW_COLLECT KW_COLLECT_SET
%token KW_BY KW_DOWNLOAD KW_HDFS KW_UUID KW_CONFIGS KW_FORCE
%token KW_GET KW_DECLARE KW_GRAPH KW_META KW_STORAGE
%token KW_TTL KW_TTL_DURATION KW_TTL_COL KW_DATA KW_STOP
@@ -199,7 +199,7 @@ static constexpr size_t MAX_ABS_INTEGER = 9223372036854775808ULL;
%token <doubleval> DOUBLE
%token <strval> STRING VARIABLE LABEL IPV4
-%type <strval> name_label unreserved_keyword agg_function predicate_name
+%type <strval> name_label unreserved_keyword predicate_name
%type <expr> expression
%type <expr> property_expression
%type <expr> vertex_prop_expression
@@ -223,7 +223,6 @@ static constexpr size_t MAX_ABS_INTEGER = 9223372036854775808ULL;
%type <expr> list_comprehension_expression
%type <expr> reduce_expression
%type <expr> compound_expression
-%type <expr> aggregate_expression
%type <expr> text_search_expression
%type <expr> constant_expression
%type <argument_list> argument_list opt_argument_list
@@ -422,17 +421,6 @@ unreserved_keyword
| KW_DBA { $$ = new std::string("dba"); }
| KW_GUEST { $$ = new std::string("guest"); }
| KW_GROUP { $$ = new std::string("group"); }
- | KW_COUNT { $$ = new std::string("count"); }
- | KW_SUM { $$ = new std::string("sum"); }
- | KW_AVG { $$ = new std::string("avg"); }
- | KW_MAX { $$ = new std::string("max"); }
- | KW_MIN { $$ = new std::string("min"); }
- | KW_STD { $$ = new std::string("std"); }
- | KW_BIT_AND { $$ = new std::string("bit_and"); }
- | KW_BIT_OR { $$ = new std::string("bit_or"); }
- | KW_BIT_XOR { $$ = new std::string("bit_xor"); }
- | KW_COLLECT { $$ = new std::string("collect"); }
- | KW_COLLECT_SET { $$ = new std::string("collect_set"); }
| KW_PATH { $$ = new std::string("path"); }
| KW_DATA { $$ = new std::string("data"); }
| KW_LEADER { $$ = new std::string("leader"); }
@@ -467,7 +455,6 @@ unreserved_keyword
| KW_REDUCE { $$ = new std::string("reduce"); }
| KW_SHORTEST { $$ = new std::string("shortest"); }
| KW_NOLOOP { $$ = new std::string("noloop"); }
- | KW_COUNT_DISTINCT { $$ = new std::string("count_distinct"); }
| KW_CONTAINS { $$ = new std::string("contains"); }
| KW_STARTS { $$ = new std::string("starts"); }
| KW_ENDS { $$ = new std::string("ends"); }
@@ -507,20 +494,6 @@ unreserved_keyword
| KW_PLAN { $$ = new std::string("plan"); }
;
-agg_function
- : KW_COUNT { $$ = new std::string("COUNT"); }
- | KW_SUM { $$ = new std::string("SUM"); }
- | KW_AVG { $$ = new std::string("AVG"); }
- | KW_MAX { $$ = new std::string("MAX"); }
- | KW_MIN { $$ = new std::string("MIN"); }
- | KW_STD { $$ = new std::string("STD"); }
- | KW_BIT_AND { $$ = new std::string("BIT_AND"); }
- | KW_BIT_OR { $$ = new std::string("BIT_OR"); }
- | KW_BIT_XOR { $$ = new std::string("BIT_XOR"); }
- | KW_COLLECT { $$ = new std::string("COLLECT"); }
- | KW_COLLECT_SET { $$ = new std::string("COLLECT_SET"); }
- ;
-
expression
: constant_expression {
$$ = $1;
@@ -534,9 +507,6 @@ expression
| compound_expression {
$$ = $1;
}
- | aggregate_expression {
- $$ = $1;
- }
| MINUS {
scanner.setUnaryMinus(true);
} expression %prec UNARY_MINUS {
@@ -892,7 +862,51 @@ edge_prop_expression
function_call_expression
: LABEL L_PAREN opt_argument_list R_PAREN {
- $$ = new FunctionCallExpression($1, $3);
+ if (!$3) {
+ if (FunctionManager::find(*$1, 0).ok()) {
+ $$ = new FunctionCallExpression($1, $3);
+ } else {
+ throw nebula::GraphParser::syntax_error(@1, "Unknown function ");
+ }
+ } else if ($3->numArgs() == 1 && AggFunctionManager::find(*$1).ok()) {
+ $$ = new AggregateExpression($1, $3->args()[0].release(), false);
+ delete($3);
+ } else if (FunctionManager::find(*$1, $3->numArgs()).ok()) {
+ $$ = new FunctionCallExpression($1, $3);
+ } else {
+ delete($1);
+ delete($3);
+ throw nebula::GraphParser::syntax_error(@1, "Unknown function ");
+ }
+ }
+ | LABEL L_PAREN KW_DISTINCT expression R_PAREN {
+ if (AggFunctionManager::find(*$1).ok()) {
+ $$ = new AggregateExpression($1, $4, true);
+ } else {
+ delete($1);
+ delete($4);
+ throw nebula::GraphParser::syntax_error(@1, "Unknown aggregate function ");
+ }
+ }
+ | LABEL L_PAREN STAR R_PAREN {
+ std::transform($1->begin(), $1->end(), $1->begin(), ::toupper);
+ if (!$1->compare("COUNT")) {
+ auto star = new ConstantExpression(std::string("*"));
+ $$ = new AggregateExpression($1, star, false);
+ } else {
+ delete($1);
+ throw nebula::GraphParser::syntax_error(@1, "Could not apply aggregation function on `*`");
+ }
+ }
+ | LABEL L_PAREN KW_DISTINCT STAR R_PAREN {
+ std::transform($1->begin(), $1->end(), $1->begin(), ::toupper);
+ if (!$1->compare("COUNT")) {
+ auto star = new ConstantExpression(std::string("*"));
+ $$ = new AggregateExpression($1, star, true);
+ } else {
+ delete($1);
+ throw nebula::GraphParser::syntax_error(@1, "Could not apply aggregation function on `*`");
+ }
}
| KW_TIMESTAMP L_PAREN opt_argument_list R_PAREN {
$$ = new FunctionCallExpression(new std::string("timestamp"), $3);
@@ -914,23 +928,6 @@ function_call_expression
}
;
-aggregate_expression
- : agg_function L_PAREN expression R_PAREN {
- $$ = new AggregateExpression($1, $3, false/*distinct*/);
- }
- | agg_function L_PAREN KW_DISTINCT expression R_PAREN {
- $$ = new AggregateExpression($1, $4, true/*distinct*/);
- }
- | agg_function L_PAREN STAR R_PAREN {
- auto star = new ConstantExpression(std::string("*"));
- $$ = new AggregateExpression($1, star, false/*distinct*/);
- }
- | agg_function L_PAREN KW_DISTINCT STAR R_PAREN {
- auto star = new ConstantExpression(std::string("*"));
- $$ = new AggregateExpression($1, star, true/*distinct*/);
- }
- ;
-
uuid_expression
: KW_UUID L_PAREN STRING R_PAREN {
$$ = new UUIDExpression($3);
diff --git a/src/parser/scanner.lex b/src/parser/scanner.lex
index 695a5d23fdbf13a48edfd7fe8fbf4cd3128f2a74..cde1f455adcd38b90c48db809d3b5ab8747da61d 100644
--- a/src/parser/scanner.lex
+++ b/src/parser/scanner.lex
@@ -183,18 +183,6 @@ IP_OCTET ([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])
"ACCOUNT" { return TokenType::KW_ACCOUNT; }
"JOBS" { return TokenType::KW_JOBS; }
"JOB" { return TokenType::KW_JOB; }
-"COUNT" { return TokenType::KW_COUNT; }
-"COUNT_DISTINCT" { return TokenType::KW_COUNT_DISTINCT; }
-"SUM" { return TokenType::KW_SUM; }
-"AVG" { return TokenType::KW_AVG; }
-"MAX" { return TokenType::KW_MAX; }
-"MIN" { return TokenType::KW_MIN; }
-"STD" { return TokenType::KW_STD; }
-"BIT_AND" { return TokenType::KW_BIT_AND; }
-"BIT_OR" { return TokenType::KW_BIT_OR; }
-"BIT_XOR" { return TokenType::KW_BIT_XOR; }
-"COLLECT" { return TokenType::KW_COLLECT; }
-"COLLECT_SET" { return TokenType::KW_COLLECT_SET; }
"PATH" { return TokenType::KW_PATH; }
"BIDIRECT" { return TokenType::KW_BIDIRECT; }
"STATS" { return TokenType::KW_STATS; }
diff --git a/src/parser/test/CMakeLists.txt b/src/parser/test/CMakeLists.txt
index bf0da49348256be184c1421461cd3733461e15a2..626b0a84a5977b378bee642e984714be6184df57 100644
--- a/src/parser/test/CMakeLists.txt
+++ b/src/parser/test/CMakeLists.txt
@@ -17,6 +17,7 @@ set(PARSER_TEST_LIBS
$<TARGET_OBJECTS:common_datatypes_obj>
$<TARGET_OBJECTS:common_base_obj>
$<TARGET_OBJECTS:common_function_manager_obj>
+ $<TARGET_OBJECTS:common_agg_function_manager_obj>
$<TARGET_OBJECTS:common_meta_thrift_obj>
$<TARGET_OBJECTS:common_graph_thrift_obj>
$<TARGET_OBJECTS:common_http_client_obj>
diff --git a/src/parser/test/ParserTest.cpp b/src/parser/test/ParserTest.cpp
index c3db9582f9133ab64b64730c03017b3e8e47fe3c..c7204e8143edc4d76d0ec13ff6e83851a38e61c7 100644
--- a/src/parser/test/ParserTest.cpp
+++ b/src/parser/test/ParserTest.cpp
@@ -1887,10 +1887,10 @@ TEST(Parser, GroupBy) {
"BIT_OR(DISTINCT $^.person.name ), "
"BIT_XOR(DISTINCT $$.person.name ),"
"BIT_XOR(DISTINCT $-.name ),"
- "F_STD($^.person.name ), "
- "F_BIT_AND($^.person.name ), "
- "F_BIT_OR($^.person.name ), "
- "F_BIT_XOR($^.person.name )";
+ "STD($^.person.name ), "
+ "BIT_AND($^.person.name ), "
+ "BIT_OR($^.person.name ), "
+ "BIT_XOR($^.person.name )";
auto result = parse(query);
ASSERT_TRUE(result.ok()) << result.status();
@@ -1922,10 +1922,10 @@ TEST(Parser, GroupBy) {
"BIT_OR(DISTINCT $^.person.name ), "
"BIT_XOR(DISTINCT $$.person.name ),"
"BIT_XOR(DISTINCT $-.name ),"
- "F_STD($^.person.name ), "
- "F_BIT_AND($^.person.name ), "
- "F_BIT_OR($^.person.name ), "
- "F_BIT_XOR($^.person.name )";
+ "STD($^.person.name ), "
+ "BIT_AND($^.person.name ), "
+ "BIT_OR($^.person.name ), "
+ "BIT_XOR($^.person.name )";
auto result = parse(query);
ASSERT_TRUE(result.ok()) << result.status();
diff --git a/src/parser/test/ScannerTest.cpp b/src/parser/test/ScannerTest.cpp
index ff020d250f2ad77798d8fde25641d5f213bf28f7..e4cc3391d1f22d8f33873e6bdea9a5d7e42d2cef 100644
--- a/src/parser/test/ScannerTest.cpp
+++ b/src/parser/test/ScannerTest.cpp
@@ -407,15 +407,6 @@ TEST(Scanner, Basic) {
CHECK_SEMANTIC_TYPE("SNAPSHOTS", TokenType::KW_SNAPSHOTS),
CHECK_SEMANTIC_TYPE("Snapshots", TokenType::KW_SNAPSHOTS),
CHECK_SEMANTIC_TYPE("snapshots", TokenType::KW_SNAPSHOTS),
- CHECK_SEMANTIC_TYPE("BIT_AND", TokenType::KW_BIT_AND),
- CHECK_SEMANTIC_TYPE("Bit_and", TokenType::KW_BIT_AND),
- CHECK_SEMANTIC_TYPE("bit_and", TokenType::KW_BIT_AND),
- CHECK_SEMANTIC_TYPE("BIT_OR", TokenType::KW_BIT_OR),
- CHECK_SEMANTIC_TYPE("Bit_or", TokenType::KW_BIT_OR),
- CHECK_SEMANTIC_TYPE("bit_or", TokenType::KW_BIT_OR),
- CHECK_SEMANTIC_TYPE("BIT_XOR", TokenType::KW_BIT_XOR),
- CHECK_SEMANTIC_TYPE("Bit_xor", TokenType::KW_BIT_XOR),
- CHECK_SEMANTIC_TYPE("bit_xor", TokenType::KW_BIT_XOR),
CHECK_SEMANTIC_TYPE("SHORTEST", TokenType::KW_SHORTEST),
CHECK_SEMANTIC_TYPE("Shortest", TokenType::KW_SHORTEST),
CHECK_SEMANTIC_TYPE("shortest", TokenType::KW_SHORTEST),
diff --git a/src/util/ExpressionUtils.cpp b/src/util/ExpressionUtils.cpp
index bd28d80afc23e09045c151a2454861acb1561be0..a39d4dc82d5f01ba9c973d3a3e07869cd3445b4f 100644
--- a/src/util/ExpressionUtils.cpp
+++ b/src/util/ExpressionUtils.cpp
@@ -9,6 +9,7 @@
#include <memory>
#include "common/expression/PropertyExpression.h"
+#include "common/function/AggFunctionManager.h"
#include "visitor/FoldConstantExprVisitor.h"
#include "visitor/EvaluableExprVisitor.h"
@@ -204,16 +205,10 @@ std::vector<std::unique_ptr<Expression>> ExpressionUtils::expandImplOr(const Exp
Status ExpressionUtils::checkAggExpr(const AggregateExpression* aggExpr) {
- auto func = aggExpr->name();
- if (!func) {
- return Status::SemanticError("`%s' aggregate function not set.",
- aggExpr->toString().c_str());
- }
+ auto func = *aggExpr->name();
+ std::transform(func.begin(), func.end(), func.begin(), ::toupper);
- auto iter = AggregateExpression::NAME_ID_MAP.find(func->c_str());
- if (iter == AggregateExpression::NAME_ID_MAP.end()) {
- return Status::SemanticError("Unknown aggregate function `%s'", func->c_str());
- }
+ NG_RETURN_IF_ERROR(AggFunctionManager::find(func));
auto* aggArg = aggExpr->arg();
if (graph::ExpressionUtils::findAny(aggArg,
@@ -222,7 +217,7 @@ Status ExpressionUtils::checkAggExpr(const AggregateExpression* aggExpr) {
aggExpr->toString().c_str());
}
- if (iter->second != AggregateExpression::Function::kCount) {
+ if (func.compare("COUNT")) {
if (aggArg->toString() == "*") {
return Status::SemanticError("Could not apply aggregation function `%s' on `*`",
aggExpr->toString().c_str());
diff --git a/src/util/test/CMakeLists.txt b/src/util/test/CMakeLists.txt
index 6cc021d50a2ccdfd2070cd71f0adabecc9ee43d8..aeabd61504c70d49ebcc490c39d538a83f742368 100644
--- a/src/util/test/CMakeLists.txt
+++ b/src/util/test/CMakeLists.txt
@@ -10,6 +10,7 @@ nebula_add_test(
$<TARGET_OBJECTS:common_datatypes_obj>
$<TARGET_OBJECTS:common_expression_obj>
$<TARGET_OBJECTS:common_function_manager_obj>
+ $<TARGET_OBJECTS:common_agg_function_manager_obj>
$<TARGET_OBJECTS:common_time_obj>
$<TARGET_OBJECTS:common_meta_thrift_obj>
$<TARGET_OBJECTS:common_meta_client_obj>
diff --git a/src/validator/GroupByValidator.cpp b/src/validator/GroupByValidator.cpp
index 475398acc8c81c092edc280dc779d030c2051aaa..2a5161000fa3bc97770fc4ef5d9ebfc9d9ad32e5 100644
--- a/src/validator/GroupByValidator.cpp
+++ b/src/validator/GroupByValidator.cpp
@@ -197,16 +197,9 @@ Status GroupByValidator::rewriteInnerAggExpr(YieldColumn* col, bool& rewrited) {
}
Status GroupByValidator::checkAggExpr(AggregateExpression* aggExpr) {
- auto func = aggExpr->name();
- if (!func) {
- return Status::SemanticError("`%s' aggregate function not set.",
- aggExpr->toString().c_str());
- }
-
- auto iter = AggregateExpression::NAME_ID_MAP.find(func->c_str());
- if (iter == AggregateExpression::NAME_ID_MAP.end()) {
- return Status::SemanticError("Unknown aggregate function `%s'", func->c_str());
- }
+ auto func = *aggExpr->name();
+ std::transform(func.begin(), func.end(), func.begin(), ::toupper);
+ NG_RETURN_IF_ERROR(AggFunctionManager::find(func));
auto* aggArg = aggExpr->arg();
if (graph::ExpressionUtils::findAny(aggArg,
@@ -215,8 +208,8 @@ Status GroupByValidator::checkAggExpr(AggregateExpression* aggExpr) {
aggExpr->toString().c_str());
}
- if (iter->second != AggregateExpression::Function::kCount) {
- if (aggArg->toString() == "\"*\"") {
+ if (func.compare("COUNT")) {
+ if (aggArg->toString() == "*") {
return Status::SemanticError("Could not apply aggregation function `%s' on `*`",
aggExpr->toString().c_str());
}
diff --git a/src/validator/test/CMakeLists.txt b/src/validator/test/CMakeLists.txt
index 51dc4be115bc884d76cd5a64e733f685750b3748..0934d88689f8745fdbbbfb08f63519e3e230348f 100644
--- a/src/validator/test/CMakeLists.txt
+++ b/src/validator/test/CMakeLists.txt
@@ -41,6 +41,7 @@ set(VALIDATOR_TEST_LIBS
$<TARGET_OBJECTS:common_meta_client_obj>
$<TARGET_OBJECTS:common_file_based_cluster_id_man_obj>
$<TARGET_OBJECTS:common_function_manager_obj>
+ $<TARGET_OBJECTS:common_agg_function_manager_obj>
$<TARGET_OBJECTS:common_conf_obj>
$<TARGET_OBJECTS:common_encryption_obj>
$<TARGET_OBJECTS:common_http_client_obj>
diff --git a/src/validator/test/GroupByValidatorTest.cpp b/src/validator/test/GroupByValidatorTest.cpp
index 761546768b6f1cd2d0c571c4c9e2ebbeebd85318..b39b839348a8585f65bf794b440e624935b66434 100644
--- a/src/validator/test/GroupByValidatorTest.cpp
+++ b/src/validator/test/GroupByValidatorTest.cpp
@@ -290,19 +290,21 @@ TEST_F(GroupByValidatorTest, InvalidTest) {
"SemanticError: Group `noexist' invalid");
}
{
+ // TODO: move to parser UT
// use sum(*)
std::string query = "GO FROM \"1\" OVER like YIELD like._dst AS id, $^.person.age AS age "
"| GROUP BY $-.id YIELD SUM(*)";
auto result = checkResult(query);
EXPECT_EQ(std::string(result.message()),
- "SemanticError: Could not apply aggregation function `SUM(*)' on `*`");
+ "SyntaxError: Could not apply aggregation function on `*` near `SUM'");
}
{
+ // TODO: move to parser UT
// use agg fun has more than two inputs
std::string query = "GO FROM \"1\" OVER like YIELD like._dst AS id, $^.person.age AS age "
"| GROUP BY $-.id YIELD COUNT($-.id, $-.age)";
auto result = checkResult(query);
- EXPECT_EQ(std::string(result.message()), "SyntaxError: syntax error near `, $-.age'");
+ EXPECT_EQ(std::string(result.message()), "SyntaxError: Unknown function near `COUNT'");
}
{
// group col has agg fun
diff --git a/src/validator/test/YieldValidatorTest.cpp b/src/validator/test/YieldValidatorTest.cpp
index bcd6503180aa51c0889803334439e59f33be35b1..68775e43624ebfd5e017cf5a8928fb7b11fd5f63 100644
--- a/src/validator/test/YieldValidatorTest.cpp
+++ b/src/validator/test/YieldValidatorTest.cpp
@@ -123,11 +123,11 @@ TEST_F(YieldValidatorTest, FuncitonCall) {
"Parameter's type error");
}
{
+ // TODO: move to parser UT
std::string query = "YIELD noexist(12)";
auto result = checkResult(query);
EXPECT_EQ(std::string(result.message()),
- "SemanticError: `noexist(12)' is not a valid expression : Function `noexist' not "
- "defined");
+ "SyntaxError: Unknown function near `noexist'");
}
}
diff --git a/src/visitor/DeduceTypeVisitor.cpp b/src/visitor/DeduceTypeVisitor.cpp
index 674b74d87fffba46ba0de488031147248923bb47..e1ddd573d74b39bab4436695fbb8da52ad128add 100644
--- a/src/visitor/DeduceTypeVisitor.cpp
+++ b/src/visitor/DeduceTypeVisitor.cpp
@@ -414,60 +414,7 @@ void DeduceTypeVisitor::visit(FunctionCallExpression *expr) {
void DeduceTypeVisitor::visit(AggregateExpression *expr) {
expr->arg()->accept(this);
if (!ok()) return;
- auto arg_type = type_;
-
- auto func = AggregateExpression::NAME_ID_MAP[expr->name()->c_str()];
- switch (func) {
- case AggregateExpression::Function::kCount: {
- type_ = Value::Type::INT;
- break;
- }
- case AggregateExpression::Function::kSum: {
- type_ = arg_type;
- break;
- }
- case AggregateExpression::Function::kAvg: {
- type_ = Value::Type::FLOAT;
- break;
- }
- case AggregateExpression::Function::kMax: {
- type_ = arg_type;
- break;
- }
- case AggregateExpression::Function::kMin: {
- type_ = arg_type;
- break;
- }
- case AggregateExpression::Function::kStdev: {
- type_ = Value::Type::FLOAT;
- break;
- }
- case AggregateExpression::Function::kBitAnd: {
- type_ = Value::Type::INT;
- break;
- }
- case AggregateExpression::Function::kBitOr: {
- type_ = Value::Type::INT;
- break;
- }
- case AggregateExpression::Function::kBitXor: {
- type_ = Value::Type::INT;
- break;
- }
- case AggregateExpression::Function::kCollect: {
- type_ = Value::Type::LIST;
- break;
- }
- case AggregateExpression::Function::kCollectSet: {
- type_ = Value::Type::SET;
- break;
- }
- default: {
- LOG(FATAL) << "Invalid Aggregate expression kind: "
- << expr->name()->c_str();
- break;
- }
- }
+ type_ = Value::Type::__EMPTY__;
}
void DeduceTypeVisitor::visit(UUIDExpression *) {
diff --git a/src/visitor/test/CMakeLists.txt b/src/visitor/test/CMakeLists.txt
index cb009d7801fcbf5daa3715af3cdf4a54a4895cfa..fb9a87f14b923f95c266d9536cf71ac75386181c 100644
--- a/src/visitor/test/CMakeLists.txt
+++ b/src/visitor/test/CMakeLists.txt
@@ -42,6 +42,7 @@ nebula_add_test(
$<TARGET_OBJECTS:common_meta_client_obj>
$<TARGET_OBJECTS:common_file_based_cluster_id_man_obj>
$<TARGET_OBJECTS:common_function_manager_obj>
+ $<TARGET_OBJECTS:common_agg_function_manager_obj>
$<TARGET_OBJECTS:common_conf_obj>
$<TARGET_OBJECTS:common_encryption_obj>
$<TARGET_OBJECTS:common_http_client_obj>
diff --git a/tests/tck/features/agg/Agg.feature b/tests/tck/features/agg/Agg.feature
index 72cb247a9dd9e407d27c0e98ad1c0232babde0d8..7bb2f02f70fa2f731471fd42dbc00e90692f76d4 100644
--- a/tests/tck/features/agg/Agg.feature
+++ b/tests/tck/features/agg/Agg.feature
@@ -13,10 +13,10 @@ Feature: Basic Aggregate and GroupBy
| 1 | 2 |
When executing query:
"""
- YIELD count(*)+1 ,1+2 ,(INT)abs(count(2))
+ YIELD COUNT(*)+1 ,1+2 ,(INT)abs(count(2))
"""
Then the result should be, in any order, with relax comparison:
- | (COUNT(*)+1) | (1+2) | (INT)abs(COUNT(2)) |
+ | (COUNT(*)+1) | (1+2) | (INT)abs(count(2)) |
| 2 | 3 | 1 |
Scenario: [1] Basic GroupBy
@@ -473,7 +473,7 @@ Feature: Basic Aggregate and GroupBy
"""
YIELD avg(*)+1 ,1+2 ,(INT)abs(min(2))
"""
- Then a SemanticError should be raised at runtime: Could not apply aggregation function `AVG(*)' on `*`
+ Then a SyntaxError should be raised at runtime: Could not apply aggregation function on `*` near `avg'
When executing query:
"""
GO FROM "Tim Duncan" OVER like YIELD like._dst AS dst, $$.player.age AS age
@@ -503,19 +503,19 @@ Feature: Basic Aggregate and GroupBy
GO FROM "Tim Duncan" OVER like YIELD like._dst AS dst, $$.player.age AS age
| GROUP BY $-.age+1 YIELD $-.age+1,abs(avg(distinct count($-.age))) AS age
"""
- Then a SemanticError should be raised at runtime: Aggregate function nesting is not allowed: `abs(AVG(distinct COUNT($-.age)))'
+ Then a SemanticError should be raised at runtime: Aggregate function nesting is not allowed: `abs(avg(distinct count($-.age)))'
When executing query:
"""
GO FROM "Tim Duncan" OVER like YIELD like._dst AS dst, $$.player.age AS age
| GROUP BY $-.age+1 YIELD $-.age+1,avg(distinct count($-.age+1)) AS age
"""
- Then a SemanticError should be raised at runtime: Aggregate function nesting is not allowed: `AVG(distinct COUNT(($-.age+1)))'
+ Then a SemanticError should be raised at runtime: Aggregate function nesting is not allowed: `avg(distinct count(($-.age+1)))'
When executing query:
"""
GO FROM "Tim Duncan" OVER like YIELD like._dst AS dst, $$.player.age AS age
| GROUP BY avg($-.age+1)+1 YIELD $-.age,avg(distinct $-.age) AS age
"""
- Then a SemanticError should be raised at runtime: Group `(AVG(($-.age+1))+1)' invalid
+ Then a SemanticError should be raised at runtime: Group `(avg(($-.age+1))+1)' invalid
When executing query:
"""
$var=GO FROM "Tim Duncan" OVER like YIELD like._dst AS dst, $$.player.age AS age;
@@ -537,7 +537,7 @@ Feature: Basic Aggregate and GroupBy
Then a SemanticError should be raised at runtime: `COUNT(*)', not support aggregate function in go sentence.
When executing query:
"""
- GO FROM "Tim Duncan" OVER like where count(*) > 2
+ GO FROM "Tim Duncan" OVER like where COUNT(*) > 2
"""
Then a SemanticError should be raised at runtime: `(COUNT(*)>2)', not support aggregate function in where sentence.
When executing query:
@@ -585,7 +585,7 @@ Feature: Basic Aggregate and GroupBy
| GROUP BY $-.name
YIELD SUM(*)
"""
- Then a SemanticError should be raised at runtime: Could not apply aggregation function `SUM(*)' on `*`
+ Then a SyntaxError should be raised at runtime: Could not apply aggregation function on `*` near `SUM'
When executing query:
"""
GO FROM "Marco Belinelli" OVER serve
@@ -594,7 +594,7 @@ Feature: Basic Aggregate and GroupBy
| GROUP BY $-.name
YIELD COUNT($-.name, $-.id)
"""
- Then a SyntaxError should be raised at runtime: syntax error near `, $-.id)'
+ Then a SyntaxError should be raised at runtime: Unknown function near `COUNT'
When executing query:
"""
GO FROM "Marco Belinelli" OVER serve
diff --git a/tests/tck/features/go/GroupbyLimit.IntVid.feature b/tests/tck/features/go/GroupbyLimit.IntVid.feature
index 5bceeed297bcc490be6003d439f861e6224d5dc0..b6d95cf403bde21f54e696ec2ff40070950cfcd6 100644
--- a/tests/tck/features/go/GroupbyLimit.IntVid.feature
+++ b/tests/tck/features/go/GroupbyLimit.IntVid.feature
@@ -50,7 +50,7 @@ Feature: Groupby & limit Sentence
"""
GO FROM hash("Marco Belinelli") OVER serve YIELD $$.team.name AS name, serve._dst AS id | GROUP BY $-.name YIELD SUM(*)
"""
- Then a SemanticError should be raised at runtime:
+ Then a SyntaxError should be raised at runtime:
Scenario: Syntax test9
When executing query:
@@ -263,10 +263,10 @@ Feature: Groupby & limit Sentence
YIELD $$.player.name AS name, $$.player.age AS dst_age, $$.player.age AS src_age, like.likeness AS likeness
| GROUP BY $-.name YIELD $-.name AS name, SUM($-.dst_age) AS sum_dst_age, AVG($-.dst_age) AS avg_dst_age,
MAX($-.src_age) AS max_src_age, MIN($-.src_age) AS min_src_age, BIT_AND(1) AS bit_and, BIT_OR(2) AS bit_or, BIT_XOR(3) AS bit_xor,
- COUNT($-.likeness), COUNT_DISTINCT($-.likeness)
+ COUNT($-.likeness), COUNT(DISTINCT $-.likeness)
"""
Then the result should be, in any order, with relax comparison:
- | name | sum_dst_age | avg_dst_age | max_src_age | min_src_age | bit_and | bit_or | bit_xor | COUNT($-.likeness) | COUNT_DISTINCT($-.likeness) |
+ | name | sum_dst_age | avg_dst_age | max_src_age | min_src_age | bit_and | bit_or | bit_xor | COUNT($-.likeness) | COUNT(DISTINCT $-.likeness) |
| "Carmelo Anthony" | 34 | 34.0 | 34 | 34 | 1 | 2 | 3 | 1 | 1 |
| "Dwyane Wade" | 37 | 37.0 | 37 | 37 | 1 | 2 | 3 | 1 | 1 |
| "Chris Paul" | 66 | 33.0 | 33 | 33 | 1 | 2 | 0 | 2 | 1 |
diff --git a/tests/tck/features/go/GroupbyLimit.feature b/tests/tck/features/go/GroupbyLimit.feature
index fb2a65cb49150d885106af0841a63fb82ae33ecc..8bde7d5e409c054540625f48f17c95b686d1cdde 100644
--- a/tests/tck/features/go/GroupbyLimit.feature
+++ b/tests/tck/features/go/GroupbyLimit.feature
@@ -57,7 +57,7 @@ Feature: Groupby & limit Sentence
"""
GO FROM "Marco Belinelli" OVER serve YIELD $$.team.name AS name, serve._dst AS id | GROUP BY $-.name YIELD SUM(*)
"""
- Then a SemanticError should be raised at runtime:
+ Then a SyntaxError should be raised at runtime:
Scenario: Syntax test9
When executing query:
@@ -278,14 +278,14 @@ Feature: Groupby & limit Sentence
YIELD $$.player.name AS name, $$.player.age AS dst_age, $$.player.age AS src_age, like.likeness AS likeness
| GROUP BY $-.name YIELD $-.name AS name, SUM($-.dst_age) AS sum_dst_age, AVG($-.dst_age) AS avg_dst_age,
MAX($-.src_age) AS max_src_age, MIN($-.src_age) AS min_src_age, BIT_AND(1) AS bit_and, BIT_OR(2) AS bit_or, BIT_XOR(3) AS bit_xor,
- COUNT($-.likeness), COUNT_DISTINCT($-.likeness)
+ COUNT($-.likeness), COUNT(DISTINCT $-.likeness)
"""
Then the result should be, in any order, with relax comparison:
- | name | sum_dst_age | avg_dst_age | max_src_age | min_src_age | bit_and | bit_or | bit_xor | COUNT($-.likeness) | COUNT_DISTINCT($-.likeness) |
- | "Carmelo Anthony" | 34 | 34.0 | 34 | 34 | 1 | 2 | 3 | 1 | 1 |
- | "Dwyane Wade" | 37 | 37.0 | 37 | 37 | 1 | 2 | 3 | 1 | 1 |
- | "Chris Paul" | 66 | 33.0 | 33 | 33 | 1 | 2 | 0 | 2 | 1 |
- | "LeBron James" | 68 | 34.0 | 34 | 34 | 1 | 2 | 0 | 2 | 1 |
+ | name | sum_dst_age | avg_dst_age | max_src_age | min_src_age | bit_and | bit_or | bit_xor | COUNT($-.likeness) | COUNT(DINSTINCT $-.likeness) |
+ | "Carmelo Anthony" | 34 | 34.0 | 34 | 34 | 1 | 2 | 3 | 1 | 1 |
+ | "Dwyane Wade" | 37 | 37.0 | 37 | 37 | 1 | 2 | 3 | 1 | 1 |
+ | "Chris Paul" | 66 | 33.0 | 33 | 33 | 1 | 2 | 0 | 2 | 1 |
+ | "LeBron James" | 68 | 34.0 | 34 | 34 | 1 | 2 | 0 | 2 | 1 |
Scenario: Groupby works with orderby or limit test
When executing query:
diff --git a/tests/tck/features/match/MatchById.feature b/tests/tck/features/match/MatchById.feature
index b5bc328088de14cf811278be2477c49b8607834c..8216cadebb6c7f7793042acef38a4d8328b373d4 100644
--- a/tests/tck/features/match/MatchById.feature
+++ b/tests/tck/features/match/MatchById.feature
@@ -908,7 +908,7 @@ Feature: Match By Id
RETURN 1 | YIELD count(1)
"""
Then the result should be, in any order, with relax comparison:
- | COUNT(1) |
+ | count(1) |
| 292 |
When executing query:
"""
@@ -916,7 +916,7 @@ Feature: Match By Id
RETURN 1 | YIELD count(1)
"""
Then the result should be, in any order, with relax comparison:
- | COUNT(1) |
+ | count(1) |
| 927 |
Scenario: the referred vertex of id fn is not the first
diff --git a/tests/tck/features/match/WithUnwind.feature b/tests/tck/features/match/WithUnwind.feature
index 4fb1b9c591ec20ae3e8ee0b1c59b28d213d869a7..41812c09f6a562719c2b144540824bd3060bc3de 100644
--- a/tests/tck/features/match/WithUnwind.feature
+++ b/tests/tck/features/match/WithUnwind.feature
@@ -52,7 +52,7 @@ Feature: With clause and Unwind clause
RETURN count(a)
"""
Then the result should be, in any order:
- | COUNT(a) |
+ | count(a) |
| 1 |
Scenario: match with return