Introduce DATE_ADD/DATE_SUB/TIMESTAMP_ADD/TIMESTAMP_SUB #3705

This commit is contained in:
Ivan Blinkov 2018-12-19 14:37:14 +03:00
parent f88b497555
commit 0352c5a57c
6 changed files with 105 additions and 31 deletions

View File

@ -66,6 +66,31 @@ public:
ParserInterval() : interval_kind(IntervalKind::Incorrect) {}
const char * getToIntervalKindFunctionName()
{
switch (interval_kind)
{
case ParserInterval::IntervalKind::Second:
return "toIntervalSecond";
case ParserInterval::IntervalKind::Minute:
return "toIntervalMinute";
case ParserInterval::IntervalKind::Hour:
return "toIntervalHour";
case ParserInterval::IntervalKind::Day:
return "toIntervalDay";
case ParserInterval::IntervalKind::Week:
return "toIntervalWeek";
case ParserInterval::IntervalKind::Month:
return "toIntervalMonth";
case ParserInterval::IntervalKind::Quarter:
return "toIntervalQuarter";
case ParserInterval::IntervalKind::Year:
return "toIntervalYear";
default:
return nullptr;
}
}
protected:
const char * getName() const override { return "interval"; }

View File

@ -714,13 +714,78 @@ bool ParserExtractExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & exp
return true;
}
bool ParserDateAddExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
const char * function_name = nullptr;
ASTPtr left_node;
ASTPtr right_node;
if (ParserKeyword("DATEADD").ignore(pos, expected) || ParserKeyword("DATE_ADD").ignore(pos, expected)
|| ParserKeyword("TIMESTAMPADD").ignore(pos, expected) || ParserKeyword("TIMESTAMP_ADD").ignore(pos, expected))
function_name = "plus";
else if (ParserKeyword("DATESUB").ignore(pos, expected) || ParserKeyword("DATE_SUB").ignore(pos, expected)
|| ParserKeyword("TIMESTAMPSUB").ignore(pos, expected) || ParserKeyword("TIMESTAMP_SUB").ignore(pos, expected))
function_name = "minus";
else
return false;
if (pos->type != TokenType::OpeningRoundBracket)
return false;
++pos;
ParserInterval interval_parser;
if (!interval_parser.ignore(pos, expected))
return false;
const char * interval_function_name = interval_parser.getToIntervalKindFunctionName();
if (pos->type != TokenType::Comma)
return false;
++pos;
if (!ParserExpression().parse(pos, left_node, expected))
return false;
if (pos->type != TokenType::Comma)
return false;
++pos;
if (!ParserExpression().parse(pos, right_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 = {left_node};
auto interval_func_node = std::make_shared<ASTFunction>();
interval_func_node->name = interval_function_name;
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 = {right_node, interval_func_node};
auto func_node = std::make_shared<ASTFunction>();
func_node->name = function_name;
func_node->arguments = std::move(expr_list_args);
func_node->children.push_back(func_node->arguments);
node = std::move(func_node);
return true;
}
bool ParserDateDiffExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
const char * interval_name = nullptr;
ASTPtr left_node;
ASTPtr right_node;
if (!(ParserKeyword("DATEDIFF").ignore(pos, expected) || ParserKeyword("DATE_DIFF").ignore(pos, expected)))
if (!(ParserKeyword("DATEDIFF").ignore(pos, expected) || ParserKeyword("DATE_DIFF").ignore(pos, expected)
|| ParserKeyword("TIMESTAMPDIFF").ignore(pos, expected) || ParserKeyword("TIMESTAMP_DIFF").ignore(pos, expected)))
return false;
if (pos->type != TokenType::OpeningRoundBracket)
@ -1093,6 +1158,7 @@ bool ParserExpressionElement::parseImpl(Pos & pos, ASTPtr & node, Expected & exp
|| ParserLiteral().parse(pos, node, expected)
|| ParserCastExpression().parse(pos, node, expected)
|| ParserExtractExpression().parse(pos, node, expected)
|| ParserDateAddExpression().parse(pos, node, expected)
|| ParserDateDiffExpression().parse(pos, node, expected)
|| ParserSubstringExpression().parse(pos, node, expected)
|| ParserTrimExpression().parse(pos, node, expected)

View File

@ -131,6 +131,13 @@ protected:
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
class ParserDateAddExpression : public IParserBase
{
protected:
const char * getName() const override { return "DATE_ADD expression"; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
class ParserDateDiffExpression : public IParserBase
{
protected:

View File

@ -607,41 +607,13 @@ bool ParserIntervalOperatorExpression::parseImpl(Pos & pos, ASTPtr & node, Expec
if (!ParserExpressionWithOptionalAlias(false).parse(pos, expr, expected))
return false;
const char * function_name = nullptr;
ParserInterval interval_parser;
if (!interval_parser.ignore(pos, expected))
return false;
switch (interval_parser.interval_kind)
{
case ParserInterval::IntervalKind::Second:
function_name = "toIntervalSecond";
break;
case ParserInterval::IntervalKind::Minute:
function_name = "toIntervalMinute";
break;
case ParserInterval::IntervalKind::Hour:
function_name = "toIntervalHour";
break;
case ParserInterval::IntervalKind::Day:
function_name = "toIntervalDay";
break;
case ParserInterval::IntervalKind::Week:
function_name = "toIntervalWeek";
break;
case ParserInterval::IntervalKind::Month:
function_name = "toIntervalMonth";
break;
case ParserInterval::IntervalKind::Quarter:
function_name = "toIntervalQuarter";
break;
case ParserInterval::IntervalKind::Year:
function_name = "toIntervalYear";
break;
default:
return false;
}
const char * function_name = interval_parser.getToIntervalKindFunctionName();
/// the function corresponding to the operator
auto function = std::make_shared<ASTFunction>();

View File

@ -23,3 +23,5 @@ fooabbafoo
foo*
-11
-3
2021-01-01
2018-07-18 01:02:03

View File

@ -25,3 +25,5 @@ select TRIM(both 'ab' FROM 'abbafooabbafooabba');
select trim(LEADING '*[]{}|\\' FROM '\\|[[[}}}*foo*');
select DATE_DIFF(MONTH, toDate('2018-12-18'), toDate('2018-01-01'));
select DATE_DIFF(QQ, toDate('2018-12-18'), toDate('2018-01-01'));
select DATE_ADD(YEAR, 3, toDate('2018-01-01'));
select timestamp_sub(SQL_TSI_MONTH, 5, toDateTime('2018-12-18 01:02:03'));