Merge pull request #15978 from ucasFL/interval-op

INTERVAL operator support string literal
This commit is contained in:
Alexander Kuzmenkov 2020-10-23 14:44:05 +03:00 committed by GitHub
commit 28c9e66dc1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 106 additions and 23 deletions

View File

@ -789,6 +789,7 @@ bool ParserDateAddExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & exp
++pos;
IntervalKind interval_kind;
ASTPtr interval_func_node;
if (parseIntervalKind(pos, expected, interval_kind))
{
/// function(unit, offset, timestamp)
@ -805,6 +806,13 @@ bool ParserDateAddExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & exp
if (!ParserExpression().parse(pos, timestamp_node, expected))
return false;
auto interval_expr_list_args = std::make_shared<ASTExpressionList>();
interval_expr_list_args->children = {offset_node};
interval_func_node = std::make_shared<ASTFunction>();
interval_func_node->as<ASTFunction &>().name = interval_kind.toNameOfFunctionToIntervalDataType();
interval_func_node->as<ASTFunction &>().arguments = std::move(interval_expr_list_args);
interval_func_node->as<ASTFunction &>().children.push_back(interval_func_node->as<ASTFunction &>().arguments);
}
else
{
@ -816,27 +824,13 @@ bool ParserDateAddExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & exp
return false;
++pos;
if (!ParserKeyword("INTERVAL").ignore(pos, expected))
return false;
if (!ParserExpression().parse(pos, offset_node, expected))
return false;
if (!parseIntervalKind(pos, expected, interval_kind))
if (!ParserIntervalOperatorExpression{}.parse(pos, interval_func_node, expected))
return false;
}
if (pos->type != TokenType::ClosingRoundBracket)
return false;
++pos;
auto interval_expr_list_args = std::make_shared<ASTExpressionList>();
interval_expr_list_args->children = {offset_node};
auto interval_func_node = std::make_shared<ASTFunction>();
interval_func_node->name = interval_kind.toNameOfFunctionToIntervalDataType();
interval_func_node->arguments = std::move(interval_expr_list_args);
interval_func_node->children.push_back(interval_func_node->arguments);
auto expr_list_args = std::make_shared<ASTExpressionList>();
expr_list_args->children = {timestamp_node, interval_func_node};

View File

@ -645,6 +645,47 @@ bool ParserTimestampOperatorExpression::parseImpl(Pos & pos, ASTPtr & node, Expe
return true;
}
bool ParserIntervalOperatorExpression::parseArgumentAndIntervalKind(
Pos & pos, ASTPtr & expr, IntervalKind & interval_kind, Expected & expected)
{
auto begin = pos;
auto init_expected = expected;
ASTPtr string_literal;
//// A String literal followed INTERVAL keyword,
/// the literal can be a part of an expression or
/// include Number and INTERVAL TYPE at the same time
if (ParserStringLiteral{}.parse(pos, string_literal, expected))
{
String literal;
if (string_literal->as<ASTLiteral &>().value.tryGet(literal))
{
Tokens tokens(literal.data(), literal.data() + literal.size());
Pos token_pos(tokens, 0);
Expected token_expected;
if (!ParserNumber{}.parse(token_pos, expr, token_expected))
return false;
else
{
/// case: INTERVAL '1' HOUR
/// back to begin
if (!token_pos.isValid())
{
pos = begin;
expected = init_expected;
}
else
/// case: INTERVAL '1 HOUR'
return parseIntervalKind(token_pos, token_expected, interval_kind);
}
}
}
// case: INTERVAL expr HOUR
if (!ParserExpressionWithOptionalAlias(false).parse(pos, expr, expected))
return false;
return parseIntervalKind(pos, expected, interval_kind);
}
bool ParserIntervalOperatorExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
auto begin = pos;
@ -654,15 +695,8 @@ bool ParserIntervalOperatorExpression::parseImpl(Pos & pos, ASTPtr & node, Expec
return next_parser.parse(pos, node, expected);
ASTPtr expr;
/// Any expression can be inside, because operator surrounds it.
if (!ParserExpressionWithOptionalAlias(false).parse(pos, expr, expected))
{
pos = begin;
return next_parser.parse(pos, node, expected);
}
IntervalKind interval_kind;
if (!parseIntervalKind(pos, expected, interval_kind))
if (!parseArgumentAndIntervalKind(pos, expr, interval_kind, expected))
{
pos = begin;
return next_parser.parse(pos, node, expected);
@ -729,3 +763,4 @@ bool ParserKeyValuePairsList::parseImpl(Pos & pos, ASTPtr & node, Expected & exp
}
}

View File

@ -5,6 +5,7 @@
#include <Parsers/IParserBase.h>
#include <Parsers/CommonParsers.h>
#include <Common/IntervalKind.h>
namespace DB
{
@ -232,6 +233,9 @@ protected:
const char * getName() const override { return "INTERVAL operator expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
private:
static bool parseArgumentAndIntervalKind(Pos & pos, ASTPtr & expr, IntervalKind & interval_kind, Expected & expected);
};
class ParserAdditiveExpression : public IParserBase

View File

@ -0,0 +1,25 @@
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2009-02-14 00:31:30
2009-02-14 00:31:30
2009-02-14 00:31:30
2009-02-15 23:31:30
2009-02-15 23:31:30
2009-02-15 23:31:30

View File

@ -0,0 +1,25 @@
SELECT INTERVAL 2 year;
SELECT INTERVAL '2' year;
SELECT INTERVAL '2 year';
SELECT INTERVAL 2 month;
SELECT INTERVAL '2' month;
SELECT INTERVAL '2 month';
SELECT INTERVAL 2 week;
SELECT INTERVAL '2' week;
SELECT INTERVAL '2 week';
SELECT INTERVAL 2 day;
SELECT INTERVAL '2' day;
SELECT INTERVAL '2 day';
SELECT INTERVAL 2 hour;
SELECT INTERVAL '2' hour;
SELECT INTERVAL '2 hour';
SELECT INTERVAL 2 minute;
SELECT INTERVAL '2' minute;
SELECT INTERVAL '2 minute';
SELECT INTERVAL '2' AS n minute;
SELECT DATE_ADD(hour, '1', toDateTime(1234567890, 'UTC'));
SELECT DATE_ADD(hour, 1, toDateTime(1234567890, 'UTC'));
SELECT DATE_ADD(hour, (SELECT 1), toDateTime(1234567890, 'UTC'));
SELECT DATE_ADD(toDateTime(1234567890, 'UTC'), INTERVAL 2 day);
SELECT DATE_ADD(toDateTime(1234567890, 'UTC'), INTERVAL '2 day');
SELECT DATE_ADD(toDateTime(1234567890, 'UTC'), INTERVAL '2' day);