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>
|
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>
|
2010-06-24 19:12:10 +00:00
|
|
|
|
|
|
|
|
|
#include <DB/Parsers/ExpressionElementParsers.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ParserArray::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
ASTPtr contents_node;
|
|
|
|
|
ParserString open("["), close("]");
|
|
|
|
|
ParserExpressionList contents;
|
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
|
|
|
|
|
|
|
|
|
if (!open.ignore(pos, end, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
contents.parse(pos, end, contents_node, expected);
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
if (!close.ignore(pos, end, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ASTFunction * function_node = new ASTFunction(StringRange(begin, pos));
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ParserParenthesisExpression::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
ASTPtr contents_node;
|
|
|
|
|
ParserString open("("), close(")");
|
|
|
|
|
ParserExpressionList contents;
|
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
|
|
|
|
|
|
|
|
|
if (!open.ignore(pos, end, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
contents.parse(pos, end, contents_node, expected);
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
if (!close.ignore(pos, end, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
2010-06-25 19:55:19 +00:00
|
|
|
|
ASTExpressionList & expr_list = dynamic_cast<ASTExpressionList &>(*contents_node);
|
2010-06-24 19:12:10 +00:00
|
|
|
|
|
|
|
|
|
/// пустое выражение в скобках недопустимо
|
|
|
|
|
if (expr_list.children.empty())
|
|
|
|
|
{
|
|
|
|
|
expected = "not empty list of expressions in parenthesis";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (expr_list.children.size() == 1)
|
|
|
|
|
{
|
|
|
|
|
node = expr_list.children.front();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ASTFunction * function_node = new ASTFunction(StringRange(begin, pos));
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ParserSubquery::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
ASTPtr select_node;
|
|
|
|
|
ParserString open("("), close(")");
|
|
|
|
|
ParserSelectQuery select;
|
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
|
|
|
|
|
|
|
|
|
if (!open.ignore(pos, end, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
select.parse(pos, end, select_node, expected);
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
if (!close.ignore(pos, end, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
node = new ASTSubquery(StringRange(begin, pos));
|
|
|
|
|
dynamic_cast<ASTSubquery &>(*node).children.push_back(select_node);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2010-06-24 19:12:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ParserIdentifier::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
pos += buf.count();
|
|
|
|
|
node = new ASTIdentifier(StringRange(begin, pos), s);
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
node = new ASTIdentifier(StringRange(begin, pos), String(begin, pos - begin));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ParserCompoundIdentifier::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
|
2011-11-01 17:57:37 +00:00
|
|
|
|
/// Идентификатор в обратных кавычках
|
|
|
|
|
if (pos != end && *pos == '`')
|
2010-06-24 19:12:10 +00:00
|
|
|
|
{
|
2011-11-01 17:57:37 +00:00
|
|
|
|
ReadBuffer buf(const_cast<char *>(pos), end - pos, 0);
|
|
|
|
|
String s;
|
|
|
|
|
readBackQuotedString(s, buf);
|
|
|
|
|
pos += buf.count();
|
|
|
|
|
node = new ASTIdentifier(StringRange(begin, pos), s);
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
2011-11-01 17:57:37 +00:00
|
|
|
|
{
|
2013-07-16 15:10:37 +00:00
|
|
|
|
while (pos != end)
|
|
|
|
|
{
|
|
|
|
|
while (pos != end
|
|
|
|
|
&& ((*pos >= 'a' && *pos <= 'z')
|
|
|
|
|
|| (*pos >= 'A' && *pos <= 'Z')
|
|
|
|
|
|| (*pos == '_')
|
|
|
|
|
|| (pos != begin && *pos >= '0' && *pos <= '9')))
|
|
|
|
|
++pos;
|
|
|
|
|
|
|
|
|
|
/// Если следующий символ - точка '.' и за ней следует, не цифра,
|
|
|
|
|
/// то продолжаем парсинг имени идентификатора
|
|
|
|
|
if (pos != begin && pos + 1 < end && *pos == '.' &&
|
|
|
|
|
!(*(pos + 1) >= '0' && *(pos + 1) <= '9'))
|
|
|
|
|
++pos;
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-11-01 17:57:37 +00:00
|
|
|
|
|
|
|
|
|
if (pos != begin)
|
|
|
|
|
{
|
|
|
|
|
node = new ASTIdentifier(StringRange(begin, pos), String(begin, pos - begin));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2010-06-24 19:12:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ParserFunction::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
|
|
|
|
|
ParserIdentifier id_parser;
|
|
|
|
|
ParserString open("("), close(")");
|
|
|
|
|
ParserExpressionList contents;
|
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
|
|
|
|
|
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
|
|
|
|
|
2010-06-25 16:36:13 +00:00
|
|
|
|
if (!id_parser.parse(pos, end, identifier, expected))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
if (!open.ignore(pos, end, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
2012-10-29 02:58:52 +00:00
|
|
|
|
contents.parse(pos, end, expr_list_args, expected);
|
2010-06-24 19:12:10 +00:00
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
if (!close.ignore(pos, end, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
2012-10-29 02:58:52 +00:00
|
|
|
|
/// У параметрической агрегатной функции - два списка (параметры и аргументы) в круглых скобках. Пример: quantile(0.9)(x).
|
|
|
|
|
if (open.ignore(pos, end, expected))
|
|
|
|
|
{
|
|
|
|
|
expr_list_params = expr_list_args;
|
|
|
|
|
expr_list_args = NULL;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
contents.parse(pos, end, expr_list_args, expected);
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
if (!close.ignore(pos, end, expected))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
ASTFunction * function_node = new ASTFunction(StringRange(begin, pos));
|
2010-06-25 16:36:13 +00:00
|
|
|
|
function_node->name = dynamic_cast<ASTIdentifier &>(*identifier).name;
|
2012-10-29 02:58:52 +00:00
|
|
|
|
|
|
|
|
|
function_node->arguments = expr_list_args;
|
|
|
|
|
function_node->children.push_back(function_node->arguments);
|
|
|
|
|
|
|
|
|
|
if (expr_list_params)
|
|
|
|
|
{
|
|
|
|
|
function_node->parameters = expr_list_params;
|
|
|
|
|
function_node->children.push_back(function_node->parameters);
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
node = function_node;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ParserNull::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
2010-06-25 16:36:13 +00:00
|
|
|
|
ParserString nested_parser("NULL", true);
|
2010-06-24 19:12:10 +00:00
|
|
|
|
if (nested_parser.parse(pos, end, node, expected))
|
|
|
|
|
{
|
|
|
|
|
node = new ASTLiteral(StringRange(StringRange(begin, pos)), Null());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ParserNumber::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
|
|
|
|
Field res;
|
|
|
|
|
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
if (pos == end)
|
|
|
|
|
return false;
|
|
|
|
|
|
2012-12-15 04:26:48 +00:00
|
|
|
|
errno = 0; /// Функции strto* не очищают errno.
|
2010-06-24 19:12:10 +00:00
|
|
|
|
Float64 float_value = std::strtod(pos, const_cast<char**>(&pos));
|
|
|
|
|
if (pos == begin || errno == ERANGE)
|
|
|
|
|
{
|
|
|
|
|
expected = "number (this cause range error)";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
res = float_value;
|
|
|
|
|
|
|
|
|
|
/// попробуем использовать более точный тип - UInt64 или Int64
|
|
|
|
|
|
|
|
|
|
Pos pos_integer = begin;
|
|
|
|
|
if (float_value < 0)
|
|
|
|
|
{
|
2012-12-15 04:26:48 +00:00
|
|
|
|
errno = 0;
|
2010-06-24 19:12:10 +00:00
|
|
|
|
Int64 int_value = std::strtoll(pos_integer, const_cast<char**>(&pos_integer), 0);
|
|
|
|
|
if (pos_integer == pos && errno != ERANGE)
|
|
|
|
|
res = int_value;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2012-12-15 04:26:48 +00:00
|
|
|
|
errno = 0;
|
2010-06-24 19:12:10 +00:00
|
|
|
|
UInt64 uint_value = std::strtoull(pos_integer, const_cast<char**>(&pos_integer), 0);
|
|
|
|
|
if (pos_integer == pos && errno != ERANGE)
|
|
|
|
|
res = uint_value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
node = new ASTLiteral(StringRange(begin, pos), res);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ParserStringLiteral::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
String s;
|
|
|
|
|
|
|
|
|
|
if (pos == end || *pos != '\'')
|
|
|
|
|
{
|
|
|
|
|
expected = "opening single quote";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-25 16:36:13 +00:00
|
|
|
|
++pos;
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
while (pos != end)
|
|
|
|
|
{
|
|
|
|
|
size_t bytes = 0;
|
|
|
|
|
for (; pos + bytes != end; ++bytes)
|
|
|
|
|
if (pos[bytes] == '\\' || pos[bytes] == '\'')
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
s.append(pos, bytes);
|
|
|
|
|
pos += bytes;
|
|
|
|
|
|
|
|
|
|
if (*pos == '\'')
|
|
|
|
|
{
|
|
|
|
|
++pos;
|
|
|
|
|
node = new ASTLiteral(StringRange(begin, pos), s);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*pos == '\\')
|
|
|
|
|
{
|
|
|
|
|
++pos;
|
|
|
|
|
if (pos == end)
|
|
|
|
|
{
|
|
|
|
|
expected = "escape sequence";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
s += parseEscapeSequence(*pos);
|
|
|
|
|
++pos;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expected = "closing single quote";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ParserLiteral::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
|
|
|
|
|
ParserNull null_p;
|
|
|
|
|
ParserNumber num_p;
|
|
|
|
|
ParserStringLiteral str_p;
|
|
|
|
|
|
|
|
|
|
if (null_p.parse(pos, end, node, expected))
|
|
|
|
|
return true;
|
|
|
|
|
pos = begin;
|
|
|
|
|
|
|
|
|
|
if (num_p.parse(pos, end, node, expected))
|
|
|
|
|
return true;
|
|
|
|
|
pos = begin;
|
|
|
|
|
|
|
|
|
|
if (str_p.parse(pos, end, node, expected))
|
|
|
|
|
return true;
|
|
|
|
|
pos = begin;
|
|
|
|
|
|
|
|
|
|
expected = "literal: one of NULL, number, single quoted string";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-11-06 04:21:09 +00:00
|
|
|
|
bool ParserAlias::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
|
|
|
|
ParserString s_as("AS", true, true);
|
|
|
|
|
ParserIdentifier id_p;
|
|
|
|
|
|
|
|
|
|
if (!s_as.parse(pos, end, node, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
if (!id_p.parse(pos, end, node, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
bool ParserExpressionElement::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
ParserLiteral lit_p;
|
|
|
|
|
ParserFunction 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
|
|
|
|
|
2012-08-22 18:46:09 +00:00
|
|
|
|
if (subquery_p.parse(pos, end, node, expected))
|
|
|
|
|
return true;
|
|
|
|
|
pos = begin;
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
if (paren_p.parse(pos, end, node, expected))
|
|
|
|
|
return true;
|
|
|
|
|
pos = begin;
|
|
|
|
|
|
|
|
|
|
if (array_p.parse(pos, end, node, expected))
|
|
|
|
|
return true;
|
|
|
|
|
pos = begin;
|
|
|
|
|
|
|
|
|
|
if (lit_p.parse(pos, end, node, expected))
|
|
|
|
|
return true;
|
|
|
|
|
pos = begin;
|
|
|
|
|
|
|
|
|
|
if (fun_p.parse(pos, end, node, expected))
|
|
|
|
|
return true;
|
|
|
|
|
pos = begin;
|
|
|
|
|
|
|
|
|
|
if (id_p.parse(pos, end, node, expected))
|
|
|
|
|
return true;
|
|
|
|
|
pos = begin;
|
|
|
|
|
|
2011-08-28 08:50:27 +00:00
|
|
|
|
if (asterisk_p.parse(pos, end, node, expected))
|
|
|
|
|
{
|
|
|
|
|
node = new ASTAsterisk(StringRange(begin, pos));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
pos = begin;
|
|
|
|
|
|
2012-08-22 18:46:09 +00:00
|
|
|
|
expected = "expression element: one of array, literal, function, identifier, asterisk, parenthised expression, subquery";
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-11-06 20:47:07 +00:00
|
|
|
|
bool ParserWithOptionalAlias::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
2011-11-06 04:21:09 +00:00
|
|
|
|
{
|
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
|
|
|
|
ParserAlias alias_p;
|
|
|
|
|
|
2011-11-06 20:47:07 +00:00
|
|
|
|
if (!elem_parser->parse(pos, end, node, expected))
|
2011-11-06 04:21:09 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
|
|
|
|
ASTPtr alias_node;
|
|
|
|
|
if (alias_p.parse(pos, end, alias_node, expected))
|
|
|
|
|
{
|
|
|
|
|
String alias_name = dynamic_cast<ASTIdentifier &>(*alias_node).name;
|
|
|
|
|
|
|
|
|
|
if (ASTFunction * func = dynamic_cast<ASTFunction *>(&*node))
|
|
|
|
|
func->alias = alias_name;
|
|
|
|
|
else if (ASTIdentifier * ident = dynamic_cast<ASTIdentifier *>(&*node))
|
|
|
|
|
ident->alias = alias_name;
|
|
|
|
|
else if (ASTLiteral * lit = dynamic_cast<ASTLiteral *>(&*node))
|
|
|
|
|
lit->alias = alias_name;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
expected = "alias cannot be here";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-09-04 05:14:52 +00:00
|
|
|
|
bool ParserOrderByElement::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
|
|
|
|
|
|
|
|
|
ParserWhiteSpaceOrComments ws;
|
2011-11-06 20:47:07 +00:00
|
|
|
|
ParserExpressionWithOptionalAlias elem_p;
|
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;
|
|
|
|
|
if (!elem_p.parse(pos, end, expr_elem, expected))
|
|
|
|
|
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);
|
2013-05-28 16:56:05 +00:00
|
|
|
|
|
2013-05-29 11:33:55 +00:00
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
2013-05-28 16:56:05 +00:00
|
|
|
|
Poco::SharedPtr<Collator> collator = NULL;
|
|
|
|
|
if (collate.ignore(pos, end))
|
|
|
|
|
{
|
2013-05-29 11:33:55 +00:00
|
|
|
|
ws.ignore(pos, end);
|
|
|
|
|
|
2013-05-28 16:56:05 +00:00
|
|
|
|
ASTPtr locale_node;
|
|
|
|
|
if (!collate_locale_parser.parse(pos, end, locale_node, expected))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const String & locale = dynamic_cast<const ASTLiteral &>(*locale_node).value.safeGet<String>();
|
2013-05-30 14:28:27 +00:00
|
|
|
|
collator = new Collator(locale);
|
2013-05-28 16:56:05 +00:00
|
|
|
|
}
|
2011-09-04 05:14:52 +00:00
|
|
|
|
|
2013-05-28 16:56:05 +00:00
|
|
|
|
node = new ASTOrderByElement(StringRange(begin, pos), direction, collator);
|
2011-09-04 05:14:52 +00:00
|
|
|
|
node->children.push_back(expr_elem);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
}
|
|
|
|
|
|