diff --git a/dbms/src/Interpreters/InterpreterFactory.cpp b/dbms/src/Interpreters/InterpreterFactory.cpp index cbd7a10b8c..63ceb3d1c4 100644 --- a/dbms/src/Interpreters/InterpreterFactory.cpp +++ b/dbms/src/Interpreters/InterpreterFactory.cpp @@ -32,6 +32,9 @@ #include #include +#include +#include "InterpreterSystemQuery.h" + namespace DB { @@ -123,6 +126,11 @@ std::unique_ptr InterpreterFactory::get(ASTPtr & query, Context & { return std::make_unique(query, context); } + else if (typeid_cast(query.get())) + { + throwIfReadOnly(context); + return std::make_unique(query, context); + } else throw Exception("Unknown type of query: " + query->getID(), ErrorCodes::UNKNOWN_TYPE_OF_QUERY); } diff --git a/dbms/src/Interpreters/InterpreterSystemQuery.cpp b/dbms/src/Interpreters/InterpreterSystemQuery.cpp new file mode 100644 index 0000000000..b454b5375e --- /dev/null +++ b/dbms/src/Interpreters/InterpreterSystemQuery.cpp @@ -0,0 +1,14 @@ +#include "InterpreterSystemQuery.h" + +namespace DB +{ + +InterpreterSystemQuery::InterpreterSystemQuery(const ASTPtr & query_ptr_, Context & context_) + : query_ptr(query_ptr_), context(context_) {} + +BlockIO InterpreterSystemQuery::execute() +{ + return BlockIO(); +} + +} \ No newline at end of file diff --git a/dbms/src/Interpreters/InterpreterSystemQuery.h b/dbms/src/Interpreters/InterpreterSystemQuery.h new file mode 100644 index 0000000000..f6010dafc5 --- /dev/null +++ b/dbms/src/Interpreters/InterpreterSystemQuery.h @@ -0,0 +1,27 @@ +#pragma once +#include + +namespace DB +{ + +class Context; +class IAST; +using ASTPtr = std::shared_ptr; + + +/** Return list of currently executing queries. + */ +class InterpreterSystemQuery : public IInterpreter +{ +public: + InterpreterSystemQuery(const ASTPtr & query_ptr_, Context & context_); + + BlockIO execute() override; + +private: + ASTPtr query_ptr; + Context & context; +}; + + +} diff --git a/dbms/src/Interpreters/evaluateConstantExpression.cpp b/dbms/src/Interpreters/evaluateConstantExpression.cpp index 24ea8924c3..82fda24457 100644 --- a/dbms/src/Interpreters/evaluateConstantExpression.cpp +++ b/dbms/src/Interpreters/evaluateConstantExpression.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -62,10 +63,30 @@ ASTPtr evaluateConstantExpressionAsLiteral(ASTPtr & node, const Context & contex ASTPtr evaluateConstantExpressionOrIdentifierAsLiteral(ASTPtr & node, const Context & context) { - if (const ASTIdentifier * id = typeid_cast(node.get())) + if (auto id = typeid_cast(node.get())) return std::make_shared(node->range, Field(id->name)); return evaluateConstantExpressionAsLiteral(node, context); } + +bool parseIdentifierOrStringLiteral(IParser::Pos & pos, Expected & expected, String & result) +{ + IParser::Pos begin = pos; + ASTPtr res; + + if (!ParserIdentifier().parse(pos, res, expected)) + { + pos = begin; + if (!ParserStringLiteral().parse(pos, res, expected)) + return false; + + result = typeid_cast(*res).value.safeGet(); + } + else + result = typeid_cast(*res).name; + + return true; +} + } diff --git a/dbms/src/Interpreters/evaluateConstantExpression.h b/dbms/src/Interpreters/evaluateConstantExpression.h index ed3befdf02..f5833a1af1 100644 --- a/dbms/src/Interpreters/evaluateConstantExpression.h +++ b/dbms/src/Interpreters/evaluateConstantExpression.h @@ -2,6 +2,7 @@ #include #include +#include namespace DB @@ -11,6 +12,7 @@ class IAST; class Context; class IDataType; + /** Evaluate constant expression and its type. * Used in rare cases - for elements of set for IN, for data to INSERT. * Quite suboptimal. @@ -31,4 +33,8 @@ std::shared_ptr evaluateConstantExpressionAsLiteral(std::shared_ptr */ std::shared_ptr evaluateConstantExpressionOrIdentifierAsLiteral(std::shared_ptr & node, const Context & context); +/** Parses a name of an object which could be written in 3 forms: + * name, `name` or 'name' */ +bool parseIdentifierOrStringLiteral(IParser::Pos & pos, Expected & expected, String & result); + } diff --git a/dbms/src/Parsers/ASTQueryWithOnCluster.cpp b/dbms/src/Parsers/ASTQueryWithOnCluster.cpp index 98dacfab2c..4812bdd110 100644 --- a/dbms/src/Parsers/ASTQueryWithOnCluster.cpp +++ b/dbms/src/Parsers/ASTQueryWithOnCluster.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace DB @@ -21,21 +22,7 @@ bool ASTQueryWithOnCluster::parse(Pos & pos, std::string & cluster_str, Expected if (!ParserKeyword{"CLUSTER"}.ignore(pos, expected)) return false; - Pos begin = pos; - ASTPtr res; - - if (!ParserIdentifier().parse(pos, res, expected)) - { - pos = begin; - if (!ParserStringLiteral().parse(pos, res, expected)) - return false; - else - cluster_str = typeid_cast(*res).value.safeGet(); - } - else - cluster_str = typeid_cast(*res).name; - - return true; + return parseIdentifierOrStringLiteral(pos, expected, cluster_str); } diff --git a/dbms/src/Parsers/ASTSetQuery.h b/dbms/src/Parsers/ASTSetQuery.h index d359f6d4e2..c2acb2c3af 100644 --- a/dbms/src/Parsers/ASTSetQuery.h +++ b/dbms/src/Parsers/ASTSetQuery.h @@ -24,7 +24,7 @@ public: Changes changes; ASTSetQuery() = default; - ASTSetQuery(const StringRange range_) : IAST(range_) {} + explicit ASTSetQuery(const StringRange range_) : IAST(range_) {} /** Get the text that identifies this element. */ String getID() const override { return "Set"; }; diff --git a/dbms/src/Parsers/ASTSystemQuery.cpp b/dbms/src/Parsers/ASTSystemQuery.cpp new file mode 100644 index 0000000000..2eb45f5b5e --- /dev/null +++ b/dbms/src/Parsers/ASTSystemQuery.cpp @@ -0,0 +1,55 @@ +#include +#include + + +namespace ErrorCodes +{ + extern const int BAD_TYPE_OF_FIELD; +} + + +namespace DB +{ + + +const char * ASTSystemQuery::typeToString(Type type) +{ + switch (type) + { + case Type::SHUTDOWN: + return "SHUTDOWN"; + case Type::KILL: + return "KILL"; + case Type::DROP_DNS_CACHE: + return "DROP DNS CACHE"; + case Type::DROP_MARK_CACHE: + return "DROP MARK CACHE"; + case Type::DROP_UNCOMPRESSED_CACHE: + return "DROP UNCOMPRESSED CACHE"; + case Type::STOP_LISTEN_QUERIES: + return "STOP LISTEN QUERIES"; + case Type::START_LISTEN_QUERIES: + return "START LISTEN QUERIES"; + case Type::RESTART_REPLICAS: + return "RESTART REPLICAS"; + case Type::SYNC_REPLICA: + return "SYNC REPLICA"; + case Type::RELOAD_DICTIONARY: + return "RELOAD DICTIONARY"; + case Type::RELOAD_DICTIONARIES: + return "RELOAD DICTIONARIES"; + case Type::STOP_MERGES: + return "STOP MERGES"; + case Type::START_MERGES: + return "START MERGES"; + case Type::STOP_REPLICATION_QUEUES: + return "STOP REPLICATION QUEUES"; + case Type::START_REPLICATION_QUEUES: + return "START REPLICATION QUEUES"; + default: + throw Exception("Unknown SYSTEM query command", ErrorCodes::BAD_TYPE_OF_FIELD); + } +} + + +} \ No newline at end of file diff --git a/dbms/src/Parsers/ASTSystemQuery.h b/dbms/src/Parsers/ASTSystemQuery.h new file mode 100644 index 0000000000..e4f08a4eb1 --- /dev/null +++ b/dbms/src/Parsers/ASTSystemQuery.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include + + +namespace DB +{ + +class ASTSystemQuery : public IAST +{ +public: + + enum class Type + { + _UNKNOWN, + SHUTDOWN, + KILL, + DROP_DNS_CACHE, + DROP_MARK_CACHE, + DROP_UNCOMPRESSED_CACHE, + STOP_LISTEN_QUERIES, + START_LISTEN_QUERIES, + RESTART_REPLICAS, + SYNC_REPLICA, + RELOAD_DICTIONARY, + RELOAD_DICTIONARIES, + STOP_MERGES, + START_MERGES, + STOP_REPLICATION_QUEUES, + START_REPLICATION_QUEUES, + _END + }; + + static const char * typeToString(Type type); + + Type type = Type::_UNKNOWN; + + String target_dictionary; + //String target_replica; + + ASTSystemQuery() = default; + explicit ASTSystemQuery(const StringRange range) : IAST(range) {} + + String getID() const override { return "SYSTEM"; }; + + ASTPtr clone() const override { return std::make_shared(*this); } + + ~ASTSystemQuery() override = default; + +protected: + + void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override + { + settings.ostr << (settings.hilite ? hilite_keyword : "") << "SYSTEM " << (settings.hilite ? hilite_none : ""); + } +}; + + +} \ No newline at end of file diff --git a/dbms/src/Parsers/ParserQuery.cpp b/dbms/src/Parsers/ParserQuery.cpp index 6a93110c14..3506c8c92e 100644 --- a/dbms/src/Parsers/ParserQuery.cpp +++ b/dbms/src/Parsers/ParserQuery.cpp @@ -8,6 +8,7 @@ #include #include #include +#include "ParserSystemQuery.h" namespace DB @@ -22,12 +23,14 @@ bool ParserQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) ParserUseQuery use_p; ParserSetQuery set_p; ParserOptimizeQuery optimize_p; + ParserSystemQuery system_p; bool res = query_with_output_p.parse(pos, node, expected) || insert_p.parse(pos, node, expected) || use_p.parse(pos, node, expected) || set_p.parse(pos, node, expected) - || optimize_p.parse(pos, node, expected); + || optimize_p.parse(pos, node, expected) + || system_p.parse(pos, node, expected); return res; } diff --git a/dbms/src/Parsers/ParserSetQuery.h b/dbms/src/Parsers/ParserSetQuery.h index 64f6b5d96b..d48ecd8dda 100644 --- a/dbms/src/Parsers/ParserSetQuery.h +++ b/dbms/src/Parsers/ParserSetQuery.h @@ -13,11 +13,11 @@ namespace DB class ParserSetQuery : public IParserBase { public: - ParserSetQuery(bool parse_only_internals_ = false) : parse_only_internals(parse_only_internals_) {} + explicit ParserSetQuery(bool parse_only_internals_ = false) : parse_only_internals(parse_only_internals_) {} protected: - const char * getName() const { return "SET query"; } - bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); + const char * getName() const override { return "SET query"; } + bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; /// Parse the list `name = value` pairs, without SET [GLOBAL]. bool parse_only_internals; diff --git a/dbms/src/Parsers/ParserSystemQuery.cpp b/dbms/src/Parsers/ParserSystemQuery.cpp new file mode 100644 index 0000000000..5aa340a478 --- /dev/null +++ b/dbms/src/Parsers/ParserSystemQuery.cpp @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include +#include "ASTSystemQuery.h" + + +namespace ErrorCodes +{ + extern const int NOT_IMPLEMENTED; +} + + +namespace DB +{ + + +bool ParserSystemQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected) +{ + if (!ParserKeyword{"SYSTEM"}.ignore(pos)) + return false; + + using Type = ASTSystemQuery::Type; + + auto res = std::make_shared(); + + bool found = false; + for (int i = static_cast(Type::SHUTDOWN); i < static_cast(Type::_END); ++i) + { + Type t = static_cast(i); + if (ParserKeyword{ASTSystemQuery::typeToString(t)}.ignore(pos)) + { + res->type = t; + found = true; + } + } + + if (!found) + return false; + + if (res->type == Type::RELOAD_DICTIONARY) + { + if (!parseIdentifierOrStringLiteral(pos, expected, res->target_dictionary)) + return false; + } + else if (res->type == Type::SYNC_REPLICA) + { + throw Exception("SYNC REPLICA is not supported yet", ErrorCodes::NOT_IMPLEMENTED); + } + + node = std::move(res); + return true; +} + +} diff --git a/dbms/src/Parsers/ParserSystemQuery.h b/dbms/src/Parsers/ParserSystemQuery.h new file mode 100644 index 0000000000..745e774822 --- /dev/null +++ b/dbms/src/Parsers/ParserSystemQuery.h @@ -0,0 +1,19 @@ +#pragma once +#include + + +namespace DB +{ + + +class ParserSystemQuery : public IParserBase +{ +public: + ParserSystemQuery() = default; + +protected: + const char * getName() const override { return "SYSTEM query"; } + bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; +}; + +} \ No newline at end of file diff --git a/dbms/tests/queries/0_stateless/00486_system_query_simple.reference b/dbms/tests/queries/0_stateless/00486_system_query_simple.reference new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dbms/tests/queries/0_stateless/00486_system_query_simple.sh b/dbms/tests/queries/0_stateless/00486_system_query_simple.sh new file mode 100755 index 0000000000..1b20cb032d --- /dev/null +++ b/dbms/tests/queries/0_stateless/00486_system_query_simple.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -e + +cli="clickhouse-client -q " + +$cli "SYSTEM SHUTDOWN" +$cli "SYSTEM KILL" +$cli "SYSTEM DROP DNS CACHE" +$cli "SYSTEM DROP MARK CACHE" +$cli "SYSTEM DROP UNCOMPRESSED CACHE" +$cli "SYSTEM STOP LISTEN QUERIES" +$cli "SYSTEM START LISTEN QUERIES" +$cli "SYSTEM RESTART REPLICAS" +#$cli "SYSTEM SYNC REPLICA test" +$cli "SYSTEM RELOAD DICTIONARY dict" +$cli "SYSTEM RELOAD DICTIONARIES" +$cli "SYSTEM STOP MERGES" +$cli "SYSTEM START MERGES" +$cli "SYSTEM STOP REPLICATION QUEUES" +$cli "SYSTEM START REPLICATION QUEUES"