2017-03-22 23:38:43 +08:00
|
|
|
#pragma once
|
|
|
|
|
2017-06-21 17:29:13 +08:00
|
|
|
#include <gflags/gflags.h>
|
|
|
|
|
2017-09-27 20:02:24 +08:00
|
|
|
#include "data_structures/concurrent/concurrent_map.hpp"
|
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"
|
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"
|
2018-01-26 23:22:59 +08:00
|
|
|
#include "query/plan/distributed.hpp"
|
2017-09-19 22:58:22 +08:00
|
|
|
#include "query/plan/operator.hpp"
|
2018-05-30 19:00:25 +08:00
|
|
|
#include "utils/thread/sync.hpp"
|
2017-07-15 01:33:45 +08:00
|
|
|
#include "utils/timer.hpp"
|
2017-03-22 23:38:43 +08:00
|
|
|
|
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-03-13 17:35:14 +08:00
|
|
|
namespace distributed {
|
|
|
|
class PlanDispatcher;
|
|
|
|
}
|
|
|
|
|
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 {
|
|
|
|
|
2017-06-21 17:29:13 +08:00
|
|
|
class Interpreter {
|
2017-09-19 22:58:22 +08:00
|
|
|
private:
|
2018-03-15 22:00:43 +08:00
|
|
|
/// Encapsulates a plan for caching. Takes care of remote (worker) cache
|
|
|
|
/// updating in distributed memgraph.
|
2017-09-19 22:58:22 +08:00
|
|
|
class CachedPlan {
|
|
|
|
public:
|
2018-03-15 22:00:43 +08:00
|
|
|
/// Creates a cached plan and sends it to all the workers.
|
|
|
|
CachedPlan(plan::DistributedPlan distributed_plan, double cost,
|
|
|
|
distributed::PlanDispatcher *plan_dispatcher);
|
|
|
|
|
|
|
|
/// Removes the cached plan from all the workers.
|
|
|
|
~CachedPlan();
|
2017-09-19 22:58:22 +08:00
|
|
|
|
2018-01-26 23:22:59 +08:00
|
|
|
const auto &plan() const { return *distributed_plan_.master_plan; }
|
|
|
|
const auto &distributed_plan() const { return distributed_plan_; }
|
2017-09-19 22:58:22 +08:00
|
|
|
double cost() const { return cost_; }
|
2018-01-26 23:22:59 +08:00
|
|
|
const auto &symbol_table() const { return distributed_plan_.symbol_table; }
|
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-01-26 23:22:59 +08:00
|
|
|
plan::DistributedPlan distributed_plan_;
|
2017-09-19 22:58:22 +08:00
|
|
|
double cost_;
|
|
|
|
utils::Timer cache_timer_;
|
2018-03-13 17:35:14 +08:00
|
|
|
|
|
|
|
// Optional, only available in a distributed master.
|
|
|
|
distributed::PlanDispatcher *plan_dispatcher_{nullptr};
|
|
|
|
};
|
|
|
|
|
2018-03-15 22:00:43 +08:00
|
|
|
using PlanCacheT = ConcurrentMap<HashType, std::shared_ptr<CachedPlan>>;
|
|
|
|
|
2017-06-08 00:28:31 +08:00
|
|
|
public:
|
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;
|
2017-12-27 19:11:20 +08:00
|
|
|
Results(Context ctx, std::shared_ptr<CachedPlan> plan,
|
|
|
|
std::unique_ptr<query::plan::Cursor> cursor,
|
2017-12-22 20:39:31 +08:00
|
|
|
std::vector<Symbol> output_symbols, std::vector<std::string> header,
|
2018-08-16 16:13:04 +08:00
|
|
|
std::map<std::string, TypedValue> summary, PlanCacheT &plan_cache,
|
|
|
|
std::vector<AuthQuery::Privilege> privileges)
|
2017-12-22 20:39:31 +08:00
|
|
|
: ctx_(std::move(ctx)),
|
2017-12-27 19:11:20 +08:00
|
|
|
plan_(plan),
|
2017-12-22 20:39:31 +08:00
|
|
|
cursor_(std::move(cursor)),
|
|
|
|
frame_(ctx_.symbol_table_.max_position()),
|
|
|
|
output_symbols_(output_symbols),
|
|
|
|
header_(header),
|
|
|
|
summary_(summary),
|
2018-08-16 16:13:04 +08:00
|
|
|
plan_cache_(plan_cache),
|
|
|
|
privileges_(std::move(privileges)) {}
|
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;
|
2017-12-22 20:39:31 +08:00
|
|
|
bool return_value = cursor_->Pull(frame_, ctx_);
|
|
|
|
if (return_value && !output_symbols_.empty()) {
|
|
|
|
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_;
|
2017-12-22 20:39:31 +08:00
|
|
|
|
|
|
|
if (ctx_.is_index_created_) {
|
2018-03-15 22:00:43 +08:00
|
|
|
auto access = plan_cache_.access();
|
|
|
|
for (auto &kv : access) {
|
|
|
|
access.remove(kv.first);
|
|
|
|
}
|
2017-12-22 20:39:31 +08:00
|
|
|
}
|
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_;
|
|
|
|
}
|
|
|
|
|
2017-12-22 20:39:31 +08:00
|
|
|
private:
|
|
|
|
Context ctx_;
|
2017-12-27 19:11:20 +08:00
|
|
|
std::shared_ptr<CachedPlan> plan_;
|
2017-12-22 20:39:31 +08:00
|
|
|
std::unique_ptr<query::plan::Cursor> cursor_;
|
|
|
|
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};
|
2017-12-22 20:39:31 +08:00
|
|
|
// Gets invalidated after if an index has been built.
|
2018-03-15 22:00:43 +08:00
|
|
|
PlanCacheT &plan_cache_;
|
2018-08-16 16:13:04 +08:00
|
|
|
|
|
|
|
std::vector<AuthQuery::Privilege> privileges_;
|
2017-12-22 20:39:31 +08:00
|
|
|
};
|
2017-06-08 00:28:31 +08:00
|
|
|
|
2018-03-13 17:35:14 +08:00
|
|
|
explicit Interpreter(database::GraphDb &db);
|
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
|
|
|
|
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
|
|
|
*/
|
2018-01-12 22:17:04 +08:00
|
|
|
Results operator()(const std::string &query,
|
|
|
|
database::GraphDbAccessor &db_accessor,
|
2017-12-22 20:39:31 +08:00
|
|
|
const std::map<std::string, TypedValue> ¶ms,
|
|
|
|
bool in_explicit_transaction);
|
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;
|
|
|
|
|
2017-06-08 00:28:31 +08:00
|
|
|
private:
|
2018-05-22 22:45:52 +08:00
|
|
|
ConcurrentMap<HashType, AstStorage> ast_cache_;
|
2018-03-15 22:00:43 +08:00
|
|
|
PlanCacheT plan_cache_;
|
|
|
|
std::atomic<int64_t> next_plan_id_{0};
|
|
|
|
// 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_;
|
2018-03-15 22:00:43 +08:00
|
|
|
|
|
|
|
// Optional, not null only in a distributed master.
|
|
|
|
distributed::PlanDispatcher *plan_dispatcher_{nullptr};
|
|
|
|
|
2018-08-16 16:13:04 +08:00
|
|
|
// high level tree -> CachedPlan
|
|
|
|
std::shared_ptr<CachedPlan> AstToPlan(AstStorage &ast_storage, Context &ctx);
|
2017-09-19 22:58:22 +08:00
|
|
|
// stripped query -> high level tree
|
2018-05-22 22:45:52 +08:00
|
|
|
AstStorage QueryToAst(const StrippedQuery &stripped, Context &ctx);
|
2017-09-19 22:58:22 +08:00
|
|
|
|
|
|
|
// high level tree -> (logical plan, plan cost)
|
2018-05-22 22:45:52 +08:00
|
|
|
// AstStorage and SymbolTable may be modified during planning.
|
2017-09-19 22:58:22 +08:00
|
|
|
std::pair<std::unique_ptr<plan::LogicalOperator>, double> MakeLogicalPlan(
|
2018-05-22 22:45:52 +08:00
|
|
|
AstStorage &, Context &);
|
2017-06-08 00:28:31 +08:00
|
|
|
};
|
2017-04-26 22:12:39 +08:00
|
|
|
|
|
|
|
} // namespace query
|