diff --git a/dbms/src/Parsers/ASTSelectQuery.cpp b/dbms/src/Parsers/ASTSelectQuery.cpp index da7277abee1..2218ef0e797 100644 --- a/dbms/src/Parsers/ASTSelectQuery.cpp +++ b/dbms/src/Parsers/ASTSelectQuery.cpp @@ -143,6 +143,8 @@ void ASTSelectQuery::formatImpl(const FormatSettings & s, FormatState & state, F s.ostr << ", "; } limitLength()->formatImpl(s, state, frame); + if (limit_with_ties) + s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << " WITH TIES" << (s.hilite ? hilite_none : ""); } if (settings()) diff --git a/dbms/src/Parsers/ASTSelectQuery.h b/dbms/src/Parsers/ASTSelectQuery.h index 374933a1d57..f2577fa3264 100644 --- a/dbms/src/Parsers/ASTSelectQuery.h +++ b/dbms/src/Parsers/ASTSelectQuery.h @@ -41,6 +41,7 @@ public: bool group_by_with_totals = false; bool group_by_with_rollup = false; bool group_by_with_cube = false; + bool limit_with_ties = false; ASTPtr & refSelect() { return getExpression(Expression::SELECT); } ASTPtr & refTables() { return getExpression(Expression::TABLES); } diff --git a/dbms/src/Parsers/ParserSelectQuery.cpp b/dbms/src/Parsers/ParserSelectQuery.cpp index c521ba4ec40..f991cb17eac 100644 --- a/dbms/src/Parsers/ParserSelectQuery.cpp +++ b/dbms/src/Parsers/ParserSelectQuery.cpp @@ -41,6 +41,7 @@ bool ParserSelectQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) ParserKeyword s_rollup("ROLLUP"); ParserKeyword s_cube("CUBE"); ParserKeyword s_top("TOP"); + ParserKeyword s_with_ties("WITH TIES"); ParserKeyword s_offset("OFFSET"); ParserNotEmptyExpressionList exp_list(false); @@ -75,7 +76,7 @@ bool ParserSelectQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) } } - /// SELECT [DISTINCT] [TOP N] expr list + /// SELECT [DISTINCT] [TOP N [WITH TIES]] expr list { if (!s_select.ignore(pos, expected)) return false; @@ -99,6 +100,9 @@ bool ParserSelectQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) if (!num.parse(pos, limit_length, expected)) return false; } + + if (s_with_ties.ignore(pos, expected)) + select_query->limit_with_ties = true; } if (!exp_list_for_select_clause.parse(pos, select_expression_list, expected)) @@ -180,7 +184,7 @@ bool ParserSelectQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) return false; } - /// LIMIT length | LIMIT offset, length | LIMIT count BY expr-list + /// LIMIT length [WITH TIES] | LIMIT offset, length [WITH TIES] | LIMIT count BY expr-list if (s_limit.ignore(pos, expected)) { if (limit_length) @@ -196,7 +200,12 @@ bool ParserSelectQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) limit_offset = limit_length; if (!exp_elem.parse(pos, limit_length, expected)) return false; + + if (s_with_ties.ignore(pos, expected)) + select_query->limit_with_ties = true; } + else if (s_with_ties.ignore(pos, expected)) + select_query->limit_with_ties = true; else if (s_by.ignore(pos, expected)) { limit_by_value = limit_length; @@ -212,7 +221,7 @@ bool ParserSelectQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) } } - /// LIMIT length | LIMIT offset, length + /// LIMIT length [WITH TIES] | LIMIT offset, length [WITH TIES] if (s_limit.ignore(pos, expected)) { if (!limit_by_value || limit_length) @@ -229,8 +238,15 @@ bool ParserSelectQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) if (!exp_elem.parse(pos, limit_length, expected)) return false; } + + if (s_with_ties.ignore(pos, expected)) + select_query->limit_with_ties = true; } + // WITH TIES was used without ORDER BY + if (!order_expression_list && select_query->limit_with_ties) + return false; + /// SETTINGS key1 = value1, key2 = value2, ... if (s_settings.ignore(pos, expected)) {