Add memory limit clause for cypher queries (#106)
* Add memory limit clause for cypher queries * Add PROCEDURE and QUERY keywords * Improve memory limit logs * Update CHANGELOG
This commit is contained in:
committed by
Antonio Andelic
parent
9c6bf4b1b8
commit
ad4c80af13
@@ -18,6 +18,7 @@
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "query/exceptions.hpp"
|
||||
#include "query/frontend/ast/ast.hpp"
|
||||
#include "query/frontend/ast/cypher_main_visitor.hpp"
|
||||
#include "query/frontend/opencypher/parser.hpp"
|
||||
@@ -2730,7 +2731,8 @@ TEST_P(CypherMainVisitorTest, CallWithoutYield) {
|
||||
|
||||
TEST_P(CypherMainVisitorTest, CallWithMemoryLimitWithoutYield) {
|
||||
auto &ast_generator = *GetParam();
|
||||
auto *query = dynamic_cast<CypherQuery *>(ast_generator.ParseQuery("CALL mg.load_all() MEMORY LIMIT 32 KB"));
|
||||
auto *query =
|
||||
dynamic_cast<CypherQuery *>(ast_generator.ParseQuery("CALL mg.load_all() PROCEDURE MEMORY LIMIT 32 KB"));
|
||||
ASSERT_TRUE(query);
|
||||
ASSERT_TRUE(query->single_query_);
|
||||
auto *single_query = query->single_query_;
|
||||
@@ -2747,7 +2749,7 @@ TEST_P(CypherMainVisitorTest, CallWithMemoryLimitWithoutYield) {
|
||||
|
||||
TEST_P(CypherMainVisitorTest, CallWithMemoryUnlimitedWithoutYield) {
|
||||
auto &ast_generator = *GetParam();
|
||||
auto *query = dynamic_cast<CypherQuery *>(ast_generator.ParseQuery("CALL mg.load_all() MEMORY UNLIMITED"));
|
||||
auto *query = dynamic_cast<CypherQuery *>(ast_generator.ParseQuery("CALL mg.load_all() PROCEDURE MEMORY UNLIMITED"));
|
||||
ASSERT_TRUE(query);
|
||||
ASSERT_TRUE(query->single_query_);
|
||||
auto *single_query = query->single_query_;
|
||||
@@ -2763,8 +2765,8 @@ TEST_P(CypherMainVisitorTest, CallWithMemoryUnlimitedWithoutYield) {
|
||||
|
||||
TEST_P(CypherMainVisitorTest, CallProcedureWithMemoryLimit) {
|
||||
auto &ast_generator = *GetParam();
|
||||
auto *query =
|
||||
dynamic_cast<CypherQuery *>(ast_generator.ParseQuery("CALL proc.with.dots() MEMORY LIMIT 32 MB YIELD res"));
|
||||
auto *query = dynamic_cast<CypherQuery *>(
|
||||
ast_generator.ParseQuery("CALL proc.with.dots() PROCEDURE MEMORY LIMIT 32 MB YIELD res"));
|
||||
ASSERT_TRUE(query);
|
||||
ASSERT_TRUE(query->single_query_);
|
||||
auto *single_query = query->single_query_;
|
||||
@@ -2788,8 +2790,8 @@ TEST_P(CypherMainVisitorTest, CallProcedureWithMemoryLimit) {
|
||||
|
||||
TEST_P(CypherMainVisitorTest, CallProcedureWithMemoryUnlimited) {
|
||||
auto &ast_generator = *GetParam();
|
||||
auto *query =
|
||||
dynamic_cast<CypherQuery *>(ast_generator.ParseQuery("CALL proc.with.dots() MEMORY UNLIMITED YIELD res"));
|
||||
auto *query = dynamic_cast<CypherQuery *>(
|
||||
ast_generator.ParseQuery("CALL proc.with.dots() PROCEDURE MEMORY UNLIMITED YIELD res"));
|
||||
ASSERT_TRUE(query);
|
||||
ASSERT_TRUE(query->single_query_);
|
||||
auto *single_query = query->single_query_;
|
||||
@@ -2822,12 +2824,10 @@ TEST_P(CypherMainVisitorTest, IncorrectCallProcedure) {
|
||||
ASSERT_THROW(ast_generator.ParseQuery("RETURN 42, CALL procedure() YIELD"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("RETURN 42, CALL procedure() YIELD res"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("RETURN 42 AS x CALL procedure() YIELD res"), SemanticException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CALL proc.with.dots() YIELD res MEMORY UNLIMITED"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CALL proc.with.dots() YIELD res MEMORY LIMIT 32 KB"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CALL proc.with.dots() MEMORY YIELD res"), SyntaxException);
|
||||
// mg.procedures returns something, so it needs to have a YIELD.
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CALL mg.procedures()"), SemanticException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CALL mg.procedures() MEMORY UNLIMITED"), SemanticException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CALL mg.procedures() PROCEDURE MEMORY UNLIMITED"), SemanticException);
|
||||
// TODO: Implement support for the following syntax. These are defined in
|
||||
// Neo4j and accepted in openCypher CIP.
|
||||
ASSERT_THROW(ast_generator.ParseQuery("CALL proc"), SyntaxException);
|
||||
@@ -2935,4 +2935,115 @@ TEST_P(CypherMainVisitorTest, TestLoadCsvClause) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(CypherMainVisitorTest, MemoryLimit) {
|
||||
auto &ast_generator = *GetParam();
|
||||
|
||||
ASSERT_THROW(ast_generator.ParseQuery("RETURN x QUE"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("RETURN x QUERY"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("RETURN x QUERY MEM"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("RETURN x QUERY MEMORY"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("RETURN x QUERY MEMORY LIM"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("RETURN x QUERY MEMORY LIMIT"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("RETURN x QUERY MEMORY LIMIT KB"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("RETURN x QUERY MEMORY LIMIT 12GB"), SyntaxException);
|
||||
ASSERT_THROW(ast_generator.ParseQuery("QUERY MEMORY LIMIT 12KB RETURN x"), SyntaxException);
|
||||
|
||||
{
|
||||
auto *query = dynamic_cast<CypherQuery *>(ast_generator.ParseQuery("RETURN x"));
|
||||
ASSERT_TRUE(query);
|
||||
ASSERT_FALSE(query->memory_limit_);
|
||||
}
|
||||
|
||||
{
|
||||
auto *query = dynamic_cast<CypherQuery *>(ast_generator.ParseQuery("RETURN x QUERY MEMORY LIMIT 12KB"));
|
||||
ASSERT_TRUE(query);
|
||||
ASSERT_TRUE(query->memory_limit_);
|
||||
ast_generator.CheckLiteral(query->memory_limit_, 12);
|
||||
ASSERT_EQ(query->memory_scale_, 1024U);
|
||||
}
|
||||
|
||||
{
|
||||
auto *query = dynamic_cast<CypherQuery *>(ast_generator.ParseQuery("RETURN x QUERY MEMORY LIMIT 12MB"));
|
||||
ASSERT_TRUE(query);
|
||||
ASSERT_TRUE(query->memory_limit_);
|
||||
ast_generator.CheckLiteral(query->memory_limit_, 12);
|
||||
ASSERT_EQ(query->memory_scale_, 1024U * 1024U);
|
||||
}
|
||||
|
||||
{
|
||||
auto *query = dynamic_cast<CypherQuery *>(
|
||||
ast_generator.ParseQuery("CALL mg.procedures() YIELD x RETURN x QUERY MEMORY LIMIT 12MB"));
|
||||
ASSERT_TRUE(query);
|
||||
ASSERT_TRUE(query->memory_limit_);
|
||||
ast_generator.CheckLiteral(query->memory_limit_, 12);
|
||||
ASSERT_EQ(query->memory_scale_, 1024U * 1024U);
|
||||
|
||||
ASSERT_TRUE(query->single_query_);
|
||||
auto *single_query = query->single_query_;
|
||||
ASSERT_EQ(single_query->clauses_.size(), 2U);
|
||||
auto *call_proc = dynamic_cast<CallProcedure *>(single_query->clauses_[0]);
|
||||
CheckCallProcedureDefaultMemoryLimit(ast_generator, *call_proc);
|
||||
}
|
||||
|
||||
{
|
||||
auto *query = dynamic_cast<CypherQuery *>(ast_generator.ParseQuery(
|
||||
"CALL mg.procedures() PROCEDURE MEMORY LIMIT 3KB YIELD x RETURN x QUERY MEMORY LIMIT 12MB"));
|
||||
ASSERT_TRUE(query);
|
||||
ASSERT_TRUE(query->memory_limit_);
|
||||
ast_generator.CheckLiteral(query->memory_limit_, 12);
|
||||
ASSERT_EQ(query->memory_scale_, 1024U * 1024U);
|
||||
|
||||
ASSERT_TRUE(query->single_query_);
|
||||
auto *single_query = query->single_query_;
|
||||
ASSERT_EQ(single_query->clauses_.size(), 2U);
|
||||
auto *call_proc = dynamic_cast<CallProcedure *>(single_query->clauses_[0]);
|
||||
ASSERT_TRUE(call_proc->memory_limit_);
|
||||
ast_generator.CheckLiteral(call_proc->memory_limit_, 3);
|
||||
ASSERT_EQ(call_proc->memory_scale_, 1024U);
|
||||
}
|
||||
|
||||
{
|
||||
auto *query = dynamic_cast<CypherQuery *>(
|
||||
ast_generator.ParseQuery("CALL mg.procedures() PROCEDURE MEMORY LIMIT 3KB YIELD x RETURN x"));
|
||||
ASSERT_TRUE(query);
|
||||
ASSERT_FALSE(query->memory_limit_);
|
||||
|
||||
ASSERT_TRUE(query->single_query_);
|
||||
auto *single_query = query->single_query_;
|
||||
ASSERT_EQ(single_query->clauses_.size(), 2U);
|
||||
auto *call_proc = dynamic_cast<CallProcedure *>(single_query->clauses_[0]);
|
||||
ASSERT_TRUE(call_proc->memory_limit_);
|
||||
ast_generator.CheckLiteral(call_proc->memory_limit_, 3);
|
||||
ASSERT_EQ(call_proc->memory_scale_, 1024U);
|
||||
}
|
||||
|
||||
{
|
||||
auto *query =
|
||||
dynamic_cast<CypherQuery *>(ast_generator.ParseQuery("CALL mg.load_all() PROCEDURE MEMORY LIMIT 3KB"));
|
||||
ASSERT_TRUE(query);
|
||||
ASSERT_FALSE(query->memory_limit_);
|
||||
|
||||
ASSERT_TRUE(query->single_query_);
|
||||
auto *single_query = query->single_query_;
|
||||
ASSERT_EQ(single_query->clauses_.size(), 1U);
|
||||
auto *call_proc = dynamic_cast<CallProcedure *>(single_query->clauses_[0]);
|
||||
ASSERT_TRUE(call_proc->memory_limit_);
|
||||
ast_generator.CheckLiteral(call_proc->memory_limit_, 3);
|
||||
ASSERT_EQ(call_proc->memory_scale_, 1024U);
|
||||
}
|
||||
|
||||
{
|
||||
auto *query = dynamic_cast<CypherQuery *>(ast_generator.ParseQuery("CALL mg.load_all() QUERY MEMORY LIMIT 3KB"));
|
||||
ASSERT_TRUE(query);
|
||||
ASSERT_TRUE(query->memory_limit_);
|
||||
ast_generator.CheckLiteral(query->memory_limit_, 3);
|
||||
ASSERT_EQ(query->memory_scale_, 1024U);
|
||||
|
||||
ASSERT_TRUE(query->single_query_);
|
||||
auto *single_query = query->single_query_;
|
||||
ASSERT_EQ(single_query->clauses_.size(), 1U);
|
||||
auto *call_proc = dynamic_cast<CallProcedure *>(single_query->clauses_[0]);
|
||||
CheckCallProcedureDefaultMemoryLimit(ast_generator, *call_proc);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user