From 848678d65698bb0712c9707a609e96282cfc53f1 Mon Sep 17 00:00:00 2001 From: alesapin Date: Mon, 6 Apr 2020 14:02:17 +0300 Subject: [PATCH] Now layout type for dictionaries DDL with no arguments can be written without brackets --- src/Parsers/ASTDictionary.cpp | 11 +++++-- src/Parsers/ASTDictionary.h | 2 ++ .../ASTFunctionWithKeyValueArguments.cpp | 4 +-- .../ASTFunctionWithKeyValueArguments.h | 7 ++++ src/Parsers/ExpressionElementParsers.cpp | 26 +++++++++++---- src/Parsers/ExpressionElementParsers.h | 7 ++++ src/Parsers/ParserDictionary.cpp | 7 +++- ...tionary_layout_without_arguments.reference | 3 ++ ...10_dictionary_layout_without_arguments.sql | 33 +++++++++++++++++++ 9 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 tests/queries/0_stateless/01110_dictionary_layout_without_arguments.reference create mode 100644 tests/queries/0_stateless/01110_dictionary_layout_without_arguments.sql diff --git a/src/Parsers/ASTDictionary.cpp b/src/Parsers/ASTDictionary.cpp index 5c477c2aab7..9ff600333c5 100644 --- a/src/Parsers/ASTDictionary.cpp +++ b/src/Parsers/ASTDictionary.cpp @@ -24,6 +24,7 @@ void ASTDictionaryRange::formatImpl(const FormatSettings & settings, << "(" << (settings.hilite ? hilite_keyword : "") << "MIN " + << (settings.hilite ? hilite_none : "") << min_attr_name << " " << (settings.hilite ? hilite_keyword : "") << "MAX " @@ -52,6 +53,7 @@ void ASTDictionaryLifetime::formatImpl(const FormatSettings & settings, << "(" << (settings.hilite ? hilite_keyword : "") << "MIN " + << (settings.hilite ? hilite_none : "") << min_sec << " " << (settings.hilite ? hilite_keyword : "") << "MAX " @@ -86,7 +88,9 @@ void ASTDictionaryLayout::formatImpl(const FormatSettings & settings, << Poco::toUpper(layout_type) << (settings.hilite ? hilite_none : ""); - settings.ostr << "("; + if (has_brackets) + settings.ostr << "("; + if (parameter) { settings.ostr << (settings.hilite ? hilite_keyword : "") @@ -96,7 +100,10 @@ void ASTDictionaryLayout::formatImpl(const FormatSettings & settings, parameter->second->formatImpl(settings, state, frame); } - settings.ostr << ")"; + + if (has_brackets) + settings.ostr << ")"; + settings.ostr << ")"; } diff --git a/src/Parsers/ASTDictionary.h b/src/Parsers/ASTDictionary.h index e146162cbdf..6982381f14d 100644 --- a/src/Parsers/ASTDictionary.h +++ b/src/Parsers/ASTDictionary.h @@ -33,6 +33,8 @@ public: String layout_type; /// optional parameter (size_in_cells) std::optional parameter; + /// has brackets after layout type + bool has_brackets = true; String getID(char) const override { return "Dictionary layout"; } diff --git a/src/Parsers/ASTFunctionWithKeyValueArguments.cpp b/src/Parsers/ASTFunctionWithKeyValueArguments.cpp index 8fdeb90c25b..0843bddac7d 100644 --- a/src/Parsers/ASTFunctionWithKeyValueArguments.cpp +++ b/src/Parsers/ASTFunctionWithKeyValueArguments.cpp @@ -64,9 +64,9 @@ ASTPtr ASTFunctionWithKeyValueArguments::clone() const void ASTFunctionWithKeyValueArguments::formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const { - settings.ostr << (settings.hilite ? hilite_keyword : "") << Poco::toUpper(name) << (settings.hilite ? hilite_none : "") << "("; + settings.ostr << (settings.hilite ? hilite_keyword : "") << Poco::toUpper(name) << (settings.hilite ? hilite_none : "") << (has_brackets ? "(" : ""); elements->formatImpl(settings, state, frame); - settings.ostr << ")"; + settings.ostr << (has_brackets ? ")" : ""); settings.ostr << (settings.hilite ? hilite_none : ""); } diff --git a/src/Parsers/ASTFunctionWithKeyValueArguments.h b/src/Parsers/ASTFunctionWithKeyValueArguments.h index e09e477417f..3f31b4a7c5b 100644 --- a/src/Parsers/ASTFunctionWithKeyValueArguments.h +++ b/src/Parsers/ASTFunctionWithKeyValueArguments.h @@ -44,6 +44,13 @@ public: String name; /// Expression list ASTPtr elements; + /// Has brackets around arguments + bool has_brackets; + + ASTFunctionWithKeyValueArguments(bool has_brackets_ = true) + : has_brackets(has_brackets_) + { + } public: String getID(char delim) const override; diff --git a/src/Parsers/ExpressionElementParsers.cpp b/src/Parsers/ExpressionElementParsers.cpp index c4e43829da9..30fa4a2e9fb 100644 --- a/src/Parsers/ExpressionElementParsers.cpp +++ b/src/Parsers/ExpressionElementParsers.cpp @@ -1400,18 +1400,30 @@ bool ParserFunctionWithKeyValueArguments::parseImpl(Pos & pos, ASTPtr & node, Ex if (!id_parser.parse(pos, identifier, expected)) return false; - if (pos.get().type != TokenType::OpeningRoundBracket) - return false; - ++pos; + bool left_bracket_found = false; + if (pos.get().type != TokenType::OpeningRoundBracket) + { + if (!brackets_can_be_omitted) + return false; + } + else + { + ++pos; + left_bracket_found = true; + } + if (!pairs_list_parser.parse(pos, expr_list_args, expected)) return false; - if (pos.get().type != TokenType::ClosingRoundBracket) - return false; + if (left_bracket_found) + { + if (pos.get().type != TokenType::ClosingRoundBracket) + return false; + ++pos; + } - ++pos; - auto function = std::make_shared(); + auto function = std::make_shared(left_bracket_found); function->name = Poco::toLower(typeid_cast(*identifier.get()).name); function->elements = expr_list_args; function->children.push_back(function->elements); diff --git a/src/Parsers/ExpressionElementParsers.h b/src/Parsers/ExpressionElementParsers.h index b9d8d5db42c..b02b29fb2e5 100644 --- a/src/Parsers/ExpressionElementParsers.h +++ b/src/Parsers/ExpressionElementParsers.h @@ -346,9 +346,16 @@ protected: */ class ParserFunctionWithKeyValueArguments : public IParserBase { +public: + ParserFunctionWithKeyValueArguments(bool brackets_can_be_omitted_ = false) + : brackets_can_be_omitted(brackets_can_be_omitted_) {} protected: + const char * getName() const override { return "function with key-value arguments"; } bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; + + /// brackets for function arguments can be omitted + bool brackets_can_be_omitted; }; /** Data type or table engine, possibly with parameters. For example, UInt8 or see examples from ParserIdentifierWithParameters diff --git a/src/Parsers/ParserDictionary.cpp b/src/Parsers/ParserDictionary.cpp index ca9c2ad031a..8f41882c399 100644 --- a/src/Parsers/ParserDictionary.cpp +++ b/src/Parsers/ParserDictionary.cpp @@ -109,7 +109,7 @@ bool ParserDictionaryRange::parseImpl(Pos & pos, ASTPtr & node, Expected & expec bool ParserDictionaryLayout::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { - ParserFunctionWithKeyValueArguments key_value_func_p; + ParserFunctionWithKeyValueArguments key_value_func_p(/* brackets_can_be_omitted = */ true); ASTPtr ast_func; if (!key_value_func_p.parse(pos, ast_func, expected)) return false; @@ -121,12 +121,17 @@ bool ParserDictionaryLayout::parseImpl(Pos & pos, ASTPtr & node, Expected & expe return false; res->layout_type = func.name; + res->has_brackets = func.has_brackets; const ASTExpressionList & type_expr_list = func.elements->as(); /// there are no layout with more than 1 parameter if (type_expr_list.children.size() > 1) return false; + /// if layout has params than brackets must be specified + if (type_expr_list.children.size() != 0 && !res->has_brackets) + return false; + if (type_expr_list.children.size() == 1) { const ASTPair * pair = dynamic_cast(type_expr_list.children.at(0).get()); diff --git a/tests/queries/0_stateless/01110_dictionary_layout_without_arguments.reference b/tests/queries/0_stateless/01110_dictionary_layout_without_arguments.reference new file mode 100644 index 00000000000..a0518e78891 --- /dev/null +++ b/tests/queries/0_stateless/01110_dictionary_layout_without_arguments.reference @@ -0,0 +1,3 @@ +World +CREATE DICTIONARY db_for_dict.dict_with_hashed_layout (`key1` UInt64, `value` String) PRIMARY KEY key1 SOURCE(CLICKHOUSE(HOST \'localhost\' PORT 9000 USER \'default\' TABLE \'table_for_dict\' DB \'db_for_dict\')) LIFETIME(MIN 1 MAX 10) LAYOUT(HASHED) +Hello diff --git a/tests/queries/0_stateless/01110_dictionary_layout_without_arguments.sql b/tests/queries/0_stateless/01110_dictionary_layout_without_arguments.sql new file mode 100644 index 00000000000..718e7f295b3 --- /dev/null +++ b/tests/queries/0_stateless/01110_dictionary_layout_without_arguments.sql @@ -0,0 +1,33 @@ +DROP DATABASE IF EXISTS db_for_dict; +CREATE DATABASE db_for_dict; + +CREATE TABLE db_for_dict.table_for_dict +( + key1 UInt64, + value String +) +ENGINE = Memory(); + +INSERT INTO db_for_dict.table_for_dict VALUES (1, 'Hello'), (2, 'World'); + +CREATE DICTIONARY db_for_dict.dict_with_hashed_layout +( + key1 UInt64, + value String +) +PRIMARY KEY key1 +LAYOUT(HASHED) +SOURCE(CLICKHOUSE(HOST 'localhost' PORT 9000 USER 'default' TABLE 'table_for_dict' DB 'db_for_dict')) +LIFETIME(MIN 1 MAX 10); + +SELECT dictGet('db_for_dict.dict_with_hashed_layout', 'value', toUInt64(2)); + +DETACH DICTIONARY db_for_dict.dict_with_hashed_layout; + +ATTACH DICTIONARY db_for_dict.dict_with_hashed_layout; + +SHOW CREATE DICTIONARY db_for_dict.dict_with_hashed_layout; + +SELECT dictGet('db_for_dict.dict_with_hashed_layout', 'value', toUInt64(1)); + +DROP DATABASE IF EXISTS db_for_dict;