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 # 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 ## v0.14.0
### Breaking Changes ### 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() # 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 It aims to deliver developers the speed, simplicity and scale required to build
the next generation of applications driver by real-time connected data.") the next generation of applications driver by real-time connected data.")
# Add `openssl` package to dependencies list. Used to generate SSL certificates. # 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. # All variables must be set before including.
include(CPack) include(CPack)

View File

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

View File

@@ -31,12 +31,8 @@
mkdir build_release mkdir build_release
cd build_release cd build_release
cmake -DCMAKE_BUILD_TYPE=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 TIMEOUT=1200 make -j$THREADS memgraph tools memgraph__macro_benchmark memgraph__stress
cd ..
# Generate distributed card fraud dataset.
cd ../tests/distributed/card_fraud
./generate_dataset.sh
cd ../../..
# Checkout to parent commit and initialize. # Checkout to parent commit and initialize.
cd ../parent cd ../parent
@@ -83,7 +79,3 @@
mkdir output mkdir output
cd output cd output
cpack -G DEB --config ../CPackConfig.cmake 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} CXX=${CMAKE_CXX_COMPILER}
INSTALL_COMMAND true) 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 # Setup libbcrypt
import_external_library(libbcrypt STATIC import_external_library(libbcrypt STATIC
${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/bcrypt.a ${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 rocksdb_tag="dbd8fa09b823826dd2a30bc119dad7a6fa9a4c6d" # v5.11.3 Mar 12, 2018
clone git://deps.memgraph.io/rocksdb.git rocksdb $rocksdb_tag 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 chmod 750 /var/lib/memgraph || exit 1
chown memgraph:adm /var/log/memgraph || exit 1 chown memgraph:adm /var/log/memgraph || exit 1
chmod 750 /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 # Generate SSL certificates
if [ ! -d /etc/memgraph/ssl ]; then if [ ! -d /etc/memgraph/ssl ]; then

View File

@@ -4,12 +4,9 @@
add_subdirectory(lisp) add_subdirectory(lisp)
add_subdirectory(utils) add_subdirectory(utils)
add_subdirectory(requests) add_subdirectory(requests)
add_subdirectory(integrations)
add_subdirectory(io) add_subdirectory(io)
add_subdirectory(telemetry) add_subdirectory(telemetry)
add_subdirectory(communication) add_subdirectory(communication)
add_subdirectory(stats)
add_subdirectory(auth)
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# Memgraph Single Node # Memgraph Single Node
@@ -24,12 +21,10 @@ set(mg_single_node_sources
durability/single_node/recovery.cpp durability/single_node/recovery.cpp
durability/single_node/snapshooter.cpp durability/single_node/snapshooter.cpp
durability/single_node/wal.cpp durability/single_node/wal.cpp
glue/auth.cpp
glue/communication.cpp glue/communication.cpp
query/common.cpp query/common.cpp
query/frontend/ast/ast.cpp query/frontend/ast/ast.cpp
query/frontend/ast/cypher_main_visitor.cpp query/frontend/ast/cypher_main_visitor.cpp
query/frontend/semantic/required_privileges.cpp
query/frontend/semantic/symbol_generator.cpp query/frontend/semantic/symbol_generator.cpp
query/frontend/stripped.cpp query/frontend/stripped.cpp
query/interpret/awesome_memgraph_functions.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}) add_custom_target(generate_lcp_single_node DEPENDS ${generated_lcp_single_node_files})
set(MG_SINGLE_NODE_LIBS stdc++fs Threads::Threads fmt cppitertools set(MG_SINGLE_NODE_LIBS stdc++fs Threads::Threads fmt cppitertools
antlr_opencypher_parser_lib dl glog gflags capnp kj antlr_opencypher_parser_lib dl glog gflags
mg-utils mg-io mg-integrations-kafka mg-requests mg-communication mg-auth mg-stats) mg-utils mg-io mg-requests mg-communication)
if (USE_LTALLOC) if (USE_LTALLOC)
list(APPEND MG_SINGLE_NODE_LIBS 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 # 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) string(TOLOWER ${CMAKE_BUILD_TYPE} lower_build_type)
# STATIC library used to store key-value pairs # STATIC library used to store key-value pairs
@@ -311,18 +151,3 @@ install(
${CMAKE_BINARY_DIR}/tests/manual/bolt_client ${CMAKE_BINARY_DIR}/tests/manual/bolt_client
WORKING_DIRECTORY ${examples})") WORKING_DIRECTORY ${examples})")
install(DIRECTORY ${examples}/build/ DESTINATION share/memgraph/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 client.cpp
context.cpp context.cpp
helpers.cpp helpers.cpp
init.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})
add_library(mg-communication STATIC ${communication_src_files}) 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 Threads::Threads mg-utils mg-io fmt glog gflags)
target_link_libraries(mg-communication ${OPENSSL_LIBRARIES}) target_link_libraries(mg-communication ${OPENSSL_LIBRARIES})
target_include_directories(mg-communication SYSTEM PUBLIC ${OPENSSL_INCLUDE_DIR}) 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. */ /** Aborts currently running query. */
virtual void Abort() = 0; 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. * Executes the session after data has been read into the buffer.
* Goes through the bolt states in order to execute commands from the client. * 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()) LOG(INFO) << fmt::format("Client connected '{}'", client_name.ValueString())
<< std::endl; << 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. // Return success.
if (!session.encoder_.MessageSuccess()) { if (!session.encoder_.MessageSuccess()) {
DLOG(WARNING) << "Couldn't send success message to the client!"; 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) { ClientContext::ClientContext(bool use_ssl) : use_ssl_(use_ssl), ctx_(nullptr) {
if (use_ssl_) { if (use_ssl_) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
ctx_ = SSL_CTX_new(SSLv23_client_method());
#else
ctx_ = SSL_CTX_new(TLS_client_method()); ctx_ = SSL_CTX_new(TLS_client_method());
#endif
CHECK(ctx_ != nullptr) << "Couldn't create client SSL_CTX object!"; CHECK(ctx_ != nullptr) << "Couldn't create client SSL_CTX object!";
// Disable legacy SSL support. Other options can be seen here: // 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, ServerContext::ServerContext(const std::string &key_file,
const std::string &cert_file, const std::string &cert_file,
const std::string &ca_file, bool verify_peer) 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 support for encrypted private keys
// TODO (mferencevic): add certificate revocation list (CRL) // TODO (mferencevic): add certificate revocation list (CRL)
CHECK(SSL_CTX_use_certificate_file(ctx_, cert_file.c_str(), 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; return true;
} }
bool DistributedVersionConsistency(const int64_t master_version) {
return durability::kVersion == master_version;
}
bool ContainsDurabilityFiles(const fs::path &durability_dir) { bool ContainsDurabilityFiles(const fs::path &durability_dir) {
for (const auto &durability_type : {kSnapshotDir, kWalDir}) { for (const auto &durability_type : {kSnapshotDir, kWalDir}) {
auto recovery_dir = durability_dir / durability_type; auto recovery_dir = durability_dir / durability_type;

View File

@@ -75,15 +75,6 @@ bool ReadSnapshotSummary(HashedFileReader &buffer, int64_t &vertex_count,
bool VersionConsistency( bool VersionConsistency(
const std::experimental::filesystem::path &durability_dir); 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 * Checks whether the durability directory contains snapshot
* or write-ahead log file. * or write-ahead log file.

View File

@@ -4,13 +4,5 @@ set(io_src_files
network/socket.cpp network/socket.cpp
network/utils.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}) 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 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; 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 { bool Endpoint::operator==(const Endpoint &other) const {
return address_ == other.address_ && port_ == other.port_ && return address_ == other.address_ && port_ == other.port_ &&
family_ == other.family_; family_ == other.family_;

View File

@@ -5,7 +5,6 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#include "io/network/endpoint.capnp.h"
#include "utils/exceptions.hpp" #include "utils/exceptions.hpp"
namespace io::network { namespace io::network {
@@ -33,8 +32,4 @@ class Endpoint {
unsigned char family_{0}; 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 } // namespace io::network

View File

@@ -11,8 +11,6 @@
#include "communication/server.hpp" #include "communication/server.hpp"
#include "database/single_node/graph_db.hpp" #include "database/single_node/graph_db.hpp"
#include "integrations/kafka/exceptions.hpp"
#include "integrations/kafka/streams.hpp"
#include "memgraph_init.hpp" #include "memgraph_init.hpp"
#include "query/exceptions.hpp" #include "query/exceptions.hpp"
#include "telemetry/telemetry.hpp" #include "telemetry/telemetry.hpp"
@@ -48,25 +46,6 @@ void SingleNodeMain() {
query::Interpreter interpreter; query::Interpreter interpreter;
SessionData session_data{&db, &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; ServerContext context;
std::string service_name = "Bolt"; std::string service_name = "Bolt";
if (FLAGS_key_file != "" && FLAGS_cert_file != "") { if (FLAGS_key_file != "" && FLAGS_cert_file != "") {

View File

@@ -3,11 +3,9 @@
#include <glog/logging.h> #include <glog/logging.h>
#include "config.hpp" #include "config.hpp"
#include "glue/auth.hpp"
#include "glue/communication.hpp" #include "glue/communication.hpp"
#include "query/exceptions.hpp" #include "query/exceptions.hpp"
#include "requests/requests.hpp" #include "requests/requests.hpp"
#include "stats/stats.hpp"
#include "utils/signals.hpp" #include "utils/signals.hpp"
#include "utils/sysinfo/memory.hpp" #include "utils/sysinfo/memory.hpp"
#include "utils/terminate_handler.hpp" #include "utils/terminate_handler.hpp"
@@ -28,8 +26,7 @@ BoltSession::BoltSession(SessionData *data, const io::network::Endpoint &,
: communication::bolt::Session<communication::InputStream, : communication::bolt::Session<communication::InputStream,
communication::OutputStream>(input_stream, communication::OutputStream>(input_stream,
output_stream), output_stream),
transaction_engine_(data->db, data->interpreter), transaction_engine_(data->db, data->interpreter) {}
auth_(&data->auth) {}
using TEncoder = using TEncoder =
communication::bolt::Session<communication::InputStream, communication::bolt::Session<communication::InputStream,
@@ -42,21 +39,7 @@ std::vector<std::string> BoltSession::Interpret(
for (const auto &kv : params) for (const auto &kv : params)
params_pv.emplace(kv.first, glue::ToPropertyValue(kv.second)); params_pv.emplace(kv.first, glue::ToPropertyValue(kv.second));
try { try {
auto result = transaction_engine_.Interpret(query, params_pv); return 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;
} catch (const query::QueryException &e) { } catch (const query::QueryException &e) {
// Wrap QueryException into ClientError, because we want to allow the // Wrap QueryException into ClientError, because we want to allow the
// client to fix their query. // client to fix their query.
@@ -83,13 +66,6 @@ std::map<std::string, communication::bolt::Value> BoltSession::PullAll(
void BoltSession::Abort() { transaction_engine_.Abort(); } 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) BoltSession::TypedValueResultStream::TypedValueResultStream(TEncoder *encoder)
: encoder_(encoder) {} : encoder_(encoder) {}
@@ -103,24 +79,6 @@ void BoltSession::TypedValueResultStream::Result(
encoder_->MessageRecord(decoded_values); 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. // 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 // 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 // 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. // Unhandled exception handler init.
std::set_terminate(&utils::TerminateHandler); std::set_terminate(&utils::TerminateHandler);
stats::InitStatsLogging(get_stats_prefix());
utils::OnScopeExit stop_stats([] { stats::StopStatsLogging(); });
// Initialize the communication library. // Initialize the communication library.
communication::Init(); communication::Init();

View File

@@ -9,7 +9,6 @@
#include <gflags/gflags.h> #include <gflags/gflags.h>
#include "auth/auth.hpp"
#include "communication/bolt/v1/session.hpp" #include "communication/bolt/v1/session.hpp"
#include "communication/init.hpp" #include "communication/init.hpp"
#include "communication/session.hpp" #include "communication/session.hpp"
@@ -23,8 +22,6 @@ DECLARE_string(durability_directory);
struct SessionData { struct SessionData {
database::GraphDb *db{nullptr}; database::GraphDb *db{nullptr};
query::Interpreter *interpreter{nullptr}; query::Interpreter *interpreter{nullptr};
auth::Auth auth{
std::experimental::filesystem::path(FLAGS_durability_directory) / "auth"};
}; };
class BoltSession final class BoltSession final
@@ -47,9 +44,6 @@ class BoltSession final
void Abort() override; void Abort() override;
bool Authenticate(const std::string &username,
const std::string &password) override;
private: private:
/// Wrapper around TEncoder which converts TypedValue to Value /// Wrapper around TEncoder which converts TypedValue to Value
/// before forwarding the calls to original TEncoder. /// before forwarding the calls to original TEncoder.
@@ -64,17 +58,6 @@ class BoltSession final
}; };
query::TransactionEngine transaction_engine_; 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. /// Writes data streamed from kafka to memgraph.

View File

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

View File

@@ -115,19 +115,4 @@ class RemoveAttachedVertexException : public QueryRuntimeException {
"connections. Consider using DETACH DELETE.") {} "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 } // namespace query

View File

@@ -2202,146 +2202,6 @@ cpp<#
cpp<#) cpp<#)
(:serialize :capnp)) (: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 #>cpp
#undef CLONE_BINARY_EXPRESSION #undef CLONE_BINARY_EXPRESSION
#undef CLONE_UNARY_EXPRESSION #undef CLONE_UNARY_EXPRESSION

View File

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

View File

@@ -108,24 +108,6 @@ antlrcpp::Any CypherMainVisitor::visitDropIndex(
return index_query; 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( antlrcpp::Any CypherMainVisitor::visitCypherUnion(
MemgraphCypher::CypherUnionContext *ctx) { MemgraphCypher::CypherUnionContext *ctx) {
bool distinct = !ctx->ALL(); bool distinct = !ctx->ALL();
@@ -277,380 +259,6 @@ antlrcpp::Any CypherMainVisitor::visitCreate(
return create; 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( antlrcpp::Any CypherMainVisitor::visitCypherReturn(
MemgraphCypher::CypherReturnContext *ctx) { MemgraphCypher::CypherReturnContext *ctx) {
auto *return_clause = storage_->Create<Return>(); auto *return_clause = storage_->Create<Return>();

View File

@@ -152,17 +152,6 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
antlrcpp::Any visitExplainQuery( antlrcpp::Any visitExplainQuery(
MemgraphCypher::ExplainQueryContext *ctx) override; MemgraphCypher::ExplainQueryContext *ctx) override;
/**
* @return AuthQuery*
*/
antlrcpp::Any visitAuthQuery(MemgraphCypher::AuthQueryContext *ctx) override;
/**
* @return StreamQuery*
*/
antlrcpp::Any visitStreamQuery(
MemgraphCypher::StreamQueryContext *ctx) override;
/** /**
* @return CypherUnion* * @return CypherUnion*
*/ */
@@ -191,28 +180,6 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
*/ */
antlrcpp::Any visitCreate(MemgraphCypher::CreateContext *ctx) override; 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* * @return IndexQuery*
*/ */
@@ -230,136 +197,6 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
*/ */
antlrcpp::Any visitDropIndex(MemgraphCypher::DropIndexContext *ctx) override; 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* * @return Return*
*/ */

View File

@@ -5,140 +5,3 @@ parser grammar MemgraphCypher ;
options { tokenVocab=MemgraphCypherLexer; } options { tokenVocab=MemgraphCypherLexer; }
import Cypher ; 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 ; lexer grammar MemgraphCypherLexer ;
import CypherLexer ; 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(IndexQuery &) { return true; }
bool SymbolGenerator::Visit(AuthQuery &) { return true; }
bool SymbolGenerator::Visit(StreamQuery &) { return true; }
// Expressions // Expressions
SymbolGenerator::ReturnType SymbolGenerator::Visit(Identifier &ident) { SymbolGenerator::ReturnType SymbolGenerator::Visit(Identifier &ident) {

View File

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

View File

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

View File

@@ -3,15 +3,10 @@
#include <glog/logging.h> #include <glog/logging.h>
#include <limits> #include <limits>
#include "auth/auth.hpp"
#include "glue/auth.hpp"
#include "glue/communication.hpp" #include "glue/communication.hpp"
#include "integrations/kafka/exceptions.hpp"
#include "integrations/kafka/streams.hpp"
#include "query/exceptions.hpp" #include "query/exceptions.hpp"
#include "query/frontend/ast/cypher_main_visitor.hpp" #include "query/frontend/ast/cypher_main_visitor.hpp"
#include "query/frontend/opencypher/parser.hpp" #include "query/frontend/opencypher/parser.hpp"
#include "query/frontend/semantic/required_privileges.hpp"
#include "query/frontend/semantic/symbol_generator.hpp" #include "query/frontend/semantic/symbol_generator.hpp"
#include "query/interpret/eval.hpp" #include "query/interpret/eval.hpp"
#include "query/plan/planner.hpp" #include "query/plan/planner.hpp"
@@ -67,446 +62,6 @@ TypedValue EvaluateOptionalExpression(Expression *expression,
return expression ? expression->Accept(*eval) : TypedValue::Null; 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, Callback HandleIndexQuery(IndexQuery *index_query,
std::function<void()> invalidate_plan_cache, std::function<void()> invalidate_plan_cache,
database::GraphDbAccessor *db_accessor) { database::GraphDbAccessor *db_accessor) {
@@ -633,8 +188,7 @@ Interpreter::Results Interpreter::operator()(
auto cursor = plan->plan().MakeCursor(db_accessor); auto cursor = plan->plan().MakeCursor(db_accessor);
return Results(std::move(execution_context), plan, std::move(cursor), return Results(std::move(execution_context), plan, std::move(cursor),
output_symbols, header, summary, output_symbols, header, summary);
parsed_query.required_privileges);
} }
if (auto *explain_query = dynamic_cast<ExplainQuery *>(parsed_query.query)) { 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); auto cursor = plan->plan().MakeCursor(db_accessor);
return Results(std::move(execution_context), plan, std::move(cursor), return Results(std::move(execution_context), plan, std::move(cursor),
output_symbols, header, summary, output_symbols, header, summary);
parsed_query.required_privileges);
} }
Callback callback; Callback callback;
@@ -697,19 +250,6 @@ Interpreter::Results Interpreter::operator()(
}; };
callback = callback =
HandleIndexQuery(index_query, invalidate_plan_cache, &db_accessor); 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 { } else {
LOG(FATAL) << "Should not get here -- unknown query type!"; LOG(FATAL) << "Should not get here -- unknown query type!";
} }
@@ -731,8 +271,7 @@ Interpreter::Results Interpreter::operator()(
auto cursor = plan->plan().MakeCursor(db_accessor); auto cursor = plan->plan().MakeCursor(db_accessor);
return Results(std::move(execution_context), plan, std::move(cursor), return Results(std::move(execution_context), plan, std::move(cursor),
output_symbols, callback.header, summary, output_symbols, callback.header, summary);
parsed_query.required_privileges);
} }
std::shared_ptr<Interpreter::CachedPlan> Interpreter::CypherQueryToPlan( std::shared_ptr<Interpreter::CachedPlan> Interpreter::CypherQueryToPlan(
@@ -768,8 +307,7 @@ Interpreter::ParsedQuery Interpreter::ParseQuery(
// Convert antlr4 AST into Memgraph AST. // Convert antlr4 AST into Memgraph AST.
frontend::CypherMainVisitor visitor(context, ast_storage, db_accessor); frontend::CypherMainVisitor visitor(context, ast_storage, db_accessor);
visitor.visit(parser->tree()); visitor.visit(parser->tree());
return ParsedQuery{visitor.query(), return ParsedQuery{visitor.query()};
query::GetRequiredPrivileges(visitor.query())};
} }
auto stripped_query_hash = fnv(stripped_query); auto stripped_query_hash = fnv(stripped_query);
@@ -799,15 +337,13 @@ Interpreter::ParsedQuery Interpreter::ParseQuery(
frontend::CypherMainVisitor visitor(context, &cached_ast_storage, frontend::CypherMainVisitor visitor(context, &cached_ast_storage,
db_accessor); db_accessor);
visitor.visit(parser->tree()); visitor.visit(parser->tree());
CachedQuery cached_query{std::move(cached_ast_storage), visitor.query(), CachedQuery cached_query{std::move(cached_ast_storage), visitor.query()};
query::GetRequiredPrivileges(visitor.query())};
// Cache it. // Cache it.
ast_it = ast_it =
ast_cache_accessor.insert(stripped_query_hash, std::move(cached_query)) ast_cache_accessor.insert(stripped_query_hash, std::move(cached_query))
.first; .first;
} }
return ParsedQuery{ast_it->second.query->Clone(*ast_storage), return ParsedQuery{ast_it->second.query->Clone(*ast_storage)};
ast_it->second.required_privileges};
} }
std::unique_ptr<LogicalPlan> Interpreter::MakeLogicalPlan( std::unique_ptr<LogicalPlan> Interpreter::MakeLogicalPlan(

View File

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

View File

@@ -13,13 +13,9 @@
#include "glog/logging.h" #include "glog/logging.h"
#include "auth/auth.hpp"
#include "communication/result_stream_faker.hpp" #include "communication/result_stream_faker.hpp"
#include "database/graph_db_accessor.hpp" #include "database/graph_db_accessor.hpp"
#include "glue/auth.hpp"
#include "glue/communication.hpp" #include "glue/communication.hpp"
#include "integrations/kafka/exceptions.hpp"
#include "integrations/kafka/streams.hpp"
#include "query/context.hpp" #include "query/context.hpp"
#include "query/exceptions.hpp" #include "query/exceptions.hpp"
#include "query/frontend/ast/ast.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(PrimitiveLiteral &) override { return true; }
bool Visit(ParameterLookup &) override { return true; } bool Visit(ParameterLookup &) override { return true; }
bool Visit(query::IndexQuery &) 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_; std::unordered_set<Symbol> symbols_;
const SymbolTable &symbol_table_; const SymbolTable &symbol_table_;

View File

@@ -402,16 +402,6 @@ class ReturnBodyContext : public HierarchicalTreeVisitor {
return true; 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. // Creates NamedExpression with an Identifier for each user declared symbol.
// This should be used when body.all_identifiers is true, to generate // This should be used when body.all_identifiers is true, to generate
// expressions for Produce operator. // expressions for Produce operator.

View File

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

View File

@@ -88,15 +88,18 @@ class Edges {
/** Helper function that skips edges that don't satisfy the predicate /** Helper function that skips edges that don't satisfy the predicate
* present in this iterator. */ * present in this iterator. */
void update_position() { void update_position() {
if (vertex_) { if (vertex_ && edge_types_) {
position_ = std::find_if(position_, end_,
[v = this->vertex_.value()](const Element &e) {
return e.vertex == v;
});
}
if (edge_types_) {
position_ = std::find_if(position_, end_, [this](const Element &e) { 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 /** Helper function that skips edges that don't satisfy the predicate
* present in this iterator. */ * present in this iterator. */
void update_position() { void update_position() {
if (vertex_) { if (vertex_ && edge_types_) {
position_ = std::find_if(position_,
end_, [v = this->vertex_](const Element &e) {
return e.vertex == v;
});
}
if (edge_types_) {
position_ = std::find_if(position_, end_, [this](const Element &e) { 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 "data_structures/concurrent/concurrent_map.hpp"
#include "mvcc/single_node/version_list.hpp" #include "mvcc/single_node/version_list.hpp"
#include "stats/metrics.hpp"
#include "storage/single_node/deferred_deleter.hpp" #include "storage/single_node/deferred_deleter.hpp"
#include "storage/single_node/edge.hpp" #include "storage/single_node/edge.hpp"
#include "storage/single_node/garbage_collector.hpp" #include "storage/single_node/garbage_collector.hpp"

View File

@@ -7,13 +7,5 @@ set(utils_src_files
uuid.cpp uuid.cpp
watchdog.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}) 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 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 # integration test binaries
add_subdirectory(integration) 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) add_benchmark(mvcc.cpp)
target_link_libraries(${test_prefix}mvcc mg-single-node kvstore_dummy_lib) 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) add_benchmark(tx_engine.cpp)
target_link_libraries(${test_prefix}tx_engine mg-single-node kvstore_dummy_lib) 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 # transactions test binaries
add_subdirectory(transactions) 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 - runner.sh # runner script
- ../../../build_debug/memgraph # memgraph binary - ../../../build_debug/memgraph # memgraph binary
- ../../../build_debug/tests/integration/transactions/tester # tester 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) endfunction(add_macro_benchmark)
add_macro_benchmark(clients/pokec_client.cpp) 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) 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) 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) add_macro_benchmark(clients/query_client.cpp)
target_link_libraries(${test_prefix}query_client mg-communication mg-io mg-utils) target_link_libraries(${test_prefix}query_client mg-communication mg-io mg-utils)
add_macro_benchmark(clients/card_fraud_client.cpp) 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 "gflags/gflags.h"
#include "communication/rpc/client.hpp"
#include "stats/stats.hpp"
#include "stats/stats_rpc_messages.hpp"
#include "utils/thread/sync.hpp" #include "utils/thread/sync.hpp"
#include "long_running_common.hpp" #include "long_running_common.hpp"
@@ -23,14 +20,6 @@ DEFINE_string(config, "", "test config");
enum class Role { WORKER, ANALYTIC, CLEANUP }; 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) { int64_t NumNodesWithLabel(Client &client, std::string label) {
std::string query = fmt::format("MATCH (u :{}) RETURN count(u)", label); std::string query = fmt::format("MATCH (u :{}) RETURN count(u)", label);
auto result = ExecuteNTimesTillSuccess(client, query, {}, MAX_RETRIES); auto result = ExecuteNTimesTillSuccess(client, query, {}, MAX_RETRIES);
@@ -176,7 +165,6 @@ class CardFraudClient : public TestClient {
card_id, tx_id, pos_id); card_id, tx_id, pos_id);
num_transactions++; num_transactions++;
UpdateStats();
} }
int64_t UniformInt(int64_t a, int64_t b) { 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, deleted,
num_transactions - num_transactions_db); num_transactions - num_transactions_db);
num_transactions = num_transactions_db; num_transactions = num_transactions_db;
UpdateStats();
} }
std::this_thread::sleep_for( std::this_thread::sleep_for(
@@ -334,9 +321,6 @@ int main(int argc, char **argv) {
communication::Init(); communication::Init();
stats::InitStatsLogging(
fmt::format("client.long_running.{}.{}", FLAGS_group, FLAGS_scenario));
Endpoint endpoint(FLAGS_address, FLAGS_port); Endpoint endpoint(FLAGS_address, FLAGS_port);
ClientContext context(FLAGS_use_ssl); ClientContext context(FLAGS_use_ssl);
Client client(&context); Client client(&context);
@@ -382,7 +366,5 @@ int main(int argc, char **argv) {
RunMultithreadedTest(clients); RunMultithreadedTest(clients);
stats::StopStatsLogging();
return 0; return 0;
} }

View File

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

View File

@@ -14,8 +14,6 @@
#include "json/json.hpp" #include "json/json.hpp"
#include "stats/metrics.hpp"
#include "stats/stats.hpp"
#include "utils/timer.hpp" #include "utils/timer.hpp"
#include "common.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(group, "unknown", "Test group name");
DEFINE_string(scenario, "unknown", "Test scenario name"); DEFINE_string(scenario, "unknown", "Test scenario name");
auto &executed_queries = stats::GetCounter("executed_queries"); std::atomic<uint64_t> executed_queries;
auto &executed_steps = stats::GetCounter("executed_steps"); std::atomic<uint64_t> executed_steps;
auto &serialization_errors = stats::GetCounter("serialization_errors"); std::atomic<uint64_t> serialization_errors;
class TestClient { class TestClient {
public: public:
@@ -59,7 +57,7 @@ class TestClient {
runner_thread_ = std::thread([&] { runner_thread_ = std::thread([&] {
while (keep_running_) { while (keep_running_) {
Step(); Step();
executed_steps.Bump(); ++executed_steps;
} }
}); });
} }
@@ -82,7 +80,7 @@ class TestClient {
std::tie(result, retries) = std::tie(result, retries) =
ExecuteNTimesTillSuccess(client_, query, params, MAX_RETRIES); ExecuteNTimesTillSuccess(client_, query, params, MAX_RETRIES);
} catch (const utils::BasicException &e) { } catch (const utils::BasicException &e) {
serialization_errors.Bump(MAX_RETRIES); serialization_errors += MAX_RETRIES;
return std::experimental::nullopt; return std::experimental::nullopt;
} }
auto wall_time = timer.Elapsed(); auto wall_time = timer.Elapsed();
@@ -96,8 +94,8 @@ class TestClient {
stats_[query].push_back(std::move(metadata)); stats_[query].push_back(std::move(metadata));
} }
} }
executed_queries.Bump(); ++executed_queries;
serialization_errors.Bump(retries); serialization_errors += retries;
return result; 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; auto it = aggregated_query_stats.insert({stat.first, Value(0.0)}).first;
it->second = (it->second.ValueDouble() * old_count + stat.second) / it->second = (it->second.ValueDouble() * old_count + stat.second) /
(old_count + new_count); (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() << ", " out << "{\"num_executed_queries\": " << executed_queries << ", "
<< "\"num_executed_steps\": " << executed_steps.Value() << ", " << "\"num_executed_steps\": " << executed_steps << ", "
<< "\"elapsed_time\": " << timer.Elapsed().count() << "\"elapsed_time\": " << timer.Elapsed().count()
<< ", \"queries\": ["; << ", \"queries\": [";
utils::PrintIterable( utils::PrintIterable(

View File

@@ -30,30 +30,8 @@ target_link_libraries(${test_prefix}binomial mg-utils)
add_manual_test(bolt_client.cpp) add_manual_test(bolt_client.cpp)
target_link_libraries(${test_prefix}bolt_client mg-communication) 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(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) add_manual_test(kvstore_console.cpp)
target_link_libraries(${test_prefix}kvstore_console kvstore_lib gflags glog) target_link_libraries(${test_prefix}kvstore_console kvstore_lib gflags glog)

View File

@@ -6,11 +6,3 @@
- ../../config # directory with config files - ../../config # directory with config files
outfile_paths: &OUTFILE_PATHS outfile_paths: &OUTFILE_PATHS
- \./memgraph/tests/qa/\.quality_assurance_status - \./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) add_unit_test(bolt_encoder.cpp)
target_link_libraries(${test_prefix}bolt_encoder mg-single-node kvstore_dummy_lib) 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) 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) 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) add_unit_test(concurrent_map.cpp)
target_link_libraries(${test_prefix}concurrent_map mg-single-node kvstore_dummy_lib) 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) add_unit_test(cypher_main_visitor.cpp)
target_link_libraries(${test_prefix}cypher_main_visitor mg-single-node kvstore_dummy_lib) 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) add_unit_test(database_label_property_index.cpp)
target_link_libraries(${test_prefix}database_label_property_index mg-single-node kvstore_dummy_lib) 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) add_unit_test(database_transaction_timeout.cpp)
target_link_libraries(${test_prefix}database_transaction_timeout mg-single-node kvstore_dummy_lib) 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) add_unit_test(deferred_deleter.cpp)
target_link_libraries(${test_prefix}deferred_deleter mg-single-node kvstore_dummy_lib) 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. # TODO (buda): Replace token sharing with centralized solution and write an appropriate test.
# add_unit_test(distributed_token_sharing.cpp) # add_unit_test(distributed_token_sharing.cpp)
# target_link_libraries(${test_prefix}distributed_token_sharing memgraph_lib kvstore_dummy_lib) # 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) add_unit_test(bfs_single_node.cpp)
target_link_libraries(${test_prefix}bfs_single_node mg-single-node kvstore_dummy_lib) 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) add_unit_test(durability.cpp)
target_link_libraries(${test_prefix}durability mg-single-node kvstore_dummy_lib) target_link_libraries(${test_prefix}durability mg-single-node kvstore_dummy_lib)
add_unit_test(dynamic_bitset.cpp) add_unit_test(dynamic_bitset.cpp)
target_link_libraries(${test_prefix}dynamic_bitset mg-single-node kvstore_dummy_lib) target_link_libraries(${test_prefix}dynamic_bitset mg-single-node kvstore_dummy_lib)
add_unit_test(gid.cpp) add_unit_test(edges_single_node.cpp)
target_link_libraries(${test_prefix}gid mg-distributed kvstore_dummy_lib) target_link_libraries(${test_prefix}edges_single_node mg-single-node kvstore_dummy_lib)
add_unit_test(graph_db_accessor.cpp) add_unit_test(graph_db_accessor.cpp)
target_link_libraries(${test_prefix}graph_db_accessor mg-single-node kvstore_dummy_lib) 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) add_unit_test(kvstore.cpp)
target_link_libraries(${test_prefix}kvstore kvstore_lib glog) 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) add_unit_test(mvcc.cpp)
target_link_libraries(${test_prefix}mvcc mg-single-node kvstore_dummy_lib) 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) add_unit_test(query_plan.cpp)
target_link_libraries(${test_prefix}query_plan mg-single-node kvstore_dummy_lib) 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) add_unit_test(query_semantic.cpp)
target_link_libraries(${test_prefix}query_semantic mg-single-node kvstore_dummy_lib) 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) add_unit_test(record_edge_vertex_accessor.cpp)
target_link_libraries(${test_prefix}record_edge_vertex_accessor mg-single-node kvstore_dummy_lib) 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) add_unit_test(skiplist_access.cpp)
target_link_libraries(${test_prefix}skiplist_access mg-single-node kvstore_dummy_lib) 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) add_unit_test(static_bitset.cpp)
target_link_libraries(${test_prefix}static_bitset mg-single-node kvstore_dummy_lib) 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) add_unit_test(stripped.cpp)
target_link_libraries(${test_prefix}stripped mg-single-node kvstore_dummy_lib) 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) add_unit_test(transaction_engine_single_node.cpp)
target_link_libraries(${test_prefix}transaction_engine_single_node mg-single-node kvstore_dummy_lib) 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) add_unit_test(network_timeouts.cpp)
target_link_libraries(${test_prefix}network_timeouts mg-communication) 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 # Test data structures
add_unit_test(ring_buffer.cpp) 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) add_unit_test(utils_watchdog.cpp)
target_link_libraries(${test_prefix}utils_watchdog mg-utils) 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 # Test LCP
add_custom_command( add_custom_command(

View File

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

View File

@@ -2009,449 +2009,6 @@ TYPED_TEST(CypherMainVisitorTest, UnionAll) {
ASSERT_FALSE(return_clause->body_.distinct); 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) { TYPED_TEST(CypherMainVisitorTest, TestExplainRegularQuery) {
{ {
TypeParam ast_generator("EXPLAIN RETURN n"); TypeParam ast_generator("EXPLAIN RETURN n");
@@ -2464,13 +2021,4 @@ TYPED_TEST(CypherMainVisitorTest, TestExplainExplainQuery) {
SyntaxException); 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 } // 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/operator.hpp"
#include "query/plan/planner.hpp" #include "query/plan/planner.hpp"
#include <capnp/message.h>
#include "query_common.hpp" #include "query_common.hpp"
namespace query { namespace query {

View File

@@ -2,10 +2,6 @@
add_executable(mg_import_csv mg_import_csv/main.cpp) add_executable(mg_import_csv mg_import_csv/main.cpp)
target_link_libraries(mg_import_csv mg-single-node kvstore_dummy_lib) 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 # Generate a version.hpp file
set(VERSION_STRING ${memgraph_VERSION}) set(VERSION_STRING ${memgraph_VERSION})
configure_file(../../src/version.hpp.in version.hpp @ONLY) 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) add_executable(mg_recovery_check mg_recovery_check.cpp)
target_link_libraries(mg_recovery_check mg-single-node gtest gtest_main kvstore_dummy_lib) 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 # Copy CSV data to CMake build dir
configure_file(csv/comment_nodes.csv csv/comment_nodes.csv COPYONLY) configure_file(csv/comment_nodes.csv csv/comment_nodes.csv COPYONLY)
configure_file(csv/comment_nodes_2.csv csv/comment_nodes_2.csv COPYONLY) configure_file(csv/comment_nodes_2.csv csv/comment_nodes_2.csv COPYONLY)