Compare commits
1 Commits
interleave
...
agg-prop-l
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5af23ee23 |
@@ -132,7 +132,7 @@ State HandlePullDiscardV4(TSession &session, const State state, const Marker mar
|
||||
return State::Close;
|
||||
}
|
||||
|
||||
if (state != State::Result && state != State::Idle) {
|
||||
if (state != State::Result) {
|
||||
if constexpr (is_pull) {
|
||||
spdlog::trace("Unexpected PULL!");
|
||||
} else {
|
||||
@@ -264,7 +264,7 @@ State HandleRunV4(TSession &session, const State state, const Marker marker) {
|
||||
return State::Close;
|
||||
}
|
||||
|
||||
if (state != State::Idle && state != State::Result) {
|
||||
if (state != State::Idle) {
|
||||
// Client could potentially recover if we move to error state, but there is
|
||||
// no legitimate situation in which well working client would end up in this
|
||||
// situation.
|
||||
|
||||
@@ -188,6 +188,8 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
|
||||
|
||||
utils::MemoryResource *GetMemoryResource() const { return ctx_->memory; }
|
||||
|
||||
void ClearPropertyLookupCache() { property_lookup_cache_.clear(); }
|
||||
|
||||
TypedValue Visit(NamedExpression &named_expression) override {
|
||||
const auto &symbol = symbol_table_->at(named_expression);
|
||||
auto value = named_expression.expression_->Accept(*this);
|
||||
|
||||
@@ -3678,13 +3678,14 @@ class AggregateCursor : public Cursor {
|
||||
for (; count_it != counts_end; ++count_it, ++value_it, ++unique_values_it, ++agg_elem_it) {
|
||||
// COUNT(*) is the only case where input expression is optional
|
||||
// handle it here
|
||||
auto input_expr_ptr = agg_elem_it->value;
|
||||
auto *input_expr_ptr = agg_elem_it->value;
|
||||
if (!input_expr_ptr) {
|
||||
*count_it += 1;
|
||||
// value is deferred to post-processing
|
||||
continue;
|
||||
}
|
||||
|
||||
evaluator->ClearPropertyLookupCache();
|
||||
TypedValue input_value = input_expr_ptr->Accept(*evaluator);
|
||||
|
||||
// Aggregations skip Null input values.
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
from typing import Set
|
||||
|
||||
import neo4j
|
||||
|
||||
MEMGRAPH_URL = "bolt://localhost:7687"
|
||||
|
||||
driver = neo4j.GraphDatabase.driver(MEMGRAPH_URL, auth=("", ""))
|
||||
|
||||
|
||||
def fill_db(tx):
|
||||
tx.run("UNWIND range(1, 2000) AS i CREATE (n:Node {id: i}) RETURN n")
|
||||
|
||||
|
||||
def run_queries(tx):
|
||||
tx.run("match (n) return n;") # A query that forces the result to have has_more=true
|
||||
tx.run("match (n) return n limit 1;") # Any query you can run
|
||||
|
||||
|
||||
with driver.session() as session:
|
||||
tx = session.begin_transaction()
|
||||
fill_db(tx)
|
||||
run_queries(tx)
|
||||
tx.commit()
|
||||
@@ -26,5 +26,4 @@ python3 max_query_length.py || exit 1
|
||||
python3 transactions.py || exit 1
|
||||
python3 path.py || exit 1
|
||||
python3 server_name.py || exit 1
|
||||
python3 explicit_tx_multiple_run.py || exit 1
|
||||
# python3 parallel_edge_import.py || exit 1
|
||||
|
||||
@@ -422,7 +422,24 @@ Feature: Aggregations
|
||||
CREATE (s:Subnet {ip: "192.168.0.1"})
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH (subnet:Subnet) WHERE FALSE WITH subnet, count(subnet.ip) as ips RETURN id(subnet) as id
|
||||
"""
|
||||
"""
|
||||
MATCH (subnet:Subnet) WHERE FALSE WITH subnet, count(subnet.ip) as ips RETURN id(subnet) as id
|
||||
"""
|
||||
Then the result should be empty
|
||||
|
||||
|
||||
Scenario: Collect nodes properties into a map:
|
||||
Given an empty graph
|
||||
And having executed
|
||||
"""
|
||||
CREATE (t:Tag {short_code: "TST", description: "SYSTEM_TAG"}), (t2:Tag {short_code: "PRD", description: "SYSTEM_TAG"}),
|
||||
(t3:Tag {short_code: "STG", description: "SYSTEM_TAG"}), (device {name: "name1"}), (device)-[a1:ASSOCIATED]->(t),
|
||||
(device)-[a2:ASSOCIATED]->(t2), (device)-[a3:ASSOCIATED]->(t3);
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH (d {name: "name1"})-[t:ASSOCIATED]-(tag:Tag) RETURN collect({short_code: tag.short_code, description: tag.description}) as tags;
|
||||
"""
|
||||
Then the result should be:
|
||||
| tags |
|
||||
| [{description: 'SYSTEM_TAG', short_code: 'TST'}, {description: 'SYSTEM_TAG', short_code: 'PRD'}, {description: 'SYSTEM_TAG', short_code: 'STG'}] |
|
||||
|
||||
@@ -426,3 +426,20 @@ Feature: Aggregations
|
||||
MATCH (subnet:Subnet) WHERE FALSE WITH subnet, count(subnet.ip) as ips RETURN id(subnet) as id
|
||||
"""
|
||||
Then the result should be empty
|
||||
|
||||
|
||||
Scenario: Collect nodes properties into a map:
|
||||
Given an empty graph
|
||||
And having executed
|
||||
"""
|
||||
CREATE (t:Tag {short_code: "TST", description: "SYSTEM_TAG"}), (t2:Tag {short_code: "PRD", description: "SYSTEM_TAG"}),
|
||||
(t3:Tag {short_code: "STG", description: "SYSTEM_TAG"}), (device {name: "name1"}), (device)-[a1:ASSOCIATED]->(t),
|
||||
(device)-[a2:ASSOCIATED]->(t2), (device)-[a3:ASSOCIATED]->(t3);
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH (d {name: "name1"})-[t:ASSOCIATED]-(tag:Tag) RETURN collect({short_code: tag.short_code, description: tag.description}) as tags;
|
||||
"""
|
||||
Then the result should be:
|
||||
| tags |
|
||||
| [{description: 'SYSTEM_TAG', short_code: 'TST'}, {description: 'SYSTEM_TAG', short_code: 'PRD'}, {description: 'SYSTEM_TAG', short_code: 'STG'}] |
|
||||
|
||||
@@ -177,8 +177,6 @@ inline constexpr uint8_t pullall_req[] = {0xb1, 0x3f, 0xa0};
|
||||
inline constexpr uint8_t pull_one_req[] = {0xb1, 0x3f, 0xa1, 0x81, 0x6e, 0x01};
|
||||
inline constexpr uint8_t reset_req[] = {0xb0, 0x0f};
|
||||
inline constexpr uint8_t goodbye[] = {0xb0, 0x02};
|
||||
inline constexpr uint8_t begin[] = {0xb1, 0x11, 0xa0};
|
||||
inline constexpr uint8_t commit[] = {0xb0, 0x12};
|
||||
inline constexpr uint8_t rollback[] = {0xb0, 0x13};
|
||||
} // namespace v4
|
||||
|
||||
@@ -210,6 +208,7 @@ constexpr std::string_view extra_w_127ms_timeout =
|
||||
"\x8a\x74\x78\x5F\x74\x69\x6D\x65\x6F\x75\x74" // String size 10 "tx_timeout"
|
||||
"\x7f"; // Integer 127 (representing 127ms)
|
||||
|
||||
inline constexpr uint8_t commit[] = {0xb0, 0x12};
|
||||
} // namespace v4_3
|
||||
|
||||
// Write bolt chunk header (length)
|
||||
@@ -281,21 +280,6 @@ void ExecuteInit(TestInputStream &input_stream, TestSession &session, std::vecto
|
||||
CheckOutput(output, response, 28);
|
||||
}
|
||||
|
||||
void ExecuteBeginTransaction(TestInputStream &input_stream, TestSession &session, std::vector<uint8_t> &output) {
|
||||
const auto *request = v4::begin;
|
||||
const auto request_size = sizeof(v4::begin);
|
||||
ExecuteCommand(input_stream, session, request, request_size);
|
||||
}
|
||||
|
||||
void ExecuteCommitTransaction(TestInputStream &input_stream, TestSession &session, std::vector<uint8_t> &output) {
|
||||
const auto *request = v4::commit;
|
||||
const auto request_size = sizeof(v4::commit);
|
||||
ExecuteCommand(input_stream, session, request, request_size);
|
||||
ASSERT_EQ(session.state_, State::Idle);
|
||||
PrintOutput(output);
|
||||
CheckSuccessMessage(output);
|
||||
}
|
||||
|
||||
// Write bolt encoded run request
|
||||
void WriteRunRequest(TestInputStream &input_stream, const char *str, const bool is_v4 = false,
|
||||
std::string_view extra = "\xA0") {
|
||||
@@ -1244,81 +1228,3 @@ TEST(BoltSession, PartialStream) {
|
||||
EXPECT_NE(find_msg, cend(output));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BoltSession, ExplicitTxBeginAndCommit) {
|
||||
{
|
||||
INIT_VARS;
|
||||
|
||||
ExecuteHandshake(input_stream, session, output, v4_3::handshake_req, v4_3::handshake_resp);
|
||||
ExecuteInit(input_stream, session, output, true);
|
||||
ExecuteBeginTransaction(input_stream, session, output);
|
||||
ExecuteCommitTransaction(input_stream, session, output);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BoltSession, ExplicitTxBeginRunPullCommit) {
|
||||
{
|
||||
INIT_VARS;
|
||||
|
||||
ExecuteHandshake(input_stream, session, output, v4_3::handshake_req, v4_3::handshake_resp);
|
||||
ExecuteInit(input_stream, session, output, true);
|
||||
ExecuteBeginTransaction(input_stream, session, output);
|
||||
WriteRunRequest(input_stream, kQueryReturn42, true, v4_3::extra_w_metadata);
|
||||
session.Execute();
|
||||
ASSERT_EQ(session.state_, State::Result);
|
||||
ExecuteCommand(input_stream, session, v4::pull_one_req, sizeof(v4::pull_one_req));
|
||||
ASSERT_EQ(session.state_, State::Idle);
|
||||
ExecuteCommitTransaction(input_stream, session, output);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BoltSession, ExplicitTxBeginRunPullAllCommit) {
|
||||
{
|
||||
INIT_VARS;
|
||||
|
||||
ExecuteHandshake(input_stream, session, output, v4_3::handshake_req, v4_3::handshake_resp);
|
||||
ExecuteInit(input_stream, session, output, true);
|
||||
ExecuteBeginTransaction(input_stream, session, output);
|
||||
|
||||
WriteRunRequest(input_stream, kQueryReturn42, true, v4_3::extra_w_metadata);
|
||||
session.Execute();
|
||||
ASSERT_EQ(session.state_, State::Result);
|
||||
ExecuteCommand(input_stream, session, v4::pull_one_req, sizeof(v4::pull_one_req));
|
||||
ASSERT_EQ(session.state_, State::Idle);
|
||||
|
||||
WriteRunRequest(input_stream, kQueryReturnMultiple, true, v4_3::extra_w_metadata);
|
||||
session.Execute();
|
||||
ASSERT_EQ(session.state_, State::Result);
|
||||
ExecuteCommand(input_stream, session, v4::pullall_req, sizeof(v4::pullall_req));
|
||||
ASSERT_EQ(session.state_, State::Idle);
|
||||
constexpr std::array<uint8_t, 10> md_has_more_true{0x88, 0x68, 0x61, 0x73, 0x5F, 0x6D, 0x6F, 0x72, 0x65, 0xC3};
|
||||
auto find_has_more = std::search(cbegin(output), cend(output), cbegin(md_has_more_true), cend(md_has_more_true));
|
||||
EXPECT_EQ(find_has_more, cend(output));
|
||||
|
||||
ExecuteCommitTransaction(input_stream, session, output);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BoltSession, ExplicitTxBeginRunRunPullAllCommit) {
|
||||
{
|
||||
INIT_VARS;
|
||||
|
||||
ExecuteHandshake(input_stream, session, output, v4_3::handshake_req, v4_3::handshake_resp);
|
||||
ExecuteInit(input_stream, session, output, true);
|
||||
ExecuteBeginTransaction(input_stream, session, output);
|
||||
|
||||
WriteRunRequest(input_stream, kQueryReturn42, true, v4_3::extra_w_metadata);
|
||||
session.Execute();
|
||||
ASSERT_EQ(session.state_, State::Result);
|
||||
WriteRunRequest(input_stream, kQueryReturnMultiple, true, v4_3::extra_w_metadata);
|
||||
session.Execute();
|
||||
ASSERT_EQ(session.state_, State::Result);
|
||||
ExecuteCommand(input_stream, session, v4::pull_one_req, sizeof(v4::pullall_req));
|
||||
ASSERT_EQ(session.state_, State::Idle);
|
||||
constexpr std::array<uint8_t, 10> md_has_more_true{0x88, 0x68, 0x61, 0x73, 0x5F, 0x6D, 0x6F, 0x72, 0x65, 0xC3};
|
||||
auto find_has_more = std::search(cbegin(output), cend(output), cbegin(md_has_more_true), cend(md_has_more_true));
|
||||
EXPECT_EQ(find_has_more, cend(output));
|
||||
|
||||
ExecuteCommitTransaction(input_stream, session, output);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user