2017-04-18 21:19:42 +08:00
|
|
|
//
|
|
|
|
// Copyright 2017 Memgraph
|
|
|
|
// Created by Florijan Stamenkovic on 14.03.17.
|
|
|
|
//
|
|
|
|
|
2017-04-20 19:31:18 +08:00
|
|
|
#include <algorithm>
|
2017-04-18 21:19:42 +08:00
|
|
|
#include <iterator>
|
|
|
|
#include <memory>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include "gmock/gmock.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
|
|
|
#include "communication/result_stream_faker.hpp"
|
|
|
|
#include "query/context.hpp"
|
|
|
|
#include "query/exceptions.hpp"
|
|
|
|
#include "query/plan/operator.hpp"
|
|
|
|
|
|
|
|
#include "query_plan_common.hpp"
|
|
|
|
|
|
|
|
using namespace query;
|
|
|
|
using namespace query::plan;
|
|
|
|
|
|
|
|
TEST(QueryPlan, Skip) {
|
2018-10-09 17:09:10 +08:00
|
|
|
database::GraphDb db;
|
2018-07-26 15:08:21 +08:00
|
|
|
auto dba = db.Access();
|
2017-04-18 21:19:42 +08:00
|
|
|
|
2018-05-22 22:45:52 +08:00
|
|
|
AstStorage storage;
|
2017-04-18 21:19:42 +08:00
|
|
|
SymbolTable symbol_table;
|
|
|
|
|
|
|
|
auto n = MakeScanAll(storage, symbol_table, "n1");
|
|
|
|
auto skip = std::make_shared<plan::Skip>(n.op_, LITERAL(2));
|
|
|
|
|
2019-01-16 18:30:17 +08:00
|
|
|
auto context = MakeContext(storage, symbol_table, dba.get());
|
Remove GraphDbAccessor and storage types from Ast
Summary:
This diff removes the need for a database when parsing a query and
creating an Ast. Instead of storing storage::{Label,Property,EdgeType}
in Ast nodes, we store the name and an index into all of the names. This
allows for easy creation of a map from {Label,Property,EdgeType} index
into the concrete storage type. Obviously, this comes with a performance
penalty during execution, but it should be minor. The upside is that the
query/frontend minimally depends on storage (PropertyValue), which makes
writing tests easier as well as running them a lot faster (there is no
database setup). This is most noticeable in the ast_serialization test
which took a long time due to start up of a distributed database.
Reviewers: mtomic, llugovic
Reviewed By: mtomic
Subscribers: mferencevic, pullbot
Differential Revision: https://phabricator.memgraph.io/D1774
2019-01-14 21:41:37 +08:00
|
|
|
EXPECT_EQ(0, PullAll(*skip, &context));
|
2017-04-18 21:19:42 +08:00
|
|
|
|
2018-07-26 15:08:21 +08:00
|
|
|
dba->InsertVertex();
|
|
|
|
dba->AdvanceCommand();
|
Remove GraphDbAccessor and storage types from Ast
Summary:
This diff removes the need for a database when parsing a query and
creating an Ast. Instead of storing storage::{Label,Property,EdgeType}
in Ast nodes, we store the name and an index into all of the names. This
allows for easy creation of a map from {Label,Property,EdgeType} index
into the concrete storage type. Obviously, this comes with a performance
penalty during execution, but it should be minor. The upside is that the
query/frontend minimally depends on storage (PropertyValue), which makes
writing tests easier as well as running them a lot faster (there is no
database setup). This is most noticeable in the ast_serialization test
which took a long time due to start up of a distributed database.
Reviewers: mtomic, llugovic
Reviewed By: mtomic
Subscribers: mferencevic, pullbot
Differential Revision: https://phabricator.memgraph.io/D1774
2019-01-14 21:41:37 +08:00
|
|
|
EXPECT_EQ(0, PullAll(*skip, &context));
|
2017-04-18 21:19:42 +08:00
|
|
|
|
2018-07-26 15:08:21 +08:00
|
|
|
dba->InsertVertex();
|
|
|
|
dba->AdvanceCommand();
|
Remove GraphDbAccessor and storage types from Ast
Summary:
This diff removes the need for a database when parsing a query and
creating an Ast. Instead of storing storage::{Label,Property,EdgeType}
in Ast nodes, we store the name and an index into all of the names. This
allows for easy creation of a map from {Label,Property,EdgeType} index
into the concrete storage type. Obviously, this comes with a performance
penalty during execution, but it should be minor. The upside is that the
query/frontend minimally depends on storage (PropertyValue), which makes
writing tests easier as well as running them a lot faster (there is no
database setup). This is most noticeable in the ast_serialization test
which took a long time due to start up of a distributed database.
Reviewers: mtomic, llugovic
Reviewed By: mtomic
Subscribers: mferencevic, pullbot
Differential Revision: https://phabricator.memgraph.io/D1774
2019-01-14 21:41:37 +08:00
|
|
|
EXPECT_EQ(0, PullAll(*skip, &context));
|
2017-04-18 21:19:42 +08:00
|
|
|
|
2018-07-26 15:08:21 +08:00
|
|
|
dba->InsertVertex();
|
|
|
|
dba->AdvanceCommand();
|
Remove GraphDbAccessor and storage types from Ast
Summary:
This diff removes the need for a database when parsing a query and
creating an Ast. Instead of storing storage::{Label,Property,EdgeType}
in Ast nodes, we store the name and an index into all of the names. This
allows for easy creation of a map from {Label,Property,EdgeType} index
into the concrete storage type. Obviously, this comes with a performance
penalty during execution, but it should be minor. The upside is that the
query/frontend minimally depends on storage (PropertyValue), which makes
writing tests easier as well as running them a lot faster (there is no
database setup). This is most noticeable in the ast_serialization test
which took a long time due to start up of a distributed database.
Reviewers: mtomic, llugovic
Reviewed By: mtomic
Subscribers: mferencevic, pullbot
Differential Revision: https://phabricator.memgraph.io/D1774
2019-01-14 21:41:37 +08:00
|
|
|
EXPECT_EQ(1, PullAll(*skip, &context));
|
2017-04-18 21:19:42 +08:00
|
|
|
|
2018-07-26 15:08:21 +08:00
|
|
|
for (int i = 0; i < 10; ++i) dba->InsertVertex();
|
|
|
|
dba->AdvanceCommand();
|
Remove GraphDbAccessor and storage types from Ast
Summary:
This diff removes the need for a database when parsing a query and
creating an Ast. Instead of storing storage::{Label,Property,EdgeType}
in Ast nodes, we store the name and an index into all of the names. This
allows for easy creation of a map from {Label,Property,EdgeType} index
into the concrete storage type. Obviously, this comes with a performance
penalty during execution, but it should be minor. The upside is that the
query/frontend minimally depends on storage (PropertyValue), which makes
writing tests easier as well as running them a lot faster (there is no
database setup). This is most noticeable in the ast_serialization test
which took a long time due to start up of a distributed database.
Reviewers: mtomic, llugovic
Reviewed By: mtomic
Subscribers: mferencevic, pullbot
Differential Revision: https://phabricator.memgraph.io/D1774
2019-01-14 21:41:37 +08:00
|
|
|
EXPECT_EQ(11, PullAll(*skip, &context));
|
2017-04-18 21:19:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(QueryPlan, Limit) {
|
2018-10-09 17:09:10 +08:00
|
|
|
database::GraphDb db;
|
2018-07-26 15:08:21 +08:00
|
|
|
auto dba = db.Access();
|
2017-04-18 21:19:42 +08:00
|
|
|
|
2018-05-22 22:45:52 +08:00
|
|
|
AstStorage storage;
|
2017-04-18 21:19:42 +08:00
|
|
|
SymbolTable symbol_table;
|
|
|
|
|
|
|
|
auto n = MakeScanAll(storage, symbol_table, "n1");
|
|
|
|
auto skip = std::make_shared<plan::Limit>(n.op_, LITERAL(2));
|
|
|
|
|
2019-01-16 18:30:17 +08:00
|
|
|
auto context = MakeContext(storage, symbol_table, dba.get());
|
Remove GraphDbAccessor and storage types from Ast
Summary:
This diff removes the need for a database when parsing a query and
creating an Ast. Instead of storing storage::{Label,Property,EdgeType}
in Ast nodes, we store the name and an index into all of the names. This
allows for easy creation of a map from {Label,Property,EdgeType} index
into the concrete storage type. Obviously, this comes with a performance
penalty during execution, but it should be minor. The upside is that the
query/frontend minimally depends on storage (PropertyValue), which makes
writing tests easier as well as running them a lot faster (there is no
database setup). This is most noticeable in the ast_serialization test
which took a long time due to start up of a distributed database.
Reviewers: mtomic, llugovic
Reviewed By: mtomic
Subscribers: mferencevic, pullbot
Differential Revision: https://phabricator.memgraph.io/D1774
2019-01-14 21:41:37 +08:00
|
|
|
EXPECT_EQ(0, PullAll(*skip, &context));
|
2017-04-18 21:19:42 +08:00
|
|
|
|
2018-07-26 15:08:21 +08:00
|
|
|
dba->InsertVertex();
|
|
|
|
dba->AdvanceCommand();
|
Remove GraphDbAccessor and storage types from Ast
Summary:
This diff removes the need for a database when parsing a query and
creating an Ast. Instead of storing storage::{Label,Property,EdgeType}
in Ast nodes, we store the name and an index into all of the names. This
allows for easy creation of a map from {Label,Property,EdgeType} index
into the concrete storage type. Obviously, this comes with a performance
penalty during execution, but it should be minor. The upside is that the
query/frontend minimally depends on storage (PropertyValue), which makes
writing tests easier as well as running them a lot faster (there is no
database setup). This is most noticeable in the ast_serialization test
which took a long time due to start up of a distributed database.
Reviewers: mtomic, llugovic
Reviewed By: mtomic
Subscribers: mferencevic, pullbot
Differential Revision: https://phabricator.memgraph.io/D1774
2019-01-14 21:41:37 +08:00
|
|
|
EXPECT_EQ(1, PullAll(*skip, &context));
|
2017-04-18 21:19:42 +08:00
|
|
|
|
2018-07-26 15:08:21 +08:00
|
|
|
dba->InsertVertex();
|
|
|
|
dba->AdvanceCommand();
|
Remove GraphDbAccessor and storage types from Ast
Summary:
This diff removes the need for a database when parsing a query and
creating an Ast. Instead of storing storage::{Label,Property,EdgeType}
in Ast nodes, we store the name and an index into all of the names. This
allows for easy creation of a map from {Label,Property,EdgeType} index
into the concrete storage type. Obviously, this comes with a performance
penalty during execution, but it should be minor. The upside is that the
query/frontend minimally depends on storage (PropertyValue), which makes
writing tests easier as well as running them a lot faster (there is no
database setup). This is most noticeable in the ast_serialization test
which took a long time due to start up of a distributed database.
Reviewers: mtomic, llugovic
Reviewed By: mtomic
Subscribers: mferencevic, pullbot
Differential Revision: https://phabricator.memgraph.io/D1774
2019-01-14 21:41:37 +08:00
|
|
|
EXPECT_EQ(2, PullAll(*skip, &context));
|
2017-04-18 21:19:42 +08:00
|
|
|
|
2018-07-26 15:08:21 +08:00
|
|
|
dba->InsertVertex();
|
|
|
|
dba->AdvanceCommand();
|
Remove GraphDbAccessor and storage types from Ast
Summary:
This diff removes the need for a database when parsing a query and
creating an Ast. Instead of storing storage::{Label,Property,EdgeType}
in Ast nodes, we store the name and an index into all of the names. This
allows for easy creation of a map from {Label,Property,EdgeType} index
into the concrete storage type. Obviously, this comes with a performance
penalty during execution, but it should be minor. The upside is that the
query/frontend minimally depends on storage (PropertyValue), which makes
writing tests easier as well as running them a lot faster (there is no
database setup). This is most noticeable in the ast_serialization test
which took a long time due to start up of a distributed database.
Reviewers: mtomic, llugovic
Reviewed By: mtomic
Subscribers: mferencevic, pullbot
Differential Revision: https://phabricator.memgraph.io/D1774
2019-01-14 21:41:37 +08:00
|
|
|
EXPECT_EQ(2, PullAll(*skip, &context));
|
2017-04-18 21:19:42 +08:00
|
|
|
|
2018-07-26 15:08:21 +08:00
|
|
|
for (int i = 0; i < 10; ++i) dba->InsertVertex();
|
|
|
|
dba->AdvanceCommand();
|
Remove GraphDbAccessor and storage types from Ast
Summary:
This diff removes the need for a database when parsing a query and
creating an Ast. Instead of storing storage::{Label,Property,EdgeType}
in Ast nodes, we store the name and an index into all of the names. This
allows for easy creation of a map from {Label,Property,EdgeType} index
into the concrete storage type. Obviously, this comes with a performance
penalty during execution, but it should be minor. The upside is that the
query/frontend minimally depends on storage (PropertyValue), which makes
writing tests easier as well as running them a lot faster (there is no
database setup). This is most noticeable in the ast_serialization test
which took a long time due to start up of a distributed database.
Reviewers: mtomic, llugovic
Reviewed By: mtomic
Subscribers: mferencevic, pullbot
Differential Revision: https://phabricator.memgraph.io/D1774
2019-01-14 21:41:37 +08:00
|
|
|
EXPECT_EQ(2, PullAll(*skip, &context));
|
2017-04-18 21:19:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(QueryPlan, CreateLimit) {
|
|
|
|
// CREATE (n), (m)
|
|
|
|
// MATCH (n) CREATE (m) LIMIT 1
|
|
|
|
// in the end we need to have 3 vertices in the db
|
2018-10-09 17:09:10 +08:00
|
|
|
database::GraphDb db;
|
2018-07-26 15:08:21 +08:00
|
|
|
auto dba = db.Access();
|
|
|
|
dba->InsertVertex();
|
|
|
|
dba->InsertVertex();
|
|
|
|
dba->AdvanceCommand();
|
2017-04-18 21:19:42 +08:00
|
|
|
|
2018-05-22 22:45:52 +08:00
|
|
|
AstStorage storage;
|
2017-04-18 21:19:42 +08:00
|
|
|
SymbolTable symbol_table;
|
|
|
|
|
|
|
|
auto n = MakeScanAll(storage, symbol_table, "n1");
|
2018-12-20 16:38:23 +08:00
|
|
|
NodeCreationInfo m;
|
|
|
|
m.symbol = symbol_table.CreateSymbol("m", true);
|
2018-08-30 19:31:50 +08:00
|
|
|
auto c = std::make_shared<CreateNode>(n.op_, m);
|
2017-04-18 21:19:42 +08:00
|
|
|
auto skip = std::make_shared<plan::Limit>(c, LITERAL(1));
|
|
|
|
|
2019-01-16 18:30:17 +08:00
|
|
|
auto context = MakeContext(storage, symbol_table, dba.get());
|
Remove GraphDbAccessor and storage types from Ast
Summary:
This diff removes the need for a database when parsing a query and
creating an Ast. Instead of storing storage::{Label,Property,EdgeType}
in Ast nodes, we store the name and an index into all of the names. This
allows for easy creation of a map from {Label,Property,EdgeType} index
into the concrete storage type. Obviously, this comes with a performance
penalty during execution, but it should be minor. The upside is that the
query/frontend minimally depends on storage (PropertyValue), which makes
writing tests easier as well as running them a lot faster (there is no
database setup). This is most noticeable in the ast_serialization test
which took a long time due to start up of a distributed database.
Reviewers: mtomic, llugovic
Reviewed By: mtomic
Subscribers: mferencevic, pullbot
Differential Revision: https://phabricator.memgraph.io/D1774
2019-01-14 21:41:37 +08:00
|
|
|
EXPECT_EQ(1, PullAll(*skip, &context));
|
2018-07-26 15:08:21 +08:00
|
|
|
dba->AdvanceCommand();
|
|
|
|
EXPECT_EQ(3, CountIterable(dba->Vertices(false)));
|
2017-04-18 21:19:42 +08:00
|
|
|
}
|
2017-04-20 19:31:18 +08:00
|
|
|
|
|
|
|
TEST(QueryPlan, OrderBy) {
|
2018-10-09 17:09:10 +08:00
|
|
|
database::GraphDb db;
|
2018-07-26 15:08:21 +08:00
|
|
|
auto dba_ptr = db.Access();
|
|
|
|
auto &dba = *dba_ptr;
|
2018-05-22 22:45:52 +08:00
|
|
|
AstStorage storage;
|
2017-04-20 19:31:18 +08:00
|
|
|
SymbolTable symbol_table;
|
2017-10-30 17:43:25 +08:00
|
|
|
auto prop = dba.Property("prop");
|
2017-04-20 19:31:18 +08:00
|
|
|
|
|
|
|
// contains a series of tests
|
|
|
|
// each test defines the ordering a vector of values in the desired order
|
Clean-up TypedValue misuse
Summary:
In a bunch of places `TypedValue` was used where `PropertyValue` should be. A lot of times it was only because `TypedValue` serialization code could be reused for `PropertyValue`, only without providing callbacks for `VERTEX`, `EDGE` and `PATH`. So first I wrote separate serialization code for `PropertyValue` and put it into storage folder. Then I fixed all the places where `TypedValue` was incorrectly used instead of `PropertyValue`. I also disabled implicit `TypedValue` to `PropertyValue` conversion in hopes of preventing misuse in the future.
After that, I wrote code for `VertexAccessor` and `EdgeAccessor` serialization and put it into `storage` folder because it was almost duplicated in distributed BFS and pull produce RPC messages. On the sender side, some subset of records (old or new or both) is serialized, and on the reciever side, records are deserialized and immediately put into transaction cache.
Then I rewrote the `TypedValue` serialization functions (`SaveCapnpTypedValue` and `LoadCapnpTypedValue`) to not take callbacks for `VERTEX`, `EDGE` and `PATH`, but use accessor serialization functions instead. That means that any code that wants to use `TypedValue` serialization must hold a reference to `GraphDbAccessor` and `DataManager`, so that should make clients reconsider if they really want to use `TypedValue` instead of `PropertyValue`.
Reviewers: teon.banek, msantl
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1598
2018-09-13 18:12:07 +08:00
|
|
|
auto Null = PropertyValue::Null;
|
|
|
|
std::vector<std::pair<Ordering, std::vector<PropertyValue>>> orderable{
|
2017-04-20 19:31:18 +08:00
|
|
|
{Ordering::ASC, {0, 0, 0.5, 1, 2, 12.6, 42, Null, Null}},
|
|
|
|
{Ordering::ASC, {false, false, true, true, Null, Null}},
|
|
|
|
{Ordering::ASC, {"A", "B", "a", "a", "aa", "ab", "aba", Null, Null}},
|
|
|
|
{Ordering::DESC, {Null, Null, 33, 33, 32.5, 32, 2.2, 2.1, 0}},
|
|
|
|
{Ordering::DESC, {Null, true, false}},
|
|
|
|
{Ordering::DESC, {Null, "zorro", "borro"}}};
|
|
|
|
|
|
|
|
for (const auto &order_value_pair : orderable) {
|
|
|
|
const auto &values = order_value_pair.second;
|
|
|
|
// empty database
|
2017-10-30 17:43:25 +08:00
|
|
|
for (auto &vertex : dba.Vertices(false)) dba.DetachRemoveVertex(vertex);
|
|
|
|
dba.AdvanceCommand();
|
|
|
|
ASSERT_EQ(0, CountIterable(dba.Vertices(false)));
|
2017-04-20 19:31:18 +08:00
|
|
|
|
|
|
|
// take some effort to shuffle the values
|
|
|
|
// because we are testing that something not ordered gets ordered
|
|
|
|
// and need to take care it does not happen by accident
|
Clean-up TypedValue misuse
Summary:
In a bunch of places `TypedValue` was used where `PropertyValue` should be. A lot of times it was only because `TypedValue` serialization code could be reused for `PropertyValue`, only without providing callbacks for `VERTEX`, `EDGE` and `PATH`. So first I wrote separate serialization code for `PropertyValue` and put it into storage folder. Then I fixed all the places where `TypedValue` was incorrectly used instead of `PropertyValue`. I also disabled implicit `TypedValue` to `PropertyValue` conversion in hopes of preventing misuse in the future.
After that, I wrote code for `VertexAccessor` and `EdgeAccessor` serialization and put it into `storage` folder because it was almost duplicated in distributed BFS and pull produce RPC messages. On the sender side, some subset of records (old or new or both) is serialized, and on the reciever side, records are deserialized and immediately put into transaction cache.
Then I rewrote the `TypedValue` serialization functions (`SaveCapnpTypedValue` and `LoadCapnpTypedValue`) to not take callbacks for `VERTEX`, `EDGE` and `PATH`, but use accessor serialization functions instead. That means that any code that wants to use `TypedValue` serialization must hold a reference to `GraphDbAccessor` and `DataManager`, so that should make clients reconsider if they really want to use `TypedValue` instead of `PropertyValue`.
Reviewers: teon.banek, msantl
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1598
2018-09-13 18:12:07 +08:00
|
|
|
std::vector<PropertyValue> shuffled(values.begin(), values.end());
|
2017-04-20 19:31:18 +08:00
|
|
|
auto order_equal = [&values, &shuffled]() {
|
|
|
|
return std::equal(values.begin(), values.end(), shuffled.begin(),
|
|
|
|
TypedValue::BoolEqual{});
|
|
|
|
};
|
|
|
|
for (int i = 0; i < 50 && order_equal(); ++i) {
|
|
|
|
std::random_shuffle(shuffled.begin(), shuffled.end());
|
|
|
|
}
|
|
|
|
ASSERT_FALSE(order_equal());
|
|
|
|
|
|
|
|
// create the vertices
|
2018-01-12 22:17:04 +08:00
|
|
|
for (const auto &value : shuffled) dba.InsertVertex().PropsSet(prop, value);
|
2017-10-30 17:43:25 +08:00
|
|
|
dba.AdvanceCommand();
|
2017-04-20 19:31:18 +08:00
|
|
|
|
|
|
|
// order by and collect results
|
|
|
|
auto n = MakeScanAll(storage, symbol_table, "n");
|
|
|
|
auto n_p = PROPERTY_LOOKUP("n", prop);
|
|
|
|
symbol_table[*n_p->expression_] = n.sym_;
|
|
|
|
auto order_by = std::make_shared<plan::OrderBy>(
|
2018-10-04 17:57:23 +08:00
|
|
|
n.op_, std::vector<SortItem>{{order_value_pair.first, n_p}},
|
2017-04-20 19:31:18 +08:00
|
|
|
std::vector<Symbol>{n.sym_});
|
|
|
|
auto n_p_ne = NEXPR("n.p", n_p);
|
2017-05-12 17:37:22 +08:00
|
|
|
symbol_table[*n_p_ne] = symbol_table.CreateSymbol("n.p", true);
|
2017-04-20 19:31:18 +08:00
|
|
|
auto produce = MakeProduce(order_by, n_p_ne);
|
2019-01-16 18:30:17 +08:00
|
|
|
auto context = MakeContext(storage, symbol_table, &dba);
|
Remove GraphDbAccessor and storage types from Ast
Summary:
This diff removes the need for a database when parsing a query and
creating an Ast. Instead of storing storage::{Label,Property,EdgeType}
in Ast nodes, we store the name and an index into all of the names. This
allows for easy creation of a map from {Label,Property,EdgeType} index
into the concrete storage type. Obviously, this comes with a performance
penalty during execution, but it should be minor. The upside is that the
query/frontend minimally depends on storage (PropertyValue), which makes
writing tests easier as well as running them a lot faster (there is no
database setup). This is most noticeable in the ast_serialization test
which took a long time due to start up of a distributed database.
Reviewers: mtomic, llugovic
Reviewed By: mtomic
Subscribers: mferencevic, pullbot
Differential Revision: https://phabricator.memgraph.io/D1774
2019-01-14 21:41:37 +08:00
|
|
|
auto results = CollectProduce(*produce, &context);
|
2017-04-20 19:31:18 +08:00
|
|
|
ASSERT_EQ(values.size(), results.size());
|
|
|
|
for (int j = 0; j < results.size(); ++j)
|
|
|
|
EXPECT_TRUE(TypedValue::BoolEqual{}(results[j][0], values[j]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(QueryPlan, OrderByMultiple) {
|
2018-10-09 17:09:10 +08:00
|
|
|
database::GraphDb db;
|
2018-07-26 15:08:21 +08:00
|
|
|
auto dba_ptr = db.Access();
|
|
|
|
auto &dba = *dba_ptr;
|
2018-05-22 22:45:52 +08:00
|
|
|
AstStorage storage;
|
2017-04-20 19:31:18 +08:00
|
|
|
SymbolTable symbol_table;
|
|
|
|
|
2017-10-30 17:43:25 +08:00
|
|
|
auto p1 = dba.Property("p1");
|
|
|
|
auto p2 = dba.Property("p2");
|
2017-04-20 19:31:18 +08:00
|
|
|
|
|
|
|
// create a bunch of vertices that in two properties
|
|
|
|
// have all the variations (with repetition) of N values.
|
|
|
|
// ensure that those vertices are not created in the
|
|
|
|
// "right" sequence, but randomized
|
|
|
|
const int N = 20;
|
|
|
|
std::vector<std::pair<int, int>> prop_values;
|
|
|
|
for (int i = 0; i < N * N; ++i) prop_values.emplace_back(i % N, i / N);
|
|
|
|
std::random_shuffle(prop_values.begin(), prop_values.end());
|
|
|
|
for (const auto &pair : prop_values) {
|
2017-10-30 17:43:25 +08:00
|
|
|
auto v = dba.InsertVertex();
|
2017-04-20 19:31:18 +08:00
|
|
|
v.PropsSet(p1, pair.first);
|
|
|
|
v.PropsSet(p2, pair.second);
|
|
|
|
}
|
2017-10-30 17:43:25 +08:00
|
|
|
dba.AdvanceCommand();
|
2017-04-20 19:31:18 +08:00
|
|
|
|
|
|
|
// order by and collect results
|
|
|
|
auto n = MakeScanAll(storage, symbol_table, "n");
|
|
|
|
auto n_p1 = PROPERTY_LOOKUP("n", p1);
|
|
|
|
symbol_table[*n_p1->expression_] = n.sym_;
|
|
|
|
auto n_p2 = PROPERTY_LOOKUP("n", p2);
|
|
|
|
symbol_table[*n_p2->expression_] = n.sym_;
|
|
|
|
// order the results so we get
|
|
|
|
// (p1: 0, p2: N-1)
|
|
|
|
// (p1: 0, p2: N-2)
|
|
|
|
// ...
|
|
|
|
// (p1: N-1, p2:0)
|
2018-10-04 17:57:23 +08:00
|
|
|
auto order_by = std::make_shared<plan::OrderBy>(n.op_,
|
|
|
|
std::vector<SortItem>{
|
|
|
|
{Ordering::ASC, n_p1},
|
|
|
|
{Ordering::DESC, n_p2},
|
|
|
|
},
|
|
|
|
std::vector<Symbol>{n.sym_});
|
2017-04-20 19:31:18 +08:00
|
|
|
auto n_p1_ne = NEXPR("n.p1", n_p1);
|
2017-05-12 17:37:22 +08:00
|
|
|
symbol_table[*n_p1_ne] = symbol_table.CreateSymbol("n.p1", true);
|
2017-04-20 19:31:18 +08:00
|
|
|
auto n_p2_ne = NEXPR("n.p2", n_p2);
|
2017-05-12 17:37:22 +08:00
|
|
|
symbol_table[*n_p2_ne] = symbol_table.CreateSymbol("n.p2", true);
|
2017-04-20 19:31:18 +08:00
|
|
|
auto produce = MakeProduce(order_by, n_p1_ne, n_p2_ne);
|
2019-01-16 18:30:17 +08:00
|
|
|
auto context = MakeContext(storage, symbol_table, &dba);
|
Remove GraphDbAccessor and storage types from Ast
Summary:
This diff removes the need for a database when parsing a query and
creating an Ast. Instead of storing storage::{Label,Property,EdgeType}
in Ast nodes, we store the name and an index into all of the names. This
allows for easy creation of a map from {Label,Property,EdgeType} index
into the concrete storage type. Obviously, this comes with a performance
penalty during execution, but it should be minor. The upside is that the
query/frontend minimally depends on storage (PropertyValue), which makes
writing tests easier as well as running them a lot faster (there is no
database setup). This is most noticeable in the ast_serialization test
which took a long time due to start up of a distributed database.
Reviewers: mtomic, llugovic
Reviewed By: mtomic
Subscribers: mferencevic, pullbot
Differential Revision: https://phabricator.memgraph.io/D1774
2019-01-14 21:41:37 +08:00
|
|
|
auto results = CollectProduce(*produce, &context);
|
2017-04-20 19:31:18 +08:00
|
|
|
ASSERT_EQ(N * N, results.size());
|
|
|
|
for (int j = 0; j < N * N; ++j) {
|
|
|
|
ASSERT_EQ(results[j][0].type(), TypedValue::Type::Int);
|
|
|
|
EXPECT_EQ(results[j][0].Value<int64_t>(), j / N);
|
|
|
|
ASSERT_EQ(results[j][1].type(), TypedValue::Type::Int);
|
|
|
|
EXPECT_EQ(results[j][1].Value<int64_t>(), N - 1 - j % N);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(QueryPlan, OrderByExceptions) {
|
2018-10-09 17:09:10 +08:00
|
|
|
database::GraphDb db;
|
2018-07-26 15:08:21 +08:00
|
|
|
auto dba_ptr = db.Access();
|
|
|
|
auto &dba = *dba_ptr;
|
2018-05-22 22:45:52 +08:00
|
|
|
AstStorage storage;
|
2017-04-20 19:31:18 +08:00
|
|
|
SymbolTable symbol_table;
|
2017-10-30 17:43:25 +08:00
|
|
|
auto prop = dba.Property("prop");
|
2017-04-20 19:31:18 +08:00
|
|
|
|
|
|
|
// a vector of pairs of typed values that should result
|
|
|
|
// in an exception when trying to order on them
|
Clean-up TypedValue misuse
Summary:
In a bunch of places `TypedValue` was used where `PropertyValue` should be. A lot of times it was only because `TypedValue` serialization code could be reused for `PropertyValue`, only without providing callbacks for `VERTEX`, `EDGE` and `PATH`. So first I wrote separate serialization code for `PropertyValue` and put it into storage folder. Then I fixed all the places where `TypedValue` was incorrectly used instead of `PropertyValue`. I also disabled implicit `TypedValue` to `PropertyValue` conversion in hopes of preventing misuse in the future.
After that, I wrote code for `VertexAccessor` and `EdgeAccessor` serialization and put it into `storage` folder because it was almost duplicated in distributed BFS and pull produce RPC messages. On the sender side, some subset of records (old or new or both) is serialized, and on the reciever side, records are deserialized and immediately put into transaction cache.
Then I rewrote the `TypedValue` serialization functions (`SaveCapnpTypedValue` and `LoadCapnpTypedValue`) to not take callbacks for `VERTEX`, `EDGE` and `PATH`, but use accessor serialization functions instead. That means that any code that wants to use `TypedValue` serialization must hold a reference to `GraphDbAccessor` and `DataManager`, so that should make clients reconsider if they really want to use `TypedValue` instead of `PropertyValue`.
Reviewers: teon.banek, msantl
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1598
2018-09-13 18:12:07 +08:00
|
|
|
std::vector<std::pair<PropertyValue, PropertyValue>> exception_pairs{
|
2017-04-20 19:31:18 +08:00
|
|
|
{42, true},
|
|
|
|
{42, "bla"},
|
Clean-up TypedValue misuse
Summary:
In a bunch of places `TypedValue` was used where `PropertyValue` should be. A lot of times it was only because `TypedValue` serialization code could be reused for `PropertyValue`, only without providing callbacks for `VERTEX`, `EDGE` and `PATH`. So first I wrote separate serialization code for `PropertyValue` and put it into storage folder. Then I fixed all the places where `TypedValue` was incorrectly used instead of `PropertyValue`. I also disabled implicit `TypedValue` to `PropertyValue` conversion in hopes of preventing misuse in the future.
After that, I wrote code for `VertexAccessor` and `EdgeAccessor` serialization and put it into `storage` folder because it was almost duplicated in distributed BFS and pull produce RPC messages. On the sender side, some subset of records (old or new or both) is serialized, and on the reciever side, records are deserialized and immediately put into transaction cache.
Then I rewrote the `TypedValue` serialization functions (`SaveCapnpTypedValue` and `LoadCapnpTypedValue`) to not take callbacks for `VERTEX`, `EDGE` and `PATH`, but use accessor serialization functions instead. That means that any code that wants to use `TypedValue` serialization must hold a reference to `GraphDbAccessor` and `DataManager`, so that should make clients reconsider if they really want to use `TypedValue` instead of `PropertyValue`.
Reviewers: teon.banek, msantl
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1598
2018-09-13 18:12:07 +08:00
|
|
|
{42, std::vector<PropertyValue>{42}},
|
2017-04-20 19:31:18 +08:00
|
|
|
{true, "bla"},
|
Clean-up TypedValue misuse
Summary:
In a bunch of places `TypedValue` was used where `PropertyValue` should be. A lot of times it was only because `TypedValue` serialization code could be reused for `PropertyValue`, only without providing callbacks for `VERTEX`, `EDGE` and `PATH`. So first I wrote separate serialization code for `PropertyValue` and put it into storage folder. Then I fixed all the places where `TypedValue` was incorrectly used instead of `PropertyValue`. I also disabled implicit `TypedValue` to `PropertyValue` conversion in hopes of preventing misuse in the future.
After that, I wrote code for `VertexAccessor` and `EdgeAccessor` serialization and put it into `storage` folder because it was almost duplicated in distributed BFS and pull produce RPC messages. On the sender side, some subset of records (old or new or both) is serialized, and on the reciever side, records are deserialized and immediately put into transaction cache.
Then I rewrote the `TypedValue` serialization functions (`SaveCapnpTypedValue` and `LoadCapnpTypedValue`) to not take callbacks for `VERTEX`, `EDGE` and `PATH`, but use accessor serialization functions instead. That means that any code that wants to use `TypedValue` serialization must hold a reference to `GraphDbAccessor` and `DataManager`, so that should make clients reconsider if they really want to use `TypedValue` instead of `PropertyValue`.
Reviewers: teon.banek, msantl
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1598
2018-09-13 18:12:07 +08:00
|
|
|
{true, std::vector<PropertyValue>{true}},
|
|
|
|
{"bla", std::vector<PropertyValue>{"bla"}},
|
2017-04-20 19:31:18 +08:00
|
|
|
// illegal comparisons of same-type values
|
Clean-up TypedValue misuse
Summary:
In a bunch of places `TypedValue` was used where `PropertyValue` should be. A lot of times it was only because `TypedValue` serialization code could be reused for `PropertyValue`, only without providing callbacks for `VERTEX`, `EDGE` and `PATH`. So first I wrote separate serialization code for `PropertyValue` and put it into storage folder. Then I fixed all the places where `TypedValue` was incorrectly used instead of `PropertyValue`. I also disabled implicit `TypedValue` to `PropertyValue` conversion in hopes of preventing misuse in the future.
After that, I wrote code for `VertexAccessor` and `EdgeAccessor` serialization and put it into `storage` folder because it was almost duplicated in distributed BFS and pull produce RPC messages. On the sender side, some subset of records (old or new or both) is serialized, and on the reciever side, records are deserialized and immediately put into transaction cache.
Then I rewrote the `TypedValue` serialization functions (`SaveCapnpTypedValue` and `LoadCapnpTypedValue`) to not take callbacks for `VERTEX`, `EDGE` and `PATH`, but use accessor serialization functions instead. That means that any code that wants to use `TypedValue` serialization must hold a reference to `GraphDbAccessor` and `DataManager`, so that should make clients reconsider if they really want to use `TypedValue` instead of `PropertyValue`.
Reviewers: teon.banek, msantl
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1598
2018-09-13 18:12:07 +08:00
|
|
|
{std::vector<PropertyValue>{42}, std::vector<PropertyValue>{42}}};
|
2017-04-20 19:31:18 +08:00
|
|
|
|
|
|
|
for (const auto &pair : exception_pairs) {
|
|
|
|
// empty database
|
2017-10-30 17:43:25 +08:00
|
|
|
for (auto &vertex : dba.Vertices(false)) dba.DetachRemoveVertex(vertex);
|
|
|
|
dba.AdvanceCommand();
|
|
|
|
ASSERT_EQ(0, CountIterable(dba.Vertices(false)));
|
2017-04-20 19:31:18 +08:00
|
|
|
|
|
|
|
// make two vertices, and set values
|
2017-10-30 17:43:25 +08:00
|
|
|
dba.InsertVertex().PropsSet(prop, pair.first);
|
|
|
|
dba.InsertVertex().PropsSet(prop, pair.second);
|
|
|
|
dba.AdvanceCommand();
|
|
|
|
ASSERT_EQ(2, CountIterable(dba.Vertices(false)));
|
|
|
|
for (const auto &va : dba.Vertices(false))
|
2017-04-20 19:31:18 +08:00
|
|
|
ASSERT_NE(va.PropsAt(prop).type(), PropertyValue::Type::Null);
|
|
|
|
|
|
|
|
// order by and expect an exception
|
|
|
|
auto n = MakeScanAll(storage, symbol_table, "n");
|
|
|
|
auto n_p = PROPERTY_LOOKUP("n", prop);
|
|
|
|
symbol_table[*n_p->expression_] = n.sym_;
|
|
|
|
auto order_by = std::make_shared<plan::OrderBy>(
|
2018-10-04 17:57:23 +08:00
|
|
|
n.op_, std::vector<SortItem>{{Ordering::ASC, n_p}},
|
2017-04-20 19:31:18 +08:00
|
|
|
std::vector<Symbol>{});
|
2019-01-16 18:30:17 +08:00
|
|
|
auto context = MakeContext(storage, symbol_table, &dba);
|
Remove GraphDbAccessor and storage types from Ast
Summary:
This diff removes the need for a database when parsing a query and
creating an Ast. Instead of storing storage::{Label,Property,EdgeType}
in Ast nodes, we store the name and an index into all of the names. This
allows for easy creation of a map from {Label,Property,EdgeType} index
into the concrete storage type. Obviously, this comes with a performance
penalty during execution, but it should be minor. The upside is that the
query/frontend minimally depends on storage (PropertyValue), which makes
writing tests easier as well as running them a lot faster (there is no
database setup). This is most noticeable in the ast_serialization test
which took a long time due to start up of a distributed database.
Reviewers: mtomic, llugovic
Reviewed By: mtomic
Subscribers: mferencevic, pullbot
Differential Revision: https://phabricator.memgraph.io/D1774
2019-01-14 21:41:37 +08:00
|
|
|
EXPECT_THROW(PullAll(*order_by, &context), QueryRuntimeException);
|
2017-04-20 19:31:18 +08:00
|
|
|
}
|
|
|
|
}
|