Compare commits

...

5 Commits

Author SHA1 Message Date
Matej Ferencevic
df12e26928 Bump version and update changelog 2019-01-22 11:31:39 +01:00
Marin Tomic
e24ff84ac0 Fix filtering of edges by edge type and destination
Summary:
`Edges` class didn't properly filter edges when given both edge type
and destination arguments, which causes weird bugs in query execution (wrong
edge getting matched in `Expand` with existing node flag set). This is probably
because we didn't support using both filters at the same time, but the API and
documentation for `VertexAccessor::in` and `VertexAccessor::out` functions
didn't reflect that.

Reviewers: teon.banek, msantl

Reviewed By: msantl

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1796
2019-01-22 11:29:01 +01:00
Matija Santl
55c1b03cca Reset TransactionEngine internal state on Abort
Summary:
With neo4j java driver 1.7.0. they don't send `ROLLBACK`. This causes
unexpected nested transaction errors. This diff should fix that.

Reviewers: mferencevic

Reviewed By: mferencevic

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1780
2019-01-22 11:22:32 +01:00
Matej Ferencevic
99ed97d988 Restore CentOS support
Reviewers: teon.banek

Reviewed By: teon.banek

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1777
2019-01-22 10:55:09 +01:00
Matej Ferencevic
2bfe6d8f4f Prepare release v0.14.0
Reviewers: buda, teon.banek

Reviewed By: teon.banek

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1707
2018-10-30 16:32:22 +01:00
61 changed files with 310 additions and 2562 deletions

View File

@@ -1,5 +1,12 @@
# Change Log
## v0.14.1
### Bug Fixes and Other Changes
* Fix bug in explicit transaction handling
* Fix bug in edge filtering by edge type and destination
## v0.14.0
### Breaking Changes

View File

@@ -42,7 +42,7 @@ string(STRIP ${COMMIT_HASH} COMMIT_HASH)
# -----------------------------------------------------------------------------
project(memgraph VERSION 0.14.0)
project(memgraph VERSION 0.14.1)
# -----------------------------------------------------------------------------
# setup CMake module path, defines path for include() and find_package()
@@ -342,7 +342,7 @@ set(CPACK_RPM_PACKAGE_DESCRIPTION "Contains Memgraph, the graph database.
It aims to deliver developers the speed, simplicity and scale required to build
the next generation of applications driver by real-time connected data.")
# Add `openssl` package to dependencies list. Used to generate SSL certificates.
set(CPACK_RPM_PACKAGE_REQUIRES "openssl >= 1.0.0")
set(CPACK_RPM_PACKAGE_REQUIRES "openssl >= 1.0.0, curl >= 7.29.0")
# All variables must be set before including.
include(CPack)

View File

@@ -1,12 +1,9 @@
- name: Binaries
archive:
- build_debug/memgraph
- build_debug/memgraph_distributed
- build_release/memgraph
- build_release/memgraph_distributed
- build_release/tools/src/mg_client
- build_release/tools/src/mg_import_csv
- build_release/tools/src/mg_statsd
- config
filename: binaries.tar.gz

View File

@@ -31,12 +31,8 @@
mkdir build_release
cd build_release
cmake -DCMAKE_BUILD_TYPE=release ..
TIMEOUT=1200 make -j$THREADS memgraph memgraph_distributed tools memgraph__macro_benchmark memgraph__stress memgraph__manual__card_fraud_generate_snapshot memgraph__feature_benchmark__kafka__benchmark
# Generate distributed card fraud dataset.
cd ../tests/distributed/card_fraud
./generate_dataset.sh
cd ../../..
TIMEOUT=1200 make -j$THREADS memgraph tools memgraph__macro_benchmark memgraph__stress
cd ..
# Checkout to parent commit and initialize.
cd ../parent
@@ -83,7 +79,3 @@
mkdir output
cd output
cpack -G DEB --config ../CPackConfig.cmake
# Generate distributed card fraud dataset.
cd ../../tests/distributed/card_fraud
./generate_dataset.sh

View File

@@ -210,46 +210,6 @@ import_external_library(rocksdb STATIC
CXX=${CMAKE_CXX_COMPILER}
INSTALL_COMMAND true)
# Setup Cap'n Proto
ExternalProject_Add(capnproto-proj
PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/capnproto
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/capnproto
BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/capnproto
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/capnproto/configure
--prefix=${CMAKE_CURRENT_SOURCE_DIR}/capnproto/local
--enable-shared=no --silent
CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER}
BUILD_COMMAND make -j${NPROC} check)
set(CAPNP_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/capnproto/local/include
CACHE FILEPATH "Path to capnproto include directory" FORCE)
set(CAPNP_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/capnproto/local/lib/libcapnp.a
CACHE FILEPATH "Path to capnproto library" FORCE)
set(KJ_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/capnproto/local/lib/libkj.a
CACHE FILEPATH "Path to kj library (used by capnproto)" FORCE)
import_library(capnp STATIC ${CAPNP_LIBRARY} capnproto-proj)
import_library(kj STATIC ${KJ_LIBRARY} capnproto-proj)
set(CAPNP_EXE ${CMAKE_CURRENT_SOURCE_DIR}/capnproto/local/bin/capnp
CACHE FILEPATH "Path to capnproto executable" FORCE)
set(CAPNP_CXX_EXE ${CMAKE_CURRENT_SOURCE_DIR}/capnproto/local/bin/capnpc-c++
CACHE FILEPATH "Path to capnproto c++ plugin executable" FORCE)
mark_as_advanced(CAPNP_INCLUDE_DIR CAPNP_LIBRARY KJ_LIBRARY CAPNP_EXE CAPNP_CXX_EXE)
# Setup librdkafka.
import_external_library(librdkafka STATIC
${CMAKE_CURRENT_SOURCE_DIR}/librdkafka/lib/librdkafka.a
${CMAKE_CURRENT_SOURCE_DIR}/librdkafka/include/librdkafka
CMAKE_ARGS -DRDKAFKA_BUILD_STATIC=ON
-DRDKAFKA_BUILD_EXAMPLES=OFF
-DRDKAFKA_BUILD_TESTS=OFF
-DCMAKE_INSTALL_LIBDIR=lib
-DWITH_SSL=ON
# If we want SASL, we need to install it on build machines
-DWITH_SASL=OFF)
import_library(librdkafka++ STATIC
${CMAKE_CURRENT_SOURCE_DIR}/librdkafka/lib/librdkafka++.a
librdkafka-proj)
# Setup libbcrypt
import_external_library(libbcrypt STATIC
${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/bcrypt.a

View File

@@ -125,15 +125,3 @@ clone git://deps.memgraph.io/zlib.git zlib $zlib_tag
rocksdb_tag="dbd8fa09b823826dd2a30bc119dad7a6fa9a4c6d" # v5.11.3 Mar 12, 2018
clone git://deps.memgraph.io/rocksdb.git rocksdb $rocksdb_tag
# Cap'n Proto serialization (and RPC) lib
wget -nv http://deps.memgraph.io/capnproto-c++-0.6.1.tar.gz -O capnproto.tar.gz
tar -xzf capnproto.tar.gz
rm -rf capnproto
mv capnproto-c++-0.6.1 capnproto
rm capnproto.tar.gz
# kafka
kafka_tag="c319b4e987d0bc4fe4f01cf91419d90b62061655" # Mar 8, 2018
# git clone https://github.com/edenhill/librdkafka.git
clone git://deps.memgraph.io/librdkafka.git librdkafka $kafka_tag

View File

@@ -69,8 +69,17 @@ chown memgraph:memgraph /var/lib/memgraph || exit 1
chmod 750 /var/lib/memgraph || exit 1
chown memgraph:adm /var/log/memgraph || exit 1
chmod 750 /var/log/memgraph || exit 1
# Make examples directory immutable (optional)
chattr +i -R /usr/share/memgraph/examples || true
# Create telemetry directory in examples
for i in /usr/share/memgraph/examples/*; do
# The telemetry directory may already exist from some prior installation
if [ ! -d $i/telemetry ]; then
mkdir $i/telemetry || exit 1
fi
chown -R memgraph:memgraph $i/telemetry || exit 1
# Make snapshots directory immutable (optional)
chattr +i -R $i/snapshots || true
done
# Generate SSL certificates
if [ ! -d /etc/memgraph/ssl ]; then

View File

@@ -4,12 +4,9 @@
add_subdirectory(lisp)
add_subdirectory(utils)
add_subdirectory(requests)
add_subdirectory(integrations)
add_subdirectory(io)
add_subdirectory(telemetry)
add_subdirectory(communication)
add_subdirectory(stats)
add_subdirectory(auth)
# ----------------------------------------------------------------------------
# Memgraph Single Node
@@ -24,12 +21,10 @@ set(mg_single_node_sources
durability/single_node/recovery.cpp
durability/single_node/snapshooter.cpp
durability/single_node/wal.cpp
glue/auth.cpp
glue/communication.cpp
query/common.cpp
query/frontend/ast/ast.cpp
query/frontend/ast/cypher_main_visitor.cpp
query/frontend/semantic/required_privileges.cpp
query/frontend/semantic/symbol_generator.cpp
query/frontend/stripped.cpp
query/interpret/awesome_memgraph_functions.cpp
@@ -60,8 +55,8 @@ add_lcp_single_node(query/plan/operator.lcp)
add_custom_target(generate_lcp_single_node DEPENDS ${generated_lcp_single_node_files})
set(MG_SINGLE_NODE_LIBS stdc++fs Threads::Threads fmt cppitertools
antlr_opencypher_parser_lib dl glog gflags capnp kj
mg-utils mg-io mg-integrations-kafka mg-requests mg-communication mg-auth mg-stats)
antlr_opencypher_parser_lib dl glog gflags
mg-utils mg-io mg-requests mg-communication)
if (USE_LTALLOC)
list(APPEND MG_SINGLE_NODE_LIBS ltalloc)
@@ -83,161 +78,6 @@ target_compile_definitions(mg-single-node PUBLIC MG_SINGLE_NODE)
# END Memgraph Single Node
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Memgraph Distributed
# ----------------------------------------------------------------------------
set(mg_distributed_sources
database/distributed/distributed_counters.cpp
database/distributed/distributed_graph_db.cpp
distributed/bfs_rpc_clients.cpp
distributed/bfs_subcursor.cpp
distributed/cluster_discovery_master.cpp
distributed/cluster_discovery_worker.cpp
distributed/coordination.cpp
distributed/coordination_master.cpp
distributed/coordination_worker.cpp
distributed/data_manager.cpp
distributed/data_rpc_clients.cpp
distributed/data_rpc_server.cpp
distributed/dgp/partitioner.cpp
distributed/dgp/vertex_migrator.cpp
distributed/durability_rpc_master.cpp
distributed/durability_rpc_worker.cpp
distributed/dynamic_worker.cpp
distributed/index_rpc_server.cpp
distributed/plan_consumer.cpp
distributed/plan_dispatcher.cpp
distributed/produce_rpc_server.cpp
distributed/pull_rpc_clients.cpp
distributed/updates_rpc_clients.cpp
distributed/updates_rpc_server.cpp
query/distributed_interpreter.cpp
query/plan/distributed.cpp
query/plan/distributed_ops.cpp
query/plan/distributed_pretty_print.cpp
storage/distributed/concurrent_id_mapper_master.cpp
storage/distributed/concurrent_id_mapper_worker.cpp
transactions/distributed/engine_master.cpp
transactions/distributed/engine_worker.cpp
data_structures/concurrent/skiplist_gc.cpp
database/distributed/config.cpp
database/distributed/graph_db_accessor.cpp
durability/distributed/state_delta.cpp
durability/distributed/paths.cpp
durability/distributed/recovery.cpp
durability/distributed/snapshooter.cpp
durability/distributed/wal.cpp
glue/auth.cpp
glue/communication.cpp
query/common.cpp
query/frontend/ast/ast.cpp
query/frontend/ast/cypher_main_visitor.cpp
query/frontend/semantic/required_privileges.cpp
query/frontend/semantic/symbol_generator.cpp
query/frontend/stripped.cpp
query/interpret/awesome_memgraph_functions.cpp
query/interpreter.cpp
query/plan/operator.cpp
query/plan/preprocess.cpp
query/plan/pretty_print.cpp
query/plan/rule_based_planner.cpp
query/plan/variable_start_planner.cpp
query/repl.cpp
query/serialization.cpp
query/typed_value.cpp
storage/common/property_value.cpp
storage/common/property_value_store.cpp
storage/distributed/edge_accessor.cpp
storage/distributed/record_accessor.cpp
storage/distributed/serialization.cpp
storage/distributed/vertex_accessor.cpp
storage/locking/record_lock.cpp
memgraph_init.cpp
transactions/distributed/engine_single_node.cpp
)
# -----------------------------------------------------------------------------
define_add_capnp(mg_distributed_sources generated_capnp_files)
define_add_lcp(add_lcp_distributed mg_distributed_sources generated_lcp_distributed_files)
add_lcp_distributed(durability/distributed/state_delta.lcp)
add_lcp_distributed(database/distributed/counters_rpc_messages.lcp CAPNP_SCHEMA @0x95a2c3ea3871e945)
add_capnp(database/distributed/counters_rpc_messages.capnp)
add_lcp_distributed(database/distributed/serialization.lcp CAPNP_SCHEMA @0xdea01657b3563887
DEPENDS durability/distributed/state_delta.lcp)
add_capnp(database/distributed/serialization.capnp)
add_lcp_distributed(distributed/bfs_rpc_messages.lcp CAPNP_SCHEMA @0x8e508640b09b6d2a)
add_capnp(distributed/bfs_rpc_messages.capnp)
add_lcp_distributed(distributed/coordination_rpc_messages.lcp CAPNP_SCHEMA @0x93df0c4703cf98fb)
add_capnp(distributed/coordination_rpc_messages.capnp)
add_lcp_distributed(distributed/data_rpc_messages.lcp CAPNP_SCHEMA @0xc1c8a341ba37aaf5)
add_capnp(distributed/data_rpc_messages.capnp)
add_lcp_distributed(distributed/durability_rpc_messages.lcp CAPNP_SCHEMA @0xf5e53bc271e2163d)
add_capnp(distributed/durability_rpc_messages.capnp)
add_lcp_distributed(distributed/index_rpc_messages.lcp CAPNP_SCHEMA @0xa8aab46862945bd6)
add_capnp(distributed/index_rpc_messages.capnp)
add_lcp_distributed(distributed/plan_rpc_messages.lcp CAPNP_SCHEMA @0xfcbc48dc9f106d28)
add_capnp(distributed/plan_rpc_messages.capnp)
add_lcp_distributed(distributed/pull_produce_rpc_messages.lcp CAPNP_SCHEMA @0xa78a9254a73685bd
DEPENDS transactions/distributed/serialization.lcp)
add_capnp(distributed/pull_produce_rpc_messages.capnp)
add_lcp_distributed(distributed/storage_gc_rpc_messages.lcp CAPNP_SCHEMA @0xd705663dfe36cf81)
add_capnp(distributed/storage_gc_rpc_messages.capnp)
add_lcp_distributed(distributed/token_sharing_rpc_messages.lcp CAPNP_SCHEMA @0x8f295db54ec4caec)
add_capnp(distributed/token_sharing_rpc_messages.capnp)
add_lcp_distributed(distributed/updates_rpc_messages.lcp CAPNP_SCHEMA @0x82d5f38d73c7b53a)
add_capnp(distributed/updates_rpc_messages.capnp)
add_lcp_distributed(distributed/dynamic_worker_rpc_messages.lcp CAPNP_SCHEMA @0x8c53f6c9a0c71b05)
add_capnp(distributed/dynamic_worker_rpc_messages.capnp)
# distributed_ops.lcp is leading the capnp code generation, so we don't need
# to generate any capnp for operator.lcp
add_lcp_distributed(query/frontend/ast/ast.lcp)
add_lcp_distributed(query/frontend/ast/ast_serialization.lcp CAPNP_SCHEMA @0xb107d3d6b4b1600b
DEPENDS query/frontend/ast/ast.lcp)
add_capnp(query/frontend/ast/ast_serialization.capnp)
add_lcp_distributed(query/plan/operator.lcp)
add_lcp_distributed(query/plan/distributed_ops.lcp CAPNP_SCHEMA @0xe5cae8d045d30c42
DEPENDS query/plan/operator.lcp)
add_capnp(query/plan/distributed_ops.capnp)
add_lcp_distributed(storage/distributed/concurrent_id_mapper_rpc_messages.lcp CAPNP_SCHEMA @0xa6068dae93d225dd)
add_capnp(storage/distributed/concurrent_id_mapper_rpc_messages.capnp)
add_lcp_distributed(transactions/distributed/engine_rpc_messages.lcp CAPNP_SCHEMA @0xde02b7c49180cad5
DEPENDS transactions/distributed/serialization.lcp)
add_capnp(transactions/distributed/engine_rpc_messages.capnp)
add_custom_target(generate_lcp_distributed DEPENDS ${generated_lcp_distributed_files})
# Registering capnp must come after registering lcp files.
add_capnp(communication/rpc/messages.capnp)
add_capnp(durability/distributed/serialization.capnp)
add_capnp(query/frontend/semantic/symbol.capnp)
add_capnp(query/serialization.capnp)
add_capnp(storage/distributed/serialization.capnp)
add_custom_target(generate_capnp DEPENDS generate_lcp_distributed ${generated_capnp_files})
set(MG_DISTRIBUTED_LIBS stdc++fs Threads::Threads fmt cppitertools
antlr_opencypher_parser_lib dl glog gflags capnp kj
mg-utils mg-io mg-integrations-kafka mg-requests mg-communication mg-auth mg-stats)
# STATIC library used by memgraph executables
add_library(mg-distributed STATIC ${mg_distributed_sources})
target_link_libraries(mg-distributed ${MG_DISTRIBUTED_LIBS})
add_dependencies(mg-distributed generate_opencypher_parser)
add_dependencies(mg-distributed generate_lcp_distributed)
add_dependencies(mg-distributed generate_capnp)
target_compile_definitions(mg-distributed PUBLIC MG_DISTRIBUTED)
# ----------------------------------------------------------------------------
# END Memgraph Distributed
# ----------------------------------------------------------------------------
string(TOLOWER ${CMAKE_BUILD_TYPE} lower_build_type)
# STATIC library used to store key-value pairs
@@ -311,18 +151,3 @@ install(
${CMAKE_BINARY_DIR}/tests/manual/bolt_client
WORKING_DIRECTORY ${examples})")
install(DIRECTORY ${examples}/build/ DESTINATION share/memgraph/examples)
# memgraph distributed main executable
add_executable(memgraph_distributed memgraph_distributed.cpp)
target_link_libraries(memgraph_distributed mg-distributed kvstore_lib telemetry_lib)
set_target_properties(memgraph_distributed PROPERTIES
# Set the executable output name to include version information.
OUTPUT_NAME "memgraph_distributed-${memgraph_VERSION}-${COMMIT_HASH}_${CMAKE_BUILD_TYPE}"
# Output the executable in main binary dir.
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
# Create symlink to the built executable.
add_custom_command(TARGET memgraph_distributed POST_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:memgraph_distributed> ${CMAKE_BINARY_DIR}/memgraph_distributed
BYPRODUCTS ${CMAKE_BINARY_DIR}/memgraph_distributed
COMMENT Creating symlink to memgraph distributed executable)

View File

@@ -4,20 +4,9 @@ set(communication_src_files
client.cpp
context.cpp
helpers.cpp
init.cpp
rpc/client.cpp
rpc/protocol.cpp
rpc/server.cpp)
define_add_capnp(communication_src_files communication_capnp_files)
add_capnp(rpc/messages.capnp)
add_custom_target(generate_communication_capnp DEPENDS ${communication_capnp_files})
init.cpp)
add_library(mg-communication STATIC ${communication_src_files})
target_link_libraries(mg-communication Threads::Threads mg-utils mg-io fmt glog gflags)
target_link_libraries(mg-communication ${OPENSSL_LIBRARIES})
target_include_directories(mg-communication SYSTEM PUBLIC ${OPENSSL_INCLUDE_DIR})
target_link_libraries(mg-communication capnp kj)
add_dependencies(mg-communication generate_communication_capnp)

View File

@@ -60,10 +60,6 @@ class Session {
/** Aborts currently running query. */
virtual void Abort() = 0;
/** Return `true` if the user was successfully authenticated. */
virtual bool Authenticate(const std::string &username,
const std::string &password) = 0;
/**
* Executes the session after data has been read into the buffer.
* Goes through the bolt states in order to execute commands from the client.

View File

@@ -60,38 +60,6 @@ State StateInitRun(Session &session) {
LOG(INFO) << fmt::format("Client connected '{}'", client_name.ValueString())
<< std::endl;
// Get authentication data.
std::string username, password;
auto &data = metadata.ValueMap();
if (!data.count("scheme")) {
LOG(WARNING) << "The client didn't supply authentication information!";
return State::Close;
}
if (data["scheme"].ValueString() == "basic") {
if (!data.count("principal") || !data.count("credentials")) {
LOG(WARNING) << "The client didn't supply authentication information!";
return State::Close;
}
username = data["principal"].ValueString();
password = data["credentials"].ValueString();
} else if (data["scheme"].ValueString() != "none") {
LOG(WARNING) << "Unsupported authentication scheme: "
<< data["scheme"].ValueString();
return State::Close;
}
// Authenticate the user.
if (!session.Authenticate(username, password)) {
if (!session.encoder_.MessageFailure(
{{"code", "Memgraph.ClientError.Security.Unauthenticated"},
{"message", "Authentication failure"}})) {
DLOG(WARNING) << "Couldn't send failure message to the client!";
}
// Throw an exception to indicate to the network stack that the session
// should be closed and cleaned up.
throw SessionClosedException("The client is not authenticated!");
}
// Return success.
if (!session.encoder_.MessageSuccess()) {
DLOG(WARNING) << "Couldn't send success message to the client!";

View File

@@ -6,7 +6,11 @@ namespace communication {
ClientContext::ClientContext(bool use_ssl) : use_ssl_(use_ssl), ctx_(nullptr) {
if (use_ssl_) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
ctx_ = SSL_CTX_new(SSLv23_client_method());
#else
ctx_ = SSL_CTX_new(TLS_client_method());
#endif
CHECK(ctx_ != nullptr) << "Couldn't create client SSL_CTX object!";
// Disable legacy SSL support. Other options can be seen here:
@@ -37,7 +41,13 @@ ServerContext::ServerContext() : use_ssl_(false), ctx_(nullptr) {}
ServerContext::ServerContext(const std::string &key_file,
const std::string &cert_file,
const std::string &ca_file, bool verify_peer)
: use_ssl_(true), ctx_(SSL_CTX_new(TLS_server_method())) {
: use_ssl_(true),
#if OPENSSL_VERSION_NUMBER < 0x10100000L
ctx_(SSL_CTX_new(SSLv23_server_method()))
#else
ctx_(SSL_CTX_new(TLS_server_method()))
#endif
{
// TODO (mferencevic): add support for encrypted private keys
// TODO (mferencevic): add certificate revocation list (CRL)
CHECK(SSL_CTX_use_certificate_file(ctx_, cert_file.c_str(),

View File

@@ -66,10 +66,6 @@ bool VersionConsistency(const fs::path &durability_dir) {
return true;
}
bool DistributedVersionConsistency(const int64_t master_version) {
return durability::kVersion == master_version;
}
bool ContainsDurabilityFiles(const fs::path &durability_dir) {
for (const auto &durability_type : {kSnapshotDir, kWalDir}) {
auto recovery_dir = durability_dir / durability_type;

View File

@@ -75,15 +75,6 @@ bool ReadSnapshotSummary(HashedFileReader &buffer, int64_t &vertex_count,
bool VersionConsistency(
const std::experimental::filesystem::path &durability_dir);
/**
* Checks whether the current memgraph binary (on a worker) is
* version consistent with the cluster master.
*
* @param master_version - Version of the master.
* @return - True if versions match.
*/
bool DistributedVersionConsistency(const int64_t master_version);
/**
* Checks whether the durability directory contains snapshot
* or write-ahead log file.

View File

@@ -4,13 +4,5 @@ set(io_src_files
network/socket.cpp
network/utils.cpp)
define_add_capnp(io_src_files io_capnp_files)
add_capnp(network/endpoint.capnp)
add_custom_target(generate_io_capnp DEPENDS ${io_capnp_files})
add_library(mg-io STATIC ${io_src_files})
target_link_libraries(mg-io stdc++fs Threads::Threads fmt glog mg-utils)
target_link_libraries(mg-io capnp kj)
add_dependencies(mg-io generate_io_capnp)

View File

@@ -24,18 +24,6 @@ Endpoint::Endpoint(const std::string &address, uint16_t port)
CHECK(family_ != 0) << "Not a valid IPv4 or IPv6 address: " << address;
}
void Save(const Endpoint &endpoint, capnp::Endpoint::Builder *builder) {
builder->setAddress(endpoint.address());
builder->setPort(endpoint.port());
builder->setFamily(endpoint.family());
}
void Load(Endpoint *endpoint, const capnp::Endpoint::Reader &reader) {
endpoint->address_ = reader.getAddress();
endpoint->port_ = reader.getPort();
endpoint->family_ = reader.getFamily();
}
bool Endpoint::operator==(const Endpoint &other) const {
return address_ == other.address_ && port_ == other.port_ &&
family_ == other.family_;

View File

@@ -5,7 +5,6 @@
#include <iostream>
#include <string>
#include "io/network/endpoint.capnp.h"
#include "utils/exceptions.hpp"
namespace io::network {
@@ -33,8 +32,4 @@ class Endpoint {
unsigned char family_{0};
};
void Save(const Endpoint &endpoint, capnp::Endpoint::Builder *builder);
void Load(Endpoint *endpoint, const capnp::Endpoint::Reader &reader);
} // namespace io::network

View File

@@ -11,8 +11,6 @@
#include "communication/server.hpp"
#include "database/single_node/graph_db.hpp"
#include "integrations/kafka/exceptions.hpp"
#include "integrations/kafka/streams.hpp"
#include "memgraph_init.hpp"
#include "query/exceptions.hpp"
#include "telemetry/telemetry.hpp"
@@ -48,25 +46,6 @@ void SingleNodeMain() {
query::Interpreter interpreter;
SessionData session_data{&db, &interpreter};
integrations::kafka::Streams kafka_streams{
std::experimental::filesystem::path(FLAGS_durability_directory) /
"streams",
[&session_data](
const std::string &query,
const std::map<std::string, communication::bolt::Value> &params) {
KafkaStreamWriter(session_data, query, params);
}};
try {
// Recover possible streams.
kafka_streams.Recover();
} catch (const integrations::kafka::KafkaStreamException &e) {
LOG(ERROR) << e.what();
}
session_data.interpreter->auth_ = &session_data.auth;
session_data.interpreter->kafka_streams_ = &kafka_streams;
ServerContext context;
std::string service_name = "Bolt";
if (FLAGS_key_file != "" && FLAGS_cert_file != "") {

View File

@@ -3,11 +3,9 @@
#include <glog/logging.h>
#include "config.hpp"
#include "glue/auth.hpp"
#include "glue/communication.hpp"
#include "query/exceptions.hpp"
#include "requests/requests.hpp"
#include "stats/stats.hpp"
#include "utils/signals.hpp"
#include "utils/sysinfo/memory.hpp"
#include "utils/terminate_handler.hpp"
@@ -28,8 +26,7 @@ BoltSession::BoltSession(SessionData *data, const io::network::Endpoint &,
: communication::bolt::Session<communication::InputStream,
communication::OutputStream>(input_stream,
output_stream),
transaction_engine_(data->db, data->interpreter),
auth_(&data->auth) {}
transaction_engine_(data->db, data->interpreter) {}
using TEncoder =
communication::bolt::Session<communication::InputStream,
@@ -42,21 +39,7 @@ std::vector<std::string> BoltSession::Interpret(
for (const auto &kv : params)
params_pv.emplace(kv.first, glue::ToPropertyValue(kv.second));
try {
auto result = transaction_engine_.Interpret(query, params_pv);
if (user_) {
const auto &permissions = user_->GetPermissions();
for (const auto &privilege : result.second) {
if (permissions.Has(glue::PrivilegeToPermission(privilege)) !=
auth::PermissionLevel::GRANT) {
transaction_engine_.Abort();
throw communication::bolt::ClientError(
"You are not authorized to execute this query! Please contact "
"your database administrator.");
}
}
}
return result.first;
return transaction_engine_.Interpret(query, params_pv);
} catch (const query::QueryException &e) {
// Wrap QueryException into ClientError, because we want to allow the
// client to fix their query.
@@ -83,13 +66,6 @@ std::map<std::string, communication::bolt::Value> BoltSession::PullAll(
void BoltSession::Abort() { transaction_engine_.Abort(); }
bool BoltSession::Authenticate(const std::string &username,
const std::string &password) {
if (!auth_->HasUsers()) return true;
user_ = auth_->Authenticate(username, password);
return !!user_;
}
BoltSession::TypedValueResultStream::TypedValueResultStream(TEncoder *encoder)
: encoder_(encoder) {}
@@ -103,24 +79,6 @@ void BoltSession::TypedValueResultStream::Result(
encoder_->MessageRecord(decoded_values);
}
void KafkaStreamWriter(
SessionData &session_data, const std::string &query,
const std::map<std::string, communication::bolt::Value> &params) {
auto dba = session_data.db->Access();
KafkaResultStream stream;
std::map<std::string, PropertyValue> params_pv;
for (const auto &kv : params)
params_pv.emplace(kv.first, glue::ToPropertyValue(kv.second));
try {
(*session_data.interpreter)(query, *dba, params_pv, false).PullAll(stream);
dba->Commit();
} catch (const utils::BasicException &e) {
LOG(WARNING) << "[Kafka] query execution failed with an exception: "
<< e.what();
dba->Abort();
}
};
// Needed to correctly handle memgraph destruction from a signal handler.
// Without having some sort of a flag, it is possible that a signal is handled
// when we are exiting main, inside destructors of database::GraphDb and
@@ -175,9 +133,6 @@ int WithInit(int argc, char **argv,
// Unhandled exception handler init.
std::set_terminate(&utils::TerminateHandler);
stats::InitStatsLogging(get_stats_prefix());
utils::OnScopeExit stop_stats([] { stats::StopStatsLogging(); });
// Initialize the communication library.
communication::Init();

View File

@@ -9,7 +9,6 @@
#include <gflags/gflags.h>
#include "auth/auth.hpp"
#include "communication/bolt/v1/session.hpp"
#include "communication/init.hpp"
#include "communication/session.hpp"
@@ -23,8 +22,6 @@ DECLARE_string(durability_directory);
struct SessionData {
database::GraphDb *db{nullptr};
query::Interpreter *interpreter{nullptr};
auth::Auth auth{
std::experimental::filesystem::path(FLAGS_durability_directory) / "auth"};
};
class BoltSession final
@@ -47,9 +44,6 @@ class BoltSession final
void Abort() override;
bool Authenticate(const std::string &username,
const std::string &password) override;
private:
/// Wrapper around TEncoder which converts TypedValue to Value
/// before forwarding the calls to original TEncoder.
@@ -64,17 +58,6 @@ class BoltSession final
};
query::TransactionEngine transaction_engine_;
auth::Auth *auth_;
std::experimental::optional<auth::User> user_;
};
/// Class that implements ResultStream API for Kafka.
///
/// Kafka doesn't need to stream the import results back to the client so we
/// don't need any functionality here.
class KafkaResultStream {
public:
void Result(const std::vector<query::TypedValue> &) {}
};
/// Writes data streamed from kafka to memgraph.

View File

@@ -8,7 +8,6 @@
#include "glog/logging.h"
#include "query/exceptions.hpp"
#include "utils/serialization.hpp"
#include "utils/string.hpp"
namespace query {

View File

@@ -115,19 +115,4 @@ class RemoveAttachedVertexException : public QueryRuntimeException {
"connections. Consider using DETACH DELETE.") {}
};
class UserModificationInMulticommandTxException : public QueryException {
public:
UserModificationInMulticommandTxException()
: QueryException(
"Authentication clause not allowed in multicommand transactions.") {
}
};
class StreamClauseInMulticommandTxException : public QueryException {
public:
StreamClauseInMulticommandTxException()
: QueryException(
"Stream clause not allowed in multicommand transactions.") {}
};
} // namespace query

View File

@@ -2202,146 +2202,6 @@ cpp<#
cpp<#)
(:serialize :capnp))
(lcp:define-class auth-query (query)
((action "Action" :scope :public)
(user "std::string" :scope :public)
(role "std::string" :scope :public)
(user-or-role "std::string" :scope :public)
(password "Expression *" :initval "nullptr" :scope :public
:capnp-type "Tree" :capnp-init nil
:capnp-save #'save-ast-pointer
:capnp-load (load-ast-pointer "Expression *"))
(privileges "std::vector<Privilege>" :scope :public))
(:public
(lcp:define-enum action
(create-role drop-role show-roles create-user
set-password drop-user show-users set-role
clear-role grant-privilege deny-privilege
revoke-privilege show-privileges
show-role-for-user show-users-for-role)
(:serialize :capnp))
(lcp:define-enum privilege
(create delete match merge set remove index auth stream)
(:serialize :capnp))
#>cpp
AuthQuery() = default;
DEFVISITABLE(TreeVisitor<TypedValue>);
DEFVISITABLE(HierarchicalTreeVisitor);
AuthQuery *Clone(AstStorage &storage) const override {
return storage.Create<AuthQuery>(
action_, user_, role_, user_or_role_,
password_ ? password_->Clone(storage) : nullptr, privileges_);
}
cpp<#)
(:protected
#>cpp
explicit AuthQuery(int uid) : Query(uid) {}
explicit AuthQuery(int uid, Action action, std::string user, std::string role,
std::string user_or_role, Expression *password,
std::vector<Privilege> privileges)
: Query(uid),
action_(action),
user_(user),
role_(role),
user_or_role_(user_or_role),
password_(password),
privileges_(privileges) {}
cpp<#)
(:private
#>cpp
friend class AstStorage;
cpp<#)
(:serialize :capnp))
#>cpp
// Constant that holds all available privileges.
const std::vector<AuthQuery::Privilege> kPrivilegesAll = {
AuthQuery::Privilege::CREATE, AuthQuery::Privilege::DELETE,
AuthQuery::Privilege::MATCH, AuthQuery::Privilege::MERGE,
AuthQuery::Privilege::SET, AuthQuery::Privilege::REMOVE,
AuthQuery::Privilege::INDEX, AuthQuery::Privilege::AUTH,
AuthQuery::Privilege::STREAM};
cpp<#
(lcp:define-class stream-query (query)
((action "Action" :scope :public)
(stream-name "std::string" :scope :public)
(stream-uri "Expression *" :scope :public :initval "nullptr"
:capnp-type "Tree" :capnp-init nil
:capnp-save #'save-ast-pointer
:capnp-load (load-ast-pointer "Expression *"))
(stream-topic "Expression *" :scope :public :initval "nullptr"
:capnp-type "Tree" :capnp-init nil
:capnp-save #'save-ast-pointer
:capnp-load (load-ast-pointer "Expression *"))
(transform-uri "Expression *" :scope :public :initval "nullptr"
:capnp-type "Tree" :capnp-init nil
:capnp-save #'save-ast-pointer
:capnp-load (load-ast-pointer "Expression *"))
(batch-interval-in-ms "Expression *" :scope :public :initval "nullptr"
:capnp-type "Tree" :capnp-init nil
:capnp-save #'save-ast-pointer
:capnp-load (load-ast-pointer "Expression *"))
(batch-size "Expression *" :scope :public :initval "nullptr"
:capnp-type "Tree" :capnp-init nil
:capnp-save #'save-ast-pointer
:capnp-load (load-ast-pointer "Expression *"))
(limit-batches "Expression *" :scope :public :initval "nullptr"
:capnp-type "Tree" :capnp-init nil
:capnp-save #'save-ast-pointer
:capnp-load (load-ast-pointer "Expression *")))
(:public
(lcp:define-enum action (create-stream drop-stream show-streams start-stream
stop-stream start-all-streams stop-all-streams test-stream)
(:serialize :capnp))
#>cpp
StreamQuery() = default;
DEFVISITABLE(TreeVisitor<TypedValue>);
DEFVISITABLE(HierarchicalTreeVisitor);
StreamQuery *Clone(AstStorage &storage) const override {
auto *stream_uri = stream_uri_ ? stream_uri_->Clone(storage) : nullptr;
auto *stream_topic = stream_topic_ ? stream_topic_->Clone(storage) : nullptr;
auto *transform_uri =
transform_uri_ ? transform_uri_->Clone(storage) : nullptr;
auto *batch_interval_in_ms =
batch_interval_in_ms_ ? batch_interval_in_ms_->Clone(storage) : nullptr;
auto *batch_size = batch_size_ ? batch_size_->Clone(storage) : nullptr;
auto *limit_batches =
limit_batches_ ? limit_batches_->Clone(storage) : nullptr;
return storage.Create<StreamQuery>(
action_, stream_name_, stream_uri, stream_topic, transform_uri,
batch_interval_in_ms, batch_size, limit_batches);
}
cpp<#)
(:protected
#>cpp
StreamQuery(int uid) : Query(uid) {}
StreamQuery(int uid, Action action, std::string stream_name,
Expression *stream_uri, Expression *stream_topic,
Expression *transform_uri, Expression *batch_interval_in_ms,
Expression *batch_size, Expression *limit_batches)
: Query(uid),
action_(action),
stream_name_(std::move(stream_name)),
stream_uri_(stream_uri),
stream_topic_(stream_topic),
transform_uri_(transform_uri),
batch_interval_in_ms_(batch_interval_in_ms),
batch_size_(batch_size),
limit_batches_(limit_batches) {}
cpp<#)
(:private
#>cpp
friend class AstStorage;
cpp<#)
(:serialize :capnp))
#>cpp
#undef CLONE_BINARY_EXPRESSION
#undef CLONE_UNARY_EXPRESSION

View File

@@ -60,10 +60,8 @@ class RemoveProperty;
class RemoveLabels;
class Merge;
class Unwind;
class AuthQuery;
class ExplainQuery;
class IndexQuery;
class StreamQuery;
using TreeCompositeVisitor = ::utils::CompositeVisitor<
CypherQuery, ExplainQuery, SingleQuery, CypherUnion, NamedExpression,
@@ -79,7 +77,7 @@ using TreeCompositeVisitor = ::utils::CompositeVisitor<
using TreeLeafVisitor =
::utils::LeafVisitor<Identifier, PrimitiveLiteral, ParameterLookup,
IndexQuery, AuthQuery, StreamQuery>;
IndexQuery>;
class HierarchicalTreeVisitor : public TreeCompositeVisitor,
public TreeLeafVisitor {
@@ -103,6 +101,6 @@ using TreeVisitor = ::utils::Visitor<
Extract, All, Single, ParameterLookup, Create, Match, Return, With, Pattern,
NodeAtom, EdgeAtom, Delete, Where, SetProperty, SetProperties, SetLabels,
RemoveProperty, RemoveLabels, Merge, Unwind, Identifier, PrimitiveLiteral,
IndexQuery, AuthQuery, StreamQuery>;
IndexQuery>;
} // namespace query

View File

@@ -108,24 +108,6 @@ antlrcpp::Any CypherMainVisitor::visitDropIndex(
return index_query;
}
antlrcpp::Any CypherMainVisitor::visitAuthQuery(
MemgraphCypher::AuthQueryContext *ctx) {
CHECK(ctx->children.size() == 1)
<< "AuthQuery should have exactly one child!";
auto *auth_query = ctx->children[0]->accept(this).as<AuthQuery *>();
query_ = auth_query;
return auth_query;
}
antlrcpp::Any CypherMainVisitor::visitStreamQuery(
MemgraphCypher::StreamQueryContext *ctx) {
CHECK(ctx->children.size() == 1)
<< "StreamQuery should have exactly one child!";
auto *stream_query = ctx->children[0]->accept(this).as<StreamQuery *>();
query_ = stream_query;
return stream_query;
}
antlrcpp::Any CypherMainVisitor::visitCypherUnion(
MemgraphCypher::CypherUnionContext *ctx) {
bool distinct = !ctx->ALL();
@@ -277,380 +259,6 @@ antlrcpp::Any CypherMainVisitor::visitCreate(
return create;
}
/**
* @return std::string
*/
antlrcpp::Any CypherMainVisitor::visitUserOrRoleName(
MemgraphCypher::UserOrRoleNameContext *ctx) {
std::string value = ctx->symbolicName()->accept(this).as<std::string>();
const std::regex NAME_REGEX("[a-zA-Z0-9_.+-]+");
if (!std::regex_match(value, NAME_REGEX)) {
throw SyntaxException("Invalid user or role name.");
}
return value;
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitCreateRole(
MemgraphCypher::CreateRoleContext *ctx) {
AuthQuery *auth = storage_->Create<AuthQuery>();
auth->action_ = AuthQuery::Action::CREATE_ROLE;
auth->role_ = ctx->role->accept(this).as<std::string>();
return auth;
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitDropRole(
MemgraphCypher::DropRoleContext *ctx) {
AuthQuery *auth = storage_->Create<AuthQuery>();
auth->action_ = AuthQuery::Action::DROP_ROLE;
auth->role_ = ctx->role->accept(this).as<std::string>();
return auth;
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitShowRoles(
MemgraphCypher::ShowRolesContext *ctx) {
AuthQuery *auth = storage_->Create<AuthQuery>();
auth->action_ = AuthQuery::Action::SHOW_ROLES;
return auth;
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitCreateUser(
MemgraphCypher::CreateUserContext *ctx) {
AuthQuery *auth = storage_->Create<AuthQuery>();
auth->action_ = AuthQuery::Action::CREATE_USER;
auth->user_ = ctx->user->accept(this).as<std::string>();
if (ctx->password) {
if (!ctx->password->StringLiteral() && !ctx->literal()->CYPHERNULL()) {
throw SyntaxException("Password should be a string literal or null.");
}
auth->password_ = ctx->password->accept(this);
}
return auth;
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitSetPassword(
MemgraphCypher::SetPasswordContext *ctx) {
AuthQuery *auth = storage_->Create<AuthQuery>();
auth->action_ = AuthQuery::Action::SET_PASSWORD;
auth->user_ = ctx->user->accept(this).as<std::string>();
if (!ctx->password->StringLiteral() && !ctx->literal()->CYPHERNULL()) {
throw SyntaxException("Password should be a string literal or null.");
}
auth->password_ = ctx->password->accept(this);
return auth;
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitDropUser(
MemgraphCypher::DropUserContext *ctx) {
AuthQuery *auth = storage_->Create<AuthQuery>();
auth->action_ = AuthQuery::Action::DROP_USER;
auth->user_ = ctx->user->accept(this).as<std::string>();
return auth;
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitShowUsers(
MemgraphCypher::ShowUsersContext *ctx) {
AuthQuery *auth = storage_->Create<AuthQuery>();
auth->action_ = AuthQuery::Action::SHOW_USERS;
return auth;
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitSetRole(
MemgraphCypher::SetRoleContext *ctx) {
AuthQuery *auth = storage_->Create<AuthQuery>();
auth->action_ = AuthQuery::Action::SET_ROLE;
auth->user_ = ctx->user->accept(this).as<std::string>();
auth->role_ = ctx->role->accept(this).as<std::string>();
return auth;
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitClearRole(
MemgraphCypher::ClearRoleContext *ctx) {
AuthQuery *auth = storage_->Create<AuthQuery>();
auth->action_ = AuthQuery::Action::CLEAR_ROLE;
auth->user_ = ctx->user->accept(this).as<std::string>();
return auth;
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitGrantPrivilege(
MemgraphCypher::GrantPrivilegeContext *ctx) {
AuthQuery *auth = storage_->Create<AuthQuery>();
auth->action_ = AuthQuery::Action::GRANT_PRIVILEGE;
auth->user_or_role_ = ctx->userOrRole->accept(this).as<std::string>();
if (ctx->privilegeList()) {
for (auto *privilege : ctx->privilegeList()->privilege()) {
auth->privileges_.push_back(privilege->accept(this));
}
} else {
/* grant all privileges */
auth->privileges_ = kPrivilegesAll;
}
return auth;
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitDenyPrivilege(
MemgraphCypher::DenyPrivilegeContext *ctx) {
AuthQuery *auth = storage_->Create<AuthQuery>();
auth->action_ = AuthQuery::Action::DENY_PRIVILEGE;
auth->user_or_role_ = ctx->userOrRole->accept(this).as<std::string>();
if (ctx->privilegeList()) {
for (auto *privilege : ctx->privilegeList()->privilege()) {
auth->privileges_.push_back(privilege->accept(this));
}
} else {
/* deny all privileges */
auth->privileges_ = kPrivilegesAll;
}
return auth;
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitRevokePrivilege(
MemgraphCypher::RevokePrivilegeContext *ctx) {
AuthQuery *auth = storage_->Create<AuthQuery>();
auth->action_ = AuthQuery::Action::REVOKE_PRIVILEGE;
auth->user_or_role_ = ctx->userOrRole->accept(this).as<std::string>();
if (ctx->privilegeList()) {
for (auto *privilege : ctx->privilegeList()->privilege()) {
auth->privileges_.push_back(privilege->accept(this));
}
} else {
/* revoke all privileges */
auth->privileges_ = kPrivilegesAll;
}
return auth;
}
/**
* @return AuthQuery::Privilege
*/
antlrcpp::Any CypherMainVisitor::visitPrivilege(
MemgraphCypher::PrivilegeContext *ctx) {
if (ctx->CREATE()) return AuthQuery::Privilege::CREATE;
if (ctx->DELETE()) return AuthQuery::Privilege::DELETE;
if (ctx->MATCH()) return AuthQuery::Privilege::MATCH;
if (ctx->MERGE()) return AuthQuery::Privilege::MERGE;
if (ctx->SET()) return AuthQuery::Privilege::SET;
if (ctx->REMOVE()) return AuthQuery::Privilege::REMOVE;
if (ctx->INDEX()) return AuthQuery::Privilege::INDEX;
if (ctx->AUTH()) return AuthQuery::Privilege::AUTH;
if (ctx->STREAM()) return AuthQuery::Privilege::STREAM;
LOG(FATAL) << "Should not get here - unknown privilege!";
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitShowPrivileges(
MemgraphCypher::ShowPrivilegesContext *ctx) {
AuthQuery *auth = storage_->Create<AuthQuery>();
auth->action_ = AuthQuery::Action::SHOW_PRIVILEGES;
auth->user_or_role_ = ctx->userOrRole->accept(this).as<std::string>();
return auth;
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitShowRoleForUser(
MemgraphCypher::ShowRoleForUserContext *ctx) {
AuthQuery *auth = storage_->Create<AuthQuery>();
auth->action_ = AuthQuery::Action::SHOW_ROLE_FOR_USER;
auth->user_ = ctx->user->accept(this).as<std::string>();
return auth;
}
/**
* @return AuthQuery*
*/
antlrcpp::Any CypherMainVisitor::visitShowUsersForRole(
MemgraphCypher::ShowUsersForRoleContext *ctx) {
AuthQuery *auth = storage_->Create<AuthQuery>();
auth->action_ = AuthQuery::Action::SHOW_USERS_FOR_ROLE;
auth->role_ = ctx->role->accept(this).as<std::string>();
return auth;
}
/**
* @return StreamQuery*
*/
antlrcpp::Any CypherMainVisitor::visitCreateStream(
MemgraphCypher::CreateStreamContext *ctx) {
auto *stream_query = storage_->Create<StreamQuery>();
stream_query->action_ = StreamQuery::Action::CREATE_STREAM;
stream_query->stream_name_ = ctx->streamName()->getText();
if (!ctx->streamUri->StringLiteral()) {
throw SyntaxException("Stream URI should be a string literal.");
}
stream_query->stream_uri_ = ctx->streamUri->accept(this);
if (!ctx->streamTopic->StringLiteral()) {
throw SyntaxException("Topic should be a string literal.");
}
stream_query->stream_topic_ = ctx->streamTopic->accept(this);
if (!ctx->transformUri->StringLiteral()) {
throw SyntaxException("Transform URI should be a string literal.");
}
stream_query->transform_uri_ = ctx->transformUri->accept(this);
if (ctx->batchIntervalOption()) {
stream_query->batch_interval_in_ms_ =
ctx->batchIntervalOption()->accept(this);
}
if (ctx->batchSizeOption()) {
stream_query->batch_size_ = ctx->batchSizeOption()->accept(this);
}
return stream_query;
}
/**
* @return Expression*
*/
antlrcpp::Any CypherMainVisitor::visitBatchIntervalOption(
MemgraphCypher::BatchIntervalOptionContext *ctx) {
if (!ctx->literal()->numberLiteral() ||
!ctx->literal()->numberLiteral()->integerLiteral()) {
throw SyntaxException("Batch interval should be an integer.");
}
return ctx->literal()->accept(this);
}
/**
* @return Expression*
*/
antlrcpp::Any CypherMainVisitor::visitBatchSizeOption(
MemgraphCypher::BatchSizeOptionContext *ctx) {
if (!ctx->literal()->numberLiteral() ||
!ctx->literal()->numberLiteral()->integerLiteral()) {
throw SyntaxException("Batch size should be an integer.");
}
return ctx->literal()->accept(this);
}
/**
* @return StreamQuery*
*/
antlrcpp::Any CypherMainVisitor::visitDropStream(
MemgraphCypher::DropStreamContext *ctx) {
auto *stream_query = storage_->Create<StreamQuery>();
stream_query->action_ = StreamQuery::Action::DROP_STREAM;
stream_query->stream_name_ = ctx->streamName()->getText();
return stream_query;
}
/**
* @return StreamQuery*
*/
antlrcpp::Any CypherMainVisitor::visitShowStreams(
MemgraphCypher::ShowStreamsContext *ctx) {
auto *stream_query = storage_->Create<StreamQuery>();
stream_query->action_ = StreamQuery::Action::SHOW_STREAMS;
return stream_query;
}
/**
* @return StreamQuery*
*/
antlrcpp::Any CypherMainVisitor::visitStartStream(
MemgraphCypher::StartStreamContext *ctx) {
auto *stream_query = storage_->Create<StreamQuery>();
stream_query->action_ = StreamQuery::Action::START_STREAM;
stream_query->stream_name_ = std::string(ctx->streamName()->getText());
if (ctx->limitBatchesOption()) {
stream_query->limit_batches_ = ctx->limitBatchesOption()->accept(this);
}
return stream_query;
}
/**
* @return StreamQuery*
*/
antlrcpp::Any CypherMainVisitor::visitStopStream(
MemgraphCypher::StopStreamContext *ctx) {
auto *stream_query = storage_->Create<StreamQuery>();
stream_query->action_ = StreamQuery::Action::STOP_STREAM;
stream_query->stream_name_ = std::string(ctx->streamName()->getText());
return stream_query;
}
/**
* @return Expression*
*/
antlrcpp::Any CypherMainVisitor::visitLimitBatchesOption(
MemgraphCypher::LimitBatchesOptionContext *ctx) {
if (!ctx->literal()->numberLiteral() ||
!ctx->literal()->numberLiteral()->integerLiteral()) {
throw SyntaxException("Batch limit should be an integer.");
}
return ctx->literal()->accept(this);
}
/*
* @return StreamQuery*
*/
antlrcpp::Any CypherMainVisitor::visitStartAllStreams(
MemgraphCypher::StartAllStreamsContext *ctx) {
auto *stream_query = storage_->Create<StreamQuery>();
stream_query->action_ = StreamQuery::Action::START_ALL_STREAMS;
return stream_query;
}
/*
* @return StreamQuery*
*/
antlrcpp::Any CypherMainVisitor::visitStopAllStreams(
MemgraphCypher::StopAllStreamsContext *ctx) {
auto *stream_query = storage_->Create<StreamQuery>();
stream_query->action_ = StreamQuery::Action::STOP_ALL_STREAMS;
return stream_query;
}
/**
* @return StreamQuery*
*/
antlrcpp::Any CypherMainVisitor::visitTestStream(
MemgraphCypher::TestStreamContext *ctx) {
auto *stream_query = storage_->Create<StreamQuery>();
stream_query->action_ = StreamQuery::Action::TEST_STREAM;
stream_query->stream_name_ = std::string(ctx->streamName()->getText());
if (ctx->limitBatchesOption()) {
stream_query->limit_batches_ = ctx->limitBatchesOption()->accept(this);
}
return stream_query;
}
antlrcpp::Any CypherMainVisitor::visitCypherReturn(
MemgraphCypher::CypherReturnContext *ctx) {
auto *return_clause = storage_->Create<Return>();

View File

@@ -152,17 +152,6 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
antlrcpp::Any visitExplainQuery(
MemgraphCypher::ExplainQueryContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitAuthQuery(MemgraphCypher::AuthQueryContext *ctx) override;
/**
* @return StreamQuery*
*/
antlrcpp::Any visitStreamQuery(
MemgraphCypher::StreamQueryContext *ctx) override;
/**
* @return CypherUnion*
*/
@@ -191,28 +180,6 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
*/
antlrcpp::Any visitCreate(MemgraphCypher::CreateContext *ctx) override;
/**
* @return std::string
*/
antlrcpp::Any visitUserOrRoleName(
MemgraphCypher::UserOrRoleNameContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitCreateRole(
MemgraphCypher::CreateRoleContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitDropRole(MemgraphCypher::DropRoleContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitShowRoles(MemgraphCypher::ShowRolesContext *ctx) override;
/**
* @return IndexQuery*
*/
@@ -230,136 +197,6 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
*/
antlrcpp::Any visitDropIndex(MemgraphCypher::DropIndexContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitCreateUser(
MemgraphCypher::CreateUserContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitSetPassword(
MemgraphCypher::SetPasswordContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitDropUser(MemgraphCypher::DropUserContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitShowUsers(MemgraphCypher::ShowUsersContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitSetRole(MemgraphCypher::SetRoleContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitClearRole(MemgraphCypher::ClearRoleContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitGrantPrivilege(
MemgraphCypher::GrantPrivilegeContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitDenyPrivilege(
MemgraphCypher::DenyPrivilegeContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitRevokePrivilege(
MemgraphCypher::RevokePrivilegeContext *ctx) override;
/**
* @return AuthQuery::Privilege
*/
antlrcpp::Any visitPrivilege(MemgraphCypher::PrivilegeContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitShowPrivileges(
MemgraphCypher::ShowPrivilegesContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitShowRoleForUser(
MemgraphCypher::ShowRoleForUserContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitShowUsersForRole(
MemgraphCypher::ShowUsersForRoleContext *ctx) override;
/**
* @return StreamQuery*
*/
antlrcpp::Any visitCreateStream(
MemgraphCypher::CreateStreamContext *ctx) override;
antlrcpp::Any visitBatchIntervalOption(
MemgraphCypher::BatchIntervalOptionContext *ctx) override;
antlrcpp::Any visitBatchSizeOption(
MemgraphCypher::BatchSizeOptionContext *ctx) override;
/**
* @return StreamQuery*
*/
antlrcpp::Any visitDropStream(
MemgraphCypher::DropStreamContext *ctx) override;
/**
* @return StreamQuery*
*/
antlrcpp::Any visitShowStreams(
MemgraphCypher::ShowStreamsContext *ctx) override;
/**
* @return StreamQuery*
*/
antlrcpp::Any visitStartStream(
MemgraphCypher::StartStreamContext *ctx) override;
/**
* @return StreamQuery*
*/
antlrcpp::Any visitStopStream(
MemgraphCypher::StopStreamContext *ctx) override;
antlrcpp::Any visitLimitBatchesOption(
MemgraphCypher::LimitBatchesOptionContext *ctx) override;
/**
* @return StreamQuery*
*/
antlrcpp::Any visitStartAllStreams(
MemgraphCypher::StartAllStreamsContext *ctx) override;
/**
* @return StreamQuery*
*/
antlrcpp::Any visitStopAllStreams(
MemgraphCypher::StopAllStreamsContext *ctx) override;
/**
* @return StreamQuery*
*/
antlrcpp::Any visitTestStream(
MemgraphCypher::TestStreamContext *ctx) override;
/**
* @return Return*
*/

View File

@@ -5,140 +5,3 @@ parser grammar MemgraphCypher ;
options { tokenVocab=MemgraphCypherLexer; }
import Cypher ;
memgraphCypherKeyword : cypherKeyword
| ALTER
| AUTH
| BATCH
| BATCHES
| CLEAR
| DATA
| DENY
| DROP
| FOR
| FROM
| GRANT
| IDENTIFIED
| INTERVAL
| K_TEST
| KAFKA
| LOAD
| PASSWORD
| PRIVILEGES
| REVOKE
| ROLE
| ROLES
| SIZE
| START
| STOP
| STREAM
| STREAMS
| TO
| TOPIC
| TRANSFORM
| USER
| USERS
;
symbolicName : UnescapedSymbolicName
| EscapedSymbolicName
| memgraphCypherKeyword
;
query : cypherQuery
| indexQuery
| explainQuery
| authQuery
| streamQuery
;
authQuery : createRole
| dropRole
| showRoles
| createUser
| setPassword
| dropUser
| showUsers
| setRole
| clearRole
| grantPrivilege
| denyPrivilege
| revokePrivilege
| showPrivileges
| showRoleForUser
| showUsersForRole
;
userOrRoleName : symbolicName ;
createRole : CREATE ROLE role=userOrRoleName ;
dropRole : DROP ROLE role=userOrRoleName ;
showRoles : SHOW ROLES ;
createUser : CREATE USER user=userOrRoleName
( IDENTIFIED BY password=literal )? ;
setPassword : SET PASSWORD FOR user=userOrRoleName TO password=literal;
dropUser : DROP USER user=userOrRoleName ;
showUsers : SHOW USERS ;
setRole : SET ROLE FOR user=userOrRoleName TO role=userOrRoleName;
clearRole : CLEAR ROLE FOR user=userOrRoleName ;
grantPrivilege : GRANT ( ALL PRIVILEGES | privileges=privilegeList ) TO userOrRole=userOrRoleName ;
denyPrivilege : DENY ( ALL PRIVILEGES | privileges=privilegeList ) TO userOrRole=userOrRoleName ;
revokePrivilege : REVOKE ( ALL PRIVILEGES | privileges=privilegeList ) FROM userOrRole=userOrRoleName ;
privilege : CREATE | DELETE | MATCH | MERGE | SET
| REMOVE | INDEX | AUTH | STREAM ;
privilegeList : privilege ( ',' privilege )* ;
showPrivileges : SHOW PRIVILEGES FOR userOrRole=userOrRoleName ;
showRoleForUser : SHOW ROLE FOR user=userOrRoleName ;
showUsersForRole : SHOW USERS FOR role=userOrRoleName ;
streamQuery : createStream
| dropStream
| showStreams
| startStream
| stopStream
| startAllStreams
| stopAllStreams
| testStream
;
streamName : symbolicName ;
createStream : CREATE STREAM streamName AS LOAD DATA KAFKA
streamUri=literal WITH TOPIC streamTopic=literal WITH TRANSFORM
transformUri=literal ( batchIntervalOption )? ( batchSizeOption )? ;
batchIntervalOption : BATCH INTERVAL literal ;
batchSizeOption : BATCH SIZE literal ;
dropStream : DROP STREAM streamName ;
showStreams : SHOW STREAMS ;
startStream : START STREAM streamName ( limitBatchesOption )? ;
stopStream : STOP STREAM streamName ;
limitBatchesOption : LIMIT limitBatches=literal BATCHES ;
startAllStreams : START ALL STREAMS ;
stopAllStreams : STOP ALL STREAMS ;
testStream : K_TEST STREAM streamName ( limitBatchesOption )? ;

View File

@@ -9,36 +9,3 @@
lexer grammar MemgraphCypherLexer ;
import CypherLexer ;
ALTER : A L T E R ;
AUTH : A U T H ;
BATCH : B A T C H ;
BATCHES : B A T C H E S ;
CLEAR : C L E A R ;
DATA : D A T A ;
DENY : D E N Y ;
DROP : D R O P ;
FOR : F O R ;
FROM : F R O M ;
GRANT : G R A N T ;
GRANTS : G R A N T S ;
IDENTIFIED : I D E N T I F I E D ;
INTERVAL : I N T E R V A L ;
K_TEST : T E S T ;
KAFKA : K A F K A ;
LOAD : L O A D ;
PASSWORD : P A S S W O R D ;
PRIVILEGES : P R I V I L E G E S ;
REVOKE : R E V O K E ;
ROLE : R O L E ;
ROLES : R O L E S ;
SIZE : S I Z E ;
START : S T A R T ;
STOP : S T O P ;
STREAM : S T R E A M ;
STREAMS : S T R E A M S ;
TO : T O ;
TOPIC : T O P I C ;
TRANSFORM : T R A N S F O R M ;
USER : U S E R ;
USERS : U S E R S ;

View File

@@ -220,10 +220,6 @@ bool SymbolGenerator::PostVisit(Match &) {
bool SymbolGenerator::Visit(IndexQuery &) { return true; }
bool SymbolGenerator::Visit(AuthQuery &) { return true; }
bool SymbolGenerator::Visit(StreamQuery &) { return true; }
// Expressions
SymbolGenerator::ReturnType SymbolGenerator::Visit(Identifier &ident) {

View File

@@ -47,8 +47,6 @@ class SymbolGenerator : public HierarchicalTreeVisitor {
bool PreVisit(Match &) override;
bool PostVisit(Match &) override;
bool Visit(IndexQuery &) override;
bool Visit(AuthQuery &) override;
bool Visit(StreamQuery &) override;
// Expressions
ReturnType Visit(Identifier &) override;

View File

@@ -57,8 +57,6 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
BLOCK_VISIT(Merge);
BLOCK_VISIT(Unwind);
BLOCK_VISIT(IndexQuery);
BLOCK_VISIT(AuthQuery);
BLOCK_VISIT(StreamQuery);
#undef BLOCK_VISIT

View File

@@ -3,15 +3,10 @@
#include <glog/logging.h>
#include <limits>
#include "auth/auth.hpp"
#include "glue/auth.hpp"
#include "glue/communication.hpp"
#include "integrations/kafka/exceptions.hpp"
#include "integrations/kafka/streams.hpp"
#include "query/exceptions.hpp"
#include "query/frontend/ast/cypher_main_visitor.hpp"
#include "query/frontend/opencypher/parser.hpp"
#include "query/frontend/semantic/required_privileges.hpp"
#include "query/frontend/semantic/symbol_generator.hpp"
#include "query/interpret/eval.hpp"
#include "query/plan/planner.hpp"
@@ -67,446 +62,6 @@ TypedValue EvaluateOptionalExpression(Expression *expression,
return expression ? expression->Accept(*eval) : TypedValue::Null;
}
Callback HandleAuthQuery(AuthQuery *auth_query, auth::Auth *auth,
const EvaluationContext &evaluation_context,
database::GraphDbAccessor *db_accessor) {
// Empty frame for evaluation of password expression. This is OK since
// password should be either null or string literal and it's evaluation
// should not depend on frame.
Frame frame(0);
SymbolTable symbol_table;
ExpressionEvaluator evaluator(&frame, symbol_table, evaluation_context,
db_accessor, GraphView::OLD);
AuthQuery::Action action = auth_query->action_;
std::string username = auth_query->user_;
std::string rolename = auth_query->role_;
std::string user_or_role = auth_query->user_or_role_;
std::vector<AuthQuery::Privilege> privileges = auth_query->privileges_;
auto password = EvaluateOptionalExpression(auth_query->password_, &evaluator);
Callback callback;
switch (auth_query->action_) {
case AuthQuery::Action::CREATE_USER:
callback.fn = [auth, username, password] {
CHECK(password.IsString() || password.IsNull());
std::lock_guard<std::mutex> lock(auth->WithLock());
auto user = auth->AddUser(
username, password.IsString() ? std::experimental::make_optional(
password.ValueString())
: std::experimental::nullopt);
if (!user) {
throw QueryRuntimeException("User or role '{}' already exists.",
username);
}
return std::vector<std::vector<TypedValue>>();
};
return callback;
case AuthQuery::Action::DROP_USER:
callback.fn = [auth, username] {
std::lock_guard<std::mutex> lock(auth->WithLock());
auto user = auth->GetUser(username);
if (!user) {
throw QueryRuntimeException("User '{}' doesn't exist.", username);
}
if (!auth->RemoveUser(username)) {
throw QueryRuntimeException("Couldn't remove user '{}'.", username);
}
return std::vector<std::vector<TypedValue>>();
};
return callback;
case AuthQuery::Action::SET_PASSWORD:
callback.fn = [auth, username, password] {
CHECK(password.IsString() || password.IsNull());
std::lock_guard<std::mutex> lock(auth->WithLock());
auto user = auth->GetUser(username);
if (!user) {
throw QueryRuntimeException("User '{}' doesn't exist.", username);
}
user->UpdatePassword(
password.IsString()
? std::experimental::make_optional(password.ValueString())
: std::experimental::nullopt);
auth->SaveUser(*user);
return std::vector<std::vector<TypedValue>>();
};
return callback;
case AuthQuery::Action::CREATE_ROLE:
callback.fn = [auth, rolename] {
std::lock_guard<std::mutex> lock(auth->WithLock());
auto role = auth->AddRole(rolename);
if (!role) {
throw QueryRuntimeException("User or role '{}' already exists.",
rolename);
}
return std::vector<std::vector<TypedValue>>();
};
return callback;
case AuthQuery::Action::DROP_ROLE:
callback.fn = [auth, rolename] {
std::lock_guard<std::mutex> lock(auth->WithLock());
auto role = auth->GetRole(rolename);
if (!role) {
throw QueryRuntimeException("Role '{}' doesn't exist.", rolename);
}
if (!auth->RemoveRole(rolename)) {
throw QueryRuntimeException("Couldn't remove role '{}'.", rolename);
}
return std::vector<std::vector<TypedValue>>();
};
return callback;
case AuthQuery::Action::SHOW_USERS:
callback.header = {"user"};
callback.fn = [auth] {
std::lock_guard<std::mutex> lock(auth->WithLock());
std::vector<std::vector<TypedValue>> users;
for (const auto &user : auth->AllUsers()) {
users.push_back({user.username()});
}
return users;
};
return callback;
case AuthQuery::Action::SHOW_ROLES:
callback.header = {"role"};
callback.fn = [auth] {
std::lock_guard<std::mutex> lock(auth->WithLock());
std::vector<std::vector<TypedValue>> roles;
for (const auto &role : auth->AllRoles()) {
roles.push_back({role.rolename()});
}
return roles;
};
return callback;
case AuthQuery::Action::SET_ROLE:
callback.fn = [auth, username, rolename] {
std::lock_guard<std::mutex> lock(auth->WithLock());
auto user = auth->GetUser(username);
if (!user) {
throw QueryRuntimeException("User '{}' doesn't exist .", username);
}
auto role = auth->GetRole(rolename);
if (!role) {
throw QueryRuntimeException("Role '{}' doesn't exist .", rolename);
}
if (user->role()) {
throw QueryRuntimeException(
"User '{}' is already a member of role '{}'.", username,
user->role()->rolename());
}
user->SetRole(*role);
auth->SaveUser(*user);
return std::vector<std::vector<TypedValue>>();
};
return callback;
case AuthQuery::Action::CLEAR_ROLE:
callback.fn = [auth, username] {
std::lock_guard<std::mutex> lock(auth->WithLock());
auto user = auth->GetUser(username);
if (!user) {
throw QueryRuntimeException("User '{}' doesn't exist .", username);
}
user->ClearRole();
auth->SaveUser(*user);
return std::vector<std::vector<TypedValue>>();
};
return callback;
case AuthQuery::Action::GRANT_PRIVILEGE:
case AuthQuery::Action::DENY_PRIVILEGE:
case AuthQuery::Action::REVOKE_PRIVILEGE: {
callback.fn = [auth, user_or_role, action, privileges] {
std::lock_guard<std::mutex> lock(auth->WithLock());
std::vector<auth::Permission> permissions;
for (const auto &privilege : privileges) {
permissions.push_back(glue::PrivilegeToPermission(privilege));
}
auto user = auth->GetUser(user_or_role);
auto role = auth->GetRole(user_or_role);
if (!user && !role) {
throw QueryRuntimeException("User or role '{}' doesn't exist.",
user_or_role);
}
if (user) {
for (const auto &permission : permissions) {
// TODO (mferencevic): should we first check that the privilege
// is granted/denied/revoked before unconditionally
// granting/denying/revoking it?
if (action == AuthQuery::Action::GRANT_PRIVILEGE) {
user->permissions().Grant(permission);
} else if (action == AuthQuery::Action::DENY_PRIVILEGE) {
user->permissions().Deny(permission);
} else {
user->permissions().Revoke(permission);
}
}
auth->SaveUser(*user);
} else {
for (const auto &permission : permissions) {
// TODO (mferencevic): should we first check that the privilege
// is granted/denied/revoked before unconditionally
// granting/denying/revoking it?
if (action == AuthQuery::Action::GRANT_PRIVILEGE) {
role->permissions().Grant(permission);
} else if (action == AuthQuery::Action::DENY_PRIVILEGE) {
role->permissions().Deny(permission);
} else {
role->permissions().Revoke(permission);
}
}
auth->SaveRole(*role);
}
return std::vector<std::vector<TypedValue>>();
};
return callback;
}
case AuthQuery::Action::SHOW_PRIVILEGES:
callback.header = {"privilege", "effective", "description"};
callback.fn = [auth, user_or_role] {
std::lock_guard<std::mutex> lock(auth->WithLock());
std::vector<std::vector<TypedValue>> grants;
auto user = auth->GetUser(user_or_role);
auto role = auth->GetRole(user_or_role);
if (!user && !role) {
throw QueryRuntimeException("User or role '{}' doesn't exist.",
user_or_role);
}
if (user) {
const auto &permissions = user->GetPermissions();
for (const auto &privilege : kPrivilegesAll) {
auto permission = glue::PrivilegeToPermission(privilege);
auto effective = permissions.Has(permission);
if (permissions.Has(permission) != auth::PermissionLevel::NEUTRAL) {
std::vector<std::string> description;
auto user_level = user->permissions().Has(permission);
if (user_level == auth::PermissionLevel::GRANT) {
description.push_back("GRANTED TO USER");
} else if (user_level == auth::PermissionLevel::DENY) {
description.push_back("DENIED TO USER");
}
if (user->role()) {
auto role_level = user->role()->permissions().Has(permission);
if (role_level == auth::PermissionLevel::GRANT) {
description.push_back("GRANTED TO ROLE");
} else if (role_level == auth::PermissionLevel::DENY) {
description.push_back("DENIED TO ROLE");
}
}
grants.push_back({auth::PermissionToString(permission),
auth::PermissionLevelToString(effective),
utils::Join(description, ", ")});
}
}
} else {
const auto &permissions = role->permissions();
for (const auto &privilege : kPrivilegesAll) {
auto permission = glue::PrivilegeToPermission(privilege);
auto effective = permissions.Has(permission);
if (effective != auth::PermissionLevel::NEUTRAL) {
std::string description;
if (effective == auth::PermissionLevel::GRANT) {
description = "GRANTED TO ROLE";
} else if (effective == auth::PermissionLevel::DENY) {
description = "DENIED TO ROLE";
}
grants.push_back({auth::PermissionToString(permission),
auth::PermissionLevelToString(effective),
description});
}
}
}
return grants;
};
return callback;
case AuthQuery::Action::SHOW_ROLE_FOR_USER:
callback.header = {"role"};
callback.fn = [auth, username] {
std::lock_guard<std::mutex> lock(auth->WithLock());
auto user = auth->GetUser(username);
if (!user) {
throw QueryRuntimeException("User '{}' doesn't exist .", username);
}
return std::vector<std::vector<TypedValue>>{std::vector<TypedValue>{
user->role() ? user->role()->rolename() : "null"}};
};
return callback;
case AuthQuery::Action::SHOW_USERS_FOR_ROLE:
callback.header = {"users"};
callback.fn = [auth, rolename] {
std::lock_guard<std::mutex> lock(auth->WithLock());
auto role = auth->GetRole(rolename);
if (!role) {
throw QueryRuntimeException("Role '{}' doesn't exist.", rolename);
}
std::vector<std::vector<TypedValue>> users;
for (const auto &user : auth->AllUsersForRole(rolename)) {
users.emplace_back(std::vector<TypedValue>{user.username()});
}
return users;
};
return callback;
default:
break;
}
}
Callback HandleStreamQuery(StreamQuery *stream_query,
integrations::kafka::Streams *streams,
const EvaluationContext &evaluation_context,
database::GraphDbAccessor *db_accessor) {
// Empty frame and symbol table for evaluation of expressions. This is OK
// since all expressions should be literals or parameter lookups.
Frame frame(0);
SymbolTable symbol_table;
ExpressionEvaluator eval(&frame, symbol_table, evaluation_context,
db_accessor, GraphView::OLD);
std::string stream_name = stream_query->stream_name_;
auto stream_uri =
EvaluateOptionalExpression(stream_query->stream_uri_, &eval);
auto stream_topic =
EvaluateOptionalExpression(stream_query->stream_topic_, &eval);
auto transform_uri =
EvaluateOptionalExpression(stream_query->transform_uri_, &eval);
auto batch_interval_in_ms =
EvaluateOptionalExpression(stream_query->batch_interval_in_ms_, &eval);
auto batch_size =
EvaluateOptionalExpression(stream_query->batch_size_, &eval);
auto limit_batches =
EvaluateOptionalExpression(stream_query->limit_batches_, &eval);
Callback callback;
switch (stream_query->action_) {
case StreamQuery::Action::CREATE_STREAM:
callback.fn = [streams, stream_name, stream_uri, stream_topic,
transform_uri, batch_interval_in_ms, batch_size] {
CHECK(stream_uri.IsString());
CHECK(stream_topic.IsString());
CHECK(transform_uri.IsString());
CHECK(batch_interval_in_ms.IsInt() || batch_interval_in_ms.IsNull());
CHECK(batch_size.IsInt() || batch_size.IsNull());
integrations::kafka::StreamInfo info;
info.stream_name = stream_name;
info.stream_uri = stream_uri.ValueString();
info.stream_topic = stream_topic.ValueString();
info.transform_uri = transform_uri.ValueString();
info.batch_interval_in_ms = batch_interval_in_ms.IsInt()
? std::experimental::make_optional(
batch_interval_in_ms.ValueInt())
: std::experimental::nullopt;
info.batch_size =
batch_size.IsInt()
? std::experimental::make_optional(batch_size.ValueInt())
: std::experimental::nullopt;
try {
streams->Create(info);
} catch (const integrations::kafka::KafkaStreamException &e) {
throw QueryRuntimeException(e.what());
}
return std::vector<std::vector<TypedValue>>();
};
return callback;
case StreamQuery::Action::DROP_STREAM:
callback.fn = [streams, stream_name] {
try {
streams->Drop(stream_name);
} catch (const integrations::kafka::KafkaStreamException &e) {
throw QueryRuntimeException(e.what());
}
return std::vector<std::vector<TypedValue>>();
};
return callback;
case StreamQuery::Action::SHOW_STREAMS:
callback.header = {"name", "uri", "topic", "transform", "status"};
callback.fn = [streams] {
std::vector<std::vector<TypedValue>> status;
for (const auto &stream : streams->Show()) {
status.push_back(std::vector<TypedValue>{
stream.stream_name, stream.stream_uri, stream.stream_topic,
stream.transform_uri, stream.stream_status});
}
return status;
};
return callback;
case StreamQuery::Action::START_STREAM:
callback.fn = [streams, stream_name, limit_batches] {
CHECK(limit_batches.IsInt() || limit_batches.IsNull());
try {
streams->Start(stream_name, limit_batches.IsInt()
? std::experimental::make_optional(
limit_batches.ValueInt())
: std::experimental::nullopt);
} catch (integrations::kafka::KafkaStreamException &e) {
throw QueryRuntimeException(e.what());
}
return std::vector<std::vector<TypedValue>>();
};
return callback;
case StreamQuery::Action::STOP_STREAM:
callback.fn = [streams, stream_name] {
try {
streams->Stop(stream_name);
} catch (integrations::kafka::KafkaStreamException &e) {
throw QueryRuntimeException(e.what());
}
return std::vector<std::vector<TypedValue>>();
};
return callback;
case StreamQuery::Action::START_ALL_STREAMS:
callback.fn = [streams] {
try {
streams->StartAll();
} catch (integrations::kafka::KafkaStreamException &e) {
throw QueryRuntimeException(e.what());
}
return std::vector<std::vector<TypedValue>>();
};
return callback;
case StreamQuery::Action::STOP_ALL_STREAMS:
callback.fn = [streams] {
try {
streams->StopAll();
} catch (integrations::kafka::KafkaStreamException &e) {
throw QueryRuntimeException(e.what());
}
return std::vector<std::vector<TypedValue>>();
};
return callback;
case StreamQuery::Action::TEST_STREAM:
callback.header = {"query", "params"};
callback.fn = [streams, stream_name, limit_batches] {
CHECK(limit_batches.IsInt() || limit_batches.IsNull());
std::vector<std::vector<TypedValue>> rows;
try {
auto results = streams->Test(
stream_name,
limit_batches.IsInt()
? std::experimental::make_optional(limit_batches.ValueInt())
: std::experimental::nullopt);
for (const auto &result : results) {
std::map<std::string, TypedValue> params;
for (const auto &param : result.second) {
params.emplace(param.first, glue::ToTypedValue(param.second));
}
rows.emplace_back(std::vector<TypedValue>{result.first, params});
}
} catch (integrations::kafka::KafkaStreamException &e) {
throw QueryRuntimeException(e.what());
}
return rows;
};
return callback;
}
}
Callback HandleIndexQuery(IndexQuery *index_query,
std::function<void()> invalidate_plan_cache,
database::GraphDbAccessor *db_accessor) {
@@ -633,8 +188,7 @@ Interpreter::Results Interpreter::operator()(
auto cursor = plan->plan().MakeCursor(db_accessor);
return Results(std::move(execution_context), plan, std::move(cursor),
output_symbols, header, summary,
parsed_query.required_privileges);
output_symbols, header, summary);
}
if (auto *explain_query = dynamic_cast<ExplainQuery *>(parsed_query.query)) {
@@ -679,8 +233,7 @@ Interpreter::Results Interpreter::operator()(
auto cursor = plan->plan().MakeCursor(db_accessor);
return Results(std::move(execution_context), plan, std::move(cursor),
output_symbols, header, summary,
parsed_query.required_privileges);
output_symbols, header, summary);
}
Callback callback;
@@ -697,19 +250,6 @@ Interpreter::Results Interpreter::operator()(
};
callback =
HandleIndexQuery(index_query, invalidate_plan_cache, &db_accessor);
} else if (auto *auth_query = dynamic_cast<AuthQuery *>(parsed_query.query)) {
if (in_explicit_transaction) {
throw UserModificationInMulticommandTxException();
}
callback =
HandleAuthQuery(auth_query, auth_, evaluation_context, &db_accessor);
} else if (auto *stream_query =
dynamic_cast<StreamQuery *>(parsed_query.query)) {
if (in_explicit_transaction) {
throw StreamClauseInMulticommandTxException();
}
callback = HandleStreamQuery(stream_query, kafka_streams_,
evaluation_context, &db_accessor);
} else {
LOG(FATAL) << "Should not get here -- unknown query type!";
}
@@ -731,8 +271,7 @@ Interpreter::Results Interpreter::operator()(
auto cursor = plan->plan().MakeCursor(db_accessor);
return Results(std::move(execution_context), plan, std::move(cursor),
output_symbols, callback.header, summary,
parsed_query.required_privileges);
output_symbols, callback.header, summary);
}
std::shared_ptr<Interpreter::CachedPlan> Interpreter::CypherQueryToPlan(
@@ -768,8 +307,7 @@ Interpreter::ParsedQuery Interpreter::ParseQuery(
// Convert antlr4 AST into Memgraph AST.
frontend::CypherMainVisitor visitor(context, ast_storage, db_accessor);
visitor.visit(parser->tree());
return ParsedQuery{visitor.query(),
query::GetRequiredPrivileges(visitor.query())};
return ParsedQuery{visitor.query()};
}
auto stripped_query_hash = fnv(stripped_query);
@@ -799,15 +337,13 @@ Interpreter::ParsedQuery Interpreter::ParseQuery(
frontend::CypherMainVisitor visitor(context, &cached_ast_storage,
db_accessor);
visitor.visit(parser->tree());
CachedQuery cached_query{std::move(cached_ast_storage), visitor.query(),
query::GetRequiredPrivileges(visitor.query())};
CachedQuery cached_query{std::move(cached_ast_storage), visitor.query()};
// Cache it.
ast_it =
ast_cache_accessor.insert(stripped_query_hash, std::move(cached_query))
.first;
}
return ParsedQuery{ast_it->second.query->Clone(*ast_storage),
ast_it->second.required_privileges};
return ParsedQuery{ast_it->second.query->Clone(*ast_storage)};
}
std::unique_ptr<LogicalPlan> Interpreter::MakeLogicalPlan(

View File

@@ -16,14 +16,6 @@
DECLARE_bool(query_cost_planner);
DECLARE_int32(query_plan_cache_ttl);
namespace auth {
class Auth;
} // namespace auth
namespace integrations::kafka {
class Streams;
} // namespace integrations::kafka
namespace query {
// TODO: Maybe this should move to query/plan/planner.
@@ -60,12 +52,10 @@ class Interpreter {
struct CachedQuery {
AstStorage ast_storage;
Query *query;
std::vector<AuthQuery::Privilege> required_privileges;
};
struct ParsedQuery {
Query *query;
std::vector<AuthQuery::Privilege> required_privileges;
};
using PlanCacheT = ConcurrentMap<HashType, std::shared_ptr<CachedPlan>>;
@@ -80,16 +70,14 @@ class Interpreter {
Results(Context ctx, std::shared_ptr<CachedPlan> plan,
std::unique_ptr<query::plan::Cursor> cursor,
std::vector<Symbol> output_symbols, std::vector<std::string> header,
std::map<std::string, TypedValue> summary,
std::vector<AuthQuery::Privilege> privileges)
std::map<std::string, TypedValue> summary)
: ctx_(std::move(ctx)),
plan_(plan),
cursor_(std::move(cursor)),
frame_(ctx_.symbol_table_.max_position()),
output_symbols_(output_symbols),
header_(header),
summary_(summary),
privileges_(std::move(privileges)) {}
summary_(summary) {}
public:
Results(const Results &) = delete;
@@ -138,10 +126,6 @@ class Interpreter {
const std::vector<std::string> &header() { return header_; }
const std::map<std::string, TypedValue> &summary() { return summary_; }
const std::vector<AuthQuery::Privilege> &privileges() {
return privileges_;
}
private:
Context ctx_;
std::shared_ptr<CachedPlan> plan_;
@@ -153,8 +137,6 @@ class Interpreter {
std::map<std::string, TypedValue> summary_;
double execution_time_{0};
std::vector<AuthQuery::Privilege> privileges_;
};
Interpreter() = default;
@@ -174,9 +156,6 @@ class Interpreter {
const std::map<std::string, PropertyValue> &params,
bool in_explicit_transaction);
auth::Auth *auth_ = nullptr;
integrations::kafka::Streams *kafka_streams_ = nullptr;
protected:
// high level tree -> logical plan
// AstStorage and SymbolTable may be modified during planning. The created

View File

@@ -13,13 +13,9 @@
#include "glog/logging.h"
#include "auth/auth.hpp"
#include "communication/result_stream_faker.hpp"
#include "database/graph_db_accessor.hpp"
#include "glue/auth.hpp"
#include "glue/communication.hpp"
#include "integrations/kafka/exceptions.hpp"
#include "integrations/kafka/streams.hpp"
#include "query/context.hpp"
#include "query/exceptions.hpp"
#include "query/frontend/ast/ast.hpp"

View File

@@ -53,8 +53,6 @@ class UsedSymbolsCollector : public HierarchicalTreeVisitor {
bool Visit(PrimitiveLiteral &) override { return true; }
bool Visit(ParameterLookup &) override { return true; }
bool Visit(query::IndexQuery &) override { return true; }
bool Visit(query::AuthQuery &) override { return true; }
bool Visit(query::StreamQuery &) override { return true; }
std::unordered_set<Symbol> symbols_;
const SymbolTable &symbol_table_;

View File

@@ -402,16 +402,6 @@ class ReturnBodyContext : public HierarchicalTreeVisitor {
return true;
}
bool Visit(query::AuthQuery &) override {
has_aggregation_.emplace_back(false);
return true;
}
bool Visit(query::StreamQuery &) override {
has_aggregation_.emplace_back(false);
return true;
}
// Creates NamedExpression with an Identifier for each user declared symbol.
// This should be used when body.all_identifiers is true, to generate
// expressions for Produce operator.

View File

@@ -16,8 +16,7 @@ class TransactionEngine final {
~TransactionEngine() { Abort(); }
std::pair<std::vector<std::string>, std::vector<query::AuthQuery::Privilege>>
Interpret(const std::string &query,
std::vector<std::string> Interpret(const std::string &query,
const std::map<std::string, PropertyValue> &params) {
// Clear pending results.
results_ = std::experimental::nullopt;
@@ -64,7 +63,7 @@ class TransactionEngine final {
try {
results_.emplace((*interpreter_)(query, *db_accessor_, params,
in_explicit_transaction_));
return {results_->header(), results_->privileges()};
return results_->header();
} catch (const utils::BasicException &) {
AbortCommand();
throw;
@@ -93,6 +92,8 @@ class TransactionEngine final {
void Abort() {
results_ = std::experimental::nullopt;
expect_rollback_ = false;
in_explicit_transaction_ = false;
if (!db_accessor_) return;
db_accessor_->Abort();
db_accessor_ = nullptr;

View File

@@ -88,15 +88,18 @@ class Edges {
/** Helper function that skips edges that don't satisfy the predicate
* present in this iterator. */
void update_position() {
if (vertex_) {
position_ = std::find_if(position_, end_,
[v = this->vertex_.value()](const Element &e) {
return e.vertex == v;
});
}
if (edge_types_) {
if (vertex_ && edge_types_) {
position_ = std::find_if(position_, end_, [this](const Element &e) {
return utils::Contains(*edge_types_, e.edge_type);
return e.vertex == this->vertex_ &&
utils::Contains(*this->edge_types_, e.edge_type);
});
} else if (vertex_) {
position_ = std::find_if(position_, end_, [this](const Element &e) {
return e.vertex == this->vertex_;
});
} else if (edge_types_) {
position_ = std::find_if(position_, end_, [this](const Element &e) {
return utils::Contains(*this->edge_types_, e.edge_type);
});
}
}

View File

@@ -86,15 +86,18 @@ class Edges {
/** Helper function that skips edges that don't satisfy the predicate
* present in this iterator. */
void update_position() {
if (vertex_) {
position_ = std::find_if(position_,
end_, [v = this->vertex_](const Element &e) {
return e.vertex == v;
});
}
if (edge_types_) {
if (vertex_ && edge_types_) {
position_ = std::find_if(position_, end_, [this](const Element &e) {
return utils::Contains(*edge_types_, e.edge_type);
return e.vertex == this->vertex_ &&
utils::Contains(*this->edge_types_, e.edge_type);
});
} else if (vertex_) {
position_ = std::find_if(position_, end_, [this](const Element &e) {
return e.vertex == this->vertex_;
});
} else if (edge_types_) {
position_ = std::find_if(position_, end_, [this](const Element &e) {
return utils::Contains(*this->edge_types_, e.edge_type);
});
}
}

View File

@@ -5,7 +5,6 @@
#include "data_structures/concurrent/concurrent_map.hpp"
#include "mvcc/single_node/version_list.hpp"
#include "stats/metrics.hpp"
#include "storage/single_node/deferred_deleter.hpp"
#include "storage/single_node/edge.hpp"
#include "storage/single_node/garbage_collector.hpp"

View File

@@ -7,13 +7,5 @@ set(utils_src_files
uuid.cpp
watchdog.cpp)
define_add_capnp(utils_src_files utils_capnp_files)
add_capnp(serialization.capnp)
add_custom_target(generate_utils_capnp DEPENDS ${utils_capnp_files})
add_library(mg-utils STATIC ${utils_src_files})
target_link_libraries(mg-utils stdc++fs Threads::Threads fmt glog gflags uuid)
target_link_libraries(mg-utils capnp kj)
add_dependencies(mg-utils generate_utils_capnp)

View File

@@ -27,6 +27,3 @@ add_subdirectory(property_based)
# integration test binaries
add_subdirectory(integration)
# feature benchmark test binaries
add_subdirectory(feature_benchmark)

View File

@@ -51,9 +51,6 @@ target_link_libraries(${test_prefix}edge_storage mg-single-node kvstore_dummy_li
add_benchmark(mvcc.cpp)
target_link_libraries(${test_prefix}mvcc mg-single-node kvstore_dummy_lib)
add_benchmark(serialization.cpp)
target_link_libraries(${test_prefix}serialization mg-distributed kvstore_dummy_lib)
add_benchmark(tx_engine.cpp)
target_link_libraries(${test_prefix}tx_engine mg-single-node kvstore_dummy_lib)

View File

@@ -1,47 +0,0 @@
#!/usr/bin/env python3
import json
import os
import re
import subprocess
from card_fraud import NUM_MACHINES, BINARIES
# paths
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
WORKSPACE_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, "..", "..", "..", ".."))
OUTPUT_DIR_REL = os.path.join(os.path.relpath(SCRIPT_DIR, WORKSPACE_DIR), "output")
# generate runs
runs = []
binaries = list(map(lambda x: os.path.join("..", "..", "build_release", x), BINARIES))
for i in range(NUM_MACHINES):
name = "master" if i == 0 else "worker" + str(i)
additional = ["master.py"] if i == 0 else []
outfile_paths = ["\\./" + OUTPUT_DIR_REL + "/.+"] if i == 0 else []
if i == 0:
cmd = "master.py"
args = "--machines-num {0} --test-suite card_fraud " \
"--test card_fraud".format(NUM_MACHINES)
else:
cmd = "jail_service.py"
args = ""
runs.append({
"name": "distributed__card_fraud__" + name,
"cd": "..",
"supervisor": cmd,
"arguments": args,
"infiles": binaries + [
"common.py",
"jail_service.py",
"card_fraud/card_fraud.py",
"card_fraud/snapshots/worker_" + str(i),
] + additional,
"outfile_paths": outfile_paths,
"parallel_run": "distributed__card_fraud",
"slave_group": "remote_4c32g",
"enable_network": True,
})
print(json.dumps(runs, indent=4, sort_keys=True))

View File

@@ -1,10 +0,0 @@
- name: feature_benchmark__kafka
cd: kafka
commands: ./runner.sh
infiles:
- runner.sh # runner script
- transform.py # transform script
- generate.py # dataset generator script
- ../../../build_release/tests/feature_benchmark/kafka/kafka.py # kafka script
- ../../../build_release/tests/feature_benchmark/kafka/benchmark # benchmark binary
enable_network: true

View File

@@ -6,12 +6,3 @@ add_subdirectory(ssl)
# transactions test binaries
add_subdirectory(transactions)
# kafka test binaries
add_subdirectory(kafka)
# auth test binaries
add_subdirectory(auth)
# distributed test binaries
add_subdirectory(distributed)

View File

@@ -22,31 +22,3 @@
- runner.sh # runner script
- ../../../build_debug/memgraph # memgraph binary
- ../../../build_debug/tests/integration/transactions/tester # tester binary
- name: integration__kafka
cd: kafka
commands: ./runner.sh
infiles:
- runner.sh # runner script
- transform.py # transform script
- ../../../build_debug/memgraph # memgraph binary
- ../../../build_debug/kafka.py # kafka script
- ../../../build_debug/tests/integration/kafka/tester # tester binary
enable_network: true
- name: integration__auth
cd: auth
commands: TIMEOUT=820 ./runner.py
infiles:
- runner.py # runner script
- ../../../build_debug/memgraph # memgraph binary
- ../../../build_debug/tests/integration/auth/checker # checker binary
- ../../../build_debug/tests/integration/auth/tester # tester binary
- name: integration__distributed
cd: distributed
commands: TIMEOUT=480 ./runner.py
infiles:
- runner.py # runner script
- ../../../build_debug/memgraph_distributed # memgraph distributed binary
- ../../../build_debug/tests/integration/distributed/tester # tester binary

View File

@@ -15,16 +15,16 @@ function(add_macro_benchmark test_cpp)
endfunction(add_macro_benchmark)
add_macro_benchmark(clients/pokec_client.cpp)
target_link_libraries(${test_prefix}pokec_client mg-communication mg-io mg-utils mg-stats json)
target_link_libraries(${test_prefix}pokec_client mg-communication mg-io mg-utils json)
add_macro_benchmark(clients/graph_500_bfs.cpp)
target_link_libraries(${test_prefix}graph_500_bfs mg-communication mg-io mg-utils mg-stats json)
target_link_libraries(${test_prefix}graph_500_bfs mg-communication mg-io mg-utils json)
add_macro_benchmark(clients/bfs_pokec_client.cpp)
target_link_libraries(${test_prefix}bfs_pokec_client mg-communication mg-io mg-utils mg-stats json)
target_link_libraries(${test_prefix}bfs_pokec_client mg-communication mg-io mg-utils json)
add_macro_benchmark(clients/query_client.cpp)
target_link_libraries(${test_prefix}query_client mg-communication mg-io mg-utils)
add_macro_benchmark(clients/card_fraud_client.cpp)
target_link_libraries(${test_prefix}card_fraud_client mg-communication mg-io mg-utils mg-stats json)
target_link_libraries(${test_prefix}card_fraud_client mg-communication mg-io mg-utils json)

View File

@@ -5,9 +5,6 @@
#include "gflags/gflags.h"
#include "communication/rpc/client.hpp"
#include "stats/stats.hpp"
#include "stats/stats_rpc_messages.hpp"
#include "utils/thread/sync.hpp"
#include "long_running_common.hpp"
@@ -23,14 +20,6 @@ DEFINE_string(config, "", "test config");
enum class Role { WORKER, ANALYTIC, CLEANUP };
stats::Gauge &num_vertices = stats::GetGauge("vertices");
stats::Gauge &num_edges = stats::GetGauge("edges");
void UpdateStats() {
num_vertices.Set(num_pos + num_cards + num_transactions);
num_edges.Set(2 * num_transactions);
}
int64_t NumNodesWithLabel(Client &client, std::string label) {
std::string query = fmt::format("MATCH (u :{}) RETURN count(u)", label);
auto result = ExecuteNTimesTillSuccess(client, query, {}, MAX_RETRIES);
@@ -176,7 +165,6 @@ class CardFraudClient : public TestClient {
card_id, tx_id, pos_id);
num_transactions++;
UpdateStats();
}
int64_t UniformInt(int64_t a, int64_t b) {
@@ -261,7 +249,6 @@ class CardFraudClient : public TestClient {
num_transactions, num_transactions_db, deleted,
num_transactions - num_transactions_db);
num_transactions = num_transactions_db;
UpdateStats();
}
std::this_thread::sleep_for(
@@ -334,9 +321,6 @@ int main(int argc, char **argv) {
communication::Init();
stats::InitStatsLogging(
fmt::format("client.long_running.{}.{}", FLAGS_group, FLAGS_scenario));
Endpoint endpoint(FLAGS_address, FLAGS_port);
ClientContext context(FLAGS_use_ssl);
Client client(&context);
@@ -382,7 +366,5 @@ int main(int argc, char **argv) {
RunMultithreadedTest(clients);
stats::StopStatsLogging();
return 0;
}

View File

@@ -6,8 +6,6 @@
#include "gflags/gflags.h"
#include "long_running_common.hpp"
#include "stats/stats.hpp"
#include "stats/stats_rpc_messages.hpp"
class Graph500BfsClient : public TestClient {
public:
@@ -55,7 +53,5 @@ int main(int argc, char **argv) {
RunMultithreadedTest(clients);
stats::StopStatsLogging();
return 0;
}

View File

@@ -14,8 +14,6 @@
#include "json/json.hpp"
#include "stats/metrics.hpp"
#include "stats/stats.hpp"
#include "utils/timer.hpp"
#include "common.hpp"
@@ -35,9 +33,9 @@ DEFINE_int32(duration, 30, "Number of seconds to execute benchmark");
DEFINE_string(group, "unknown", "Test group name");
DEFINE_string(scenario, "unknown", "Test scenario name");
auto &executed_queries = stats::GetCounter("executed_queries");
auto &executed_steps = stats::GetCounter("executed_steps");
auto &serialization_errors = stats::GetCounter("serialization_errors");
std::atomic<uint64_t> executed_queries;
std::atomic<uint64_t> executed_steps;
std::atomic<uint64_t> serialization_errors;
class TestClient {
public:
@@ -59,7 +57,7 @@ class TestClient {
runner_thread_ = std::thread([&] {
while (keep_running_) {
Step();
executed_steps.Bump();
++executed_steps;
}
});
}
@@ -82,7 +80,7 @@ class TestClient {
std::tie(result, retries) =
ExecuteNTimesTillSuccess(client_, query, params, MAX_RETRIES);
} catch (const utils::BasicException &e) {
serialization_errors.Bump(MAX_RETRIES);
serialization_errors += MAX_RETRIES;
return std::experimental::nullopt;
}
auto wall_time = timer.Elapsed();
@@ -96,8 +94,8 @@ class TestClient {
stats_[query].push_back(std::move(metadata));
}
}
executed_queries.Bump();
serialization_errors.Bump(retries);
++executed_queries;
serialization_errors += retries;
return result;
}
@@ -177,16 +175,11 @@ void RunMultithreadedTest(std::vector<std::unique_ptr<TestClient>> &clients) {
auto it = aggregated_query_stats.insert({stat.first, Value(0.0)}).first;
it->second = (it->second.ValueDouble() * old_count + stat.second) /
(old_count + new_count);
stats::LogStat(
fmt::format("queries.{}.{}", query_stats.first, stat.first),
(stat.second / new_count));
}
stats::LogStat(fmt::format("queries.{}.count", query_stats.first),
new_count);
}
out << "{\"num_executed_queries\": " << executed_queries.Value() << ", "
<< "\"num_executed_steps\": " << executed_steps.Value() << ", "
out << "{\"num_executed_queries\": " << executed_queries << ", "
<< "\"num_executed_steps\": " << executed_steps << ", "
<< "\"elapsed_time\": " << timer.Elapsed().count()
<< ", \"queries\": [";
utils::PrintIterable(

View File

@@ -30,30 +30,8 @@ target_link_libraries(${test_prefix}binomial mg-utils)
add_manual_test(bolt_client.cpp)
target_link_libraries(${test_prefix}bolt_client mg-communication)
add_manual_test(card_fraud_generate_snapshot.cpp)
target_link_libraries(${test_prefix}card_fraud_generate_snapshot mg-distributed kvstore_dummy_lib)
add_manual_test(card_fraud_local.cpp)
target_link_libraries(${test_prefix}card_fraud_local mg-distributed kvstore_dummy_lib gtest)
add_manual_test(distributed_query_planner.cpp interactive_planning.cpp)
target_link_libraries(${test_prefix}distributed_query_planner mg-distributed
kvstore_dummy_lib)
if (READLINE_FOUND)
target_link_libraries(${test_prefix}distributed_query_planner readline)
endif()
add_manual_test(distributed_repl.cpp)
target_link_libraries(${test_prefix}distributed_repl mg-distributed kvstore_dummy_lib gtest readline)
add_manual_test(endinan.cpp)
add_manual_test(generate_snapshot.cpp)
target_link_libraries(${test_prefix}generate_snapshot mg-distributed kvstore_dummy_lib)
add_manual_test(graph_500_generate_snapshot.cpp)
target_link_libraries(${test_prefix}graph_500_generate_snapshot mg-distributed kvstore_dummy_lib)
add_manual_test(kvstore_console.cpp)
target_link_libraries(${test_prefix}kvstore_console kvstore_lib gflags glog)

View File

@@ -6,11 +6,3 @@
- ../../config # directory with config files
outfile_paths: &OUTFILE_PATHS
- \./memgraph/tests/qa/\.quality_assurance_status
- name: quality_assurance_distributed
commands: TIMEOUT=300 ./continuous_integration --distributed
infiles:
- . # current directory
- ../../build_debug/memgraph_distributed # memgraph distributed debug binary
- ../../config # directory with config files
outfile_paths: *OUTFILE_PATHS

View File

@@ -22,9 +22,6 @@ endfunction(add_unit_test)
add_unit_test(bolt_encoder.cpp)
target_link_libraries(${test_prefix}bolt_encoder mg-single-node kvstore_dummy_lib)
add_unit_test(concurrent_id_mapper_distributed.cpp)
target_link_libraries(${test_prefix}concurrent_id_mapper_distributed mg-distributed kvstore_dummy_lib)
add_unit_test(concurrent_id_mapper_single_node.cpp)
target_link_libraries(${test_prefix}concurrent_id_mapper_single_node mg-single-node kvstore_dummy_lib)
@@ -34,9 +31,6 @@ target_link_libraries(${test_prefix}concurrent_map_access mg-single-node kvstore
add_unit_test(concurrent_map.cpp)
target_link_libraries(${test_prefix}concurrent_map mg-single-node kvstore_dummy_lib)
add_unit_test(counters.cpp)
target_link_libraries(${test_prefix}counters mg-distributed kvstore_dummy_lib)
add_unit_test(cypher_main_visitor.cpp)
target_link_libraries(${test_prefix}cypher_main_visitor mg-single-node kvstore_dummy_lib)
@@ -46,9 +40,6 @@ target_link_libraries(${test_prefix}database_key_index mg-single-node kvstore_du
add_unit_test(database_label_property_index.cpp)
target_link_libraries(${test_prefix}database_label_property_index mg-single-node kvstore_dummy_lib)
add_unit_test(database_master.cpp)
target_link_libraries(${test_prefix}database_master mg-distributed kvstore_dummy_lib)
add_unit_test(database_transaction_timeout.cpp)
target_link_libraries(${test_prefix}database_transaction_timeout mg-single-node kvstore_dummy_lib)
@@ -58,63 +49,21 @@ target_link_libraries(${test_prefix}datastructure_union_find mg-single-node kvst
add_unit_test(deferred_deleter.cpp)
target_link_libraries(${test_prefix}deferred_deleter mg-single-node kvstore_dummy_lib)
add_unit_test(distributed_coordination.cpp)
target_link_libraries(${test_prefix}distributed_coordination mg-distributed kvstore_dummy_lib)
add_unit_test(distributed_data_exchange.cpp)
target_link_libraries(${test_prefix}distributed_data_exchange mg-distributed kvstore_dummy_lib)
add_unit_test(distributed_dgp_vertex_migrator.cpp)
target_link_libraries(${test_prefix}distributed_dgp_vertex_migrator mg-distributed kvstore_dummy_lib)
add_unit_test(distributed_durability.cpp)
target_link_libraries(${test_prefix}distributed_durability mg-distributed kvstore_dummy_lib)
add_unit_test(distributed_dynamic_worker.cpp)
target_link_libraries(${test_prefix}distributed_dynamic_worker mg-distributed kvstore_dummy_lib)
add_unit_test(distributed_gc.cpp)
target_link_libraries(${test_prefix}distributed_gc mg-distributed kvstore_dummy_lib)
add_unit_test(distributed_graph_db.cpp)
target_link_libraries(${test_prefix}distributed_graph_db mg-distributed kvstore_dummy_lib)
add_unit_test(distributed_interpretation.cpp)
target_link_libraries(${test_prefix}distributed_interpretation mg-distributed kvstore_dummy_lib)
add_unit_test(distributed_query_plan.cpp)
target_link_libraries(${test_prefix}distributed_query_plan mg-distributed kvstore_dummy_lib)
add_unit_test(distributed_reset.cpp)
target_link_libraries(${test_prefix}distributed_reset mg-distributed kvstore_dummy_lib)
add_unit_test(distributed_serialization.cpp)
target_link_libraries(${test_prefix}distributed_serialization mg-distributed kvstore_dummy_lib)
add_unit_test(distributed_updates.cpp)
target_link_libraries(${test_prefix}distributed_updates mg-distributed kvstore_dummy_lib)
# TODO (buda): Replace token sharing with centralized solution and write an appropriate test.
# add_unit_test(distributed_token_sharing.cpp)
# target_link_libraries(${test_prefix}distributed_token_sharing memgraph_lib kvstore_dummy_lib)
add_unit_test(bfs_distributed.cpp)
target_link_libraries(${test_prefix}bfs_distributed mg-distributed kvstore_dummy_lib)
add_unit_test(bfs_single_node.cpp)
target_link_libraries(${test_prefix}bfs_single_node mg-single-node kvstore_dummy_lib)
add_unit_test(distributed_dgp_partitioner.cpp)
target_link_libraries(${test_prefix}distributed_dgp_partitioner mg-distributed kvstore_dummy_lib)
add_unit_test(durability.cpp)
target_link_libraries(${test_prefix}durability mg-single-node kvstore_dummy_lib)
add_unit_test(dynamic_bitset.cpp)
target_link_libraries(${test_prefix}dynamic_bitset mg-single-node kvstore_dummy_lib)
add_unit_test(gid.cpp)
target_link_libraries(${test_prefix}gid mg-distributed kvstore_dummy_lib)
add_unit_test(edges_single_node.cpp)
target_link_libraries(${test_prefix}edges_single_node mg-single-node kvstore_dummy_lib)
add_unit_test(graph_db_accessor.cpp)
target_link_libraries(${test_prefix}graph_db_accessor mg-single-node kvstore_dummy_lib)
@@ -131,9 +80,6 @@ target_link_libraries(${test_prefix}interpreter mg-single-node kvstore_dummy_lib
add_unit_test(kvstore.cpp)
target_link_libraries(${test_prefix}kvstore kvstore_lib glog)
add_unit_test(metrics.cpp)
target_link_libraries(${test_prefix}metrics mg-single-node kvstore_dummy_lib)
add_unit_test(mvcc.cpp)
target_link_libraries(${test_prefix}mvcc mg-single-node kvstore_dummy_lib)
@@ -179,9 +125,6 @@ target_link_libraries(${test_prefix}query_plan_match_filter_return mg-single-nod
add_unit_test(query_plan.cpp)
target_link_libraries(${test_prefix}query_plan mg-single-node kvstore_dummy_lib)
add_unit_test(query_required_privileges.cpp)
target_link_libraries(${test_prefix}query_required_privileges mg-single-node kvstore_dummy_lib)
add_unit_test(query_semantic.cpp)
target_link_libraries(${test_prefix}query_semantic mg-single-node kvstore_dummy_lib)
@@ -194,9 +137,6 @@ target_link_libraries(${test_prefix}queue mg-single-node kvstore_dummy_lib)
add_unit_test(record_edge_vertex_accessor.cpp)
target_link_libraries(${test_prefix}record_edge_vertex_accessor mg-single-node kvstore_dummy_lib)
add_unit_test(serialization.cpp)
target_link_libraries(${test_prefix}serialization mg-distributed kvstore_dummy_lib)
add_unit_test(skiplist_access.cpp)
target_link_libraries(${test_prefix}skiplist_access mg-single-node kvstore_dummy_lib)
@@ -218,15 +158,9 @@ target_link_libraries(${test_prefix}state_delta mg-single-node kvstore_dummy_lib
add_unit_test(static_bitset.cpp)
target_link_libraries(${test_prefix}static_bitset mg-single-node kvstore_dummy_lib)
add_unit_test(storage_address.cpp)
target_link_libraries(${test_prefix}storage_address mg-distributed kvstore_dummy_lib)
add_unit_test(stripped.cpp)
target_link_libraries(${test_prefix}stripped mg-single-node kvstore_dummy_lib)
add_unit_test(transaction_engine_distributed.cpp)
target_link_libraries(${test_prefix}transaction_engine_distributed mg-distributed kvstore_dummy_lib)
add_unit_test(transaction_engine_single_node.cpp)
target_link_libraries(${test_prefix}transaction_engine_single_node mg-single-node kvstore_dummy_lib)
@@ -253,9 +187,6 @@ target_link_libraries(${test_prefix}communication_buffer mg-communication)
add_unit_test(network_timeouts.cpp)
target_link_libraries(${test_prefix}network_timeouts mg-communication)
add_unit_test(rpc.cpp)
target_link_libraries(${test_prefix}rpc mg-communication)
# Test data structures
add_unit_test(ring_buffer.cpp)
@@ -310,11 +241,6 @@ target_link_libraries(${test_prefix}utils_timestamp mg-utils)
add_unit_test(utils_watchdog.cpp)
target_link_libraries(${test_prefix}utils_watchdog mg-utils)
# Test mg-auth
add_unit_test(auth.cpp)
target_link_libraries(${test_prefix}auth mg-auth kvstore_lib)
# Test LCP
add_custom_command(

View File

@@ -50,11 +50,6 @@ class TestSession : public Session<TestInputStream, TestOutputStream> {
void Abort() override {}
bool Authenticate(const std::string &username,
const std::string &password) override {
return true;
}
private:
std::string query_;
};

View File

@@ -2009,449 +2009,6 @@ TYPED_TEST(CypherMainVisitorTest, UnionAll) {
ASSERT_FALSE(return_clause->body_.distinct);
}
template <typename AstGeneratorT>
void check_auth_query(std::string input, AuthQuery::Action action,
std::string user, std::string role,
std::string user_or_role,
std::experimental::optional<TypedValue> password,
std::vector<AuthQuery::Privilege> privileges) {
AstGeneratorT ast_generator(input);
auto *auth_query = dynamic_cast<AuthQuery *>(ast_generator.query_);
ASSERT_TRUE(auth_query);
EXPECT_EQ(auth_query->action_, action);
EXPECT_EQ(auth_query->user_, user);
EXPECT_EQ(auth_query->role_, role);
EXPECT_EQ(auth_query->user_or_role_, user_or_role);
ASSERT_EQ(static_cast<bool>(auth_query->password_),
static_cast<bool>(password));
if (password) {
ast_generator.CheckLiteral(auth_query->password_, *password);
}
EXPECT_EQ(auth_query->privileges_, privileges);
}
TYPED_TEST(CypherMainVisitorTest, UserOrRoleName) {
ASSERT_THROW(TypeParam("CREATE ROLE `us|er`"), SyntaxException);
ASSERT_THROW(TypeParam("CREATE ROLE `us er`"), SyntaxException);
check_auth_query<TypeParam>("CREATE ROLE `user`",
AuthQuery::Action::CREATE_ROLE, "", "user", "",
{}, {});
check_auth_query<TypeParam>("CREATE ROLE us___er",
AuthQuery::Action::CREATE_ROLE, "", "us___er", "",
{}, {});
check_auth_query<TypeParam>("CREATE ROLE `us+er`",
AuthQuery::Action::CREATE_ROLE, "", "us+er", "",
{}, {});
}
TYPED_TEST(CypherMainVisitorTest, CreateRole) {
ASSERT_THROW(TypeParam("CREATE ROLE"), SyntaxException);
check_auth_query<TypeParam>("CREATE ROLE rola",
AuthQuery::Action::CREATE_ROLE, "", "rola", "",
{}, {});
ASSERT_THROW(TypeParam("CREATE ROLE lagano rolamo"), SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, DropRole) {
ASSERT_THROW(TypeParam("DROP ROLE"), SyntaxException);
check_auth_query<TypeParam>("DROP ROLE rola", AuthQuery::Action::DROP_ROLE,
"", "rola", "", {}, {});
ASSERT_THROW(TypeParam("DROP ROLE lagano rolamo"), SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, ShowRoles) {
ASSERT_THROW(TypeParam("SHOW ROLES ROLES"), SyntaxException);
check_auth_query<TypeParam>("SHOW ROLES", AuthQuery::Action::SHOW_ROLES, "",
"", "", {}, {});
}
TYPED_TEST(CypherMainVisitorTest, CreateUser) {
ASSERT_THROW(TypeParam("CREATE USER"), SyntaxException);
ASSERT_THROW(TypeParam("CREATE USER 123"), SyntaxException);
check_auth_query<TypeParam>("CREATE USER user",
AuthQuery::Action::CREATE_USER, "user", "", "",
{}, {});
check_auth_query<TypeParam>("CREATE USER user IDENTIFIED BY 'password'",
AuthQuery::Action::CREATE_USER, "user", "", "",
"password", {});
check_auth_query<TypeParam>("CREATE USER user IDENTIFIED BY ''",
AuthQuery::Action::CREATE_USER, "user", "", "",
"", {});
check_auth_query<TypeParam>("CREATE USER user IDENTIFIED BY null",
AuthQuery::Action::CREATE_USER, "user", "", "",
TypedValue::Null, {});
ASSERT_THROW(TypeParam("CRATE USER user IDENTIFIED BY password"),
SyntaxException);
ASSERT_THROW(TypeParam("CREATE USER user IDENTIFIED BY 5"), SyntaxException);
ASSERT_THROW(TypeParam("CREATE USER user IDENTIFIED BY "), SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, SetPassword) {
ASSERT_THROW(TypeParam("SET PASSWORD FOR"), SyntaxException);
ASSERT_THROW(TypeParam("SET PASSWORD FOR user "), SyntaxException);
check_auth_query<TypeParam>("SET PASSWORD FOR user TO null",
AuthQuery::Action::SET_PASSWORD, "user", "", "",
TypedValue::Null, {});
check_auth_query<TypeParam>("SET PASSWORD FOR user TO 'password'",
AuthQuery::Action::SET_PASSWORD, "user", "", "",
"password", {});
ASSERT_THROW(TypeParam("SET PASSWORD FOR user To 5"), SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, DropUser) {
ASSERT_THROW(TypeParam("DROP USER"), SyntaxException);
check_auth_query<TypeParam>("DROP USER user", AuthQuery::Action::DROP_USER,
"user", "", "", {}, {});
ASSERT_THROW(TypeParam("DROP USER lagano rolamo"), SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, ShowUsers) {
ASSERT_THROW(TypeParam("SHOW USERS ROLES"), SyntaxException);
check_auth_query<TypeParam>("SHOW USERS", AuthQuery::Action::SHOW_USERS, "",
"", "", {}, {});
}
TYPED_TEST(CypherMainVisitorTest, SetRole) {
ASSERT_THROW(TypeParam("SET ROLE"), SyntaxException);
ASSERT_THROW(TypeParam("SET ROLE user"), SyntaxException);
ASSERT_THROW(TypeParam("SET ROLE FOR user"), SyntaxException);
ASSERT_THROW(TypeParam("SET ROLE FOR user TO"), SyntaxException);
check_auth_query<TypeParam>("SET ROLE FOR user TO role",
AuthQuery::Action::SET_ROLE, "user", "role", "",
{}, {});
check_auth_query<TypeParam>("SET ROLE FOR user TO null",
AuthQuery::Action::SET_ROLE, "user", "null", "",
{}, {});
}
TYPED_TEST(CypherMainVisitorTest, ClearRole) {
ASSERT_THROW(TypeParam("CLEAR ROLE"), SyntaxException);
ASSERT_THROW(TypeParam("CLEAR ROLE user"), SyntaxException);
ASSERT_THROW(TypeParam("CLEAR ROLE FOR user TO"), SyntaxException);
check_auth_query<TypeParam>("CLEAR ROLE FOR user",
AuthQuery::Action::CLEAR_ROLE, "user", "", "", {},
{});
}
TYPED_TEST(CypherMainVisitorTest, GrantPrivilege) {
ASSERT_THROW(TypeParam("GRANT"), SyntaxException);
ASSERT_THROW(TypeParam("GRANT TO user"), SyntaxException);
ASSERT_THROW(TypeParam("GRANT BLABLA TO user"), SyntaxException);
ASSERT_THROW(TypeParam("GRANT MATCH, TO user"), SyntaxException);
ASSERT_THROW(TypeParam("GRANT MATCH, BLABLA TO user"), SyntaxException);
check_auth_query<TypeParam>("GRANT MATCH TO user",
AuthQuery::Action::GRANT_PRIVILEGE, "", "",
"user", {}, {AuthQuery::Privilege::MATCH});
check_auth_query<TypeParam>(
"GRANT MATCH, AUTH TO user", AuthQuery::Action::GRANT_PRIVILEGE, "", "",
"user", {}, {AuthQuery::Privilege::MATCH, AuthQuery::Privilege::AUTH});
}
TYPED_TEST(CypherMainVisitorTest, DenyPrivilege) {
ASSERT_THROW(TypeParam("DENY"), SyntaxException);
ASSERT_THROW(TypeParam("DENY TO user"), SyntaxException);
ASSERT_THROW(TypeParam("DENY BLABLA TO user"), SyntaxException);
ASSERT_THROW(TypeParam("DENY MATCH, TO user"), SyntaxException);
ASSERT_THROW(TypeParam("DENY MATCH, BLABLA TO user"), SyntaxException);
check_auth_query<TypeParam>("DENY MATCH TO user",
AuthQuery::Action::DENY_PRIVILEGE, "", "", "user",
{}, {AuthQuery::Privilege::MATCH});
check_auth_query<TypeParam>(
"DENY MATCH, AUTH TO user", AuthQuery::Action::DENY_PRIVILEGE, "", "",
"user", {}, {AuthQuery::Privilege::MATCH, AuthQuery::Privilege::AUTH});
}
TYPED_TEST(CypherMainVisitorTest, RevokePrivilege) {
ASSERT_THROW(TypeParam("REVOKE"), SyntaxException);
ASSERT_THROW(TypeParam("REVOKE FROM user"), SyntaxException);
ASSERT_THROW(TypeParam("REVOKE BLABLA FROM user"), SyntaxException);
ASSERT_THROW(TypeParam("REVOKE MATCH, FROM user"), SyntaxException);
ASSERT_THROW(TypeParam("REVOKE MATCH, BLABLA FROM user"), SyntaxException);
check_auth_query<TypeParam>("REVOKE MATCH FROM user",
AuthQuery::Action::REVOKE_PRIVILEGE, "", "",
"user", {}, {AuthQuery::Privilege::MATCH});
check_auth_query<TypeParam>(
"REVOKE MATCH, AUTH FROM user", AuthQuery::Action::REVOKE_PRIVILEGE, "",
"", "user", {},
{AuthQuery::Privilege::MATCH, AuthQuery::Privilege::AUTH});
check_auth_query<TypeParam>(
"REVOKE ALL PRIVILEGES FROM user", AuthQuery::Action::REVOKE_PRIVILEGE,
"", "", "user", {},
{AuthQuery::Privilege::CREATE, AuthQuery::Privilege::DELETE,
AuthQuery::Privilege::MATCH, AuthQuery::Privilege::MERGE,
AuthQuery::Privilege::SET, AuthQuery::Privilege::REMOVE,
AuthQuery::Privilege::INDEX, AuthQuery::Privilege::AUTH,
AuthQuery::Privilege::STREAM});
}
TYPED_TEST(CypherMainVisitorTest, ShowPrivileges) {
ASSERT_THROW(TypeParam("SHOW PRIVILEGES FOR"), SyntaxException);
check_auth_query<TypeParam>("SHOW PRIVILEGES FOR user",
AuthQuery::Action::SHOW_PRIVILEGES, "", "",
"user", {}, {});
ASSERT_THROW(TypeParam("SHOW PRIVILEGES FOR user1, user2"), SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, ShowRoleForUser) {
ASSERT_THROW(TypeParam("SHOW ROLE FOR "), SyntaxException);
check_auth_query<TypeParam>("SHOW ROLE FOR user",
AuthQuery::Action::SHOW_ROLE_FOR_USER, "user", "",
"", {}, {});
ASSERT_THROW(TypeParam("SHOW ROLE FOR user1, user2"), SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, ShowUsersForRole) {
ASSERT_THROW(TypeParam("SHOW USERS FOR "), SyntaxException);
check_auth_query<TypeParam>("SHOW USERS FOR role",
AuthQuery::Action::SHOW_USERS_FOR_ROLE, "",
"role", "", {}, {});
ASSERT_THROW(TypeParam("SHOW USERS FOR role1, role2"), SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, CreateStream) {
auto check_create_stream =
[](std::string input, const std::string &stream_name,
const std::string &stream_uri, const std::string &stream_topic,
const std::string &transform_uri,
std::experimental::optional<int64_t> batch_interval_in_ms,
std::experimental::optional<int64_t> batch_size) {
TypeParam ast_generator(input);
auto *stream_query = dynamic_cast<StreamQuery *>(ast_generator.query_);
ASSERT_TRUE(stream_query);
EXPECT_EQ(stream_query->action_, StreamQuery::Action::CREATE_STREAM);
EXPECT_EQ(stream_query->stream_name_, stream_name);
ASSERT_TRUE(stream_query->stream_uri_);
ast_generator.CheckLiteral(stream_query->stream_uri_,
TypedValue(stream_uri));
ASSERT_TRUE(stream_query->stream_topic_);
ast_generator.CheckLiteral(stream_query->stream_topic_,
TypedValue(stream_topic));
ASSERT_TRUE(stream_query->transform_uri_);
ast_generator.CheckLiteral(stream_query->transform_uri_,
TypedValue(transform_uri));
if (batch_interval_in_ms) {
ASSERT_TRUE(stream_query->batch_interval_in_ms_);
ast_generator.CheckLiteral(stream_query->batch_interval_in_ms_,
TypedValue(*batch_interval_in_ms));
} else {
EXPECT_EQ(stream_query->batch_interval_in_ms_, nullptr);
}
if (batch_size) {
ASSERT_TRUE(stream_query->batch_size_);
ast_generator.CheckLiteral(stream_query->batch_size_,
TypedValue(*batch_size));
} else {
EXPECT_EQ(stream_query->batch_size_, nullptr);
}
};
check_create_stream(
"CREATE STREAM stream AS LOAD DATA KAFKA 'localhost' "
"WITH TOPIC 'tropika' "
"WITH TRANSFORM 'localhost/test.py'",
"stream", "localhost", "tropika", "localhost/test.py",
std::experimental::nullopt, std::experimental::nullopt);
check_create_stream(
"CreaTE StreaM stream AS LOad daTA KAFKA 'localhost' "
"WitH TopIC 'tropika' "
"WITH TRAnsFORM 'localhost/test.py' bAtCH inTErvAL 168",
"stream", "localhost", "tropika", "localhost/test.py", 168,
std::experimental::nullopt);
check_create_stream(
"CreaTE StreaM stream AS LOad daTA KAFKA 'localhost' "
"WITH TopIC 'tropika' "
"WITH TRAnsFORM 'localhost/test.py' bAtCH SizE 17",
"stream", "localhost", "tropika", "localhost/test.py",
std::experimental::nullopt, 17);
check_create_stream(
"CreaTE StreaM stream AS LOad daTA KAFKA 'localhost' "
"WitH TOPic 'tropika' "
"WITH TRAnsFORM 'localhost/test.py' bAtCH inTErvAL 168 Batch SIze 17",
"stream", "localhost", "tropika", "localhost/test.py", 168, 17);
EXPECT_THROW(check_create_stream(
"CREATE STREAM stream AS LOAD DATA KAFKA 'localhost' "
"WITH TRANSFORM 'localhost/test.py' BATCH INTERVAL 'jedan' ",
"stream", "localhost", "tropika", "localhost/test.py", 168,
std::experimental::nullopt),
SyntaxException);
EXPECT_THROW(check_create_stream(
"CREATE STREAM stream AS LOAD DATA KAFKA 'localhost' "
"WITH TOPIC 'tropika' "
"WITH TRANSFORM 'localhost/test.py' BATCH SIZE 'jedan' ",
"stream", "localhost", "tropika", "localhost/test.py",
std::experimental::nullopt, 17),
SyntaxException);
EXPECT_THROW(check_create_stream(
"CREATE STREAM 123 AS LOAD DATA KAFKA 'localhost' "
"WITH TOPIC 'tropika' "
"WITH TRANSFORM 'localhost/test.py' BATCH INTERVAL 168 ",
"stream", "localhost", "tropika", "localhost/test.py", 168,
std::experimental::nullopt),
SyntaxException);
EXPECT_THROW(check_create_stream(
"CREATE STREAM stream AS LOAD DATA KAFKA localhost "
"WITH TOPIC 'tropika' "
"WITH TRANSFORM 'localhost/test.py'",
"stream", "localhost", "tropika", "localhost/test.py",
std::experimental::nullopt, std::experimental::nullopt),
SyntaxException);
EXPECT_THROW(check_create_stream(
"CREATE STREAM stream AS LOAD DATA KAFKA 'localhost' "
"WITH TOPIC 2"
"WITH TRANSFORM localhost/test.py BATCH INTERVAL 168 ",
"stream", "localhost", "tropika", "localhost/test.py", 168,
std::experimental::nullopt),
SyntaxException);
EXPECT_THROW(check_create_stream(
"CREATE STREAM stream AS LOAD DATA KAFKA 'localhost' "
"WITH TOPIC 'tropika'"
"WITH TRANSFORM localhost/test.py BATCH INTERVAL 168 ",
"stream", "localhost", "tropika", "localhost/test.py", 168,
std::experimental::nullopt),
SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, DropStream) {
auto check_drop_stream = [](std::string input,
const std::string &stream_name) {
TypeParam ast_generator(input);
auto *stream_query = dynamic_cast<StreamQuery *>(ast_generator.query_);
ASSERT_TRUE(stream_query);
EXPECT_EQ(stream_query->action_, StreamQuery::Action::DROP_STREAM);
EXPECT_EQ(stream_query->stream_name_, stream_name);
};
check_drop_stream("DRop stREAm stream", "stream");
check_drop_stream("DRop stREAm strim", "strim");
EXPECT_THROW(check_drop_stream("DROp sTREAM", ""), SyntaxException);
EXPECT_THROW(check_drop_stream("DROP STreAM 123", "123"), SyntaxException);
EXPECT_THROW(check_drop_stream("DroP STREAM '123'", "123"), SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, ShowStreams) {
auto check_show_streams = [](std::string input) {
TypeParam ast_generator(input);
auto *stream_query = dynamic_cast<StreamQuery *>(ast_generator.query_);
ASSERT_TRUE(stream_query);
EXPECT_EQ(stream_query->action_, StreamQuery::Action::SHOW_STREAMS);
};
check_show_streams("SHOW STREAMS");
EXPECT_THROW(check_show_streams("SHOW STREAMS lololo"), SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, StartStopStream) {
auto check_start_stop_stream =
[](std::string input, const std::string &stream_name, bool is_start,
std::experimental::optional<int64_t> limit_batches) {
TypeParam ast_generator(input);
auto *stream_query = dynamic_cast<StreamQuery *>(ast_generator.query_);
ASSERT_TRUE(stream_query);
EXPECT_EQ(stream_query->stream_name_, stream_name);
EXPECT_EQ(stream_query->action_,
is_start ? StreamQuery::Action::START_STREAM
: StreamQuery::Action::STOP_STREAM);
if (limit_batches) {
ASSERT_TRUE(is_start);
ASSERT_TRUE(stream_query->limit_batches_);
ast_generator.CheckLiteral(stream_query->limit_batches_,
TypedValue(*limit_batches));
} else {
EXPECT_EQ(stream_query->limit_batches_, nullptr);
}
};
check_start_stop_stream("stARt STreaM STREAM", "STREAM", true,
std::experimental::nullopt);
check_start_stop_stream("stARt STreaM strim", "strim", true,
std::experimental::nullopt);
check_start_stop_stream("StARt STreAM strim LimIT 10 BATchES", "strim", true,
10);
check_start_stop_stream("StoP StrEAM strim", "strim", false,
std::experimental::nullopt);
EXPECT_THROW(check_start_stop_stream("staRT STReaM 'strim'", "strim", true,
std::experimental::nullopt),
SyntaxException);
EXPECT_THROW(check_start_stop_stream("sTART STReaM strim LImiT 'dva' BATCheS",
"strim", true, 2),
SyntaxException);
EXPECT_THROW(check_start_stop_stream("StoP STreAM 'strim'", "strim", false,
std::experimental::nullopt),
SyntaxException);
EXPECT_THROW(check_start_stop_stream("STOp sTREAM strim LIMit 2 baTCHES",
"strim", false, 2),
SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, StartStopAllStreams) {
auto check_start_stop_all_streams = [](std::string input, bool is_start) {
TypeParam ast_generator(input);
auto *stream_query = dynamic_cast<StreamQuery *>(ast_generator.query_);
ASSERT_TRUE(stream_query);
EXPECT_EQ(stream_query->action_,
is_start ? StreamQuery::Action::START_ALL_STREAMS
: StreamQuery::Action::STOP_ALL_STREAMS);
};
check_start_stop_all_streams("STarT AlL StreAMs", true);
check_start_stop_all_streams("StoP aLL STrEAMs", false);
EXPECT_THROW(check_start_stop_all_streams("StaRT aLL STreAM", true),
SyntaxException);
EXPECT_THROW(check_start_stop_all_streams("SToP AlL STREaM", false),
SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, TestStream) {
auto check_test_stream =
[](std::string input, const std::string &stream_name,
std::experimental::optional<int64_t> limit_batches) {
TypeParam ast_generator(input);
auto *stream_query = dynamic_cast<StreamQuery *>(ast_generator.query_);
ASSERT_TRUE(stream_query);
EXPECT_EQ(stream_query->stream_name_, stream_name);
EXPECT_EQ(stream_query->action_, StreamQuery::Action::TEST_STREAM);
if (limit_batches) {
ASSERT_TRUE(stream_query->limit_batches_);
ast_generator.CheckLiteral(stream_query->limit_batches_,
TypedValue(*limit_batches));
} else {
EXPECT_EQ(stream_query->limit_batches_, nullptr);
}
};
check_test_stream("TesT STreaM strim", "strim", std::experimental::nullopt);
check_test_stream("TesT STreaM STREAM", "STREAM", std::experimental::nullopt);
check_test_stream("tESt STreAM STREAM LimIT 10 BATchES", "STREAM", 10);
check_test_stream("Test StrEAM STREAM", "STREAM", std::experimental::nullopt);
EXPECT_THROW(check_test_stream("tEST STReaM 'strim'", "strim",
std::experimental::nullopt),
SyntaxException);
EXPECT_THROW(
check_test_stream("test STReaM strim LImiT 'dva' BATCheS", "strim", 2),
SyntaxException);
EXPECT_THROW(check_test_stream("test STreAM 'strim'", "strim",
std::experimental::nullopt),
SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, TestExplainRegularQuery) {
{
TypeParam ast_generator("EXPLAIN RETURN n");
@@ -2464,13 +2021,4 @@ TYPED_TEST(CypherMainVisitorTest, TestExplainExplainQuery) {
SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, TestExplainAuthQuery) {
EXPECT_THROW(TypeParam ast_generator("EXPLAIN SHOW ROLES"), SyntaxException);
}
TYPED_TEST(CypherMainVisitorTest, TestExplainStreamQuery) {
EXPECT_THROW(TypeParam ast_generator("EXPLAIN SHOW STREAMS"),
SyntaxException);
}
} // namespace

View File

@@ -0,0 +1,125 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "distributed/coordination.hpp"
#include "storage/distributed/edge.hpp"
#include "storage/distributed/vertex.hpp"
#include "transactions/distributed/engine_master.hpp"
#include "utils/algorithm.hpp"
#include "test_coordination.hpp"
#include "storage/distributed/edges.hpp"
TEST(Edges, Filtering) {
Edges edges;
TestMasterCoordination coordination;
tx::EngineMaster tx_engine(&coordination);
auto tx = tx_engine.Begin();
int64_t vertex_gid = 0;
mvcc::VersionList<Vertex> v0(*tx, vertex_gid, vertex_gid);
storage::VertexAddress va0{&v0};
vertex_gid++;
mvcc::VersionList<Vertex> v1(*tx, vertex_gid, vertex_gid);
storage::VertexAddress va1{&v1};
vertex_gid++;
mvcc::VersionList<Vertex> v2(*tx, vertex_gid, vertex_gid);
storage::VertexAddress va2{&v2};
vertex_gid++;
mvcc::VersionList<Vertex> v3(*tx, vertex_gid, vertex_gid);
storage::VertexAddress va3{&v3};
vertex_gid++;
storage::EdgeType t1{1};
storage::EdgeType t2{2};
int64_t edge_gid = 0;
mvcc::VersionList<Edge> e1(*tx, edge_gid, edge_gid, va0, va1, t1);
storage::EdgeAddress ea1(&e1);
edges.emplace(va1, ea1, t1);
edge_gid++;
mvcc::VersionList<Edge> e2(*tx, edge_gid, edge_gid, va0, va2, t1);
storage::EdgeAddress ea2(&e2);
edges.emplace(va2, ea2, t2);
edge_gid++;
mvcc::VersionList<Edge> e3(*tx, edge_gid, edge_gid, va0, va3, t1);
storage::EdgeAddress ea3(&e3);
edges.emplace(va3, ea3, t1);
edge_gid++;
mvcc::VersionList<Edge> e4(*tx, edge_gid, edge_gid, va0, va1, t1);
storage::EdgeAddress ea4(&e4);
edges.emplace(va1, ea4, t2);
edge_gid++;
mvcc::VersionList<Edge> e5(*tx, edge_gid, edge_gid, va0, va2, t1);
storage::EdgeAddress ea5(&e5);
edges.emplace(va2, ea5, t1);
edge_gid++;
mvcc::VersionList<Edge> e6(*tx, edge_gid, edge_gid, va0, va3, t1);
storage::EdgeAddress ea6(&e6);
edges.emplace(va3, ea6, t2);
edge_gid++;
auto edge_addresses =
[edges](std::experimental::optional<storage::VertexAddress> dest,
std::vector<storage::EdgeType> *edge_types) {
std::vector<storage::EdgeAddress> ret;
for (auto it = edges.begin(dest, edge_types); it != edges.end(); ++it)
ret.push_back(it->edge);
return ret;
};
{ // no filtering
EXPECT_THAT(edge_addresses(std::experimental::nullopt, nullptr),
::testing::UnorderedElementsAre(ea1, ea2, ea3, ea4, ea5, ea6));
}
{
// filter by node
EXPECT_THAT(edge_addresses(va1, nullptr),
::testing::UnorderedElementsAre(ea1, ea4));
EXPECT_THAT(edge_addresses(va2, nullptr),
::testing::UnorderedElementsAre(ea2, ea5));
EXPECT_THAT(edge_addresses(va3, nullptr),
::testing::UnorderedElementsAre(ea3, ea6));
}
{
// filter by edge type
std::vector<storage::EdgeType> f1{t1};
std::vector<storage::EdgeType> f2{t2};
std::vector<storage::EdgeType> f3{t1, t2};
EXPECT_THAT(edge_addresses(std::experimental::nullopt, &f1),
::testing::UnorderedElementsAre(ea1, ea3, ea5));
EXPECT_THAT(edge_addresses(std::experimental::nullopt, &f2),
::testing::UnorderedElementsAre(ea2, ea4, ea6));
EXPECT_THAT(edge_addresses(std::experimental::nullopt, &f3),
::testing::UnorderedElementsAre(ea1, ea2, ea3, ea4, ea5, ea6));
}
{
// filter by both node and edge type
std::vector<storage::EdgeType> f1{t1};
std::vector<storage::EdgeType> f2{t2};
EXPECT_THAT(edge_addresses(va1, &f1), ::testing::UnorderedElementsAre(ea1));
EXPECT_THAT(edge_addresses(va1, &f2), ::testing::UnorderedElementsAre(ea4));
EXPECT_THAT(edge_addresses(va2, &f1), ::testing::UnorderedElementsAre(ea5));
EXPECT_THAT(edge_addresses(va2, &f2), ::testing::UnorderedElementsAre(ea2));
EXPECT_THAT(edge_addresses(va3, &f1), ::testing::UnorderedElementsAre(ea3));
EXPECT_THAT(edge_addresses(va3, &f2), ::testing::UnorderedElementsAre(ea6));
}
tx_engine.Abort(*tx);
}

View File

@@ -0,0 +1,96 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "storage/single_node/edge.hpp"
#include "storage/single_node/vertex.hpp"
#include "transactions/single_node/engine.hpp"
#include "utils/algorithm.hpp"
#include "storage/single_node/edges.hpp"
TEST(Edges, Filtering) {
Edges edges;
tx::Engine tx_engine;
auto tx = tx_engine.Begin();
int64_t vertex_gid = 0;
mvcc::VersionList<Vertex> v0(*tx, vertex_gid++);
mvcc::VersionList<Vertex> v1(*tx, vertex_gid++);
mvcc::VersionList<Vertex> v2(*tx, vertex_gid++);
mvcc::VersionList<Vertex> v3(*tx, vertex_gid++);
storage::EdgeType t1{1};
storage::EdgeType t2{2};
int64_t edge_gid = 0;
mvcc::VersionList<Edge> e1(*tx, edge_gid++, &v0, &v1, t1);
edges.emplace(&v1, &e1, t1);
mvcc::VersionList<Edge> e2(*tx, edge_gid++, &v0, &v2, t2);
edges.emplace(&v2, &e2, t2);
mvcc::VersionList<Edge> e3(*tx, edge_gid++, &v0, &v3, t1);
edges.emplace(&v3, &e3, t1);
mvcc::VersionList<Edge> e4(*tx, edge_gid++, &v0, &v1, t2);
edges.emplace(&v1, &e4, t2);
mvcc::VersionList<Edge> e5(*tx, edge_gid++, &v0, &v2, t1);
edges.emplace(&v2, &e5, t1);
mvcc::VersionList<Edge> e6(*tx, edge_gid++, &v0, &v3, t2);
edges.emplace(&v3, &e6, t2);
auto edge_addresses = [edges](mvcc::VersionList<Vertex> *dest,
std::vector<storage::EdgeType> *edge_types) {
std::vector<mvcc::VersionList<Edge> *> ret;
for (auto it = edges.begin(dest, edge_types); it != edges.end(); ++it)
ret.push_back(it->edge);
return ret;
};
{ // no filtering
EXPECT_THAT(edge_addresses(nullptr, nullptr),
::testing::UnorderedElementsAre(&e1, &e2, &e3, &e4, &e5, &e6));
}
{
// filter by node
EXPECT_THAT(edge_addresses(&v1, nullptr),
::testing::UnorderedElementsAre(&e1, &e4));
EXPECT_THAT(edge_addresses(&v2, nullptr),
::testing::UnorderedElementsAre(&e2, &e5));
EXPECT_THAT(edge_addresses(&v3, nullptr),
::testing::UnorderedElementsAre(&e3, &e6));
}
{
// filter by edge type
std::vector<storage::EdgeType> f1{t1};
std::vector<storage::EdgeType> f2{t2};
std::vector<storage::EdgeType> f3{t1, t2};
EXPECT_THAT(edge_addresses(nullptr, &f1),
::testing::UnorderedElementsAre(&e1, &e3, &e5));
EXPECT_THAT(edge_addresses(nullptr, &f2),
::testing::UnorderedElementsAre(&e2, &e4, &e6));
EXPECT_THAT(edge_addresses(nullptr, &f3),
::testing::UnorderedElementsAre(&e1, &e2, &e3, &e4, &e5, &e6));
}
{
// filter by both node and edge type
std::vector<storage::EdgeType> f1{t1};
std::vector<storage::EdgeType> f2{t2};
EXPECT_THAT(edge_addresses(&v1, &f1), ::testing::UnorderedElementsAre(&e1));
EXPECT_THAT(edge_addresses(&v1, &f2), ::testing::UnorderedElementsAre(&e4));
EXPECT_THAT(edge_addresses(&v2, &f1), ::testing::UnorderedElementsAre(&e5));
EXPECT_THAT(edge_addresses(&v2, &f2), ::testing::UnorderedElementsAre(&e2));
EXPECT_THAT(edge_addresses(&v3, &f1), ::testing::UnorderedElementsAre(&e3));
EXPECT_THAT(edge_addresses(&v3, &f2), ::testing::UnorderedElementsAre(&e6));
}
tx_engine.Abort(*tx);
}

View File

@@ -16,8 +16,6 @@
#include "query/plan/operator.hpp"
#include "query/plan/planner.hpp"
#include <capnp/message.h>
#include "query_common.hpp"
namespace query {

View File

@@ -2,10 +2,6 @@
add_executable(mg_import_csv mg_import_csv/main.cpp)
target_link_libraries(mg_import_csv mg-single-node kvstore_dummy_lib)
# StatsD Target
add_executable(mg_statsd mg_statsd/main.cpp)
target_link_libraries(mg_statsd mg-communication mg-io mg-utils mg-stats)
# Generate a version.hpp file
set(VERSION_STRING ${memgraph_VERSION})
configure_file(../../src/version.hpp.in version.hpp @ONLY)

View File

@@ -3,9 +3,6 @@ include_directories(SYSTEM ${GTEST_INCLUDE_DIR})
add_executable(mg_recovery_check mg_recovery_check.cpp)
target_link_libraries(mg_recovery_check mg-single-node gtest gtest_main kvstore_dummy_lib)
add_executable(mg_statsd_client statsd/mg_statsd_client.cpp)
target_link_libraries(mg_statsd_client mg-communication mg-io mg-utils mg-stats)
# Copy CSV data to CMake build dir
configure_file(csv/comment_nodes.csv csv/comment_nodes.csv COPYONLY)
configure_file(csv/comment_nodes_2.csv csv/comment_nodes_2.csv COPYONLY)