diff --git a/src/Parsers/ExpressionElementParsers.cpp b/src/Parsers/ExpressionElementParsers.cpp index dfce06fa7c5..74fbe5eee54 100644 --- a/src/Parsers/ExpressionElementParsers.cpp +++ b/src/Parsers/ExpressionElementParsers.cpp @@ -40,6 +40,7 @@ #include #include +#include namespace DB @@ -53,89 +54,6 @@ namespace ErrorCodes } -bool ParserArray::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) -{ - ASTPtr contents_node; - ParserExpressionList contents(false); - - if (pos->type != TokenType::OpeningSquareBracket) - return false; - ++pos; - - if (!contents.parse(pos, contents_node, expected)) - return false; - - if (pos->type != TokenType::ClosingSquareBracket) - return false; - ++pos; - - auto function_node = std::make_shared(); - function_node->name = "array"; - function_node->arguments = contents_node; - function_node->children.push_back(contents_node); - node = function_node; - - return true; -} - - -bool ParserParenthesisExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) -{ - ASTPtr contents_node; - ParserExpressionList contents(false); - - if (pos->type != TokenType::OpeningRoundBracket) - return false; - ++pos; - - if (!contents.parse(pos, contents_node, expected)) - return false; - - bool is_elem = true; - if (pos->type == TokenType::Comma) - { - is_elem = false; - ++pos; - } - - if (pos->type != TokenType::ClosingRoundBracket) - return false; - ++pos; - - const auto & expr_list = contents_node->as(); - - /// Empty expression in parentheses is not allowed. - if (expr_list.children.empty()) - { - expected.add(pos, "non-empty parenthesized list of expressions"); - return false; - } - - /// Special case for one-element tuple. - if (expr_list.children.size() == 1 && is_elem) - { - auto * ast_literal = expr_list.children.front()->as(); - /// But only if its argument is not tuple, - /// since otherwise it will do incorrect transformation: - /// - /// (foo,bar) IN (('foo','bar')) -> (foo,bar) IN ('foo','bar') - if (!(ast_literal && ast_literal->value.getType() == Field::Types::Tuple)) - { - node = expr_list.children.front(); - return true; - } - } - - auto function_node = std::make_shared(); - function_node->name = "tuple"; - function_node->arguments = contents_node; - function_node->children.push_back(contents_node); - node = function_node; - - return true; -} - - bool ParserSubquery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ASTPtr select_node; @@ -1885,6 +1803,7 @@ bool ParserCollectionOfLiterals::parseImpl(Pos & pos, ASTPtr & node, std::vector> layers; layers.emplace_back(pos); + pos.increaseDepth(); ParserLiteral literal_p; @@ -1905,6 +1824,7 @@ bool ParserCollectionOfLiterals::parseImpl(Pos & pos, ASTPtr & node, literal->end = ++pos; layers.pop_back(); + pos.decreaseDepth(); if (layers.empty()) { @@ -1913,6 +1833,7 @@ bool ParserCollectionOfLiterals::parseImpl(Pos & pos, ASTPtr & node, } layers.back().arr.push_back(literal->value); + continue; } else if (pos->type == TokenType::Comma) { @@ -1931,9 +1852,14 @@ bool ParserCollectionOfLiterals::parseImpl(Pos & pos, ASTPtr & node, ASTPtr literal_node; if (literal_p.parse(pos, literal_node, expected)) + { layers.back().arr.push_back(literal_node->as().value); + } else if (pos->type == opening_bracket) + { layers.emplace_back(pos); + pos.increaseDepth(); + } else return false; } diff --git a/src/Parsers/ExpressionElementParsers.h b/src/Parsers/ExpressionElementParsers.h index abd63f81424..3bdb9731d79 100644 --- a/src/Parsers/ExpressionElementParsers.h +++ b/src/Parsers/ExpressionElementParsers.h @@ -9,26 +9,6 @@ namespace DB { -class ParserArray : public IParserBase -{ -protected: - const char * getName() const override { return "array"; } - bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; -}; - - -/** If in parenthesis an expression from one element - returns this element in `node`; - * or if there is a SELECT subquery in parenthesis, then this subquery returned in `node`; - * otherwise returns `tuple` function from the contents of brackets. - */ -class ParserParenthesisExpression : public IParserBase -{ -protected: - const char * getName() const override { return "parenthesized expression"; } - bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; -}; - - /** The SELECT subquery is in parenthesis. */ class ParserSubquery : public IParserBase diff --git a/src/Parsers/ExpressionListParsers.cpp b/src/Parsers/ExpressionListParsers.cpp index 636077ae0c1..e337324df01 100644 --- a/src/Parsers/ExpressionListParsers.cpp +++ b/src/Parsers/ExpressionListParsers.cpp @@ -2158,6 +2158,12 @@ bool ParserIntervalOperatorExpression::parseImpl(Pos & pos, ASTPtr & node, Expec && ParserExpressionImpl().parse(pos, node, expected); } +bool ParserArray::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) +{ + return ParserToken(TokenType::OpeningSquareBracket).ignore(pos, expected) + && ParserExpressionImpl().parse(pos, node, expected); +} + template std::vector> ParserExpressionImpl::operators_table({ {"->", Operator("lambda", 1, 2, OperatorType::Lambda)}, @@ -2362,7 +2368,7 @@ typename ParserExpressionImpl::ParseResult ParserExpressionImpl::try if (ParseDateOperatorExpression(pos, tmp, expected) || ParseTimestampOperatorExpression(pos, tmp, expected) || tuple_literal_parser.parse(pos, tmp, expected) || - (layers.size() == 1 && array_literal_parser.parse(pos, tmp, expected)) || + array_literal_parser.parse(pos, tmp, expected) || number_parser.parse(pos, tmp, expected) || literal_parser.parse(pos, tmp, expected) || asterisk_parser.parse(pos, tmp, expected) || diff --git a/src/Parsers/ExpressionListParsers.h b/src/Parsers/ExpressionListParsers.h index 3ed6055af84..c235739d4ed 100644 --- a/src/Parsers/ExpressionListParsers.h +++ b/src/Parsers/ExpressionListParsers.h @@ -240,6 +240,15 @@ protected: bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; }; +/// TODO: ? +class ParserArray : public IParserBase +{ +protected: + const char * getName() const override { return "array"; } + bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; +}; + + // It's used to parse expressions in table function. class ParserTableFunctionExpression : public IParserBase { diff --git a/tests/queries/0_stateless/00984_parser_stack_overflow.reference b/tests/queries/0_stateless/00984_parser_stack_overflow.reference index 35186521642..0cf6a1f96df 100644 --- a/tests/queries/0_stateless/00984_parser_stack_overflow.reference +++ b/tests/queries/0_stateless/00984_parser_stack_overflow.reference @@ -1,3 +1,4 @@ exceeded +exceeded 20002 1