diff --git a/src/Parsers/ExpressionElementParsers.cpp b/src/Parsers/ExpressionElementParsers.cpp index 5e2dd8e5c58..3c1c9fd1b2f 100644 --- a/src/Parsers/ExpressionElementParsers.cpp +++ b/src/Parsers/ExpressionElementParsers.cpp @@ -754,7 +754,10 @@ bool ParserFunction::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) has_all = true; if (has_all && has_distinct) + { + pos.noBacktrackOnFailure(); return false; + } if (has_all || has_distinct) { @@ -772,11 +775,17 @@ bool ParserFunction::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) const char * contents_begin = pos->begin; if (!contents.parse(pos, expr_list_args, expected)) + { + pos.noBacktrackOnFailure(); return false; + } const char * contents_end = pos->begin; if (pos->type != TokenType::ClosingRoundBracket) + { + pos.noBacktrackOnFailure(); return false; + } ++pos; /** Check for a common error case - often due to the complexity of quoting command-line arguments, @@ -809,7 +818,10 @@ bool ParserFunction::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) /// Parametric aggregate functions cannot have DISTINCT in parameters list. if (has_distinct) + { + pos.noBacktrackOnFailure(); return false; + } expr_list_params = expr_list_args; expr_list_args = nullptr; @@ -827,7 +839,10 @@ bool ParserFunction::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) has_all = true; if (has_all && has_distinct) + { + pos.noBacktrackOnFailure(); return false; + } if (has_all || has_distinct) { @@ -841,10 +856,16 @@ bool ParserFunction::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) } if (!contents.parse(pos, expr_list_args, expected)) + { + pos.noBacktrackOnFailure(); return false; + } if (pos->type != TokenType::ClosingRoundBracket) + { + pos.noBacktrackOnFailure(); return false; + } ++pos; } @@ -878,6 +899,7 @@ bool ParserFunction::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) ParserFilterClause filter_parser; if (!filter_parser.parse(pos, function_node_as_iast, expected)) { + pos.noBacktrackOnFailure(); return false; } } @@ -891,6 +913,7 @@ bool ParserFunction::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) ParserWindowReference window_reference; if (!window_reference.parse(pos, function_node_as_iast, expected)) { + pos.noBacktrackOnFailure(); return false; } } diff --git a/src/Parsers/IParser.h b/src/Parsers/IParser.h index 64f117c707f..3fd0d1c6fea 100644 --- a/src/Parsers/IParser.h +++ b/src/Parsers/IParser.h @@ -59,6 +59,7 @@ public: { uint32_t depth = 0; uint32_t max_depth = 0; + bool no_backtrack_on_failure = false; Pos(Tokens & tokens_, uint32_t max_depth_) : TokenIterator(tokens_), max_depth(max_depth_) {} @@ -77,6 +78,11 @@ public: throw Exception("Logical error in parser: incorrect calculation of parse depth", ErrorCodes::LOGICAL_ERROR); --depth; } + + void noBacktrackOnFailure() + { + no_backtrack_on_failure = true; + } }; /** Get the text of this parser parses. */ diff --git a/src/Parsers/IParserBase.cpp b/src/Parsers/IParserBase.cpp index 0241250926d..21bacebb98b 100644 --- a/src/Parsers/IParserBase.cpp +++ b/src/Parsers/IParserBase.cpp @@ -6,6 +6,9 @@ namespace DB bool IParserBase::parse(Pos & pos, ASTPtr & node, Expected & expected) { + if (pos.no_backtrack_on_failure) + return false; + expected.add(pos, getName()); return wrapParseImpl(pos, IncreaseDepthTag{}, [&] diff --git a/src/Parsers/IParserBase.h b/src/Parsers/IParserBase.h index ce08bdef790..90789dc3a9c 100644 --- a/src/Parsers/IParserBase.h +++ b/src/Parsers/IParserBase.h @@ -16,7 +16,7 @@ public: { Pos begin = pos; bool res = func(); - if (!res) + if (!res && !pos.no_backtrack_on_failure) pos = begin; return res; } @@ -30,7 +30,7 @@ public: pos.increaseDepth(); bool res = func(); pos.decreaseDepth(); - if (!res) + if (!res && !pos.no_backtrack_on_failure) pos = begin; return res; }