ClickHouse/dbms/src/Parsers/ExpressionListParsers.cpp

627 lines
16 KiB
C++

#include <Parsers/IAST.h>
#include <Parsers/ASTExpressionList.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/CommonParsers.h>
#include <Parsers/ExpressionElementParsers.h>
#include <Parsers/ExpressionListParsers.h>
#include <Parsers/ParserCreateQuery.h>
#include <Common/typeid_cast.h>
#include <Common/StringUtils/StringUtils.h>
namespace DB
{
const char * ParserMultiplicativeExpression::operators[] =
{
"*", "multiply",
"/", "divide",
"%", "modulo",
nullptr
};
const char * ParserUnaryMinusExpression::operators[] =
{
"-", "negate",
nullptr
};
const char * ParserAdditiveExpression::operators[] =
{
"+", "plus",
"-", "minus",
nullptr
};
const char * ParserComparisonExpression::operators[] =
{
"==", "equals",
"!=", "notEquals",
"<>", "notEquals",
"<=", "lessOrEquals",
">=", "greaterOrEquals",
"<", "less",
">", "greater",
"=", "equals",
"LIKE", "like",
"NOT LIKE", "notLike",
"IN", "in",
"NOT IN", "notIn",
"GLOBAL IN", "globalIn",
"GLOBAL NOT IN", "globalNotIn",
nullptr
};
const char * ParserLogicalNotExpression::operators[] =
{
"NOT", "not",
nullptr
};
const char * ParserArrayElementExpression::operators[] =
{
"[", "arrayElement",
nullptr
};
const char * ParserTupleElementExpression::operators[] =
{
".", "tupleElement",
nullptr
};
bool ParserList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
bool first = true;
auto list = std::make_shared<ASTExpressionList>();
node = list;
while (true)
{
if (first)
{
ASTPtr elem;
if (!elem_parser->parse(pos, elem, expected))
break;
list->children.push_back(elem);
first = false;
}
else
{
auto prev_pos = pos;
if (!separator_parser->ignore(pos, expected))
break;
ASTPtr elem;
if (!elem_parser->parse(pos, elem, expected))
{
pos = prev_pos;
break;
}
list->children.push_back(elem);
}
}
if (!allow_empty && first)
return false;
return true;
}
static bool parseOperator(IParser::Pos & pos, const char * op, Expected & expected)
{
if (isWordCharASCII(*op))
{
return ParserKeyword(op).ignore(pos, expected);
}
else
{
if (strlen(op) == pos->size() && 0 == memcmp(op, pos->begin, pos->size()))
{
++pos;
return true;
}
return false;
}
}
bool ParserLeftAssociativeBinaryOperatorList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
bool first = true;
while (1)
{
if (first)
{
ASTPtr elem;
if (!first_elem_parser->parse(pos, elem, expected))
return false;
node = elem;
first = false;
}
else
{
/// try to find any of the valid operators
const char ** it;
for (it = operators; *it; it += 2)
if (parseOperator(pos, *it, expected))
break;
if (!*it)
break;
/// the function corresponding to the operator
auto function = std::make_shared<ASTFunction>();
/// function arguments
auto exp_list = std::make_shared<ASTExpressionList>();
ASTPtr elem;
if (!(remaining_elem_parser ? remaining_elem_parser : first_elem_parser)->parse(pos, elem, expected))
return false;
/// the first argument of the function is the previous element, the second is the next one
function->name = it[1];
function->arguments = exp_list;
function->children.push_back(exp_list);
exp_list->children.push_back(node);
exp_list->children.push_back(elem);
/** special exception for the access operator to the element of the array `x[y]`, which
* contains the infix part '[' and the suffix ''] '(specified as' [')
*/
if (0 == strcmp(it[0], "["))
{
if (pos->type != TokenType::ClosingSquareBracket)
return false;
++pos;
}
node = function;
}
}
return true;
}
bool ParserVariableArityOperatorList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
ASTPtr arguments;
if (!elem_parser->parse(pos, node, expected))
return false;
while (true)
{
if (!parseOperator(pos, infix, expected))
break;
if (!arguments)
{
node = makeASTFunction(function_name, node);
arguments = node->as<ASTFunction &>().arguments;
}
ASTPtr elem;
if (!elem_parser->parse(pos, elem, expected))
return false;
arguments->children.push_back(elem);
}
return true;
}
bool ParserBetweenExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
/// For the expression (subject [NOT] BETWEEN left AND right)
/// create an AST the same as for (subject> = left AND subject <= right).
ParserKeyword s_not("NOT");
ParserKeyword s_between("BETWEEN");
ParserKeyword s_and("AND");
ASTPtr subject;
ASTPtr left;
ASTPtr right;
if (!elem_parser.parse(pos, subject, expected))
return false;
bool negative = s_not.ignore(pos, expected);
if (!s_between.ignore(pos, expected))
{
if (negative)
--pos;
/// No operator was parsed, just return element.
node = subject;
}
else
{
if (!elem_parser.parse(pos, left, expected))
return false;
if (!s_and.ignore(pos, expected))
return false;
if (!elem_parser.parse(pos, right, expected))
return false;
auto f_combined_expression = std::make_shared<ASTFunction>();
auto args_combined_expression = std::make_shared<ASTExpressionList>();
/// [NOT] BETWEEN left AND right
auto f_left_expr = std::make_shared<ASTFunction>();
auto args_left_expr = std::make_shared<ASTExpressionList>();
auto f_right_expr = std::make_shared<ASTFunction>();
auto args_right_expr = std::make_shared<ASTExpressionList>();
args_left_expr->children.emplace_back(subject);
args_left_expr->children.emplace_back(left);
args_right_expr->children.emplace_back(subject);
args_right_expr->children.emplace_back(right);
if (negative)
{
/// NOT BETWEEN
f_left_expr->name = "less";
f_right_expr->name = "greater";
f_combined_expression->name = "or";
}
else
{
/// BETWEEN
f_left_expr->name = "greaterOrEquals";
f_right_expr->name = "lessOrEquals";
f_combined_expression->name = "and";
}
f_left_expr->arguments = args_left_expr;
f_left_expr->children.emplace_back(f_left_expr->arguments);
f_right_expr->arguments = args_right_expr;
f_right_expr->children.emplace_back(f_right_expr->arguments);
args_combined_expression->children.emplace_back(f_left_expr);
args_combined_expression->children.emplace_back(f_right_expr);
f_combined_expression->arguments = args_combined_expression;
f_combined_expression->children.emplace_back(f_combined_expression->arguments);
node = f_combined_expression;
}
return true;
}
bool ParserTernaryOperatorExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
ParserToken symbol1(TokenType::QuestionMark);
ParserToken symbol2(TokenType::Colon);
ASTPtr elem_cond;
ASTPtr elem_then;
ASTPtr elem_else;
if (!elem_parser.parse(pos, elem_cond, expected))
return false;
if (!symbol1.ignore(pos, expected))
node = elem_cond;
else
{
if (!elem_parser.parse(pos, elem_then, expected))
return false;
if (!symbol2.ignore(pos, expected))
return false;
if (!elem_parser.parse(pos, elem_else, expected))
return false;
/// the function corresponding to the operator
auto function = std::make_shared<ASTFunction>();
/// function arguments
auto exp_list = std::make_shared<ASTExpressionList>();
function->name = "if";
function->arguments = exp_list;
function->children.push_back(exp_list);
exp_list->children.push_back(elem_cond);
exp_list->children.push_back(elem_then);
exp_list->children.push_back(elem_else);
node = function;
}
return true;
}
bool ParserLambdaExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
ParserToken arrow(TokenType::Arrow);
ParserToken open(TokenType::OpeningRoundBracket);
ParserToken close(TokenType::ClosingRoundBracket);
Pos begin = pos;
do
{
ASTPtr inner_arguments;
ASTPtr expression;
bool was_open = false;
if (open.ignore(pos, expected))
{
was_open = true;
}
if (!ParserList(std::make_unique<ParserIdentifier>(), std::make_unique<ParserToken>(TokenType::Comma)).parse(pos, inner_arguments, expected))
break;
if (was_open)
{
if (!close.ignore(pos, expected))
break;
}
if (!arrow.ignore(pos, expected))
break;
if (!elem_parser.parse(pos, expression, expected))
return false;
/// lambda(tuple(inner_arguments), expression)
auto lambda = std::make_shared<ASTFunction>();
node = lambda;
lambda->name = "lambda";
auto outer_arguments = std::make_shared<ASTExpressionList>();
lambda->arguments = outer_arguments;
lambda->children.push_back(lambda->arguments);
auto tuple = std::make_shared<ASTFunction>();
outer_arguments->children.push_back(tuple);
tuple->name = "tuple";
tuple->arguments = inner_arguments;
tuple->children.push_back(inner_arguments);
outer_arguments->children.push_back(expression);
return true;
}
while (false);
pos = begin;
return elem_parser.parse(pos, node, expected);
}
bool ParserPrefixUnaryOperatorExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
/// try to find any of the valid operators
const char ** it;
for (it = operators; *it; it += 2)
{
if (parseOperator(pos, *it, expected))
break;
}
/// Let's parse chains of the form `NOT NOT x`. This is hack.
/** This is done, because among the unary operators there is only a minus and NOT.
* But for a minus the chain of unary operators does not need to be supported.
*/
if (it[0] && 0 == strncmp(it[0], "NOT", 3))
{
/// Was there an even number of NOTs.
bool even = false;
const char ** jt;
while (true)
{
for (jt = operators; *jt; jt += 2)
if (parseOperator(pos, *jt, expected))
break;
if (!*jt)
break;
even = !even;
}
if (even)
it = jt; /// Zero the result of parsing the first NOT. It turns out, as if there is no `NOT` chain at all.
}
ASTPtr elem;
if (!elem_parser->parse(pos, elem, expected))
return false;
if (!*it)
node = elem;
else
{
/// the function corresponding to the operator
auto function = std::make_shared<ASTFunction>();
/// function arguments
auto exp_list = std::make_shared<ASTExpressionList>();
function->name = it[1];
function->arguments = exp_list;
function->children.push_back(exp_list);
exp_list->children.push_back(elem);
node = function;
}
return true;
}
bool ParserUnaryMinusExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
/// As an exception, negative numbers should be parsed as literals, and not as an application of the operator.
if (pos->type == TokenType::Minus)
{
ParserLiteral lit_p;
Pos begin = pos;
if (lit_p.parse(pos, node, expected))
return true;
pos = begin;
}
return operator_parser.parse(pos, node, expected);
}
bool ParserArrayElementExpression::parseImpl(Pos & pos, ASTPtr & node, Expected &expected)
{
return ParserLeftAssociativeBinaryOperatorList{
operators,
std::make_unique<ParserExpressionElement>(),
std::make_unique<ParserExpressionWithOptionalAlias>(false)
}.parse(pos, node, expected);
}
bool ParserTupleElementExpression::parseImpl(Pos & pos, ASTPtr & node, Expected &expected)
{
return ParserLeftAssociativeBinaryOperatorList{
operators,
std::make_unique<ParserArrayElementExpression>(),
std::make_unique<ParserUnsignedInteger>()
}.parse(pos, node, expected);
}
ParserExpressionWithOptionalAlias::ParserExpressionWithOptionalAlias(bool allow_alias_without_as_keyword, bool prefer_alias_to_column_name)
: impl(std::make_unique<ParserWithOptionalAlias>(std::make_unique<ParserExpression>(),
allow_alias_without_as_keyword, prefer_alias_to_column_name))
{
}
bool ParserExpressionList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
return ParserList(
std::make_unique<ParserExpressionWithOptionalAlias>(allow_alias_without_as_keyword, prefer_alias_to_column_name),
std::make_unique<ParserToken>(TokenType::Comma))
.parse(pos, node, expected);
}
bool ParserNotEmptyExpressionList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
return nested_parser.parse(pos, node, expected) && !node->children.empty();
}
bool ParserOrderByExpressionList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
return ParserList(std::make_unique<ParserOrderByElement>(), std::make_unique<ParserToken>(TokenType::Comma), false)
.parse(pos, node, expected);
}
bool ParserNullityChecking::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
ASTPtr node_comp;
if (!ParserComparisonExpression{}.parse(pos, node_comp, expected))
return false;
ParserKeyword s_is{"IS"};
ParserKeyword s_not{"NOT"};
ParserKeyword s_null{"NULL"};
if (s_is.ignore(pos, expected))
{
bool is_not = false;
if (s_not.ignore(pos, expected))
is_not = true;
if (!s_null.ignore(pos, expected))
return false;
auto args = std::make_shared<ASTExpressionList>();
args->children.push_back(node_comp);
auto function = std::make_shared<ASTFunction>();
function->name = is_not ? "isNotNull" : "isNull";
function->arguments = args;
function->children.push_back(function->arguments);
node = function;
}
else
node = node_comp;
return true;
}
bool ParserIntervalOperatorExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
/// If no INTERVAL keyword, go to nested parser.
if (!ParserKeyword("INTERVAL").ignore(pos, expected))
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))
return false;
ParserInterval interval_parser;
if (!interval_parser.ignore(pos, expected))
return false;
const char * function_name = interval_parser.getToIntervalKindFunctionName();
/// the function corresponding to the operator
auto function = std::make_shared<ASTFunction>();
/// function arguments
auto exp_list = std::make_shared<ASTExpressionList>();
/// the first argument of the function is the previous element, the second is the next one
function->name = function_name;
function->arguments = exp_list;
function->children.push_back(exp_list);
exp_list->children.push_back(expr);
node = function;
return true;
}
}