2011-08-12 18:27:39 +00:00
|
|
|
|
#include <DB/DataTypes/FieldToDataType.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-08-12 18:27:39 +00:00
|
|
|
|
#include <DB/Parsers/ASTExpressionList.h>
|
2011-09-24 20:32:41 +00:00
|
|
|
|
#include <DB/Parsers/ASTSelectQuery.h>
|
2011-08-12 18:27:39 +00:00
|
|
|
|
|
|
|
|
|
#include <DB/Interpreters/Expression.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
2011-09-05 00:32:22 +00:00
|
|
|
|
|
2011-11-03 20:30:12 +00:00
|
|
|
|
NamesAndTypesList::const_iterator Expression::findColumn(const String & name)
|
|
|
|
|
{
|
|
|
|
|
NamesAndTypesList::const_iterator it;
|
|
|
|
|
for (it = context.columns.begin(); it != context.columns.end(); ++it)
|
|
|
|
|
if (it->first == name)
|
|
|
|
|
break;
|
|
|
|
|
return it;
|
|
|
|
|
}
|
2011-11-06 04:21:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Expression::createAliasesDict(ASTPtr & ast)
|
|
|
|
|
{
|
|
|
|
|
/// Обход снизу-вверх. Не опускаемся в подзапросы.
|
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
|
|
|
|
if (!dynamic_cast<ASTSelectQuery *>(&**it))
|
|
|
|
|
createAliasesDict(*it);
|
2011-11-03 20:30:12 +00:00
|
|
|
|
|
2011-11-06 04:21:09 +00:00
|
|
|
|
if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
if (!node->alias.empty())
|
|
|
|
|
aliases[node->alias] = ast;
|
|
|
|
|
}
|
|
|
|
|
else if (ASTIdentifier * node = dynamic_cast<ASTIdentifier *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
if (!node->alias.empty())
|
|
|
|
|
aliases[node->alias] = ast;
|
|
|
|
|
}
|
|
|
|
|
else if (ASTLiteral * node = dynamic_cast<ASTLiteral *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
if (!node->alias.empty())
|
|
|
|
|
aliases[node->alias] = ast;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-03 20:30:12 +00:00
|
|
|
|
|
2011-08-28 08:50:27 +00:00
|
|
|
|
void Expression::addSemantic(ASTPtr & ast)
|
2011-08-12 18:27:39 +00:00
|
|
|
|
{
|
2011-11-06 01:25:05 +00:00
|
|
|
|
/// rewrite правила, которые действуют при обходе сверху-вниз.
|
|
|
|
|
if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
/** Нет ли в таблице столбца, название которого полностью совпадает с записью функции?
|
|
|
|
|
* Например, в таблице есть столбец "domain(URL)", и мы запросили domain(URL).
|
|
|
|
|
*/
|
|
|
|
|
String function_string = node->getColumnName();
|
|
|
|
|
NamesAndTypesList::const_iterator it = findColumn(function_string);
|
|
|
|
|
if (context.columns.end() != it)
|
|
|
|
|
{
|
|
|
|
|
ASTIdentifier * ast_id = new ASTIdentifier(node->range, std::string(node->range.first, node->range.second));
|
|
|
|
|
ast_id->type = it->second;
|
|
|
|
|
required_columns.insert(function_string);
|
|
|
|
|
ast = ast_id;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-06 02:29:13 +00:00
|
|
|
|
/// Обход снизу-вверх. Не опускаемся в подзапросы.
|
2011-09-25 05:07:47 +00:00
|
|
|
|
|
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2011-11-06 02:29:13 +00:00
|
|
|
|
if (!dynamic_cast<ASTSelectQuery *>(&**it))
|
|
|
|
|
addSemantic(*it);
|
2011-09-25 05:07:47 +00:00
|
|
|
|
|
2011-08-28 08:50:27 +00:00
|
|
|
|
if (dynamic_cast<ASTAsterisk *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
ASTExpressionList * all_columns = new ASTExpressionList(ast->range);
|
2011-11-03 20:30:12 +00:00
|
|
|
|
for (NamesAndTypesList::const_iterator it = context.columns.begin(); it != context.columns.end(); ++it)
|
2011-08-28 08:50:27 +00:00
|
|
|
|
all_columns->children.push_back(new ASTIdentifier(ast->range, it->first));
|
|
|
|
|
ast = all_columns;
|
2011-09-26 05:18:19 +00:00
|
|
|
|
|
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
|
|
|
|
addSemantic(*it);
|
2011-08-28 08:50:27 +00:00
|
|
|
|
}
|
|
|
|
|
else if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
|
2011-08-12 18:27:39 +00:00
|
|
|
|
{
|
2011-11-06 01:25:05 +00:00
|
|
|
|
Functions::const_iterator it = context.functions->find(node->name);
|
2011-08-12 18:27:39 +00:00
|
|
|
|
|
2011-11-06 01:25:05 +00:00
|
|
|
|
/// Типы аргументов
|
|
|
|
|
DataTypes argument_types;
|
|
|
|
|
ASTs & arguments = dynamic_cast<ASTExpressionList &>(*node->arguments).children;
|
2011-09-25 05:07:47 +00:00
|
|
|
|
|
2011-11-06 01:25:05 +00:00
|
|
|
|
for (ASTs::iterator it = arguments.begin(); it != arguments.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
if (ASTFunction * arg = dynamic_cast<ASTFunction *>(&**it))
|
|
|
|
|
argument_types.push_back(arg->return_type);
|
|
|
|
|
else if (ASTIdentifier * arg = dynamic_cast<ASTIdentifier *>(&**it))
|
|
|
|
|
argument_types.push_back(arg->type);
|
|
|
|
|
else if (ASTLiteral * arg = dynamic_cast<ASTLiteral *>(&**it))
|
|
|
|
|
argument_types.push_back(arg->type);
|
|
|
|
|
}
|
2011-11-01 17:57:37 +00:00
|
|
|
|
|
2011-11-06 01:25:05 +00:00
|
|
|
|
node->aggregate_function = context.aggregate_function_factory->tryGet(node->name, argument_types);
|
|
|
|
|
if (it == context.functions->end() && node->aggregate_function.isNull())
|
|
|
|
|
throw Exception("Unknown function " + node->name, ErrorCodes::UNKNOWN_FUNCTION);
|
|
|
|
|
if (it != context.functions->end())
|
|
|
|
|
node->function = it->second;
|
2011-11-01 17:57:37 +00:00
|
|
|
|
|
2011-11-06 01:25:05 +00:00
|
|
|
|
/// Получаем типы результата
|
|
|
|
|
if (node->aggregate_function)
|
|
|
|
|
{
|
|
|
|
|
node->aggregate_function->setArguments(argument_types);
|
|
|
|
|
node->return_type = node->aggregate_function->getReturnType();
|
2011-09-19 03:34:23 +00:00
|
|
|
|
}
|
2011-11-06 01:25:05 +00:00
|
|
|
|
else
|
|
|
|
|
node->return_type = node->function->getReturnType(argument_types);
|
2011-08-12 18:27:39 +00:00
|
|
|
|
}
|
2011-09-25 05:07:47 +00:00
|
|
|
|
else if (ASTIdentifier * node = dynamic_cast<ASTIdentifier *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
if (node->kind == ASTIdentifier::Column)
|
|
|
|
|
{
|
2011-11-03 20:30:12 +00:00
|
|
|
|
NamesAndTypesList::const_iterator it = findColumn(node->name);
|
2011-09-25 05:07:47 +00:00
|
|
|
|
if (it == context.columns.end())
|
2011-11-06 04:21:09 +00:00
|
|
|
|
{
|
|
|
|
|
/// Если это алиас
|
|
|
|
|
Aliases::const_iterator jt = aliases.find(node->name);
|
|
|
|
|
if (jt == aliases.end())
|
|
|
|
|
throw Exception("Unknown identifier " + node->name, ErrorCodes::UNKNOWN_IDENTIFIER);
|
2011-09-25 05:07:47 +00:00
|
|
|
|
|
2011-11-06 04:21:09 +00:00
|
|
|
|
/// Заменим его на соответствующий узел дерева
|
|
|
|
|
ast = jt->second;
|
|
|
|
|
|
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
|
|
|
|
addSemantic(*it);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
node->type = it->second;
|
|
|
|
|
required_columns.insert(node->name);
|
|
|
|
|
}
|
2011-09-25 05:07:47 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ASTLiteral * node = dynamic_cast<ASTLiteral *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
node->type = boost::apply_visitor(FieldToDataType(), node->value);
|
|
|
|
|
}
|
2011-08-12 18:27:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Expression::glueTree(ASTPtr ast)
|
|
|
|
|
{
|
|
|
|
|
Subtrees subtrees;
|
|
|
|
|
glueTreeImpl(ast, subtrees);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Expression::glueTreeImpl(ASTPtr ast, Subtrees & subtrees)
|
|
|
|
|
{
|
2011-11-06 02:29:13 +00:00
|
|
|
|
/// Обход в глубину. Не опускаемся в подзапросы.
|
2011-08-12 18:27:39 +00:00
|
|
|
|
|
2011-08-13 23:03:07 +00:00
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2011-11-06 02:29:13 +00:00
|
|
|
|
if (!dynamic_cast<ASTSelectQuery *>(&**it))
|
|
|
|
|
glueTreeImpl(*it, subtrees);
|
2011-08-12 18:27:39 +00:00
|
|
|
|
|
|
|
|
|
if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
String tree_id = node->arguments->getTreeID();
|
|
|
|
|
if (subtrees.end() == subtrees.find(tree_id))
|
|
|
|
|
subtrees[tree_id] = node->arguments;
|
|
|
|
|
else
|
|
|
|
|
node->arguments = subtrees[tree_id];
|
|
|
|
|
}
|
|
|
|
|
else if (ASTExpressionList * node = dynamic_cast<ASTExpressionList *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
for (ASTs::iterator it = node->children.begin(); it != node->children.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
String tree_id = (*it)->getTreeID();
|
|
|
|
|
if (subtrees.end() == subtrees.find(tree_id))
|
|
|
|
|
subtrees[tree_id] = *it;
|
|
|
|
|
else
|
|
|
|
|
*it = subtrees[tree_id];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-08-28 05:13:24 +00:00
|
|
|
|
Names Expression::getRequiredColumns()
|
|
|
|
|
{
|
|
|
|
|
Names res;
|
|
|
|
|
res.reserve(required_columns.size());
|
|
|
|
|
for (NamesSet::const_iterator it = required_columns.begin(); it != required_columns.end(); ++it)
|
|
|
|
|
res.push_back(*it);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-07-21 03:45:48 +00:00
|
|
|
|
void Expression::execute(Block & block, unsigned part_id, bool only_consts)
|
2011-08-12 18:27:39 +00:00
|
|
|
|
{
|
2012-07-21 03:45:48 +00:00
|
|
|
|
executeImpl(ast, block, part_id, only_consts);
|
2011-08-12 18:27:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-07-21 03:45:48 +00:00
|
|
|
|
void Expression::executeImpl(ASTPtr ast, Block & block, unsigned part_id, bool only_consts)
|
2011-08-12 18:27:39 +00:00
|
|
|
|
{
|
2011-12-12 06:15:34 +00:00
|
|
|
|
/// Если результат вычисления уже есть в блоке.
|
|
|
|
|
if ((dynamic_cast<ASTFunction *>(&*ast) || dynamic_cast<ASTLiteral *>(&*ast)) && block.has(ast->getColumnName()))
|
|
|
|
|
return;
|
2011-08-12 18:27:39 +00:00
|
|
|
|
|
2011-12-12 06:15:34 +00:00
|
|
|
|
/// Обход в глубину. Не опускаемся в подзапросы.
|
2011-08-13 23:03:07 +00:00
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2011-11-06 02:29:13 +00:00
|
|
|
|
if (!dynamic_cast<ASTSelectQuery *>(&**it))
|
2012-07-21 03:45:48 +00:00
|
|
|
|
executeImpl(*it, block, part_id, only_consts);
|
2011-08-12 18:27:39 +00:00
|
|
|
|
|
2011-12-12 06:15:34 +00:00
|
|
|
|
/// Если это - не указанная часть дерева.
|
|
|
|
|
if (!((ast->part_id & part_id) || (ast->part_id == 0 && part_id == 0)))
|
2011-08-12 18:27:39 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2012-07-21 05:07:14 +00:00
|
|
|
|
/** Столбцы из таблицы уже загружены в блок (если не указано only_consts).
|
2011-08-12 18:27:39 +00:00
|
|
|
|
* Вычисление состоит в добавлении в блок новых столбцов - констант и результатов вычислений функций.
|
|
|
|
|
*/
|
|
|
|
|
if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
{
|
2011-09-19 01:42:16 +00:00
|
|
|
|
if (node->function)
|
2011-08-12 20:39:42 +00:00
|
|
|
|
{
|
2011-09-19 01:42:16 +00:00
|
|
|
|
/// Вставляем в блок столбцы - результаты вычисления функции
|
|
|
|
|
ColumnNumbers argument_numbers;
|
|
|
|
|
|
2012-07-21 05:07:14 +00:00
|
|
|
|
ASTs arguments = node->arguments->children;
|
|
|
|
|
for (ASTs::iterator it = arguments.begin(); it != arguments.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
String column_name = (*it)->getColumnName();
|
|
|
|
|
if (only_consts && (!block.has(column_name) || !block.getByName(column_name).column->isConst()))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
argument_numbers.push_back(block.getPositionByName(column_name));
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-24 20:32:41 +00:00
|
|
|
|
ColumnWithNameAndType column;
|
|
|
|
|
column.type = node->return_type;
|
2011-11-06 21:09:49 +00:00
|
|
|
|
column.name = node->getColumnName();
|
2011-09-19 01:42:16 +00:00
|
|
|
|
|
2011-09-24 20:32:41 +00:00
|
|
|
|
size_t result_number = block.columns();
|
|
|
|
|
block.insert(column);
|
2011-09-19 01:42:16 +00:00
|
|
|
|
|
2011-09-24 20:32:41 +00:00
|
|
|
|
node->function->execute(block, argument_numbers, result_number);
|
2011-08-12 20:39:42 +00:00
|
|
|
|
}
|
2011-08-12 18:27:39 +00:00
|
|
|
|
}
|
|
|
|
|
else if (ASTLiteral * node = dynamic_cast<ASTLiteral *>(&*ast))
|
|
|
|
|
{
|
2011-08-12 20:39:42 +00:00
|
|
|
|
ColumnWithNameAndType column;
|
|
|
|
|
column.column = node->type->createConstColumn(block.rows(), node->value);
|
|
|
|
|
column.type = node->type;
|
2011-11-06 21:09:49 +00:00
|
|
|
|
column.name = node->getColumnName();
|
2011-08-21 03:41:37 +00:00
|
|
|
|
|
2011-08-12 20:39:42 +00:00
|
|
|
|
block.insert(column);
|
2011-08-12 18:27:39 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-13 23:03:07 +00:00
|
|
|
|
|
2011-11-06 04:21:09 +00:00
|
|
|
|
Block Expression::projectResult(Block & block, bool without_duplicates_and_aliases, unsigned part_id, ASTPtr subtree)
|
2011-08-13 23:03:07 +00:00
|
|
|
|
{
|
|
|
|
|
Block res;
|
2011-11-06 04:21:09 +00:00
|
|
|
|
collectFinalColumns(subtree ? subtree : ast, block, res, without_duplicates_and_aliases, part_id);
|
2011-08-13 23:03:07 +00:00
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-11-06 04:21:09 +00:00
|
|
|
|
void Expression::collectFinalColumns(ASTPtr ast, Block & src, Block & dst, bool without_duplicates_and_aliases, unsigned part_id)
|
2011-08-13 23:03:07 +00:00
|
|
|
|
{
|
2011-11-06 02:29:13 +00:00
|
|
|
|
/// Обход в глубину, который не заходит внутрь функций и подзапросов.
|
2011-09-04 05:14:52 +00:00
|
|
|
|
if (!((ast->part_id & part_id) || (ast->part_id == 0 && part_id == 0)))
|
2011-08-28 05:13:24 +00:00
|
|
|
|
{
|
|
|
|
|
if (!dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2011-11-06 02:29:13 +00:00
|
|
|
|
if (!dynamic_cast<ASTSelectQuery *>(&**it))
|
2011-11-06 04:21:09 +00:00
|
|
|
|
collectFinalColumns(*it, src, dst, without_duplicates_and_aliases, part_id);
|
2011-08-28 05:13:24 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-28 00:48:51 +00:00
|
|
|
|
if (ASTIdentifier * ident = dynamic_cast<ASTIdentifier *>(&*ast))
|
2011-08-28 02:22:23 +00:00
|
|
|
|
{
|
|
|
|
|
if (ident->kind == ASTIdentifier::Column)
|
2011-11-06 04:21:09 +00:00
|
|
|
|
{
|
|
|
|
|
ColumnWithNameAndType col = src.getByName(ast->getColumnName());
|
|
|
|
|
col.name = without_duplicates_and_aliases ? ast->getColumnName() : ast->getAlias();
|
|
|
|
|
without_duplicates_and_aliases ? dst.insertUnique(col) : dst.insert(col);
|
|
|
|
|
}
|
2011-09-04 05:14:52 +00:00
|
|
|
|
}
|
2011-09-24 20:32:41 +00:00
|
|
|
|
else if (dynamic_cast<ASTLiteral *>(&*ast) || dynamic_cast<ASTFunction *>(&*ast))
|
2011-11-06 04:21:09 +00:00
|
|
|
|
{
|
|
|
|
|
ColumnWithNameAndType col = src.getByName(ast->getColumnName());
|
|
|
|
|
col.name = without_duplicates_and_aliases ? ast->getColumnName() : ast->getAlias();
|
|
|
|
|
without_duplicates_and_aliases ? dst.insertUnique(col) : dst.insert(col);
|
|
|
|
|
}
|
2011-08-13 23:03:07 +00:00
|
|
|
|
else
|
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2011-11-06 02:29:13 +00:00
|
|
|
|
if (!dynamic_cast<ASTSelectQuery *>(&**it))
|
2011-11-06 04:21:09 +00:00
|
|
|
|
collectFinalColumns(*it, src, dst, without_duplicates_and_aliases, part_id);
|
2011-08-13 23:03:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-08-14 00:49:30 +00:00
|
|
|
|
|
|
|
|
|
DataTypes Expression::getReturnTypes()
|
|
|
|
|
{
|
|
|
|
|
DataTypes res;
|
|
|
|
|
getReturnTypesImpl(ast, res);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Expression::getReturnTypesImpl(ASTPtr ast, DataTypes & res)
|
|
|
|
|
{
|
2011-11-06 02:29:13 +00:00
|
|
|
|
/// Обход в глубину, который не заходит внутрь функций и подзапросов.
|
2011-08-28 08:02:11 +00:00
|
|
|
|
if (ASTIdentifier * ident = dynamic_cast<ASTIdentifier *>(&*ast))
|
2011-08-14 00:49:30 +00:00
|
|
|
|
{
|
2011-08-28 08:02:11 +00:00
|
|
|
|
if (ident->kind == ASTIdentifier::Column)
|
|
|
|
|
res.push_back(ident->type);
|
2011-08-14 00:49:30 +00:00
|
|
|
|
}
|
2011-08-28 08:02:11 +00:00
|
|
|
|
else if (ASTLiteral * lit = dynamic_cast<ASTLiteral *>(&*ast))
|
|
|
|
|
res.push_back(lit->type);
|
|
|
|
|
else if (ASTFunction * func = dynamic_cast<ASTFunction *>(&*ast))
|
2011-09-24 20:32:41 +00:00
|
|
|
|
res.push_back(func->return_type);
|
2011-08-14 00:49:30 +00:00
|
|
|
|
else
|
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2011-11-06 02:29:13 +00:00
|
|
|
|
if (!dynamic_cast<ASTSelectQuery *>(&**it))
|
|
|
|
|
getReturnTypesImpl(*it, res);
|
2011-08-14 00:49:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-09-24 20:32:41 +00:00
|
|
|
|
|
2011-10-30 05:19:41 +00:00
|
|
|
|
Block Expression::getSampleBlock()
|
|
|
|
|
{
|
|
|
|
|
Block res;
|
|
|
|
|
getSampleBlockImpl(ast, res);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Expression::getSampleBlockImpl(ASTPtr ast, Block & res)
|
|
|
|
|
{
|
|
|
|
|
ColumnWithNameAndType col;
|
|
|
|
|
|
2011-11-06 02:29:13 +00:00
|
|
|
|
/// Обход в глубину, который не заходит внутрь функций и подзапросов.
|
2011-10-30 05:19:41 +00:00
|
|
|
|
if (ASTIdentifier * ident = dynamic_cast<ASTIdentifier *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
if (ident->kind == ASTIdentifier::Column)
|
|
|
|
|
{
|
|
|
|
|
col.name = ident->name;
|
|
|
|
|
col.type = ident->type;
|
|
|
|
|
res.insert(col);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ASTLiteral * lit = dynamic_cast<ASTLiteral *>(&*ast))
|
|
|
|
|
{
|
2011-11-06 04:21:09 +00:00
|
|
|
|
col.name = lit->getAlias();
|
2011-10-30 05:19:41 +00:00
|
|
|
|
col.type = lit->type;
|
|
|
|
|
res.insert(col);
|
|
|
|
|
}
|
|
|
|
|
else if (ASTFunction * func = dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
{
|
2011-11-06 04:21:09 +00:00
|
|
|
|
col.name = func->getAlias();
|
2011-10-30 05:19:41 +00:00
|
|
|
|
col.type = func->return_type;
|
|
|
|
|
res.insert(col);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2011-11-06 02:29:13 +00:00
|
|
|
|
if (!dynamic_cast<ASTSelectQuery *>(&**it))
|
|
|
|
|
getSampleBlockImpl(*it, res);
|
2011-10-30 05:19:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-09-25 03:37:09 +00:00
|
|
|
|
void Expression::getAggregateInfoImpl(ASTPtr ast, Names & key_names, AggregateDescriptions & aggregates, NamesSet & processed)
|
2011-09-24 20:32:41 +00:00
|
|
|
|
{
|
|
|
|
|
if (ASTSelectQuery * select = dynamic_cast<ASTSelectQuery *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
if (select->group_expression_list)
|
|
|
|
|
{
|
|
|
|
|
for (ASTs::iterator it = select->group_expression_list->children.begin(); it != select->group_expression_list->children.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
if (ASTIdentifier * ident = dynamic_cast<ASTIdentifier *>(&**it))
|
|
|
|
|
{
|
|
|
|
|
if (ident->kind == ASTIdentifier::Column)
|
2011-09-25 03:37:09 +00:00
|
|
|
|
key_names.push_back((*it)->getColumnName());
|
2011-09-24 20:32:41 +00:00
|
|
|
|
}
|
|
|
|
|
else if (dynamic_cast<ASTLiteral *>(&**it) || dynamic_cast<ASTFunction *>(&**it))
|
2011-09-25 03:37:09 +00:00
|
|
|
|
key_names.push_back((*it)->getColumnName());
|
2011-09-24 20:32:41 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ASTFunction * func = dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
{
|
2011-09-25 03:37:09 +00:00
|
|
|
|
if (func->aggregate_function && processed.end() == processed.find(ast->getColumnName()))
|
2011-09-24 20:32:41 +00:00
|
|
|
|
{
|
|
|
|
|
AggregateDescription desc;
|
|
|
|
|
desc.function = func->aggregate_function;
|
2011-09-25 03:37:09 +00:00
|
|
|
|
desc.column_name = ast->getColumnName();
|
2011-09-24 20:32:41 +00:00
|
|
|
|
|
|
|
|
|
for (ASTs::iterator it = func->arguments->children.begin(); it != func->arguments->children.end(); ++it)
|
2011-09-25 03:37:09 +00:00
|
|
|
|
desc.argument_names.push_back((*it)->getColumnName());
|
2011-09-24 20:32:41 +00:00
|
|
|
|
|
|
|
|
|
aggregates.push_back(desc);
|
2011-09-25 03:37:09 +00:00
|
|
|
|
processed.insert(ast->getColumnName());
|
2011-09-24 20:32:41 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-06 02:29:13 +00:00
|
|
|
|
/// Обход в глубину. Не опускаемся в подзапросы.
|
2011-09-24 20:32:41 +00:00
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2011-11-06 02:29:13 +00:00
|
|
|
|
if (!dynamic_cast<ASTSelectQuery *>(&**it))
|
|
|
|
|
getAggregateInfoImpl(*it, key_names, aggregates, processed);
|
2011-09-24 20:32:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Expression::getAggregateInfo(Names & key_names, AggregateDescriptions & aggregates)
|
|
|
|
|
{
|
2011-09-25 03:37:09 +00:00
|
|
|
|
NamesSet processed;
|
|
|
|
|
getAggregateInfoImpl(ast, key_names, aggregates, processed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Expression::hasAggregatesImpl(ASTPtr ast)
|
|
|
|
|
{
|
|
|
|
|
if (ASTFunction * func = dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
if (func->aggregate_function)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2011-11-06 02:29:13 +00:00
|
|
|
|
if (!dynamic_cast<ASTSelectQuery *>(&**it) && hasAggregatesImpl(*it))
|
2011-09-25 03:37:09 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Expression::hasAggregates()
|
|
|
|
|
{
|
|
|
|
|
return hasAggregatesImpl(ast);
|
2011-09-24 20:32:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-09-25 03:37:09 +00:00
|
|
|
|
|
|
|
|
|
void Expression::markBeforeAndAfterAggregationImpl(ASTPtr ast, unsigned before_part_id, unsigned after_part_id, bool below)
|
|
|
|
|
{
|
|
|
|
|
if (ASTFunction * func = dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
if (func->aggregate_function)
|
|
|
|
|
below = true;
|
2011-08-12 18:27:39 +00:00
|
|
|
|
|
2011-09-25 03:37:09 +00:00
|
|
|
|
if (below)
|
|
|
|
|
ast->part_id |= before_part_id;
|
|
|
|
|
else
|
|
|
|
|
ast->part_id |= after_part_id;
|
|
|
|
|
|
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2011-11-06 02:29:13 +00:00
|
|
|
|
if (!dynamic_cast<ASTSelectQuery *>(&**it))
|
|
|
|
|
markBeforeAndAfterAggregationImpl(*it, before_part_id, after_part_id, below);
|
2011-09-25 03:37:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Expression::markBeforeAndAfterAggregation(unsigned before_part_id, unsigned after_part_id)
|
|
|
|
|
{
|
|
|
|
|
markBeforeAndAfterAggregationImpl(ast, before_part_id, after_part_id);
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-12 18:27:39 +00:00
|
|
|
|
}
|