From 4b76ab91a153d114593d91bb0c590917c4a325a7 Mon Sep 17 00:00:00 2001 From: Anton Popov Date: Mon, 9 Oct 2023 14:14:05 +0000 Subject: [PATCH] fix parsing of arrays in cast operator --- src/Parsers/ExpressionElementParsers.cpp | 52 ++++++++++--------- .../02895_cast_operator_bug.reference | 1 + .../0_stateless/02895_cast_operator_bug.sql | 1 + 3 files changed, 30 insertions(+), 24 deletions(-) create mode 100644 tests/queries/0_stateless/02895_cast_operator_bug.reference create mode 100644 tests/queries/0_stateless/02895_cast_operator_bug.sql diff --git a/src/Parsers/ExpressionElementParsers.cpp b/src/Parsers/ExpressionElementParsers.cpp index f25e7f3c7e2..ce3aa8abf38 100644 --- a/src/Parsers/ExpressionElementParsers.cpp +++ b/src/Parsers/ExpressionElementParsers.cpp @@ -719,66 +719,70 @@ static bool isOneOf(TokenType token) bool ParserCastOperator::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { + using enum TokenType; + /// Parse numbers (including decimals), strings, arrays and tuples of them. const char * data_begin = pos->begin; const char * data_end = pos->end; - bool is_string_literal = pos->type == TokenType::StringLiteral; + bool is_string_literal = pos->type == StringLiteral; - if (pos->type == TokenType::Minus) + if (pos->type == Minus) { ++pos; - if (pos->type != TokenType::Number) + if (pos->type != Number) return false; data_end = pos->end; ++pos; } - else if (pos->type == TokenType::Number || is_string_literal) + else if (pos->type == Number || is_string_literal) { ++pos; } - else if (isOneOf(pos->type)) + else if (isOneOf(pos->type)) { - TokenType last_token = TokenType::OpeningSquareBracket; + TokenType last_token = OpeningSquareBracket; std::vector stack; while (pos.isValid()) { - if (isOneOf(pos->type)) + if (isOneOf(pos->type)) { stack.push_back(pos->type); - if (!isOneOf(last_token)) + if (!isOneOf(last_token)) return false; } - else if (pos->type == TokenType::ClosingSquareBracket) + else if (pos->type == ClosingSquareBracket) { - if (isOneOf(last_token)) + if (isOneOf(last_token)) return false; - if (stack.empty() || stack.back() != TokenType::OpeningSquareBracket) + if (stack.empty() || stack.back() != OpeningSquareBracket) return false; stack.pop_back(); } - else if (pos->type == TokenType::ClosingRoundBracket) + else if (pos->type == ClosingRoundBracket) { - if (isOneOf(last_token)) + if (isOneOf(last_token)) return false; - if (stack.empty() || stack.back() != TokenType::OpeningRoundBracket) + if (stack.empty() || stack.back() != OpeningRoundBracket) return false; stack.pop_back(); } - else if (pos->type == TokenType::Comma) + else if (pos->type == Comma) { - if (isOneOf(last_token)) + if (isOneOf(last_token)) + return false; + if (stack.empty()) + break; + } + else if (pos->type == Number) + { + if (!isOneOf(last_token)) return false; } - else if (pos->type == TokenType::Number) + else if (isOneOf(pos->type)) { - if (!isOneOf(last_token)) - return false; - } - else if (isOneOf(pos->type)) - { - if (!isOneOf(last_token)) + if (!isOneOf(last_token)) return false; } else @@ -800,7 +804,7 @@ bool ParserCastOperator::parseImpl(Pos & pos, ASTPtr & node, Expected & expected return false; ASTPtr type_ast; - if (ParserToken(TokenType::DoubleColon).ignore(pos, expected) + if (ParserToken(DoubleColon).ignore(pos, expected) && ParserDataType().parse(pos, type_ast, expected)) { String s; diff --git a/tests/queries/0_stateless/02895_cast_operator_bug.reference b/tests/queries/0_stateless/02895_cast_operator_bug.reference new file mode 100644 index 00000000000..13c0de35564 --- /dev/null +++ b/tests/queries/0_stateless/02895_cast_operator_bug.reference @@ -0,0 +1 @@ +[1] 0 diff --git a/tests/queries/0_stateless/02895_cast_operator_bug.sql b/tests/queries/0_stateless/02895_cast_operator_bug.sql new file mode 100644 index 00000000000..39c5f6b2a56 --- /dev/null +++ b/tests/queries/0_stateless/02895_cast_operator_bug.sql @@ -0,0 +1 @@ +SELECT [1], 0::UInt16;