Support SUBSTRING(expr FROM start FOR length)

This commit is contained in:
Ivan Blinkov 2018-12-10 15:54:02 +03:00
parent fb2c8c854c
commit 6a90abc543
4 changed files with 83 additions and 1 deletions

View File

@ -317,6 +317,76 @@ bool ParserCastExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expect
return false;
}
bool ParserSubstringExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
/// Either SUBSTRING(expr FROM start) or SUBSTRING(expr FROM start FOR length) or SUBSTRING(expr, start, length)
/// The latter will be parsed normally as a function later.
ASTPtr expr_node;
ASTPtr start_node;
ASTPtr length_node;
if (!ParserKeyword("SUBSTRING").ignore(pos, expected))
return false;
if (pos->type != TokenType::OpeningRoundBracket)
return false;
++pos;
if (!ParserExpression().parse(pos, expr_node, expected))
return false;
if (pos->type != TokenType::Comma)
{
if (!ParserKeyword("FROM").ignore(pos, expected))
return false;
}
else
{
++pos;
}
if (!ParserExpression().parse(pos, start_node, expected))
return false;
if (pos->type == TokenType::ClosingRoundBracket)
{
++pos;
}
else
{
if (pos->type != TokenType::Comma)
{
if (!ParserKeyword("FOR").ignore(pos, expected))
return false;
}
else
{
++pos;
}
if (!ParserExpression().parse(pos, length_node, expected))
return false;
ParserToken(TokenType::ClosingRoundBracket).ignore(pos, expected);
}
/// Convert to canonical representation in functional form: SUBSTRING(expr, start, length)
auto expr_list_args = std::make_shared<ASTExpressionList>();
expr_list_args->children = {expr_node, start_node};
if (length_node)
expr_list_args->children.push_back(length_node);
auto func_node = std::make_shared<ASTFunction>();
func_node->name = "substring";
func_node->arguments = std::move(expr_list_args);
func_node->children.push_back(func_node->arguments);
node = std::move(func_node);
return true;
}
bool ParserExtractExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
@ -678,8 +748,9 @@ bool ParserExpressionElement::parseImpl(Pos & pos, ASTPtr & node, Expected & exp
|| ParserArrayOfLiterals().parse(pos, node, expected)
|| ParserArray().parse(pos, node, expected)
|| ParserLiteral().parse(pos, node, expected)
|| ParserExtractExpression().parse(pos, node, expected)
|| ParserCastExpression().parse(pos, node, expected)
|| ParserExtractExpression().parse(pos, node, expected)
|| ParserSubstringExpression().parse(pos, node, expected)
|| ParserCase().parse(pos, node, expected)
|| ParserFunction().parse(pos, node, expected)
|| ParserQualifiedAsterisk().parse(pos, node, expected)

View File

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

View File

@ -10,3 +10,5 @@ select SUBSTRING('foo', 1, 2);
select Substr('foo', 2);
select mid('foo', 3);
select IF(3>2, 1, 0);
select substring('foo' from 1 + 1);
select SUBSTRING('foo' FROM 2 FOR 1);