Correctly prepare Explain and Profile

Summary: Also test Explain and Profile through Intepreter.

Reviewers: mferencevic

Reviewed By: mferencevic

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D2546
This commit is contained in:
Teon Banek 2019-11-12 15:58:05 +01:00
parent 329818b1b0
commit b4df6ba0a9
2 changed files with 108 additions and 7 deletions

View File

@ -696,9 +696,9 @@ PreparedQuery PrepareExplainQuery(
<< "Cypher grammar should not allow other queries in EXPLAIN";
auto cypher_query_plan = CypherQueryToPlan(
parsed_query.stripped_query.hash(), std::move(parsed_query.ast_storage),
utils::Downcast<CypherQuery>(parsed_query.query), parsed_query.parameters,
&interpreter_context->plan_cache, dba);
parsed_inner_query.stripped_query.hash(),
std::move(parsed_inner_query.ast_storage), cypher_query,
parsed_inner_query.parameters, &interpreter_context->plan_cache, dba);
std::stringstream printed_plan;
plan::PrettyPrint(*dba, &cypher_query_plan->plan(), &printed_plan);
@ -739,7 +739,7 @@ PreparedQuery PrepareProfileQuery(
throw ProfileInMulticommandTxException();
}
if (interpreter_context->is_tsc_available) {
if (!interpreter_context->is_tsc_available) {
throw QueryException("TSC support is missing for PROFILE");
}
@ -759,9 +759,9 @@ PreparedQuery PrepareProfileQuery(
<< "Cypher grammar should not allow other queries in PROFILE";
auto cypher_query_plan = CypherQueryToPlan(
parsed_query.stripped_query.hash(), std::move(parsed_query.ast_storage),
utils::Downcast<CypherQuery>(parsed_query.query), parsed_query.parameters,
&interpreter_context->plan_cache, dba);
parsed_inner_query.stripped_query.hash(),
std::move(parsed_inner_query.ast_storage), cypher_query,
parsed_inner_query.parameters, &interpreter_context->plan_cache, dba);
return PreparedQuery{
{"OPERATOR", "ACTUAL HITS", "RELATIVE TIME", "ABSOLUTE TIME"},

View File

@ -329,3 +329,104 @@ TEST_F(InterpreterTest, UniqueConstraintTest) {
Interpret("MATCH (n:A{a:2, b:2}) DETACH DELETE n");
Interpret("CREATE (n:A{a:2, b:2})");
}
TEST_F(InterpreterTest, ExplainQuery) {
EXPECT_EQ(interpreter_context_.plan_cache.size(), 0U);
EXPECT_EQ(interpreter_context_.ast_cache.size(), 0U);
auto stream = Interpret("EXPLAIN MATCH (n) RETURN *;");
ASSERT_EQ(stream.GetHeader().size(), 1U);
EXPECT_EQ(stream.GetHeader().front(), "QUERY PLAN");
std::vector<std::string> expected_rows{" * Produce {n}", " * ScanAll (n)",
" * Once"};
ASSERT_EQ(stream.GetResults().size(), expected_rows.size());
auto expected_it = expected_rows.begin();
for (const auto &row : stream.GetResults()) {
ASSERT_EQ(row.size(), 1U);
EXPECT_EQ(row.front().ValueString(), *expected_it);
++expected_it;
}
// We should have a plan cache for MATCH ...
EXPECT_EQ(interpreter_context_.plan_cache.size(), 1U);
// We should have AST cache for EXPLAIN ... and for inner MATCH ...
EXPECT_EQ(interpreter_context_.ast_cache.size(), 2U);
Interpret("MATCH (n) RETURN *;");
EXPECT_EQ(interpreter_context_.plan_cache.size(), 1U);
EXPECT_EQ(interpreter_context_.ast_cache.size(), 2U);
}
TEST_F(InterpreterTest, ExplainQueryWithParams) {
EXPECT_EQ(interpreter_context_.plan_cache.size(), 0U);
EXPECT_EQ(interpreter_context_.ast_cache.size(), 0U);
auto stream = Interpret("EXPLAIN MATCH (n) WHERE n.id = $id RETURN *;",
{{"id", PropertyValue(42)}});
ASSERT_EQ(stream.GetHeader().size(), 1U);
EXPECT_EQ(stream.GetHeader().front(), "QUERY PLAN");
std::vector<std::string> expected_rows{" * Produce {n}", " * Filter",
" * ScanAll (n)", " * Once"};
ASSERT_EQ(stream.GetResults().size(), expected_rows.size());
auto expected_it = expected_rows.begin();
for (const auto &row : stream.GetResults()) {
ASSERT_EQ(row.size(), 1U);
EXPECT_EQ(row.front().ValueString(), *expected_it);
++expected_it;
}
// We should have a plan cache for MATCH ...
EXPECT_EQ(interpreter_context_.plan_cache.size(), 1U);
// We should have AST cache for EXPLAIN ... and for inner MATCH ...
EXPECT_EQ(interpreter_context_.ast_cache.size(), 2U);
Interpret("MATCH (n) WHERE n.id = $id RETURN *;",
{{"id", PropertyValue("something else")}});
EXPECT_EQ(interpreter_context_.plan_cache.size(), 1U);
EXPECT_EQ(interpreter_context_.ast_cache.size(), 2U);
}
TEST_F(InterpreterTest, ProfileQuery) {
EXPECT_EQ(interpreter_context_.plan_cache.size(), 0U);
EXPECT_EQ(interpreter_context_.ast_cache.size(), 0U);
auto stream = Interpret("PROFILE MATCH (n) RETURN *;");
std::vector<std::string> expected_header{"OPERATOR", "ACTUAL HITS",
"RELATIVE TIME", "ABSOLUTE TIME"};
EXPECT_EQ(stream.GetHeader(), expected_header);
std::vector<std::string> expected_rows{"* Produce", "* ScanAll", "* Once"};
ASSERT_EQ(stream.GetResults().size(), expected_rows.size());
auto expected_it = expected_rows.begin();
for (const auto &row : stream.GetResults()) {
ASSERT_EQ(row.size(), 4U);
EXPECT_EQ(row.front().ValueString(), *expected_it);
++expected_it;
}
// We should have a plan cache for MATCH ...
EXPECT_EQ(interpreter_context_.plan_cache.size(), 1U);
// We should have AST cache for PROFILE ... and for inner MATCH ...
EXPECT_EQ(interpreter_context_.ast_cache.size(), 2U);
Interpret("MATCH (n) RETURN *;");
EXPECT_EQ(interpreter_context_.plan_cache.size(), 1U);
EXPECT_EQ(interpreter_context_.ast_cache.size(), 2U);
}
TEST_F(InterpreterTest, ProfileQueryWithParams) {
EXPECT_EQ(interpreter_context_.plan_cache.size(), 0U);
EXPECT_EQ(interpreter_context_.ast_cache.size(), 0U);
auto stream = Interpret("PROFILE MATCH (n) WHERE n.id = $id RETURN *;",
{{"id", PropertyValue(42)}});
std::vector<std::string> expected_header{"OPERATOR", "ACTUAL HITS",
"RELATIVE TIME", "ABSOLUTE TIME"};
EXPECT_EQ(stream.GetHeader(), expected_header);
std::vector<std::string> expected_rows{"* Produce", "* Filter", "* ScanAll",
"* Once"};
ASSERT_EQ(stream.GetResults().size(), expected_rows.size());
auto expected_it = expected_rows.begin();
for (const auto &row : stream.GetResults()) {
ASSERT_EQ(row.size(), 4U);
EXPECT_EQ(row.front().ValueString(), *expected_it);
++expected_it;
}
// We should have a plan cache for MATCH ...
EXPECT_EQ(interpreter_context_.plan_cache.size(), 1U);
// We should have AST cache for PROFILE ... and for inner MATCH ...
EXPECT_EQ(interpreter_context_.ast_cache.size(), 2U);
Interpret("MATCH (n) WHERE n.id = $id RETURN *;",
{{"id", PropertyValue("something else")}});
EXPECT_EQ(interpreter_context_.plan_cache.size(), 1U);
EXPECT_EQ(interpreter_context_.ast_cache.size(), 2U);
}