2010-06-24 19:12:10 +00:00
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <cstdlib>
|
|
|
|
|
|
2011-11-01 17:57:37 +00:00
|
|
|
|
#include <DB/IO/ReadHelpers.h>
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
#include <DB/Parsers/IAST.h>
|
|
|
|
|
#include <DB/Parsers/ASTExpressionList.h>
|
|
|
|
|
#include <DB/Parsers/ASTFunction.h>
|
|
|
|
|
#include <DB/Parsers/ASTIdentifier.h>
|
|
|
|
|
#include <DB/Parsers/ASTLiteral.h>
|
2011-08-28 08:50:27 +00:00
|
|
|
|
#include <DB/Parsers/ASTAsterisk.h>
|
2011-09-04 05:14:52 +00:00
|
|
|
|
#include <DB/Parsers/ASTOrderByElement.h>
|
2012-08-22 18:46:09 +00:00
|
|
|
|
#include <DB/Parsers/ASTSelectQuery.h>
|
|
|
|
|
#include <DB/Parsers/ASTSubquery.h>
|
2016-01-28 01:00:27 +00:00
|
|
|
|
#include <DB/Parsers/ASTWeightedZooKeeperPath.h>
|
2010-06-24 19:12:10 +00:00
|
|
|
|
|
|
|
|
|
#include <DB/Parsers/CommonParsers.h>
|
|
|
|
|
#include <DB/Parsers/ExpressionListParsers.h>
|
2012-08-22 18:46:09 +00:00
|
|
|
|
#include <DB/Parsers/ParserSelectQuery.h>
|
2016-05-03 23:19:14 +00:00
|
|
|
|
#include <DB/Parsers/ParserCase.h>
|
2010-06-24 19:12:10 +00:00
|
|
|
|
|
|
|
|
|
#include <DB/Parsers/ExpressionElementParsers.h>
|
2015-12-24 17:14:10 +00:00
|
|
|
|
#include <DB/Parsers/ParserCreateQuery.h>
|
2010-06-24 19:12:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
2016-01-11 21:46:36 +00:00
|
|
|
|
namespace ErrorCodes
|
|
|
|
|
{
|
|
|
|
|
extern const int SYNTAX_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
bool ParserArray::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
2010-06-24 19:12:10 +00:00
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
ASTPtr contents_node;
|
|
|
|
|
ParserString open("["), close("]");
|
2015-11-08 00:28:12 +00:00
|
|
|
|
ParserExpressionList contents(false);
|
2010-06-24 19:12:10 +00:00
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!open.ignore(pos, end, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!contents.parse(pos, end, contents_node, max_parsed_pos, expected))
|
2014-07-18 19:47:28 +00:00
|
|
|
|
return false;
|
2010-06-24 19:12:10 +00:00
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!close.ignore(pos, end, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
2016-05-28 15:42:22 +00:00
|
|
|
|
auto function_node = std::make_shared<ASTFunction>(StringRange(begin, pos));
|
2010-06-24 19:12:10 +00:00
|
|
|
|
function_node->name = "array";
|
|
|
|
|
function_node->arguments = contents_node;
|
2011-08-13 21:05:18 +00:00
|
|
|
|
function_node->children.push_back(contents_node);
|
2010-06-24 19:12:10 +00:00
|
|
|
|
node = function_node;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
bool ParserParenthesisExpression::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
2010-06-24 19:12:10 +00:00
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
ASTPtr contents_node;
|
|
|
|
|
ParserString open("("), close(")");
|
2015-11-08 00:28:12 +00:00
|
|
|
|
ParserExpressionList contents(false);
|
2010-06-24 19:12:10 +00:00
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!open.ignore(pos, end, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!contents.parse(pos, end, contents_node, max_parsed_pos, expected))
|
2014-07-18 19:47:28 +00:00
|
|
|
|
return false;
|
2010-06-24 19:12:10 +00:00
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!close.ignore(pos, end, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
2014-06-26 00:58:14 +00:00
|
|
|
|
ASTExpressionList & expr_list = typeid_cast<ASTExpressionList &>(*contents_node);
|
2010-06-24 19:12:10 +00:00
|
|
|
|
|
|
|
|
|
/// пустое выражение в скобках недопустимо
|
|
|
|
|
if (expr_list.children.empty())
|
|
|
|
|
{
|
2014-08-04 15:25:38 +00:00
|
|
|
|
expected = "non-empty parenthesized list of expressions";
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (expr_list.children.size() == 1)
|
|
|
|
|
{
|
|
|
|
|
node = expr_list.children.front();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2016-05-28 15:42:22 +00:00
|
|
|
|
auto function_node = std::make_shared<ASTFunction>(StringRange(begin, pos));
|
2010-06-24 19:12:10 +00:00
|
|
|
|
function_node->name = "tuple";
|
|
|
|
|
function_node->arguments = contents_node;
|
2011-08-13 21:05:18 +00:00
|
|
|
|
function_node->children.push_back(contents_node);
|
2010-06-24 19:12:10 +00:00
|
|
|
|
node = function_node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2012-08-22 18:46:09 +00:00
|
|
|
|
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
bool ParserSubquery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
2012-08-22 18:46:09 +00:00
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
ASTPtr select_node;
|
|
|
|
|
ParserString open("("), close(")");
|
|
|
|
|
ParserSelectQuery select;
|
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!open.ignore(pos, end, max_parsed_pos, expected))
|
2012-08-22 18:46:09 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!select.parse(pos, end, select_node, max_parsed_pos, expected))
|
2014-07-18 19:47:28 +00:00
|
|
|
|
return false;
|
2012-08-22 18:46:09 +00:00
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!close.ignore(pos, end, max_parsed_pos, expected))
|
2012-08-22 18:46:09 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
2016-05-28 15:42:22 +00:00
|
|
|
|
node = std::make_shared<ASTSubquery>(StringRange(begin, pos));
|
2014-06-26 00:58:14 +00:00
|
|
|
|
typeid_cast<ASTSubquery &>(*node).children.push_back(select_node);
|
2012-08-22 18:46:09 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
bool ParserIdentifier::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
2010-06-24 19:12:10 +00:00
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
|
2013-07-16 15:26:35 +00:00
|
|
|
|
/// Идентификатор в обратных кавычках
|
|
|
|
|
if (pos != end && *pos == '`')
|
|
|
|
|
{
|
|
|
|
|
ReadBuffer buf(const_cast<char *>(pos), end - pos, 0);
|
|
|
|
|
String s;
|
|
|
|
|
readBackQuotedString(s, buf);
|
2014-09-26 16:10:37 +00:00
|
|
|
|
|
|
|
|
|
if (s.empty()) /// Не разрешены идентификаторы "пустая строка".
|
|
|
|
|
return false;
|
|
|
|
|
|
2013-07-16 15:26:35 +00:00
|
|
|
|
pos += buf.count();
|
2016-05-28 15:42:22 +00:00
|
|
|
|
node = std::make_shared<ASTIdentifier>(StringRange(begin, pos), s);
|
2013-07-16 15:26:35 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
while (pos != end
|
|
|
|
|
&& ((*pos >= 'a' && *pos <= 'z')
|
|
|
|
|
|| (*pos >= 'A' && *pos <= 'Z')
|
|
|
|
|
|| (*pos == '_')
|
|
|
|
|
|| (pos != begin && *pos >= '0' && *pos <= '9')))
|
|
|
|
|
++pos;
|
|
|
|
|
|
|
|
|
|
if (pos != begin)
|
|
|
|
|
{
|
2016-05-28 15:42:22 +00:00
|
|
|
|
node = std::make_shared<ASTIdentifier>(StringRange(begin, pos), String(begin, pos - begin));
|
2013-07-16 15:26:35 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
bool ParserCompoundIdentifier::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
2013-07-16 15:26:35 +00:00
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
|
2015-11-08 01:29:37 +00:00
|
|
|
|
ASTPtr id_list;
|
|
|
|
|
if (!ParserList(ParserPtr(new ParserIdentifier), ParserPtr(new ParserString(".")), false)
|
|
|
|
|
.parse(pos, end, id_list, max_parsed_pos, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
String name;
|
|
|
|
|
const ASTExpressionList & list = static_cast<const ASTExpressionList &>(*id_list.get());
|
|
|
|
|
for (const auto & child : list.children)
|
2010-06-24 19:12:10 +00:00
|
|
|
|
{
|
2015-11-08 01:29:37 +00:00
|
|
|
|
if (!name.empty())
|
|
|
|
|
name += '.';
|
|
|
|
|
name += static_cast<const ASTIdentifier &>(*child.get()).name;
|
2010-06-24 19:12:10 +00:00
|
|
|
|
}
|
2011-11-01 17:57:37 +00:00
|
|
|
|
|
2016-05-28 15:42:22 +00:00
|
|
|
|
node = std::make_shared<ASTIdentifier>(StringRange(begin, pos), name);
|
2015-11-08 01:29:37 +00:00
|
|
|
|
|
|
|
|
|
/// В children запомним идентификаторы-составляющие, если их больше одного.
|
|
|
|
|
if (list.children.size() > 1)
|
|
|
|
|
node->children.insert(node->children.end(), list.children.begin(), list.children.end());
|
|
|
|
|
|
|
|
|
|
return true;
|
2010-06-24 19:12:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
bool ParserFunction::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
2010-06-24 19:12:10 +00:00
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
|
|
|
|
|
ParserIdentifier id_parser;
|
|
|
|
|
ParserString open("("), close(")");
|
2016-07-10 15:52:35 +00:00
|
|
|
|
ParserString distinct("DISTINCT", true, true);
|
2015-11-08 00:28:12 +00:00
|
|
|
|
ParserExpressionList contents(false);
|
2010-06-24 19:12:10 +00:00
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
|
|
|
|
|
2016-07-10 15:52:35 +00:00
|
|
|
|
bool has_distinct_modifier = false;
|
|
|
|
|
|
2012-10-29 02:58:52 +00:00
|
|
|
|
ASTPtr identifier;
|
|
|
|
|
ASTPtr expr_list_args;
|
|
|
|
|
ASTPtr expr_list_params;
|
2010-06-24 19:12:10 +00:00
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!id_parser.parse(pos, end, identifier, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!open.ignore(pos, end, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
2016-07-10 15:52:35 +00:00
|
|
|
|
|
|
|
|
|
if (distinct.ignore(pos, end, max_parsed_pos, expected))
|
|
|
|
|
{
|
|
|
|
|
has_distinct_modifier = true;
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-29 19:09:11 +00:00
|
|
|
|
Pos contents_begin = pos;
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!contents.parse(pos, end, expr_list_args, max_parsed_pos, expected))
|
2014-07-18 19:47:28 +00:00
|
|
|
|
return false;
|
2014-04-29 19:09:11 +00:00
|
|
|
|
Pos contents_end = pos;
|
2010-06-24 19:12:10 +00:00
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!close.ignore(pos, end, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
2014-04-29 19:09:11 +00:00
|
|
|
|
/** Проверка на распространённый случай ошибки - часто из-за сложности квотирования аргументов командной строки,
|
|
|
|
|
* в запрос попадает выражение вида toDate(2014-01-01) вместо toDate('2014-01-01').
|
|
|
|
|
* Если не сообщить, что первый вариант - ошибка, то аргумент будет проинтерпретирован как 2014 - 01 - 01 - некоторое число,
|
|
|
|
|
* и запрос тихо вернёт неожиданный результат.
|
|
|
|
|
*/
|
2014-06-26 00:58:14 +00:00
|
|
|
|
if (typeid_cast<const ASTIdentifier &>(*identifier).name == "toDate"
|
2014-04-29 19:09:11 +00:00
|
|
|
|
&& contents_end - contents_begin == strlen("2014-01-01")
|
|
|
|
|
&& contents_begin[0] >= '2' && contents_begin[0] <= '3'
|
|
|
|
|
&& contents_begin[1] >= '0' && contents_begin[1] <= '9'
|
|
|
|
|
&& contents_begin[2] >= '0' && contents_begin[2] <= '9'
|
|
|
|
|
&& contents_begin[3] >= '0' && contents_begin[3] <= '9'
|
|
|
|
|
&& contents_begin[4] == '-'
|
|
|
|
|
&& contents_begin[5] >= '0' && contents_begin[5] <= '9'
|
|
|
|
|
&& contents_begin[6] >= '0' && contents_begin[6] <= '9'
|
|
|
|
|
&& contents_begin[7] == '-'
|
|
|
|
|
&& contents_begin[8] >= '0' && contents_begin[8] <= '9'
|
|
|
|
|
&& contents_begin[9] >= '0' && contents_begin[9] <= '9')
|
|
|
|
|
{
|
|
|
|
|
std::string contents(contents_begin, contents_end - contents_begin);
|
|
|
|
|
throw Exception("Argument of function toDate is unquoted: toDate(" + contents + "), must be: toDate('" + contents + "')"
|
|
|
|
|
, ErrorCodes::SYNTAX_ERROR);
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-29 02:58:52 +00:00
|
|
|
|
/// У параметрической агрегатной функции - два списка (параметры и аргументы) в круглых скобках. Пример: quantile(0.9)(x).
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (open.ignore(pos, end, max_parsed_pos, expected))
|
2012-10-29 02:58:52 +00:00
|
|
|
|
{
|
2016-07-10 15:52:35 +00:00
|
|
|
|
/// Parametric aggregate functions cannot have DISTINCT in parameters list.
|
|
|
|
|
if (has_distinct_modifier)
|
|
|
|
|
return false;
|
|
|
|
|
|
2012-10-29 02:58:52 +00:00
|
|
|
|
expr_list_params = expr_list_args;
|
2014-04-08 07:31:51 +00:00
|
|
|
|
expr_list_args = nullptr;
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2012-10-29 02:58:52 +00:00
|
|
|
|
ws.ignore(pos, end);
|
2016-07-10 15:52:35 +00:00
|
|
|
|
|
|
|
|
|
if (distinct.ignore(pos, end, max_parsed_pos, expected))
|
|
|
|
|
{
|
|
|
|
|
has_distinct_modifier = true;
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!contents.parse(pos, end, expr_list_args, max_parsed_pos, expected))
|
2014-07-18 19:47:28 +00:00
|
|
|
|
return false;
|
2012-10-29 02:58:52 +00:00
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!close.ignore(pos, end, max_parsed_pos, expected))
|
2012-10-29 02:58:52 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-28 15:42:22 +00:00
|
|
|
|
auto function_node = std::make_shared<ASTFunction>(StringRange(begin, pos));
|
2014-06-26 00:58:14 +00:00
|
|
|
|
function_node->name = typeid_cast<ASTIdentifier &>(*identifier).name;
|
2012-10-29 02:58:52 +00:00
|
|
|
|
|
2016-07-10 15:52:35 +00:00
|
|
|
|
/// func(DISTINCT ...) is equivalent to funcDistinct(...)
|
|
|
|
|
if (has_distinct_modifier)
|
|
|
|
|
function_node->name += "Distinct";
|
|
|
|
|
|
2012-10-29 02:58:52 +00:00
|
|
|
|
function_node->arguments = expr_list_args;
|
|
|
|
|
function_node->children.push_back(function_node->arguments);
|
|
|
|
|
|
2015-12-24 17:14:10 +00:00
|
|
|
|
if (expr_list_params)
|
|
|
|
|
{
|
|
|
|
|
function_node->parameters = expr_list_params;
|
|
|
|
|
function_node->children.push_back(function_node->parameters);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-10 15:52:35 +00:00
|
|
|
|
node = function_node;
|
2015-12-24 17:14:10 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ParserCastExpression::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
|
|
|
|
{
|
|
|
|
|
const auto begin = pos;
|
|
|
|
|
|
|
|
|
|
ParserIdentifier id_parser;
|
|
|
|
|
|
|
|
|
|
ASTPtr identifier;
|
|
|
|
|
|
|
|
|
|
if (!id_parser.parse(pos, end, identifier, max_parsed_pos, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const auto & id = typeid_cast<const ASTIdentifier &>(*identifier).name;
|
|
|
|
|
if (id.length() != strlen(name) || 0 != strcasecmp(id.c_str(), name))
|
2016-05-03 23:19:14 +00:00
|
|
|
|
{
|
|
|
|
|
/// Parse as a CASE expression.
|
|
|
|
|
return ParserCase{}.parse(pos = begin, end, node, max_parsed_pos, expected);
|
|
|
|
|
}
|
2015-12-24 17:14:10 +00:00
|
|
|
|
|
|
|
|
|
/// Parse as CAST(expression AS type)
|
|
|
|
|
ParserString open("("), close(")"), comma(",");
|
|
|
|
|
ParserExpressionInCastExpression expression_and_type(false);
|
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
|
|
|
|
|
|
|
|
|
ASTPtr expr_list_args;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
if (!open.ignore(pos, end, max_parsed_pos, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
const auto contents_begin = pos;
|
|
|
|
|
ASTPtr first_argument;
|
|
|
|
|
if (!expression_and_type.parse(pos, end, first_argument, max_parsed_pos, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
/// check for subsequent comma ","
|
|
|
|
|
if (!comma.ignore(pos, end, max_parsed_pos, expected))
|
2015-12-23 08:11:11 +00:00
|
|
|
|
{
|
2015-12-24 17:14:10 +00:00
|
|
|
|
/// CAST(expression AS type)
|
|
|
|
|
const auto type = first_argument->tryGetAlias();
|
|
|
|
|
if (type.empty())
|
2015-12-23 08:11:11 +00:00
|
|
|
|
{
|
2015-12-24 17:14:10 +00:00
|
|
|
|
/// there is only one argument and it has no alias
|
|
|
|
|
expected = "type identifier";
|
|
|
|
|
return false;
|
2015-12-23 08:11:11 +00:00
|
|
|
|
}
|
2015-12-24 17:14:10 +00:00
|
|
|
|
|
2016-05-28 15:42:22 +00:00
|
|
|
|
expr_list_args = std::make_shared<ASTExpressionList>(StringRange{contents_begin, end});
|
2015-12-24 17:14:10 +00:00
|
|
|
|
first_argument->setAlias({});
|
|
|
|
|
expr_list_args->children.push_back(first_argument);
|
2016-05-28 15:56:51 +00:00
|
|
|
|
expr_list_args->children.emplace_back(std::make_shared<ASTLiteral>(StringRange(), type));
|
2015-12-23 08:11:11 +00:00
|
|
|
|
}
|
2015-12-24 17:14:10 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/// CAST(expression, 'type')
|
|
|
|
|
/// Reparse argument list from scratch
|
|
|
|
|
max_parsed_pos = pos = contents_begin;
|
2015-12-23 08:11:11 +00:00
|
|
|
|
|
2015-12-24 17:14:10 +00:00
|
|
|
|
ParserExpressionWithOptionalAlias expression{false};
|
|
|
|
|
if (!expression.parse(pos, end, first_argument, max_parsed_pos, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end, max_parsed_pos, expected);
|
|
|
|
|
|
|
|
|
|
if (!comma.ignore(pos, end, max_parsed_pos, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end, max_parsed_pos, expected);
|
|
|
|
|
|
|
|
|
|
ParserStringLiteral p_type;
|
|
|
|
|
ASTPtr type_as_literal;
|
|
|
|
|
|
|
|
|
|
if (!p_type.parse(pos, end, type_as_literal, max_parsed_pos, expected))
|
|
|
|
|
{
|
|
|
|
|
expected = "string literal depicting type";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-28 15:42:22 +00:00
|
|
|
|
expr_list_args = std::make_shared<ASTExpressionList>(StringRange{contents_begin, end});
|
2015-12-24 17:14:10 +00:00
|
|
|
|
expr_list_args->children.push_back(first_argument);
|
|
|
|
|
expr_list_args->children.push_back(type_as_literal);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
if (!close.ignore(pos, end, max_parsed_pos, expected))
|
2012-10-29 02:58:52 +00:00
|
|
|
|
{
|
2015-12-24 17:14:10 +00:00
|
|
|
|
expected = ")";
|
|
|
|
|
return false;
|
2012-10-29 02:58:52 +00:00
|
|
|
|
}
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2016-05-28 15:42:22 +00:00
|
|
|
|
const auto function_node = std::make_shared<ASTFunction>(StringRange(begin, pos));
|
2015-12-24 17:14:10 +00:00
|
|
|
|
ASTPtr node_holder{function_node};
|
|
|
|
|
function_node->name = name;
|
|
|
|
|
|
|
|
|
|
function_node->arguments = expr_list_args;
|
|
|
|
|
function_node->children.push_back(function_node->arguments);
|
|
|
|
|
|
|
|
|
|
node = node_holder;
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
bool ParserNull::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
2010-06-24 19:12:10 +00:00
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
2010-06-25 16:36:13 +00:00
|
|
|
|
ParserString nested_parser("NULL", true);
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (nested_parser.parse(pos, end, node, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
{
|
2016-05-28 15:42:22 +00:00
|
|
|
|
node = std::make_shared<ASTLiteral>(StringRange(StringRange(begin, pos)), Null());
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
bool ParserNumber::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
2010-06-24 19:12:10 +00:00
|
|
|
|
{
|
|
|
|
|
Field res;
|
|
|
|
|
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
if (pos == end)
|
|
|
|
|
return false;
|
|
|
|
|
|
2016-06-20 21:22:46 +00:00
|
|
|
|
/** Maximum length of number. 319 symbols is enough to write maximum double in decimal form.
|
|
|
|
|
* Copy is needed to use strto* functions, which require 0-terminated string.
|
2014-04-04 02:32:35 +00:00
|
|
|
|
*/
|
|
|
|
|
char buf[320];
|
|
|
|
|
|
|
|
|
|
size_t bytes_to_copy = end - pos < 319 ? end - pos : 319;
|
|
|
|
|
memcpy(buf, pos, bytes_to_copy);
|
|
|
|
|
buf[bytes_to_copy] = 0;
|
|
|
|
|
|
|
|
|
|
char * pos_double = buf;
|
2016-06-20 21:22:46 +00:00
|
|
|
|
errno = 0; /// Functions strto* don't clear errno.
|
2014-04-04 02:32:35 +00:00
|
|
|
|
Float64 float_value = std::strtod(buf, &pos_double);
|
|
|
|
|
if (pos_double == buf || errno == ERANGE)
|
2010-06-24 19:12:10 +00:00
|
|
|
|
{
|
2014-04-04 02:32:35 +00:00
|
|
|
|
expected = "number";
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-06-20 21:22:46 +00:00
|
|
|
|
|
|
|
|
|
/// excessive "word" symbols after number
|
|
|
|
|
if (pos_double < buf + bytes_to_copy
|
|
|
|
|
&& ((*pos_double >= 'a' && *pos_double <= 'z')
|
|
|
|
|
|| (*pos_double >= 'A' && *pos_double <= 'Z')
|
|
|
|
|
|| (*pos_double == '_')
|
|
|
|
|
|| (*pos_double >= '0' && *pos_double <= '9')))
|
|
|
|
|
{
|
|
|
|
|
expected = "number";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
res = float_value;
|
|
|
|
|
|
2016-06-20 21:22:46 +00:00
|
|
|
|
/// try to use more exact type: UInt64 or Int64
|
2010-06-24 19:12:10 +00:00
|
|
|
|
|
2014-04-04 02:32:35 +00:00
|
|
|
|
char * pos_integer = buf;
|
2010-06-24 19:12:10 +00:00
|
|
|
|
if (float_value < 0)
|
|
|
|
|
{
|
2012-12-15 04:26:48 +00:00
|
|
|
|
errno = 0;
|
2014-04-04 02:32:35 +00:00
|
|
|
|
Int64 int_value = std::strtoll(buf, &pos_integer, 0);
|
|
|
|
|
if (pos_integer == pos_double && errno != ERANGE)
|
2010-06-24 19:12:10 +00:00
|
|
|
|
res = int_value;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2012-12-15 04:26:48 +00:00
|
|
|
|
errno = 0;
|
2014-04-04 02:32:35 +00:00
|
|
|
|
UInt64 uint_value = std::strtoull(buf, &pos_integer, 0);
|
|
|
|
|
if (pos_integer == pos_double && errno != ERANGE)
|
2010-06-24 19:12:10 +00:00
|
|
|
|
res = uint_value;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-04 02:32:35 +00:00
|
|
|
|
pos += pos_double - buf;
|
2016-05-28 15:42:22 +00:00
|
|
|
|
node = std::make_shared<ASTLiteral>(StringRange(begin, pos), res);
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-11-07 23:18:39 +00:00
|
|
|
|
bool ParserUnsignedInteger::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
|
|
|
|
{
|
|
|
|
|
Field res;
|
|
|
|
|
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
if (pos == end)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
UInt64 x = 0;
|
|
|
|
|
ReadBuffer in(const_cast<char *>(pos), end - pos, 0);
|
2015-12-21 16:59:21 +00:00
|
|
|
|
if (!tryReadIntText(x, in) || in.count() == 0)
|
2015-11-07 23:18:39 +00:00
|
|
|
|
{
|
|
|
|
|
expected = "unsigned integer";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res = x;
|
2015-12-21 16:59:21 +00:00
|
|
|
|
pos += in.count();
|
2016-05-28 15:42:22 +00:00
|
|
|
|
node = std::make_shared<ASTLiteral>(StringRange(begin, pos), res);
|
2015-11-07 23:18:39 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
bool ParserStringLiteral::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
2010-06-24 19:12:10 +00:00
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
String s;
|
|
|
|
|
|
|
|
|
|
if (pos == end || *pos != '\'')
|
|
|
|
|
{
|
|
|
|
|
expected = "opening single quote";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-25 03:11:17 +00:00
|
|
|
|
ReadBuffer in(const_cast<char *>(pos), end - pos, 0);
|
2010-06-25 16:36:13 +00:00
|
|
|
|
|
2015-11-25 03:11:17 +00:00
|
|
|
|
try
|
2010-06-24 19:12:10 +00:00
|
|
|
|
{
|
2015-11-25 03:11:17 +00:00
|
|
|
|
readQuotedString(s, in);
|
|
|
|
|
}
|
|
|
|
|
catch (const Exception & e)
|
|
|
|
|
{
|
|
|
|
|
expected = "string literal";
|
|
|
|
|
return false;
|
2010-06-24 19:12:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-11-25 03:11:17 +00:00
|
|
|
|
pos += in.count();
|
2016-05-28 15:42:22 +00:00
|
|
|
|
node = std::make_shared<ASTLiteral>(StringRange(begin, pos), s);
|
2015-11-25 03:11:17 +00:00
|
|
|
|
return true;
|
2010-06-24 19:12:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-06-29 04:54:52 +00:00
|
|
|
|
bool ParserArrayOfLiterals::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
Array arr;
|
|
|
|
|
|
|
|
|
|
if (pos == end || *pos != '[')
|
|
|
|
|
{
|
|
|
|
|
expected = "opening square bracket";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
|
|
|
|
ParserLiteral literal_p;
|
|
|
|
|
|
|
|
|
|
++pos;
|
|
|
|
|
|
|
|
|
|
while (pos != end)
|
|
|
|
|
{
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
if (!arr.empty())
|
|
|
|
|
{
|
|
|
|
|
if (*pos == ']')
|
|
|
|
|
{
|
|
|
|
|
++pos;
|
2016-05-28 15:42:22 +00:00
|
|
|
|
node = std::make_shared<ASTLiteral>(StringRange(begin, pos), arr);
|
2015-06-29 04:54:52 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (*pos == ',')
|
|
|
|
|
{
|
|
|
|
|
++pos;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
expected = "comma or closing square bracket";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
ASTPtr literal_node;
|
|
|
|
|
if (!literal_p.parse(pos, end, literal_node, max_parsed_pos, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
arr.push_back(typeid_cast<const ASTLiteral &>(*literal_node).value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expected = "closing square bracket";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
bool ParserLiteral::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
2010-06-24 19:12:10 +00:00
|
|
|
|
{
|
|
|
|
|
ParserNull null_p;
|
|
|
|
|
ParserNumber num_p;
|
|
|
|
|
ParserStringLiteral str_p;
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (null_p.parse(pos, end, node, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (num_p.parse(pos, end, node, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (str_p.parse(pos, end, node, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
2015-11-07 23:18:39 +00:00
|
|
|
|
expected = "literal: one of NULL, number, single quoted string";
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-12-24 17:14:10 +00:00
|
|
|
|
const char * ParserAliasBase::restricted_keywords[] =
|
2015-11-08 00:28:12 +00:00
|
|
|
|
{
|
|
|
|
|
"FROM",
|
2015-11-08 23:14:24 +00:00
|
|
|
|
"FINAL",
|
|
|
|
|
"SAMPLE",
|
2015-11-08 17:37:15 +00:00
|
|
|
|
"ARRAY",
|
2015-11-08 01:33:33 +00:00
|
|
|
|
"LEFT",
|
|
|
|
|
"RIGHT",
|
|
|
|
|
"INNER",
|
2015-11-08 23:14:24 +00:00
|
|
|
|
"FULL",
|
2015-11-08 01:33:33 +00:00
|
|
|
|
"CROSS",
|
|
|
|
|
"JOIN",
|
2015-11-23 21:34:36 +00:00
|
|
|
|
"GLOBAL",
|
2015-11-08 02:07:13 +00:00
|
|
|
|
"ANY",
|
|
|
|
|
"ALL",
|
2015-11-08 01:33:33 +00:00
|
|
|
|
"ON",
|
|
|
|
|
"USING",
|
2015-11-08 23:23:31 +00:00
|
|
|
|
"PREWHERE",
|
2015-11-08 00:28:12 +00:00
|
|
|
|
"WHERE",
|
|
|
|
|
"GROUP",
|
|
|
|
|
"WITH",
|
|
|
|
|
"HAVING",
|
|
|
|
|
"ORDER",
|
|
|
|
|
"LIMIT",
|
|
|
|
|
"SETTINGS",
|
|
|
|
|
"FORMAT",
|
|
|
|
|
"UNION",
|
|
|
|
|
nullptr
|
|
|
|
|
};
|
|
|
|
|
|
2015-12-24 17:14:10 +00:00
|
|
|
|
template <typename ParserIdentifier>
|
|
|
|
|
bool ParserAliasImpl<ParserIdentifier>::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
2011-11-06 04:21:09 +00:00
|
|
|
|
{
|
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
|
|
|
|
ParserString s_as("AS", true, true);
|
|
|
|
|
ParserIdentifier id_p;
|
|
|
|
|
|
2015-11-08 23:52:40 +00:00
|
|
|
|
bool has_as_word = s_as.parse(pos, end, node, max_parsed_pos, expected);
|
|
|
|
|
if (!allow_alias_without_as_keyword && !has_as_word)
|
2011-11-06 04:21:09 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!id_p.parse(pos, end, node, max_parsed_pos, expected))
|
2011-11-06 04:21:09 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
2015-11-08 23:52:40 +00:00
|
|
|
|
if (!has_as_word)
|
2015-11-08 00:28:12 +00:00
|
|
|
|
{
|
|
|
|
|
/** В этом случае алиас не может совпадать с ключевым словом - для того,
|
|
|
|
|
* чтобы в запросе "SELECT x FROM t", слово FROM не считалось алиасом,
|
|
|
|
|
* а в запросе "SELECT x FRO FROM t", слово FRO считалось алиасом.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
const String & name = static_cast<const ASTIdentifier &>(*node.get()).name;
|
|
|
|
|
|
|
|
|
|
for (const char ** keyword = restricted_keywords; *keyword != nullptr; ++keyword)
|
|
|
|
|
if (0 == strcasecmp(name.data(), *keyword))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-06 04:21:09 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-24 17:14:10 +00:00
|
|
|
|
template class ParserAliasImpl<ParserIdentifier>;
|
|
|
|
|
template class ParserAliasImpl<ParserTypeInCastExpression>;
|
|
|
|
|
|
2011-11-06 04:21:09 +00:00
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
bool ParserExpressionElement::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
2010-06-24 19:12:10 +00:00
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
|
|
|
|
|
ParserParenthesisExpression paren_p;
|
2012-08-22 18:46:09 +00:00
|
|
|
|
ParserSubquery subquery_p;
|
2010-06-24 19:12:10 +00:00
|
|
|
|
ParserArray array_p;
|
2015-06-29 04:54:52 +00:00
|
|
|
|
ParserArrayOfLiterals array_lite_p;
|
2010-06-24 19:12:10 +00:00
|
|
|
|
ParserLiteral lit_p;
|
2015-12-24 17:14:10 +00:00
|
|
|
|
ParserCastExpression fun_p;
|
2013-07-16 15:26:35 +00:00
|
|
|
|
ParserCompoundIdentifier id_p;
|
2011-08-28 08:50:27 +00:00
|
|
|
|
ParserString asterisk_p("*");
|
2010-06-24 19:12:10 +00:00
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (subquery_p.parse(pos, end, node, max_parsed_pos, expected))
|
2012-08-22 18:46:09 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (paren_p.parse(pos, end, node, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
2015-06-29 04:54:52 +00:00
|
|
|
|
if (array_lite_p.parse(pos, end, node, max_parsed_pos, expected))
|
|
|
|
|
return true;
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (array_p.parse(pos, end, node, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (lit_p.parse(pos, end, node, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (fun_p.parse(pos, end, node, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (id_p.parse(pos, end, node, max_parsed_pos, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (asterisk_p.parse(pos, end, node, max_parsed_pos, expected))
|
2011-08-28 08:50:27 +00:00
|
|
|
|
{
|
2016-05-28 15:42:22 +00:00
|
|
|
|
node = std::make_shared<ASTAsterisk>(StringRange(begin, pos));
|
2011-08-28 08:50:27 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-24 17:14:10 +00:00
|
|
|
|
if (!expected)
|
|
|
|
|
expected = "expression element: one of array, literal, function, identifier, asterisk, parenthesised expression, subquery";
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-12-24 17:14:10 +00:00
|
|
|
|
template <typename ParserAlias>
|
|
|
|
|
bool ParserWithOptionalAliasImpl<ParserAlias>::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
2011-11-06 04:21:09 +00:00
|
|
|
|
{
|
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!elem_parser->parse(pos, end, node, max_parsed_pos, expected))
|
2011-11-06 04:21:09 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
2015-11-11 00:20:22 +00:00
|
|
|
|
/** Маленький хак.
|
|
|
|
|
*
|
|
|
|
|
* В секции SELECT мы разрешаем парсить алиасы без указания ключевого слова AS.
|
|
|
|
|
* Эти алиасы не могут совпадать с ключевыми словами запроса.
|
|
|
|
|
* А само выражение может быть идентификатором, совпадающем с ключевым словом.
|
|
|
|
|
* Например, столбец может называться where. И в запросе может быть написано SELECT where AS x FROM table или даже SELECT where x FROM table.
|
|
|
|
|
* Даже может быть написано SELECT where AS from FROM table, но не может быть написано SELECT where from FROM table.
|
|
|
|
|
* Смотрите подробнее в реализации ParserAlias.
|
|
|
|
|
*
|
|
|
|
|
* Но возникает небольшая проблема - неудобное сообщение об ошибке, если в секции SELECT в конце есть лишняя запятая.
|
|
|
|
|
* Хотя такая ошибка очень распространена. Пример: SELECT x, y, z, FROM tbl
|
|
|
|
|
* Если ничего не предпринять, то это парсится как выбор столбца с именем FROM и алиасом tbl.
|
|
|
|
|
* Чтобы избежать такой ситуации, мы не разрешаем парсить алиас без ключевого слова AS для идентификатора с именем FROM.
|
|
|
|
|
*
|
|
|
|
|
* Замечание: это также фильтрует случай, когда идентификатор квотирован.
|
|
|
|
|
* Пример: SELECT x, y, z, `FROM` tbl. Но такой случай можно было бы разрешить.
|
|
|
|
|
*
|
|
|
|
|
* В дальнейшем было бы проще запретить неквотированные идентификаторы, совпадающие с ключевыми словами.
|
|
|
|
|
*/
|
|
|
|
|
bool allow_alias_without_as_keyword_now = allow_alias_without_as_keyword;
|
|
|
|
|
if (allow_alias_without_as_keyword)
|
|
|
|
|
if (const ASTIdentifier * id = typeid_cast<const ASTIdentifier *>(node.get()))
|
|
|
|
|
if (0 == strcasecmp(id->name.data(), "FROM"))
|
|
|
|
|
allow_alias_without_as_keyword_now = false;
|
|
|
|
|
|
2011-11-06 04:21:09 +00:00
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
ASTPtr alias_node;
|
2015-11-11 00:20:22 +00:00
|
|
|
|
if (ParserAlias(allow_alias_without_as_keyword_now).parse(pos, end, alias_node, max_parsed_pos, expected))
|
2011-11-06 04:21:09 +00:00
|
|
|
|
{
|
2014-06-26 00:58:14 +00:00
|
|
|
|
String alias_name = typeid_cast<ASTIdentifier &>(*alias_node).name;
|
|
|
|
|
|
2015-07-26 08:16:39 +00:00
|
|
|
|
if (ASTWithAlias * ast_with_alias = dynamic_cast<ASTWithAlias *>(node.get()))
|
|
|
|
|
ast_with_alias->alias = alias_name;
|
2011-11-06 04:21:09 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
expected = "alias cannot be here";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-24 17:14:10 +00:00
|
|
|
|
template class ParserWithOptionalAliasImpl<ParserAlias>;
|
|
|
|
|
template class ParserWithOptionalAliasImpl<ParserCastExpressionAlias>;
|
|
|
|
|
|
2011-11-06 04:21:09 +00:00
|
|
|
|
|
2015-04-11 03:10:23 +00:00
|
|
|
|
bool ParserOrderByElement::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
2011-09-04 05:14:52 +00:00
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
|
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
2015-11-08 00:28:12 +00:00
|
|
|
|
ParserExpressionWithOptionalAlias elem_p(false);
|
2011-09-04 05:14:52 +00:00
|
|
|
|
ParserString ascending("ASCENDING", true, true);
|
|
|
|
|
ParserString descending("DESCENDING", true, true);
|
|
|
|
|
ParserString asc("ASC", true, true);
|
|
|
|
|
ParserString desc("DESC", true, true);
|
2013-05-28 16:56:05 +00:00
|
|
|
|
ParserString collate("COLLATE", true, true);
|
|
|
|
|
ParserStringLiteral collate_locale_parser;
|
2011-09-04 05:14:52 +00:00
|
|
|
|
|
|
|
|
|
ASTPtr expr_elem;
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!elem_p.parse(pos, end, expr_elem, max_parsed_pos, expected))
|
2011-09-04 05:14:52 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
int direction = 1;
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
if (descending.ignore(pos, end) || desc.ignore(pos, end))
|
|
|
|
|
direction = -1;
|
|
|
|
|
else
|
|
|
|
|
ascending.ignore(pos, end) || asc.ignore(pos, end);
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2013-05-29 11:33:55 +00:00
|
|
|
|
ws.ignore(pos, end);
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2016-05-28 14:14:18 +00:00
|
|
|
|
std::shared_ptr<Collator> collator;
|
2013-05-28 16:56:05 +00:00
|
|
|
|
if (collate.ignore(pos, end))
|
|
|
|
|
{
|
2013-05-29 11:33:55 +00:00
|
|
|
|
ws.ignore(pos, end);
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2013-05-28 16:56:05 +00:00
|
|
|
|
ASTPtr locale_node;
|
2015-04-11 03:10:23 +00:00
|
|
|
|
if (!collate_locale_parser.parse(pos, end, locale_node, max_parsed_pos, expected))
|
2013-05-28 16:56:05 +00:00
|
|
|
|
return false;
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
|
|
|
|
const String & locale = typeid_cast<const ASTLiteral &>(*locale_node).value.safeGet<String>();
|
2016-05-28 14:14:18 +00:00
|
|
|
|
collator = std::make_shared<Collator>(locale);
|
2013-05-28 16:56:05 +00:00
|
|
|
|
}
|
2011-09-04 05:14:52 +00:00
|
|
|
|
|
2016-05-28 15:42:22 +00:00
|
|
|
|
node = std::make_shared<ASTOrderByElement>(StringRange(begin, pos), direction, collator);
|
2011-09-04 05:14:52 +00:00
|
|
|
|
node->children.push_back(expr_elem);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-28 01:00:27 +00:00
|
|
|
|
bool ParserWeightedZooKeeperPath::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected)
|
|
|
|
|
{
|
|
|
|
|
ParserString s_weight("WEIGHT", true, true);
|
|
|
|
|
ParserStringLiteral path_p;
|
|
|
|
|
ParserUnsignedInteger weight_p;
|
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
|
|
|
|
|
2016-05-28 15:42:22 +00:00
|
|
|
|
auto weighted_zookeeper_path = std::make_shared<ASTWeightedZooKeeperPath>();
|
2016-01-28 01:00:27 +00:00
|
|
|
|
node = weighted_zookeeper_path;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
ASTPtr path_node;
|
|
|
|
|
if (!path_p.parse(pos, end, path_node, max_parsed_pos, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
weighted_zookeeper_path->path = typeid_cast<const ASTLiteral &>(*path_node).value.get<const String &>();
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
bool is_weight_set = false;
|
|
|
|
|
|
|
|
|
|
if (s_weight.ignore(pos, end, max_parsed_pos, expected))
|
|
|
|
|
{
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
ASTPtr weight_node;
|
|
|
|
|
if (weight_p.parse(pos, end, weight_node, max_parsed_pos, expected))
|
|
|
|
|
{
|
|
|
|
|
is_weight_set = true;
|
|
|
|
|
weighted_zookeeper_path->weight = typeid_cast<const ASTLiteral &>(*weight_node).value.get<const UInt64 &>();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!is_weight_set)
|
|
|
|
|
weighted_zookeeper_path->weight = 1;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2011-09-04 05:14:52 +00:00
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
}
|
|
|
|
|
|