2017-03-22 23:38:43 +08:00
|
|
|
#pragma once
|
|
|
|
|
2017-06-21 17:29:13 +08:00
|
|
|
#include <gflags/gflags.h>
|
|
|
|
|
2018-03-13 17:35:14 +08:00
|
|
|
#include "database/graph_db.hpp"
|
2017-03-22 23:38:43 +08:00
|
|
|
#include "database/graph_db_accessor.hpp"
|
|
|
|
#include "query/context.hpp"
|
2017-12-22 20:39:31 +08:00
|
|
|
#include "query/frontend/ast/ast.hpp"
|
2019-01-16 18:30:17 +08:00
|
|
|
#include "query/frontend/ast/cypher_main_visitor.hpp"
|
2017-06-15 00:53:02 +08:00
|
|
|
#include "query/frontend/stripped.hpp"
|
2017-04-13 16:01:16 +08:00
|
|
|
#include "query/interpret/frame.hpp"
|
2017-09-19 22:58:22 +08:00
|
|
|
#include "query/plan/operator.hpp"
|
2019-08-20 15:33:31 +08:00
|
|
|
#include "utils/skip_list.hpp"
|
2019-01-07 16:18:52 +08:00
|
|
|
#include "utils/spin_lock.hpp"
|
2017-07-15 01:33:45 +08:00
|
|
|
#include "utils/timer.hpp"
|
2017-03-22 23:38:43 +08:00
|
|
|
|
2018-08-24 16:12:04 +08:00
|
|
|
DECLARE_bool(query_cost_planner);
|
Flags cleanup and QueryEngine removal
Summary:
I started with cleaning flags up (removing unused ones, documenting undocumented ones). There were some flags to remove in `QueryEngine`. Seeing how we never use hardcoded queries (AFAIK last Mislav's testing also indicated they aren't faster then interpretation), when removing those unused flags the `QueryEngine` becomes obsolete. That means that a bunch of other stuff becomes obsolete, along with the hardcoded queries. So I removed it all (this has been discussed and approved on the daily).
Some flags that were previously undocumented in `docs/user_technical/installation` are now documented. The following flags are NOT documented and in my opinion should not be displayed when starting `./memgraph --help` (@mferencevic):
```
query_vertex_count_to_expand_existsing (from rule_based_planner.cpp)
query_max_plans (rule_based_planner.cpp)
```
If you think that another organization is needed w.r.t. flag visibility, comment.
@teon.banek: I had to remove some stuff from CMakeLists to make it buildable. Please review what I removed and clean up if necessary if/when this lands. If the needed changes are minor, you can also comment.
Reviewers: buda, mislav.bradac, teon.banek, mferencevic
Reviewed By: buda, mislav.bradac
Subscribers: pullbot, mferencevic, teon.banek
Differential Revision: https://phabricator.memgraph.io/D825
2017-09-22 22:17:09 +08:00
|
|
|
DECLARE_int32(query_plan_cache_ttl);
|
2017-06-15 00:53:02 +08:00
|
|
|
|
2018-07-27 16:54:20 +08:00
|
|
|
namespace auth {
|
|
|
|
class Auth;
|
|
|
|
} // namespace auth
|
|
|
|
|
|
|
|
namespace integrations::kafka {
|
2018-07-06 15:28:05 +08:00
|
|
|
class Streams;
|
2018-07-27 16:54:20 +08:00
|
|
|
} // namespace integrations::kafka
|
2018-07-06 15:28:05 +08:00
|
|
|
|
2017-03-22 23:38:43 +08:00
|
|
|
namespace query {
|
|
|
|
|
2018-08-24 16:12:04 +08:00
|
|
|
// TODO: Maybe this should move to query/plan/planner.
|
|
|
|
/// Interface for accessing the root operator of a logical plan.
|
|
|
|
class LogicalPlan {
|
|
|
|
public:
|
|
|
|
virtual ~LogicalPlan() {}
|
|
|
|
|
|
|
|
virtual const plan::LogicalOperator &GetRoot() const = 0;
|
|
|
|
virtual double GetCost() const = 0;
|
|
|
|
virtual const SymbolTable &GetSymbolTable() const = 0;
|
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
|
|
|
virtual const AstStorage &GetAstStorage() const = 0;
|
2018-08-24 16:12:04 +08:00
|
|
|
};
|
|
|
|
|
2017-06-21 17:29:13 +08:00
|
|
|
class Interpreter {
|
2017-09-19 22:58:22 +08:00
|
|
|
private:
|
|
|
|
class CachedPlan {
|
|
|
|
public:
|
2018-08-24 16:12:04 +08:00
|
|
|
CachedPlan(std::unique_ptr<LogicalPlan> plan);
|
2017-09-19 22:58:22 +08:00
|
|
|
|
2018-08-24 16:12:04 +08:00
|
|
|
const auto &plan() const { return plan_->GetRoot(); }
|
|
|
|
double cost() const { return plan_->GetCost(); }
|
|
|
|
const auto &symbol_table() const { return plan_->GetSymbolTable(); }
|
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
|
|
|
const auto &ast_storage() const { return plan_->GetAstStorage(); }
|
2017-09-19 22:58:22 +08:00
|
|
|
|
|
|
|
bool IsExpired() const {
|
2018-03-13 17:35:14 +08:00
|
|
|
return cache_timer_.Elapsed() >
|
Flags cleanup and QueryEngine removal
Summary:
I started with cleaning flags up (removing unused ones, documenting undocumented ones). There were some flags to remove in `QueryEngine`. Seeing how we never use hardcoded queries (AFAIK last Mislav's testing also indicated they aren't faster then interpretation), when removing those unused flags the `QueryEngine` becomes obsolete. That means that a bunch of other stuff becomes obsolete, along with the hardcoded queries. So I removed it all (this has been discussed and approved on the daily).
Some flags that were previously undocumented in `docs/user_technical/installation` are now documented. The following flags are NOT documented and in my opinion should not be displayed when starting `./memgraph --help` (@mferencevic):
```
query_vertex_count_to_expand_existsing (from rule_based_planner.cpp)
query_max_plans (rule_based_planner.cpp)
```
If you think that another organization is needed w.r.t. flag visibility, comment.
@teon.banek: I had to remove some stuff from CMakeLists to make it buildable. Please review what I removed and clean up if necessary if/when this lands. If the needed changes are minor, you can also comment.
Reviewers: buda, mislav.bradac, teon.banek, mferencevic
Reviewed By: buda, mislav.bradac
Subscribers: pullbot, mferencevic, teon.banek
Differential Revision: https://phabricator.memgraph.io/D825
2017-09-22 22:17:09 +08:00
|
|
|
std::chrono::seconds(FLAGS_query_plan_cache_ttl);
|
2017-09-19 22:58:22 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
2018-08-24 16:12:04 +08:00
|
|
|
std::unique_ptr<LogicalPlan> plan_;
|
2017-09-19 22:58:22 +08:00
|
|
|
utils::Timer cache_timer_;
|
2018-03-13 17:35:14 +08:00
|
|
|
};
|
|
|
|
|
2018-10-10 21:19:34 +08:00
|
|
|
struct CachedQuery {
|
|
|
|
AstStorage ast_storage;
|
|
|
|
Query *query;
|
2018-10-24 23:44:53 +08:00
|
|
|
std::vector<AuthQuery::Privilege> required_privileges;
|
|
|
|
};
|
|
|
|
|
2019-01-15 18:11:06 +08:00
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* Wraps a `Query` that was created as a result of parsing a query string
|
|
|
|
* along with its privileges.
|
|
|
|
*/
|
2018-10-24 23:44:53 +08:00
|
|
|
struct ParsedQuery {
|
|
|
|
Query *query;
|
|
|
|
std::vector<AuthQuery::Privilege> required_privileges;
|
2018-10-10 21:19:34 +08:00
|
|
|
};
|
|
|
|
|
2017-12-22 20:39:31 +08:00
|
|
|
/**
|
2018-03-13 17:35:14 +08:00
|
|
|
* Encapsulates all what's necessary for the interpretation of a query
|
|
|
|
* into a single object that can be pulled (into the given Stream).
|
2017-12-22 20:39:31 +08:00
|
|
|
*/
|
|
|
|
class Results {
|
|
|
|
friend Interpreter;
|
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
|
|
|
Results(database::GraphDbAccessor *db_accessor,
|
|
|
|
const query::Parameters ¶meters,
|
|
|
|
std::shared_ptr<CachedPlan> plan,
|
2017-12-22 20:39:31 +08:00
|
|
|
std::vector<Symbol> output_symbols, std::vector<std::string> header,
|
2018-10-19 22:18:44 +08:00
|
|
|
std::map<std::string, TypedValue> summary,
|
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
|
|
|
std::vector<AuthQuery::Privilege> privileges,
|
2019-08-22 20:15:45 +08:00
|
|
|
utils::MemoryResource *execution_memory,
|
2019-04-24 23:08:41 +08:00
|
|
|
bool is_profile_query = false, bool should_abort_query = false)
|
2019-01-16 18:30:17 +08:00
|
|
|
: ctx_{db_accessor},
|
2017-12-27 19:11:20 +08:00
|
|
|
plan_(plan),
|
2019-08-22 20:15:45 +08:00
|
|
|
cursor_(plan_->plan().MakeCursor(execution_memory)),
|
|
|
|
frame_(plan_->symbol_table().max_position(), execution_memory),
|
2017-12-22 20:39:31 +08:00
|
|
|
output_symbols_(output_symbols),
|
|
|
|
header_(header),
|
|
|
|
summary_(summary),
|
2019-04-24 23:08:41 +08:00
|
|
|
privileges_(std::move(privileges)),
|
|
|
|
should_abort_query_(should_abort_query) {
|
2019-01-16 18:30:17 +08:00
|
|
|
ctx_.is_profile_query = is_profile_query;
|
|
|
|
ctx_.symbol_table = plan_->symbol_table();
|
|
|
|
ctx_.evaluation_context.timestamp =
|
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
|
|
|
std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
|
|
std::chrono::system_clock::now().time_since_epoch())
|
|
|
|
.count();
|
2019-01-16 18:30:17 +08:00
|
|
|
ctx_.evaluation_context.parameters = parameters;
|
|
|
|
ctx_.evaluation_context.properties =
|
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
|
|
|
NamesToProperties(plan_->ast_storage().properties_, db_accessor);
|
2019-01-16 18:30:17 +08:00
|
|
|
ctx_.evaluation_context.labels =
|
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
|
|
|
NamesToLabels(plan_->ast_storage().labels_, db_accessor);
|
|
|
|
}
|
2017-09-19 22:58:22 +08:00
|
|
|
|
2017-12-22 20:39:31 +08:00
|
|
|
public:
|
|
|
|
Results(const Results &) = delete;
|
|
|
|
Results(Results &&) = default;
|
|
|
|
Results &operator=(const Results &) = delete;
|
|
|
|
Results &operator=(Results &&) = default;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make the interpreter perform a single Pull. Results (if they exists) are
|
|
|
|
* pushed into the given stream. On first Pull the header is written to the
|
|
|
|
* stream, on last the summary.
|
|
|
|
*
|
|
|
|
* @param stream - The stream to push the header, results and summary into.
|
|
|
|
* @return - If this Results is eligible for another Pull. If Pulling
|
|
|
|
* after `false` has been returned, the behavior is undefined.
|
|
|
|
* @tparam TStream - Stream type.
|
|
|
|
*/
|
|
|
|
template <typename TStream>
|
|
|
|
bool Pull(TStream &stream) {
|
2018-07-18 16:40:06 +08:00
|
|
|
utils::Timer timer;
|
2019-06-17 22:35:25 +08:00
|
|
|
// Setup temporary memory for a single Pull. Initial memory should come
|
|
|
|
// from stack, 256 KiB should fit on the stack and should be more than
|
|
|
|
// enough for a single Pull.
|
|
|
|
constexpr size_t stack_size = 256 * 1024;
|
|
|
|
char stack_data[stack_size];
|
|
|
|
utils::MonotonicBufferResource memory(&stack_data[0], stack_size);
|
|
|
|
ctx_.evaluation_context.memory = &memory;
|
|
|
|
// We can now Pull a result.
|
2017-12-22 20:39:31 +08:00
|
|
|
bool return_value = cursor_->Pull(frame_, ctx_);
|
|
|
|
if (return_value && !output_symbols_.empty()) {
|
2019-06-17 22:35:25 +08:00
|
|
|
// TODO: The streamed values should also probably use the above memory.
|
2017-12-22 20:39:31 +08:00
|
|
|
std::vector<TypedValue> values;
|
|
|
|
values.reserve(output_symbols_.size());
|
|
|
|
for (const auto &symbol : output_symbols_) {
|
|
|
|
values.emplace_back(frame_[symbol]);
|
|
|
|
}
|
|
|
|
stream.Result(values);
|
|
|
|
}
|
2018-07-18 16:40:06 +08:00
|
|
|
execution_time_ += timer.Elapsed().count();
|
2017-10-10 23:57:15 +08:00
|
|
|
|
2017-12-22 20:39:31 +08:00
|
|
|
if (!return_value) {
|
2018-07-18 16:40:06 +08:00
|
|
|
summary_["plan_execution_time"] = execution_time_;
|
2019-01-17 19:28:32 +08:00
|
|
|
|
|
|
|
if (ctx_.is_profile_query) {
|
|
|
|
summary_["profile"] =
|
|
|
|
ProfilingStatsToJson(ctx_.stats, ctx_.profile_execution_time)
|
|
|
|
.dump();
|
|
|
|
}
|
|
|
|
|
2018-09-25 22:15:17 +08:00
|
|
|
cursor_->Shutdown();
|
2017-06-05 18:44:18 +08:00
|
|
|
}
|
2017-12-22 20:39:31 +08:00
|
|
|
|
|
|
|
return return_value;
|
2017-06-05 18:44:18 +08:00
|
|
|
}
|
2017-05-23 17:28:41 +08:00
|
|
|
|
2017-12-22 20:39:31 +08:00
|
|
|
/** Calls Pull() until exhausted. */
|
|
|
|
template <typename TStream>
|
|
|
|
void PullAll(TStream &stream) {
|
|
|
|
while (Pull(stream)) continue;
|
|
|
|
}
|
2017-06-08 00:28:31 +08:00
|
|
|
|
2018-07-18 16:40:06 +08:00
|
|
|
const std::vector<std::string> &header() { return header_; }
|
|
|
|
const std::map<std::string, TypedValue> &summary() { return summary_; }
|
|
|
|
|
2018-08-16 16:13:04 +08:00
|
|
|
const std::vector<AuthQuery::Privilege> &privileges() {
|
|
|
|
return privileges_;
|
|
|
|
}
|
|
|
|
|
2019-04-24 23:08:41 +08:00
|
|
|
bool ShouldAbortQuery() const { return should_abort_query_; }
|
2019-01-15 18:11:06 +08:00
|
|
|
|
2017-12-22 20:39:31 +08:00
|
|
|
private:
|
2019-01-16 18:30:17 +08:00
|
|
|
ExecutionContext ctx_;
|
2017-12-27 19:11:20 +08:00
|
|
|
std::shared_ptr<CachedPlan> plan_;
|
2019-05-09 20:21:23 +08:00
|
|
|
query::plan::UniqueCursorPtr cursor_;
|
2017-12-22 20:39:31 +08:00
|
|
|
Frame frame_;
|
|
|
|
std::vector<Symbol> output_symbols_;
|
|
|
|
|
|
|
|
std::vector<std::string> header_;
|
Extract communication to static library
Summary:
Session specifics have been move out of the Bolt `executing` state, and
are accessed via pure virtual Session type. Our server is templated on
the session and we are setting the concrete type, so there should be no
virtual call overhead. Abstract Session is used to indicate the
interface, this could have also been templated, but the explicit
interface definition makes it clearer.
Specific session implementation for running Memgraph is now implemented
in memgraph_bolt, which instantiates the concrete session type. This may
not be 100% appropriate place, but Memgraph specific session isn't
needed anywhere else.
Bolt/communication tests now use a dummy session and depend only on
communication, which significantly improves test run times.
All these changes make the communication a library which doesn't depend
on storage nor the database. Only shared connection points, which aren't
part of the base communication library are:
* glue/conversion -- which converts between storage and bolt types, and
* communication/result_stream_faker -- templated, but used in tests and query/repl
Depends on D1453
Reviewers: mferencevic, buda, mtomic, msantl
Reviewed By: mferencevic, mtomic
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1456
2018-07-10 22:18:19 +08:00
|
|
|
std::map<std::string, TypedValue> summary_;
|
2017-12-22 20:39:31 +08:00
|
|
|
|
2018-07-18 16:40:06 +08:00
|
|
|
double execution_time_{0};
|
2018-08-16 16:13:04 +08:00
|
|
|
|
|
|
|
std::vector<AuthQuery::Privilege> privileges_;
|
2019-04-24 23:08:41 +08:00
|
|
|
|
|
|
|
bool should_abort_query_;
|
2017-12-22 20:39:31 +08:00
|
|
|
};
|
2017-06-08 00:28:31 +08:00
|
|
|
|
2019-01-15 18:11:06 +08:00
|
|
|
Interpreter();
|
2017-12-22 20:39:31 +08:00
|
|
|
Interpreter(const Interpreter &) = delete;
|
|
|
|
Interpreter &operator=(const Interpreter &) = delete;
|
|
|
|
Interpreter(Interpreter &&) = delete;
|
|
|
|
Interpreter &operator=(Interpreter &&) = delete;
|
2017-10-10 00:09:28 +08:00
|
|
|
|
2018-08-24 16:12:04 +08:00
|
|
|
virtual ~Interpreter() {}
|
|
|
|
|
2017-12-22 20:39:31 +08:00
|
|
|
/**
|
|
|
|
* Generates an Results object for the parameters. The resulting object
|
2018-08-23 19:15:15 +08:00
|
|
|
* can be Pulled with its results written to an arbitrary stream.
|
2017-12-22 20:39:31 +08:00
|
|
|
*/
|
2019-01-15 18:11:06 +08:00
|
|
|
virtual Results operator()(const std::string &query,
|
|
|
|
database::GraphDbAccessor &db_accessor,
|
|
|
|
const std::map<std::string, PropertyValue> ¶ms,
|
2019-08-22 20:15:45 +08:00
|
|
|
bool in_explicit_transaction,
|
|
|
|
utils::MemoryResource *execution_memory);
|
2017-03-22 23:38:43 +08:00
|
|
|
|
2018-07-27 16:54:20 +08:00
|
|
|
auth::Auth *auth_ = nullptr;
|
2018-07-06 15:28:05 +08:00
|
|
|
integrations::kafka::Streams *kafka_streams_ = nullptr;
|
|
|
|
|
2018-08-24 16:12:04 +08:00
|
|
|
protected:
|
2019-07-10 20:30:11 +08:00
|
|
|
std::pair<frontend::StrippedQuery, ParsedQuery> StripAndParseQuery(
|
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
|
|
|
const std::string &, Parameters *, AstStorage *ast_storage,
|
2019-01-15 18:11:06 +08:00
|
|
|
database::GraphDbAccessor *,
|
|
|
|
const std::map<std::string, PropertyValue> &);
|
|
|
|
|
2018-08-24 16:12:04 +08:00
|
|
|
// high level tree -> logical plan
|
|
|
|
// AstStorage and SymbolTable may be modified during planning. The created
|
|
|
|
// LogicalPlan must take ownership of AstStorage and SymbolTable.
|
2018-10-19 22:18:44 +08:00
|
|
|
virtual std::unique_ptr<LogicalPlan> MakeLogicalPlan(
|
|
|
|
CypherQuery *, AstStorage, const Parameters &,
|
|
|
|
database::GraphDbAccessor *);
|
|
|
|
|
|
|
|
virtual void PrettyPrintPlan(const database::GraphDbAccessor &,
|
|
|
|
const plan::LogicalOperator *, std::ostream *);
|
2018-08-24 16:12:04 +08:00
|
|
|
|
2019-01-25 22:45:13 +08:00
|
|
|
virtual std::string PlanToJson(const database::GraphDbAccessor &,
|
|
|
|
const plan::LogicalOperator *);
|
|
|
|
|
2017-06-08 00:28:31 +08:00
|
|
|
private:
|
2019-08-20 15:33:31 +08:00
|
|
|
struct QueryCacheEntry {
|
|
|
|
bool operator==(const QueryCacheEntry &other) const {
|
|
|
|
return first == other.first;
|
|
|
|
}
|
|
|
|
bool operator<(const QueryCacheEntry &other) const {
|
|
|
|
return first < other.first;
|
|
|
|
}
|
|
|
|
bool operator==(const HashType &other) const { return first == other; }
|
|
|
|
bool operator<(const HashType &other) const { return first < other; }
|
|
|
|
|
|
|
|
HashType first;
|
|
|
|
// TODO: Maybe store the query string here and use it as a key with the hash
|
|
|
|
// so that we eliminate the risk of hash collisions.
|
|
|
|
CachedQuery second;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct PlanCacheEntry {
|
|
|
|
bool operator==(const PlanCacheEntry &other) const {
|
|
|
|
return first == other.first;
|
|
|
|
}
|
|
|
|
bool operator<(const PlanCacheEntry &other) const {
|
|
|
|
return first < other.first;
|
|
|
|
}
|
|
|
|
bool operator==(const HashType &other) const { return first == other; }
|
|
|
|
bool operator<(const HashType &other) const { return first < other; }
|
|
|
|
|
|
|
|
HashType first;
|
|
|
|
// TODO: Maybe store the query string here and use it as a key with the hash
|
|
|
|
// so that we eliminate the risk of hash collisions.
|
|
|
|
std::shared_ptr<CachedPlan> second;
|
|
|
|
};
|
|
|
|
|
|
|
|
utils::SkipList<QueryCacheEntry> ast_cache_;
|
|
|
|
utils::SkipList<PlanCacheEntry> plan_cache_;
|
|
|
|
|
2018-03-15 22:00:43 +08:00
|
|
|
// Antlr has singleton instance that is shared between threads. It is
|
|
|
|
// protected by locks inside of antlr. Unfortunately, they are not protected
|
|
|
|
// in a very good way. Once we have antlr version without race conditions we
|
|
|
|
// can remove this lock. This will probably never happen since antlr
|
|
|
|
// developers introduce more bugs in each version. Fortunately, we have cache
|
|
|
|
// so this lock probably won't impact performance much...
|
2018-05-30 19:00:25 +08:00
|
|
|
utils::SpinLock antlr_lock_;
|
2019-01-15 18:11:06 +08:00
|
|
|
bool is_tsc_available_;
|
2018-03-15 22:00:43 +08:00
|
|
|
|
2018-08-16 16:13:04 +08:00
|
|
|
// high level tree -> CachedPlan
|
2018-10-19 22:18:44 +08:00
|
|
|
std::shared_ptr<CachedPlan> CypherQueryToPlan(
|
|
|
|
HashType query_hash, CypherQuery *query, AstStorage ast_storage,
|
|
|
|
const Parameters ¶meters, database::GraphDbAccessor *db_accessor);
|
|
|
|
|
2017-09-19 22:58:22 +08:00
|
|
|
// stripped query -> high level tree
|
2018-10-24 23:44:53 +08:00
|
|
|
ParsedQuery ParseQuery(const std::string &stripped_query,
|
|
|
|
const std::string &original_query,
|
2019-01-16 18:30:17 +08:00
|
|
|
const frontend::ParsingContext &context,
|
|
|
|
AstStorage *ast_storage,
|
2018-10-24 23:44:53 +08:00
|
|
|
database::GraphDbAccessor *db_accessor);
|
2017-06-08 00:28:31 +08:00
|
|
|
};
|
2017-04-26 22:12:39 +08:00
|
|
|
|
|
|
|
} // namespace query
|