diff --git a/dbms/src/Functions/FunctionsConversion.cpp b/dbms/src/Functions/FunctionsConversion.cpp index b0f5bbb2ed6..596c86f07e2 100644 --- a/dbms/src/Functions/FunctionsConversion.cpp +++ b/dbms/src/Functions/FunctionsConversion.cpp @@ -47,7 +47,7 @@ void registerFunctionsConversion(FunctionFactory & factory) factory.registerFunction(); factory.registerFunction(); - factory.registerFunction(); + factory.registerFunction(FunctionFactory::CaseInsensitive); factory.registerFunction(); factory.registerFunction(); diff --git a/dbms/src/Parsers/ASTFunction.cpp b/dbms/src/Parsers/ASTFunction.cpp index 7d73e48b7ea..c972a9e64c4 100644 --- a/dbms/src/Parsers/ASTFunction.cpp +++ b/dbms/src/Parsers/ASTFunction.cpp @@ -65,27 +65,6 @@ void ASTFunction::formatImplWithoutAlias(const FormatSettings & settings, Format bool written = false; if (arguments && !parameters) { - if (0 == strcmp(name.data(), "CAST")) - { - settings.ostr << (settings.hilite ? hilite_keyword : "") << name; - - settings.ostr << '(' << (settings.hilite ? hilite_none : ""); - - arguments->children.front()->formatImpl(settings, state, nested_need_parens); - - settings.ostr << (settings.hilite ? hilite_keyword : "") << " AS " - << (settings.hilite ? hilite_none : ""); - - settings.ostr << (settings.hilite ? hilite_function : "") - << typeid_cast(*arguments->children.back()).value.safeGet() - << (settings.hilite ? hilite_none : ""); - - settings.ostr << (settings.hilite ? hilite_keyword : "") << ')' - << (settings.hilite ? hilite_none : ""); - - written = true; - } - if (arguments->children.size() == 1) { const char * operators[] = diff --git a/dbms/src/Parsers/ExpressionElementParsers.cpp b/dbms/src/Parsers/ExpressionElementParsers.cpp index 29cca1b2bda..9a199a6839e 100644 --- a/dbms/src/Parsers/ExpressionElementParsers.cpp +++ b/dbms/src/Parsers/ExpressionElementParsers.cpp @@ -22,6 +22,8 @@ #include #include +#include + namespace DB { @@ -280,107 +282,45 @@ bool ParserFunction::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) bool ParserCastExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { - const auto begin = pos; + /// Either CAST(expr AS type) or CAST(expr, 'type') + /// The latter will be parsed normally as a function later. - ParserIdentifier id_parser; + ASTPtr expr_node; + ASTPtr type_node; - ASTPtr identifier; - - if (!id_parser.parse(pos, identifier, expected)) - return false; - - const auto & id = typeid_cast(*identifier).name; - - /// TODO This is ridiculous. Please get rid of this. - if (id.length() != strlen(name) || 0 != strcasecmp(id.c_str(), name)) + if (ParserKeyword("CAST").ignore(pos, expected) + && ParserToken(TokenType::OpeningRoundBracket).ignore(pos, expected) + && ParserExpression().parse(pos, expr_node, expected) + && ParserKeyword("AS").ignore(pos, expected) + && ParserIdentifierWithOptionalParameters().parse(pos, type_node, expected) + && ParserToken(TokenType::ClosingRoundBracket).ignore(pos, expected)) { - /// Parse as a CASE expression. - pos = begin; - return ParserCase{}.parse(pos, node, expected); + /// Convert to canonical representation in functional form: CAST(expr, 'type') + + auto type_literal = std::make_shared(queryToString(type_node)); + + auto expr_list_args = std::make_shared(); + expr_list_args->children.push_back(expr_node); + expr_list_args->children.push_back(std::move(type_literal)); + + auto func_node = std::make_shared(); + func_node->name = "CAST"; + func_node->arguments = std::move(expr_list_args); + func_node->children.push_back(func_node->arguments); + + node = std::move(func_node); + return true; } - /// Parse as CAST(expression AS type) - ParserExpressionInCastExpression expression_and_type(false); - - ASTPtr expr_list_args; - - if (pos->type != TokenType::OpeningRoundBracket) - return false; - ++pos; - - const auto contents_begin = pos; - ASTPtr first_argument; - if (!expression_and_type.parse(pos, first_argument, expected)) - return false; - - /// check for subsequent comma "," - if (pos->type != TokenType::Comma) - { - /// CAST(expression AS type) - const auto type = first_argument->tryGetAlias(); - - if (type.empty()) - { - /// there is only one argument and it has no alias - expected.add(pos, "type identifier"); - return false; - } - - expr_list_args = std::make_shared(); - first_argument->setAlias({}); - expr_list_args->children.push_back(first_argument); - expr_list_args->children.emplace_back(std::make_shared(type)); - } - else - { - pos = contents_begin; - - /// CAST(expression, 'type') - /// Reparse argument list from scratch - ParserExpressionWithOptionalAlias expression{false}; - if (!expression.parse(pos, first_argument, expected)) - return false; - - if (pos->type != TokenType::Comma) - return false; - ++pos; - - ParserStringLiteral p_type; - ASTPtr type_as_literal; - - if (!p_type.parse(pos, type_as_literal, expected)) - { - expected.add(pos, "string literal depicting type"); - return false; - } - - expr_list_args = std::make_shared(); - expr_list_args->children.push_back(first_argument); - expr_list_args->children.push_back(type_as_literal); - } - - if (pos->type != TokenType::ClosingRoundBracket) - return false; - ++pos; - - const auto function_node = std::make_shared(); - ASTPtr node_holder{function_node}; - function_node->name = name; - - function_node->arguments = expr_list_args; - function_node->children.push_back(function_node->arguments); - - node = node_holder; - return true; + return false; } + bool ParserExtractExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { auto begin = pos; - ParserIdentifier id_parser; - ASTPtr identifier; - if (!id_parser.parse(pos, identifier, expected)) + if (!ParserKeyword("EXTRACT").ignore(pos, expected)) return false; if (pos->type != TokenType::OpeningRoundBracket) @@ -636,7 +576,7 @@ bool ParserLiteral::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) } -const char * ParserAliasBase::restricted_keywords[] = +const char * ParserAlias::restricted_keywords[] = { "FROM", "FINAL", @@ -667,8 +607,7 @@ const char * ParserAliasBase::restricted_keywords[] = nullptr }; -template -bool ParserAliasImpl::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) +bool ParserAlias::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_as("AS"); ParserIdentifier id_p; @@ -697,9 +636,6 @@ bool ParserAliasImpl::parseImpl(Pos & pos, ASTPtr & node, Expe return true; } -template class ParserAliasImpl; -template class ParserAliasImpl; - bool ParserAsterisk::parseImpl(Pos & pos, ASTPtr & node, Expected &) { @@ -735,53 +671,22 @@ bool ParserQualifiedAsterisk::parseImpl(Pos & pos, ASTPtr & node, Expected & exp bool ParserExpressionElement::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { - ParserParenthesisExpression paren_p; - ParserSubquery subquery_p; - ParserArray array_p; - ParserArrayOfLiterals array_lite_p; - ParserLiteral lit_p; - ParserExtractExpression extract_p; - ParserCastExpression cast_p; - ParserCompoundIdentifier id_p; - ParserAsterisk asterisk_p; - ParserQualifiedAsterisk qualified_asterisk_p; - - if (subquery_p.parse(pos, node, expected)) - return true; - - if (paren_p.parse(pos, node, expected)) - return true; - - if (array_lite_p.parse(pos, node, expected)) - return true; - - if (array_p.parse(pos, node, expected)) - return true; - - if (lit_p.parse(pos, node, expected)) - return true; - - if (extract_p.parse(pos, node, expected)) - return true; - - if (cast_p.parse(pos, node, expected)) - return true; - - if (qualified_asterisk_p.parse(pos, node, expected)) - return true; - - if (asterisk_p.parse(pos, node, expected)) - return true; - - if (id_p.parse(pos, node, expected)) - return true; - - return false; + return ParserSubquery().parse(pos, node, expected) + || ParserParenthesisExpression().parse(pos, node, expected) + || ParserArrayOfLiterals().parse(pos, node, expected) + || ParserArray().parse(pos, node, expected) + || ParserLiteral().parse(pos, node, expected) + || ParserExtractExpression().parse(pos, node, expected) + || ParserCastExpression().parse(pos, node, expected) + || ParserCase().parse(pos, node, expected) + || ParserFunction().parse(pos, node, expected) + || ParserQualifiedAsterisk().parse(pos, node, expected) + || ParserAsterisk().parse(pos, node, expected) + || ParserCompoundIdentifier().parse(pos, node, expected); } -template -bool ParserWithOptionalAliasImpl::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) +bool ParserWithOptionalAlias::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { if (!elem_parser->parse(pos, node, expected)) return false; @@ -831,9 +736,6 @@ bool ParserWithOptionalAliasImpl::parseImpl(Pos & pos, ASTPtr & nod return true; } -template class ParserWithOptionalAliasImpl; -template class ParserWithOptionalAliasImpl; - bool ParserOrderByElement::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { diff --git a/dbms/src/Parsers/ExpressionElementParsers.h b/dbms/src/Parsers/ExpressionElementParsers.h index 10a78d9f267..32e1c57dce2 100644 --- a/dbms/src/Parsers/ExpressionElementParsers.h +++ b/dbms/src/Parsers/ExpressionElementParsers.h @@ -91,20 +91,15 @@ protected: class ParserCastExpression : public IParserBase { - /// this name is used for identifying CAST expression among other function calls - static constexpr auto name = "CAST"; - protected: - const char * getName() const override { return name; } + const char * getName() const override { return "CAST expression"; } bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; }; class ParserExtractExpression : public IParserBase { - static constexpr auto name = "EXTRACT"; - protected: - const char * getName() const override { return name; } + const char * getName() const override { return "EXTRACT expression"; } bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; }; @@ -174,18 +169,14 @@ protected: /** The alias is the identifier before which `AS` comes. For example: AS x_yz123. */ -struct ParserAliasBase -{ - static const char * restricted_keywords[]; -}; - -template -class ParserAliasImpl : public IParserBase, ParserAliasBase +class ParserAlias : public IParserBase { public: - ParserAliasImpl(bool allow_alias_without_as_keyword_) + ParserAlias(bool allow_alias_without_as_keyword_) : allow_alias_without_as_keyword(allow_alias_without_as_keyword_) {} -protected: +private: + static const char * restricted_keywords[]; + bool allow_alias_without_as_keyword; const char * getName() const { return "alias"; } @@ -193,15 +184,6 @@ protected: }; -class ParserTypeInCastExpression; - -extern template class ParserAliasImpl; -extern template class ParserAliasImpl; - -using ParserAlias = ParserAliasImpl; -using ParserCastExpressionAlias = ParserAliasImpl; - - /** The expression element is one of: an expression in parentheses, an array, a literal, a function, an identifier, an asterisk. */ class ParserExpressionElement : public IParserBase @@ -214,11 +196,10 @@ protected: /** An expression element, possibly with an alias, if appropriate. */ -template -class ParserWithOptionalAliasImpl : public IParserBase +class ParserWithOptionalAlias : public IParserBase { public: - ParserWithOptionalAliasImpl(ParserPtr && elem_parser_, bool allow_alias_without_as_keyword_, bool prefer_alias_to_column_name_ = false) + ParserWithOptionalAlias(ParserPtr && elem_parser_, bool allow_alias_without_as_keyword_, bool prefer_alias_to_column_name_ = false) : elem_parser(std::move(elem_parser_)), allow_alias_without_as_keyword(allow_alias_without_as_keyword_), prefer_alias_to_column_name(prefer_alias_to_column_name_) {} protected: @@ -230,12 +211,6 @@ protected: bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); }; -extern template class ParserWithOptionalAliasImpl; -extern template class ParserWithOptionalAliasImpl; - -using ParserWithOptionalAlias = ParserWithOptionalAliasImpl; -using ParserCastExpressionWithOptionalAlias = ParserWithOptionalAliasImpl; - /** Element of ORDER BY expression - same as expression element, but in addition, ASC[ENDING] | DESC[ENDING] could be specified * and optionally, NULLS LAST|FIRST diff --git a/dbms/src/Parsers/ExpressionListParsers.cpp b/dbms/src/Parsers/ExpressionListParsers.cpp index 5ac3d9f046d..ef75267cffe 100644 --- a/dbms/src/Parsers/ExpressionListParsers.cpp +++ b/dbms/src/Parsers/ExpressionListParsers.cpp @@ -535,13 +535,6 @@ ParserExpressionWithOptionalAlias::ParserExpressionWithOptionalAlias(bool allow_ } -ParserExpressionInCastExpression::ParserExpressionInCastExpression(bool allow_alias_without_as_keyword) - : impl(std::make_unique(std::make_unique(), - allow_alias_without_as_keyword, false)) -{ -} - - bool ParserExpressionList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { return ParserList( diff --git a/dbms/src/Parsers/ExpressionListParsers.h b/dbms/src/Parsers/ExpressionListParsers.h index 887f28a144c..28a5bb5b2b9 100644 --- a/dbms/src/Parsers/ExpressionListParsers.h +++ b/dbms/src/Parsers/ExpressionListParsers.h @@ -335,22 +335,6 @@ protected: }; -class ParserExpressionInCastExpression : public IParserBase -{ -public: - ParserExpressionInCastExpression(bool allow_alias_without_as_keyword); -protected: - ParserPtr impl; - - const char * getName() const { return "expression in CAST expression"; } - - bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) - { - return impl->parse(pos, node, expected); - } -}; - - /** A comma-separated list of expressions, probably empty. */ class ParserExpressionList : public IParserBase { diff --git a/dbms/src/Parsers/ParserCase.cpp b/dbms/src/Parsers/ParserCase.cpp index e932dfdb04f..c2193e98e8f 100644 --- a/dbms/src/Parsers/ParserCase.cpp +++ b/dbms/src/Parsers/ParserCase.cpp @@ -17,14 +17,11 @@ bool ParserCase::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) ParserKeyword s_end{ "END"}; ParserExpressionWithOptionalAlias p_expr{false}; - if (!s_case.parse(pos, node, expected)) - { - /// Parse as a simple ASTFunction. - return ParserFunction{}.parse(pos, node, expected); - } + if (!s_case.ignore(pos, expected)) + return false; auto old_pos = pos; - bool has_case_expr = !s_when.parse(pos, node, expected); + bool has_case_expr = !s_when.ignore(pos, expected); pos = old_pos; ASTs args; @@ -32,7 +29,7 @@ bool ParserCase::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) auto parse_branches = [&]() { bool has_branch = false; - while (s_when.parse(pos, node, expected)) + while (s_when.ignore(pos, expected)) { has_branch = true; @@ -41,7 +38,7 @@ bool ParserCase::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) return false; args.push_back(expr_when); - if (!s_then.parse(pos, node, expected)) + if (!s_then.ignore(pos, expected)) return false; ASTPtr expr_then; @@ -53,7 +50,7 @@ bool ParserCase::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) if (!has_branch) return false; - if (!s_else.parse(pos, node, expected)) + if (!s_else.ignore(pos, expected)) return false; ASTPtr expr_else; @@ -61,7 +58,7 @@ bool ParserCase::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) return false; args.push_back(expr_else); - if (!s_end.parse(pos, node, expected)) + if (!s_end.ignore(pos, expected)) return false; return true; diff --git a/dbms/src/Parsers/ParserCreateQuery.cpp b/dbms/src/Parsers/ParserCreateQuery.cpp index b4b121b8e00..77e2a85b8e9 100644 --- a/dbms/src/Parsers/ParserCreateQuery.cpp +++ b/dbms/src/Parsers/ParserCreateQuery.cpp @@ -78,18 +78,6 @@ bool ParserIdentifierWithOptionalParameters::parseImpl(Pos & pos, ASTPtr & node, return false; } -bool ParserTypeInCastExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) -{ - if (ParserIdentifierWithOptionalParameters().parse(pos, node, expected)) - { - const auto & id_with_params = typeid_cast(*node); - node = std::make_shared(String{ id_with_params.range.first, id_with_params.range.second }); - return true; - } - - return false; -} - bool ParserNameTypePairList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { return ParserList(std::make_unique(), std::make_unique(TokenType::Comma), false) diff --git a/dbms/src/Parsers/ParserCreateQuery.h b/dbms/src/Parsers/ParserCreateQuery.h index 6c0c7a21d52..75ce5b80537 100644 --- a/dbms/src/Parsers/ParserCreateQuery.h +++ b/dbms/src/Parsers/ParserCreateQuery.h @@ -48,13 +48,6 @@ protected: bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); }; -class ParserTypeInCastExpression : public IParserBase -{ -protected: - const char * getName() const { return "type in cast expression"; } - bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); -}; - template class IParserNameTypePair : public IParserBase diff --git a/dbms/src/Storages/ColumnsDescription.cpp b/dbms/src/Storages/ColumnsDescription.cpp index f309477584b..cb67d01a4ea 100644 --- a/dbms/src/Storages/ColumnsDescription.cpp +++ b/dbms/src/Storages/ColumnsDescription.cpp @@ -67,9 +67,9 @@ String ColumnsDescription::toString() const { WriteBufferFromOwnString buf; - writeString("columns format version: 1\n", buf); + writeCString("columns format version: 1\n", buf); writeText(ordinary.size() + materialized.size() + aliases.size(), buf); - writeString(" columns:\n", buf); + writeCString(" columns:\n", buf); const auto write_columns = [this, &buf] (const NamesAndTypesList & columns) { @@ -79,7 +79,7 @@ String ColumnsDescription::toString() const writeBackQuotedString(column.name, buf); writeChar(' ', buf); - writeString(column.type->getName(), buf); + writeText(column.type->getName(), buf); if (it == std::end(defaults)) { writeChar('\n', buf); @@ -88,9 +88,9 @@ String ColumnsDescription::toString() const else writeChar('\t', buf); - writeString(DB::toString(it->second.kind), buf); + writeText(DB::toString(it->second.kind), buf); writeChar('\t', buf); - writeString(queryToString(it->second.expression), buf); + writeText(queryToString(it->second.expression), buf); writeChar('\n', buf); } }; @@ -123,7 +123,7 @@ ColumnsDescription ColumnsDescription::parse(const String & str) assertChar(' ', buf); String type_name; - readString(type_name, buf); + readText(type_name, buf); auto type = data_type_factory.get(type_name); if (*buf.position() == '\n') { @@ -135,7 +135,7 @@ ColumnsDescription ColumnsDescription::parse(const String & str) assertChar('\t', buf); String default_kind_str; - readString(default_kind_str, buf); + readText(default_kind_str, buf); const auto default_kind = columnDefaultKindFromString(default_kind_str); assertChar('\t', buf); diff --git a/dbms/tests/queries/0_stateless/00079_defaulted_columns.reference b/dbms/tests/queries/0_stateless/00079_defaulted_columns.reference index 732837d6557..0665588a532 100644 --- a/dbms/tests/queries/0_stateless/00079_defaulted_columns.reference +++ b/dbms/tests/queries/0_stateless/00079_defaulted_columns.reference @@ -32,7 +32,7 @@ key UInt64 MATERIALIZED 0 * rand() hello clickhouse 16 some string 11 payload String -payload_length UInt16 DEFAULT CAST(length(payload) AS UInt16) +payload_length UInt16 DEFAULT CAST(length(payload), \'UInt16\') date Date MATERIALIZED today() key UInt64 MATERIALIZED 0 * rand() payload String diff --git a/dbms/tests/queries/0_stateless/00294_shard_enums.reference b/dbms/tests/queries/0_stateless/00294_shard_enums.reference index d604a5a1bb4..0f354d57230 100644 --- a/dbms/tests/queries/0_stateless/00294_shard_enums.reference +++ b/dbms/tests/queries/0_stateless/00294_shard_enums.reference @@ -1,24 +1,24 @@ -d Date DEFAULT CAST(\'2015-12-29\' AS Date) +d Date DEFAULT CAST(\'2015-12-29\', \'Date\') k UInt8 DEFAULT 0 e Enum8(\'hello\' = 1, \'world\' = 2) sign Enum8(\'minus\' = -1, \'plus\' = 1) letter Enum16(\'*\' = -256, \'a\' = 0, \'b\' = 1, \'c\' = 2) 2015-12-29 0 hello minus * -d Date DEFAULT CAST(\'2015-12-29\' AS Date) +d Date DEFAULT CAST(\'2015-12-29\', \'Date\') k UInt8 DEFAULT 0 e Enum8(\'hello\' = 1, \'world\' = 2, \'!\' = 3) sign Enum8(\'minus\' = -1, \'plus\' = 1) letter Enum16(\'*\' = -256, \'a\' = 0, \'b\' = 1, \'c\' = 2) 2015-12-29 0 hello minus * 2015-12-29 0 ! plus b -d Date DEFAULT CAST(\'2015-12-29\' AS Date) +d Date DEFAULT CAST(\'2015-12-29\', \'Date\') k UInt8 DEFAULT 0 e Enum16(\'hello\' = 1, \'world\' = 2, \'!\' = 3) sign Enum16(\'minus\' = -1, \'plus\' = 1) letter Enum16(\'no letter\' = -256, \'a\' = 0, \'b\' = 1, \'c\' = 2) 2015-12-29 0 hello minus no letter 2015-12-29 0 ! plus b -d Date DEFAULT CAST(\'2015-12-29\' AS Date) +d Date DEFAULT CAST(\'2015-12-29\', \'Date\') k UInt8 DEFAULT 0 e Enum8(\'hello\' = 1, \'world\' = 2, \'!\' = 3) sign Enum8(\'minus\' = -1, \'plus\' = 1) diff --git a/dbms/tests/queries/0_stateless/00515_shard_desc_table_functions_and_subqueries.reference b/dbms/tests/queries/0_stateless/00515_shard_desc_table_functions_and_subqueries.reference index b0615b7993f..f24dcad7c8d 100644 --- a/dbms/tests/queries/0_stateless/00515_shard_desc_table_functions_and_subqueries.reference +++ b/dbms/tests/queries/0_stateless/00515_shard_desc_table_functions_and_subqueries.reference @@ -1,25 +1,25 @@ date Date val UInt64 val2 UInt8 DEFAULT 42 -val3 UInt8 DEFAULT CAST((val2 + 1) AS UInt8) +val3 UInt8 DEFAULT CAST(val2 + 1, \'UInt8\') val4 UInt64 ALIAS val - date Date val UInt64 val2 UInt8 DEFAULT 42 -val3 UInt8 DEFAULT CAST((val2 + 1) AS UInt8) +val3 UInt8 DEFAULT CAST(val2 + 1, \'UInt8\') val4 UInt64 ALIAS val - date Date val UInt64 val2 UInt8 DEFAULT 42 -val3 UInt8 DEFAULT CAST((val2 + 1) AS UInt8) +val3 UInt8 DEFAULT CAST(val2 + 1, \'UInt8\') val4 UInt64 ALIAS val - date Date val UInt64 val2 UInt8 DEFAULT 42 -val3 UInt8 DEFAULT CAST((val2 + 1) AS UInt8) +val3 UInt8 DEFAULT CAST(val2 + 1, \'UInt8\') val4 UInt64 ALIAS val - 1 UInt8 diff --git a/dbms/tests/queries/0_stateless/00642_cast.reference b/dbms/tests/queries/0_stateless/00642_cast.reference new file mode 100644 index 00000000000..fcfb7325442 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00642_cast.reference @@ -0,0 +1,12 @@ +hello +hello +hello +hello +hello +hello +hello +hello +CREATE TABLE test.cast ( x UInt8, e Enum8('hello' = 1, 'world' = 2) DEFAULT CAST(x, 'Enum8(\'hello\' = 1, \'world\' = 2)')) ENGINE = MergeTree ORDER BY e SETTINGS index_granularity = 8192 +x UInt8 +e Enum8(\'hello\' = 1, \'world\' = 2) DEFAULT CAST(x, \'Enum8(\\\'hello\\\' = 1, \\\'world\\\' = 2)\') +1 hello diff --git a/dbms/tests/queries/0_stateless/00642_cast.sql b/dbms/tests/queries/0_stateless/00642_cast.sql new file mode 100644 index 00000000000..0e50d4c7e53 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00642_cast.sql @@ -0,0 +1,46 @@ +SELECT CAST(1 AS Enum8('hello' = 1, 'world' = 2)); +SELECT cast(1 AS Enum8('hello' = 1, 'world' = 2)); + +SELECT CAST(1, 'Enum8(\'hello\' = 1, \'world\' = 2)'); +SELECT cast(1, 'Enum8(\'hello\' = 1, \'world\' = 2)'); + +SELECT CAST(1 AS Enum8( + 'hello' = 1, + 'world' = 2)); + +SELECT cast(1 AS Enum8( + 'hello' = 1, + 'world' = 2)); + +SELECT CAST(1, 'Enum8(\'hello\' = 1,\n\t\'world\' = 2)'); +SELECT cast(1, 'Enum8(\'hello\' = 1,\n\t\'world\' = 2)'); + +DROP TABLE IF EXISTS test.cast; +CREATE TABLE test.cast +( + x UInt8, + e Enum8 + ( + 'hello' = 1, + 'world' = 2 + ) + DEFAULT + CAST + ( + x + AS + Enum8 + ( + 'hello' = 1, + 'world' = 2 + ) + ) +) ENGINE = MergeTree ORDER BY e; + +SHOW CREATE TABLE test.cast FORMAT TSVRaw; +DESC TABLE test.cast; + +INSERT INTO test.cast (x) VALUES (1); +SELECT * FROM test.cast; + +DROP TABLE test.cast; diff --git a/dbms/tests/queries/0_stateless/00643_cast_zookeeper.reference b/dbms/tests/queries/0_stateless/00643_cast_zookeeper.reference new file mode 100644 index 00000000000..401a354382d --- /dev/null +++ b/dbms/tests/queries/0_stateless/00643_cast_zookeeper.reference @@ -0,0 +1,5 @@ +CREATE TABLE test.cast1 ( x UInt8, e Enum8('hello' = 1, 'world' = 2) DEFAULT CAST(x, 'Enum8(\'hello\' = 1, \'world\' = 2)')) ENGINE = ReplicatedMergeTree('/clickhouse/tables/test_cast', 'r1') ORDER BY e SETTINGS index_granularity = 8192 +x UInt8 +e Enum8(\'hello\' = 1, \'world\' = 2) DEFAULT CAST(x, \'Enum8(\\\'hello\\\' = 1, \\\'world\\\' = 2)\') +1 hello +1 hello diff --git a/dbms/tests/queries/0_stateless/00643_cast_zookeeper.sql b/dbms/tests/queries/0_stateless/00643_cast_zookeeper.sql new file mode 100644 index 00000000000..8ebfee12da5 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00643_cast_zookeeper.sql @@ -0,0 +1,38 @@ +DROP TABLE IF EXISTS test.cast1; +DROP TABLE IF EXISTS test.cast2; + +CREATE TABLE test.cast1 +( + x UInt8, + e Enum8 + ( + 'hello' = 1, + 'world' = 2 + ) + DEFAULT + CAST + ( + x + AS + Enum8 + ( + 'hello' = 1, + 'world' = 2 + ) + ) +) ENGINE = ReplicatedMergeTree('/clickhouse/tables/test_cast', 'r1') ORDER BY e; + +SHOW CREATE TABLE test.cast1 FORMAT TSVRaw; +DESC TABLE test.cast1; + +INSERT INTO test.cast1 (x) VALUES (1); +SELECT * FROM test.cast1; + +CREATE TABLE test.cast2 AS test.cast1 ENGINE = ReplicatedMergeTree('/clickhouse/tables/test_cast', 'r2') ORDER BY e; + +SYSTEM SYNC REPLICA test.cast2; + +SELECT * FROM test.cast2; + +DROP TABLE test.cast1; +DROP TABLE test.cast2;