From bbfef45b37b3092663aadf0b3e0bb5f6d1f69b88 Mon Sep 17 00:00:00 2001 From: gvolfing <107616712+gvolfing@users.noreply.github.com> Date: Wed, 3 Aug 2022 18:08:44 +0200 Subject: [PATCH] Add command to return startup config (#459) Add a new command that is able to return the set of configurations that that the given instance of memgraph was started up with. The returned information currently consists of the name, the default and the current value of each flag. The hidden property of three flags were removed, namely --query-cost-planner, --query-vertex-count-to-expand-existing and --query-max-plans. The flag --log-link-basename was completely removed since it is not used. --- src/memgraph.cpp | 9 +- src/query/cypher_query_interpreter.cpp | 2 +- src/query/exceptions.hpp | 6 + src/query/frontend/ast/ast.lcp | 8 + src/query/frontend/ast/ast_visitor.hpp | 9 +- .../frontend/ast/cypher_main_visitor.cpp | 5 + .../frontend/ast/cypher_main_visitor.hpp | 5 + .../opencypher/grammar/MemgraphCypher.g4 | 3 + .../frontend/semantic/required_privileges.cpp | 2 + .../frontend/stripped_lexer_constants.hpp | 1 + src/query/interpreter.cpp | 55 ++++++ src/query/plan/rewrite/index_lookup.cpp | 11 +- src/query/plan/variable_start_planner.cpp | 5 +- tests/e2e/CMakeLists.txt | 1 + tests/e2e/configuration/CMakeLists.txt | 6 + .../e2e/configuration/configuration_check.py | 46 +++++ tests/e2e/configuration/default_config.py | 167 ++++++++++++++++++ tests/e2e/configuration/workloads.yaml | 13 ++ tests/unit/cypher_main_visitor.cpp | 18 ++ 19 files changed, 355 insertions(+), 17 deletions(-) create mode 100644 tests/e2e/configuration/CMakeLists.txt create mode 100644 tests/e2e/configuration/configuration_check.py create mode 100644 tests/e2e/configuration/default_config.py create mode 100644 tests/e2e/configuration/workloads.yaml diff --git a/src/memgraph.cpp b/src/memgraph.cpp index d4fc3bad1..fb38289c6 100644 --- a/src/memgraph.cpp +++ b/src/memgraph.cpp @@ -164,8 +164,6 @@ DEFINE_string(bolt_server_name_for_init, "", // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) DEFINE_string(data_directory, "mg_data", "Path to directory in which to save all permanent data."); // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DEFINE_HIDDEN_string(log_link_basename, "", "Basename used for symlink creation to the last log file."); -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) DEFINE_uint64(memory_warning_threshold, 1024, "Memory warning threshold, in MB. If Memgraph detects there is " "less available RAM it will log a warning. Set to 0 to " @@ -354,7 +352,8 @@ DEFINE_VALIDATED_string(query_modules_directory, "", }); // Logging flags -DEFINE_bool(also_log_to_stderr, false, "Log messages go to stderr in addition to logfiles"); +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +DEFINE_HIDDEN_bool(also_log_to_stderr, false, "Log messages go to stderr in addition to logfiles"); DEFINE_string(log_file, "", "Path to where the log should be stored."); namespace { @@ -434,9 +433,9 @@ void AddLoggerSink(spdlog::sink_ptr new_sink) { } // namespace // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DEFINE_string(license_key, "", "License key for Memgraph Enterprise."); +DEFINE_HIDDEN_string(license_key, "", "License key for Memgraph Enterprise."); // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -DEFINE_string(organization_name, "", "Organization name."); +DEFINE_HIDDEN_string(organization_name, "", "Organization name."); /// Encapsulates Dbms and Interpreter that are passed through the network server /// and worker to the session. diff --git a/src/query/cypher_query_interpreter.cpp b/src/query/cypher_query_interpreter.cpp index 05d7e417e..64672fb1d 100644 --- a/src/query/cypher_query_interpreter.cpp +++ b/src/query/cypher_query_interpreter.cpp @@ -12,7 +12,7 @@ #include "query/cypher_query_interpreter.hpp" // NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables) -DEFINE_HIDDEN_bool(query_cost_planner, true, "Use the cost-estimating query planner."); +DEFINE_bool(query_cost_planner, true, "Use the cost-estimating query planner."); // NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables) DEFINE_VALIDATED_int32(query_plan_cache_ttl, 60, "Time to live for cached query plans, in seconds.", FLAG_IN_RANGE(0, std::numeric_limits<int32_t>::max())); diff --git a/src/query/exceptions.hpp b/src/query/exceptions.hpp index a18ce0c43..b8a44d85d 100644 --- a/src/query/exceptions.hpp +++ b/src/query/exceptions.hpp @@ -188,6 +188,12 @@ class FreeMemoryModificationInMulticommandTxException : public QueryException { : QueryException("Free memory query not allowed in multicommand transactions.") {} }; +class ShowConfigModificationInMulticommandTxException : public QueryException { + public: + ShowConfigModificationInMulticommandTxException() + : QueryException("Show config query not allowed in multicommand transactions.") {} +}; + class TriggerModificationInMulticommandTxException : public QueryException { public: TriggerModificationInMulticommandTxException() diff --git a/src/query/frontend/ast/ast.lcp b/src/query/frontend/ast/ast.lcp index 6b5b5a16f..f683494fa 100644 --- a/src/query/frontend/ast/ast.lcp +++ b/src/query/frontend/ast/ast.lcp @@ -2665,5 +2665,13 @@ cpp<# (:serialize (:slk)) (:clone)) + (lcp:define-class show-config-query (query) () + (:public + #>cpp + DEFVISITABLE(QueryVisitor<void>); + cpp<#) + (:serialize (:slk)) + (:clone)) + (lcp:pop-namespace) ;; namespace query (lcp:pop-namespace) ;; namespace memgraph diff --git a/src/query/frontend/ast/ast_visitor.hpp b/src/query/frontend/ast/ast_visitor.hpp index 0e4a6012c..f9a574f17 100644 --- a/src/query/frontend/ast/ast_visitor.hpp +++ b/src/query/frontend/ast/ast_visitor.hpp @@ -94,6 +94,7 @@ class StreamQuery; class SettingQuery; class VersionQuery; class Foreach; +class ShowConfigQuery; using TreeCompositeVisitor = utils::CompositeVisitor< SingleQuery, CypherUnion, NamedExpression, OrOperator, XorOperator, AndOperator, NotOperator, AdditionOperator, @@ -125,9 +126,9 @@ class ExpressionVisitor None, ParameterLookup, Identifier, PrimitiveLiteral, RegexMatch> {}; template <class TResult> -class QueryVisitor - : public utils::Visitor<TResult, CypherQuery, ExplainQuery, ProfileQuery, IndexQuery, AuthQuery, InfoQuery, - ConstraintQuery, DumpQuery, ReplicationQuery, LockPathQuery, FreeMemoryQuery, TriggerQuery, - IsolationLevelQuery, CreateSnapshotQuery, StreamQuery, SettingQuery, VersionQuery> {}; +class QueryVisitor : public utils::Visitor<TResult, CypherQuery, ExplainQuery, ProfileQuery, IndexQuery, AuthQuery, + InfoQuery, ConstraintQuery, DumpQuery, ReplicationQuery, LockPathQuery, + FreeMemoryQuery, TriggerQuery, IsolationLevelQuery, CreateSnapshotQuery, + StreamQuery, SettingQuery, VersionQuery, ShowConfigQuery> {}; } // namespace memgraph::query diff --git a/src/query/frontend/ast/cypher_main_visitor.cpp b/src/query/frontend/ast/cypher_main_visitor.cpp index e97bdc05e..002710f1e 100644 --- a/src/query/frontend/ast/cypher_main_visitor.cpp +++ b/src/query/frontend/ast/cypher_main_visitor.cpp @@ -2353,6 +2353,11 @@ antlrcpp::Any CypherMainVisitor::visitForeach(MemgraphCypher::ForeachContext *ct return for_each; } +antlrcpp::Any CypherMainVisitor::visitShowConfigQuery(MemgraphCypher::ShowConfigQueryContext * /*ctx*/) { + query_ = storage_->Create<ShowConfigQuery>(); + return query_; +} + LabelIx CypherMainVisitor::AddLabel(const std::string &name) { return storage_->GetLabelIx(name); } PropertyIx CypherMainVisitor::AddProperty(const std::string &name) { return storage_->GetPropertyIx(name); } diff --git a/src/query/frontend/ast/cypher_main_visitor.hpp b/src/query/frontend/ast/cypher_main_visitor.hpp index d3a12072e..f041163a8 100644 --- a/src/query/frontend/ast/cypher_main_visitor.hpp +++ b/src/query/frontend/ast/cypher_main_visitor.hpp @@ -849,6 +849,11 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor { */ antlrcpp::Any visitForeach(MemgraphCypher::ForeachContext *ctx) override; + /** + * @return ShowConfigQuery* + */ + antlrcpp::Any visitShowConfigQuery(MemgraphCypher::ShowConfigQueryContext *ctx) override; + public: Query *query() { return query_; } const static std::string kAnonPrefix; diff --git a/src/query/frontend/opencypher/grammar/MemgraphCypher.g4 b/src/query/frontend/opencypher/grammar/MemgraphCypher.g4 index 8790b8731..0bab2c8e1 100644 --- a/src/query/frontend/opencypher/grammar/MemgraphCypher.g4 +++ b/src/query/frontend/opencypher/grammar/MemgraphCypher.g4 @@ -122,6 +122,7 @@ query : cypherQuery | streamQuery | settingQuery | versionQuery + | showConfigQuery ; authQuery : createRole @@ -372,4 +373,6 @@ showSetting : SHOW DATABASE SETTING settingName ; showSettings : SHOW DATABASE SETTINGS ; +showConfigQuery : SHOW CONFIG ; + versionQuery : SHOW VERSION ; diff --git a/src/query/frontend/semantic/required_privileges.cpp b/src/query/frontend/semantic/required_privileges.cpp index e8dbd21e5..2dfada82d 100644 --- a/src/query/frontend/semantic/required_privileges.cpp +++ b/src/query/frontend/semantic/required_privileges.cpp @@ -66,6 +66,8 @@ class PrivilegeExtractor : public QueryVisitor<void>, public HierarchicalTreeVis void Visit(FreeMemoryQuery &free_memory_query) override { AddPrivilege(AuthQuery::Privilege::FREE_MEMORY); } + void Visit(ShowConfigQuery & /*show_config_query*/) override { AddPrivilege(AuthQuery::Privilege::CONFIG); } + void Visit(TriggerQuery &trigger_query) override { AddPrivilege(AuthQuery::Privilege::TRIGGER); } void Visit(StreamQuery &stream_query) override { AddPrivilege(AuthQuery::Privilege::STREAM); } diff --git a/src/query/frontend/stripped_lexer_constants.hpp b/src/query/frontend/stripped_lexer_constants.hpp index 42b7b4aeb..e2a3662ca 100644 --- a/src/query/frontend/stripped_lexer_constants.hpp +++ b/src/query/frontend/stripped_lexer_constants.hpp @@ -204,6 +204,7 @@ const trie::Trie kKeywords = {"union", "pulsar", "service_url", "version", + "config", "websocket" "foreach"}; diff --git a/src/query/interpreter.cpp b/src/query/interpreter.cpp index 2925b1c14..f0fe0d925 100644 --- a/src/query/interpreter.cpp +++ b/src/query/interpreter.cpp @@ -791,6 +791,37 @@ Callback HandleStreamQuery(StreamQuery *stream_query, const Parameters ¶mete } } +Callback HandleConfigQuery() { + Callback callback; + callback.header = {"name", "default_value", "current_value", "description"}; + + callback.fn = [] { + std::vector<GFLAGS_NAMESPACE::CommandLineFlagInfo> flags; + GetAllFlags(&flags); + + std::vector<std::vector<TypedValue>> results; + + for (const auto &flag : flags) { + if (flag.hidden || + // These flags are not defined with gflags macros but are specified in config/flags.yaml + flag.name == "help" || flag.name == "help_xml" || flag.name == "version") { + continue; + } + + std::vector<TypedValue> current_fields; + current_fields.emplace_back(flag.name); + current_fields.emplace_back(flag.default_value); + current_fields.emplace_back(flag.current_value); + current_fields.emplace_back(flag.description); + + results.emplace_back(std::move(current_fields)); + } + + return results; + }; + return callback; +} + Callback HandleSettingQuery(SettingQuery *setting_query, const Parameters ¶meters, DbAccessor *db_accessor) { Frame frame(0); SymbolTable symbol_table; @@ -1521,6 +1552,28 @@ PreparedQuery PrepareFreeMemoryQuery(ParsedQuery parsed_query, const bool in_exp RWType::NONE}; } +PreparedQuery PrepareShowConfigQuery(ParsedQuery parsed_query, const bool in_explicit_transaction) { + if (in_explicit_transaction) { + throw ShowConfigModificationInMulticommandTxException(); + } + + auto callback = HandleConfigQuery(); + + return PreparedQuery{std::move(callback.header), std::move(parsed_query.required_privileges), + [callback_fn = std::move(callback.fn), pull_plan = std::shared_ptr<PullPlanVector>{nullptr}]( + AnyStream *stream, std::optional<int> n) mutable -> std::optional<QueryHandlerResult> { + if (!pull_plan) [[unlikely]] { + pull_plan = std::make_shared<PullPlanVector>(callback_fn()); + } + + if (pull_plan->Pull(stream, n)) { + return QueryHandlerResult::COMMIT; + } + return std::nullopt; + }, + RWType::NONE}; +} + TriggerEventType ToTriggerEventType(const TriggerQuery::EventType event_type) { switch (event_type) { case TriggerQuery::EventType::ANY: @@ -2181,6 +2234,8 @@ Interpreter::PrepareResult Interpreter::Prepare(const std::string &query_string, &*execution_db_accessor_); } else if (utils::Downcast<FreeMemoryQuery>(parsed_query.query)) { prepared_query = PrepareFreeMemoryQuery(std::move(parsed_query), in_explicit_transaction_, interpreter_context_); + } else if (utils::Downcast<ShowConfigQuery>(parsed_query.query)) { + prepared_query = PrepareShowConfigQuery(std::move(parsed_query), in_explicit_transaction_); } else if (utils::Downcast<TriggerQuery>(parsed_query.query)) { prepared_query = PrepareTriggerQuery(std::move(parsed_query), in_explicit_transaction_, &query_execution->notifications, diff --git a/src/query/plan/rewrite/index_lookup.cpp b/src/query/plan/rewrite/index_lookup.cpp index 6ad2735e7..532539a99 100644 --- a/src/query/plan/rewrite/index_lookup.cpp +++ b/src/query/plan/rewrite/index_lookup.cpp @@ -13,11 +13,12 @@ #include "utils/flag_validation.hpp" -DEFINE_VALIDATED_HIDDEN_int64(query_vertex_count_to_expand_existing, 10, - "Maximum count of indexed vertices which provoke " - "indexed lookup and then expand to existing, instead of " - "a regular expand. Default is 10, to turn off use -1.", - FLAG_IN_RANGE(-1, std::numeric_limits<std::int64_t>::max())); +// NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables) +DEFINE_VALIDATED_int64(query_vertex_count_to_expand_existing, 10, + "Maximum count of indexed vertices which provoke " + "indexed lookup and then expand to existing, instead of " + "a regular expand. Default is 10, to turn off use -1.", + FLAG_IN_RANGE(-1, std::numeric_limits<std::int64_t>::max())); namespace memgraph::query::plan::impl { diff --git a/src/query/plan/variable_start_planner.cpp b/src/query/plan/variable_start_planner.cpp index cd1ae3ef7..9c8e0de4c 100644 --- a/src/query/plan/variable_start_planner.cpp +++ b/src/query/plan/variable_start_planner.cpp @@ -17,8 +17,9 @@ #include "utils/flag_validation.hpp" #include "utils/logging.hpp" -DEFINE_VALIDATED_HIDDEN_uint64(query_max_plans, 1000U, "Maximum number of generated plans for a query.", - FLAG_IN_RANGE(1, std::numeric_limits<std::uint64_t>::max())); +// NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables) +DEFINE_VALIDATED_uint64(query_max_plans, 1000U, "Maximum number of generated plans for a query.", + FLAG_IN_RANGE(1, std::numeric_limits<std::uint64_t>::max())); namespace memgraph::query::plan::impl { diff --git a/tests/e2e/CMakeLists.txt b/tests/e2e/CMakeLists.txt index 1bb23f176..40ba2ca9c 100644 --- a/tests/e2e/CMakeLists.txt +++ b/tests/e2e/CMakeLists.txt @@ -37,6 +37,7 @@ add_subdirectory(isolation_levels) add_subdirectory(streams) add_subdirectory(temporal_types) add_subdirectory(write_procedures) +add_subdirectory(configuration) add_subdirectory(magic_functions) add_subdirectory(module_file_manager) add_subdirectory(monitoring_server) diff --git a/tests/e2e/configuration/CMakeLists.txt b/tests/e2e/configuration/CMakeLists.txt new file mode 100644 index 000000000..7fe4d5c00 --- /dev/null +++ b/tests/e2e/configuration/CMakeLists.txt @@ -0,0 +1,6 @@ +function(copy_configuration_check_e2e_python_files FILE_NAME) + copy_e2e_python_files(write_procedures ${FILE_NAME}) +endfunction() + +copy_configuration_check_e2e_python_files(default_config.py) +copy_configuration_check_e2e_python_files(configuration_check.py) diff --git a/tests/e2e/configuration/configuration_check.py b/tests/e2e/configuration/configuration_check.py new file mode 100644 index 000000000..82f9cb83a --- /dev/null +++ b/tests/e2e/configuration/configuration_check.py @@ -0,0 +1,46 @@ +# Copyright 2022 Memgraph Ltd. +# +# Use of this software is governed by the Business Source License +# included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source +# License, and you may not use this file except in compliance with the Business Source License. +# +# As of the Change Date specified in that file, in accordance with +# the Business Source License, use of this software will be governed +# by the Apache License, Version 2.0, included in the file +# licenses/APL.txt. + +import sys +import mgclient +import pytest + +import default_config + + +def test_does_default_config_match(): + connection = mgclient.connect(host="localhost", port=7687) + connection.autocommit = True + + cursor = connection.cursor() + cursor.execute("SHOW CONFIG") + config = cursor.fetchall() + + assert len(config) == len(default_config.startup_config_dict) + + for flag in config: + flag_name = flag[0] + + # The default value of these is dependent on the given machine. + machine_dependent_configurations = ["bolt_num_workers", "data_directory", "log_file"] + if flag_name in machine_dependent_configurations: + continue + + # default_value + assert default_config.startup_config_dict[flag_name][0] == flag[1] + # current_value + assert default_config.startup_config_dict[flag_name][1] == flag[2] + # description + assert default_config.startup_config_dict[flag_name][2] == flag[3] + + +if __name__ == "__main__": + sys.exit(pytest.main([__file__, "-rA"])) diff --git a/tests/e2e/configuration/default_config.py b/tests/e2e/configuration/default_config.py new file mode 100644 index 000000000..34e2f1763 --- /dev/null +++ b/tests/e2e/configuration/default_config.py @@ -0,0 +1,167 @@ +# Copyright 2022 Memgraph Ltd. +# +# Use of this software is governed by the Business Source License +# included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source +# License, and you may not use this file except in compliance with the Business Source License. +# +# As of the Change Date specified in that file, in accordance with +# the Business Source License, use of this software will be governed +# by the Apache License, Version 2.0, included in the file +# licenses/APL.txt. + +# In order to check the working correctness of the SHOW CONFIG command, a couple of configuration flags has been passed to the testing instance. These are: +# "--log-level=TRACE", "--storage-properties-on-edges=True", "--storage-snapshot-interval-sec", "300", "--storage-wal-enabled=True" +# If you wish to modify these, update the startup_config_dict and workloads.yaml ! + +startup_config_dict = { + "auth_module_create_missing_role": ("true", "true", "Set to false to disable creation of missing roles."), + "auth_module_create_missing_user": ("true", "true", "Set to false to disable creation of missing users."), + "auth_module_executable": ("", "", "Absolute path to the auth module executable that should be used."), + "auth_module_manage_roles": ( + "true", + "true", + "Set to false to disable management of roles through the auth module.", + ), + "auth_module_timeout_ms": ( + "10000", + "10000", + "Timeout (in milliseconds) used when waiting for a response from the auth module.", + ), + "auth_password_permit_null": ("true", "true", "Set to false to disable null passwords."), + "auth_password_strength_regex": ( + ".+", + ".+", + "The regular expression that should be used to match the entire entered password to ensure its strength.", + ), + "allow_load_csv": ("true", "true", "Controls whether LOAD CSV clause is allowed in queries."), + "audit_buffer_flush_interval_ms": ( + "200", + "200", + "Interval (in milliseconds) used for flushing the audit log buffer.", + ), + "audit_buffer_size": ("100000", "100000", "Maximum number of items in the audit log buffer."), + "audit_enabled": ("false", "false", "Set to true to enable audit logging."), + "auth_user_or_role_name_regex": ( + "[a-zA-Z0-9_.+-@]+", + "[a-zA-Z0-9_.+-@]+", + "Set to the regular expression that each user or role name must fulfill.", + ), + "bolt_address": ("0.0.0.0", "0.0.0.0", "IP address on which the Bolt server should listen."), + "bolt_cert_file": ("", "", "Certificate file which should be used for the Bolt server."), + "bolt_key_file": ("", "", "Key file which should be used for the Bolt server."), + "bolt_num_workers": ( + "12", + "12", + "Number of workers used by the Bolt server. By default, this will be the number of processing units available on the machine.", + ), + "bolt_port": ("7687", "7687", "Port on which the Bolt server should listen."), + "bolt_server_name_for_init": ( + "", + "", + "Server name which the database should send to the client in the Bolt INIT message.", + ), + "bolt_session_inactivity_timeout": ( + "1800", + "1800", + "Time in seconds after which inactive Bolt sessions will be closed.", + ), + "data_directory": ("mg_data", "mg_data", "Path to directory in which to save all permanent data."), + "isolation_level": ( + "SNAPSHOT_ISOLATION", + "SNAPSHOT_ISOLATION", + "Default isolation level used for the transactions. Allowed values: SNAPSHOT_ISOLATION, READ_COMMITTED, READ_UNCOMMITTED", + ), + "kafka_bootstrap_servers": ( + "", + "", + "List of default Kafka brokers as a comma separated list of broker host or host:port.", + ), + "log_file": ("", "", "Path to where the log should be stored."), + "log_level": ( + "WARNING", + "TRACE", + "Minimum log level. Allowed values: TRACE, DEBUG, INFO, WARNING, ERROR, CRITICAL", + ), + "memory_limit": ( + "0", + "0", + "Total memory limit in MiB. Set to 0 to use the default values which are 100% of the phyisical memory if the swap is enabled and 90% of the physical memory otherwise.", + ), + "memory_warning_threshold": ( + "1024", + "1024", + "Memory warning threshold, in MB. If Memgraph detects there is less available RAM it will log a warning. Set to 0 to disable.", + ), + "monitoring_address": ( + "0.0.0.0", + "0.0.0.0", + "IP address on which the websocket server for Memgraph monitoring should listen.", + ), + "monitoring_port": ("7444", "7444", "Port on which the websocket server for Memgraph monitoring should listen."), + "pulsar_service_url": ("", "", "Default URL used while connecting to Pulsar brokers."), + "query_execution_timeout_sec": ( + "600", + "600", + "Maximum allowed query execution time. Queries exceeding this limit will be aborted. Value of 0 means no limit.", + ), + "query_modules_directory": ( + "", + "", + "Directory where modules with custom query procedures are stored. NOTE: Multiple comma-separated directories can be defined.", + ), + "replication_replica_check_frequency_sec": ( + "1", + "1", + "The time duration between two replica checks/pings. If < 1, replicas will NOT be checked at all. NOTE: The MAIN instance allocates a new thread for each REPLICA.", + ), + "storage_gc_cycle_sec": ("30", "30", "Storage garbage collector interval (in seconds)."), + "storage_properties_on_edges": ("false", "true", "Controls whether edges have properties."), + "storage_recover_on_startup": ( + "false", + "false", + "Controls whether the storage recovers persisted data on startup.", + ), + "storage_restore_replicas_on_startup": ("true", "true", "Controls replicas should be restored automatically."), + "storage_snapshot_interval_sec": ( + "0", + "300", + "Storage snapshot creation interval (in seconds). Set to 0 to disable periodic snapshot creation.", + ), + "storage_snapshot_on_exit": ("false", "false", "Controls whether the storage creates another snapshot on exit."), + "storage_snapshot_retention_count": ("3", "3", "The number of snapshots that should always be kept."), + "storage_wal_enabled": ( + "false", + "true", + "Controls whether the storage uses write-ahead-logging. To enable WAL periodic snapshots must be enabled.", + ), + "storage_wal_file_flush_every_n_tx": ( + "100000", + "100000", + "Issue a 'fsync' call after this amount of transactions are written to the WAL file. Set to 1 for fully synchronous operation.", + ), + "storage_wal_file_size_kib": ("20480", "20480", "Minimum file size of each WAL file."), + "stream_transaction_conflict_retries": ( + "30", + "30", + "Number of times to retry when a stream transformation fails to commit because of conflicting transactions", + ), + "stream_transaction_retry_interval": ( + "500", + "500", + "Retry interval in milliseconds when a stream transformation fails to commit because of conflicting transactions", + ), + "telemetry_enabled": ( + "false", + "false", + "Set to true to enable telemetry. We collect information about the running system (CPU and memory information) and information about the database runtime (vertex and edge counts and resource usage) to allow for easier improvement of the product.", + ), + "query_cost_planner": ("true", "true", "Use the cost-estimating query planner."), + "query_plan_cache_ttl": ("60", "60", "Time to live for cached query plans, in seconds."), + "query_vertex_count_to_expand_existing": ( + "10", + "10", + "Maximum count of indexed vertices which provoke indexed lookup and then expand to existing, instead of a regular expand. Default is 10, to turn off use -1.", + ), + "query_max_plans": ("1000", "1000", "Maximum number of generated plans for a query."), + "flag_file": ("", "", "load flags from file"), +} diff --git a/tests/e2e/configuration/workloads.yaml b/tests/e2e/configuration/workloads.yaml new file mode 100644 index 000000000..62f19c3bc --- /dev/null +++ b/tests/e2e/configuration/workloads.yaml @@ -0,0 +1,13 @@ +template_cluster: &template_cluster + cluster: + main: + args: ["--log-level=TRACE", "--storage-properties-on-edges=True", "--storage-snapshot-interval-sec", "300", "--storage-wal-enabled=True"] + log_file: "configuration-check-e2e.log" + setup_queries: [] + validation_queries: [] + +workloads: + - name: "Configuration check" + binary: "tests/e2e/pytest_runner.sh" + args: ["configuration/configuration_check.py"] + <<: *template_cluster diff --git a/tests/unit/cypher_main_visitor.cpp b/tests/unit/cypher_main_visitor.cpp index 40aeb0161..0584326f8 100644 --- a/tests/unit/cypher_main_visitor.cpp +++ b/tests/unit/cypher_main_visitor.cpp @@ -4124,6 +4124,24 @@ TEST_P(CypherMainVisitorTest, VersionQuery) { ASSERT_NO_THROW(ast_generator.ParseQuery("SHOW VERSION")); } +TEST_P(CypherMainVisitorTest, ConfigQuery) { + auto &ast_generator = *GetParam(); + + TestInvalidQuery("SHOW CF", ast_generator); + TestInvalidQuery("SHOW CFG", ast_generator); + TestInvalidQuery("SHOW CFGS", ast_generator); + TestInvalidQuery("SHOW CONF", ast_generator); + TestInvalidQuery("SHOW CONFIGS", ast_generator); + TestInvalidQuery("SHOW CONFIGURATION", ast_generator); + TestInvalidQuery("SHOW CONFIGURATIONS", ast_generator); + + Query *query = ast_generator.ParseQuery("SHOW CONFIG"); + auto *ptr = dynamic_cast<ShowConfigQuery *>(query); + ASSERT_TRUE(ptr != nullptr); + + ASSERT_NO_THROW(ast_generator.ParseQuery("SHOW CONFIG")); +} + TEST_P(CypherMainVisitorTest, ForeachThrow) { auto &ast_generator = *GetParam(); EXPECT_THROW(ast_generator.ParseQuery("FOREACH(i IN [1, 2] | UNWIND [1,2,3] AS j CREATE (n))"), SyntaxException);