ClickHouse/dbms/src/Interpreters/Expression.cpp

681 lines
22 KiB
C++
Raw Normal View History

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>
2012-08-22 20:29:01 +00:00
#include <DB/Parsers/ASTSubquery.h>
#include <DB/Parsers/ASTSet.h>
2011-08-12 18:27:39 +00:00
2012-08-23 19:38:45 +00:00
#include <DB/DataTypes/DataTypeSet.h>
2012-08-26 02:08:18 +00:00
#include <DB/DataTypes/DataTypeTuple.h>
#include <DB/Functions/FunctionsMiscellaneous.h>
2012-08-23 19:38:45 +00:00
#include <DB/Columns/ColumnSet.h>
2012-08-22 20:29:01 +00:00
#include <DB/Interpreters/InterpreterSelectQuery.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;
2012-08-02 17:33:31 +00:00
for (it = context.getColumns().begin(); it != context.getColumns().end(); ++it)
2011-11-03 20:30:12 +00:00
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);
2012-08-02 17:33:31 +00:00
if (context.getColumns().end() != it)
2011-11-06 01:25:05 +00:00
{
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);
2012-08-02 17:33:31 +00:00
for (NamesAndTypesList::const_iterator it = context.getColumns().begin(); it != context.getColumns().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
{
2012-08-02 17:33:31 +00:00
Functions::const_iterator it = context.getFunctions().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)
2012-08-24 19:42:03 +00:00
argument_types.push_back(getType(*it));
2011-11-01 17:57:37 +00:00
2012-08-02 17:33:31 +00:00
node->aggregate_function = context.getAggregateFunctionsFactory().tryGet(node->name, argument_types);
if (it == context.getFunctions().end() && node->aggregate_function.isNull())
2011-11-06 01:25:05 +00:00
throw Exception("Unknown function " + node->name, ErrorCodes::UNKNOWN_FUNCTION);
2012-08-02 17:33:31 +00:00
if (it != context.getFunctions().end())
2011-11-06 01:25:05 +00:00
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
}
2012-08-26 02:08:18 +00:00
else if (FunctionTupleElement * func_tuple_elem = dynamic_cast<FunctionTupleElement *>(&*node->function))
{
/// Особый случай - для функции tupleElement обычный метод getReturnType не работает.
if (arguments.size() != 2)
throw Exception("Function tupleElement requires exactly two arguments: tuple and element index.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
node->return_type = func_tuple_elem->getReturnType(argument_types, boost::get<UInt64>(dynamic_cast<ASTLiteral &>(*arguments[1]).value));
}
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);
2012-08-02 17:33:31 +00:00
if (it == context.getColumns().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
}
2012-08-24 19:42:03 +00:00
DataTypePtr Expression::getType(ASTPtr ast)
{
if (ASTFunction * arg = dynamic_cast<ASTFunction *>(&*ast))
return arg->return_type;
else if (ASTIdentifier * arg = dynamic_cast<ASTIdentifier *>(&*ast))
return arg->type;
else if (ASTLiteral * arg = dynamic_cast<ASTLiteral *>(&*ast))
return arg->type;
else if (dynamic_cast<ASTSubquery *>(&*ast) || dynamic_cast<ASTSet *>(&*ast))
return new DataTypeSet;
else
throw Exception("Unknown type of AST node " + ast->getID(), ErrorCodes::UNKNOWN_TYPE_OF_AST_NODE);
}
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
2012-08-23 19:38:45 +00:00
block.insert(column);
}
else if (ASTSet * node = dynamic_cast<ASTSet *>(&*ast))
{
/// Множество в секции IN.
ColumnWithNameAndType column;
column.column = new ColumnSet(block.rows(), node->set);
column.type = new DataTypeSet;
column.name = node->getColumnName();
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
2012-08-27 05:13:14 +00:00
void Expression::markBeforeAggregationImpl(ASTPtr ast, unsigned before_part_id, bool below)
2011-09-25 03:37:09 +00:00
{
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;
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-08-27 05:13:14 +00:00
markBeforeAggregationImpl(*it, before_part_id, below);
}
void Expression::markBeforeAggregation(unsigned before_part_id)
{
markBeforeAggregationImpl(ast, before_part_id);
}
bool Expression::getArrayJoinInfoImpl(ASTPtr ast, String & column_name)
{
if (ASTFunction * func = dynamic_cast<ASTFunction *>(&*ast))
{
if (func->name == "arrayJoin")
{
column_name = func->arguments->children.at(0)->getColumnName();
return true;
}
}
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
if (!dynamic_cast<ASTSelectQuery *>(&**it) && getArrayJoinInfoImpl(*it, column_name))
return true;
return false;
}
void Expression::markBeforeArrayJoinImpl(ASTPtr ast, unsigned part_id, bool below)
{
if (below)
ast->part_id |= part_id;
if (ASTFunction * func = dynamic_cast<ASTFunction *>(&*ast))
if (func->name == "arrayJoin")
below = true;
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
if (!dynamic_cast<ASTSelectQuery *>(&**it))
markBeforeArrayJoinImpl(*it, part_id, below);
}
bool Expression::getArrayJoinInfo(String & column_name)
{
return getArrayJoinInfoImpl(ast, column_name);
2011-09-25 03:37:09 +00:00
}
2012-08-27 05:13:14 +00:00
void Expression::markBeforeArrayJoin(unsigned part_id)
2011-09-25 03:37:09 +00:00
{
2012-08-27 05:13:14 +00:00
markBeforeArrayJoinImpl(ast, part_id);
2011-09-25 03:37:09 +00:00
}
2012-08-22 20:29:01 +00:00
void Expression::makeSets()
{
makeSetsImpl(ast);
}
void Expression::makeSetsImpl(ASTPtr ast)
{
2012-08-24 20:40:34 +00:00
bool made = false;
2012-08-22 20:29:01 +00:00
/// Обход в глубину. Ищем выражения IN.
if (ASTFunction * func = dynamic_cast<ASTFunction *>(&*ast))
{
if (func->name == "in" || func->name == "notIn")
{
2012-08-24 20:40:34 +00:00
made = true;
2012-08-22 20:29:01 +00:00
if (func->children.size() != 1)
throw Exception("Function IN requires exactly 2 arguments",
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
/// У функции должно быть два аргумента.
ASTExpressionList & args = dynamic_cast<ASTExpressionList &>(*func->children[0]);
if (args.children.size() != 2)
throw Exception("Function IN requires exactly 2 arguments",
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
/** Нужно преобразовать правый аргумент в множество.
* Это может быть перечисление значений или подзапрос.
* Перечисление значений парсится как функция tuple.
*/
2012-08-23 19:38:45 +00:00
ASTPtr & arg = args.children[1];
2012-08-22 20:29:01 +00:00
if (dynamic_cast<ASTSubquery *>(&*arg))
{
/// Исполняем подзапрос, превращаем результат в множество, и кладём это множество на место подзапроса.
2012-08-23 19:38:45 +00:00
InterpreterSelectQuery interpreter(arg->children[0], context, QueryProcessingStage::Complete);
ASTSet * ast_set = new ASTSet(arg->getColumnName());
2012-08-22 20:29:01 +00:00
ast_set->set = new Set;
ast_set->set->create(interpreter.execute());
arg = ast_set;
}
2012-08-24 19:42:03 +00:00
else if (ASTFunction * set_func = dynamic_cast<ASTFunction *>(&*arg))
{
/// Случай явного перечисления значений.
if (set_func->name != "tuple")
throw Exception("Incorrect type of 2nd argument for function IN. Must be subquery or set of values.",
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
DataTypes set_element_types;
ASTPtr & left_arg = args.children[0];
if (ASTFunction * left_arg_tuple = dynamic_cast<ASTFunction *>(&*left_arg))
for (ASTs::const_iterator it = left_arg_tuple->arguments->children.begin();
it != left_arg_tuple->arguments->children.end();
++it)
set_element_types.push_back(getType(*it));
else
set_element_types.push_back(getType(left_arg));
ASTSet * ast_set = new ASTSet(arg->getColumnName());
ast_set->set = new Set;
ast_set->set->create(set_element_types, set_func->arguments);
arg = ast_set;
}
else
2012-08-22 20:29:01 +00:00
throw Exception("Incorrect type of 2nd argument for function IN. Must be subquery or set of values.",
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
}
}
2012-08-24 20:40:34 +00:00
/// Рекурсивно обходим всё дерево, не опускаясь в только что созданные множества.
if (!made)
2012-08-22 20:29:01 +00:00
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
if (!dynamic_cast<ASTSelectQuery *>(&**it))
makeSetsImpl(*it);
}
2012-08-24 20:40:34 +00:00
void Expression::resolveScalarSubqueries()
{
2012-08-26 02:08:18 +00:00
resolveScalarSubqueriesImpl(ast);
2012-08-24 20:40:34 +00:00
}
void Expression::resolveScalarSubqueriesImpl(ASTPtr & ast)
{
/// Обход в глубину. Ищем подзапросы.
if (ASTSubquery * subquery = dynamic_cast<ASTSubquery *>(&*ast))
{
/// Исполняем подзапрос, превращаем результат в множество, и кладём это множество на место подзапроса.
InterpreterSelectQuery interpreter(subquery->children[0], context, QueryProcessingStage::Complete);
BlockInputStreamPtr res_stream = interpreter.execute();
Block res_block = res_stream->read();
/// В блоке должна быть одна строка.
if (res_stream->read() || res_block.rows() != 1)
throw Exception("Scalar subquery must return exactly one row.", ErrorCodes::INCORRECT_RESULT_OF_SCALAR_SUBQUERY);
/// Создаём литерал или tuple.
if (res_block.columns() == 1)
{
ASTLiteral * lit = new ASTLiteral(subquery->range, (*res_block.getByPosition(0).column)[0]);
lit->type = res_block.getByPosition(0).type;
/// NOTE можно разрешить подзапросам иметь alias.
ast = lit;
}
else
{
2012-08-26 02:08:18 +00:00
ASTFunction * tuple = new ASTFunction(subquery->range);
ASTExpressionList * args = new ASTExpressionList(subquery->range);
size_t columns = res_block.columns();
for (size_t i = 0; i < columns; ++i)
args->children.push_back(new ASTLiteral(subquery->range, (*res_block.getByPosition(i).column)[0]));
tuple->name = "tuple";
tuple->arguments = args;
tuple->children.push_back(tuple->arguments);
ast = tuple;
addSemantic(ast);
2012-08-24 20:40:34 +00:00
}
}
else
{
/// Обходим рекурсивно, но не опускаемся в секции IN.
bool recurse = true;
if (ASTFunction * func = dynamic_cast<ASTFunction *>(&*ast))
if (func->name == "in" || func->name == "notIn")
recurse = false;
if (recurse)
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
if (!dynamic_cast<ASTSelectQuery *>(&**it)) /// А также не опускаемся в подзапросы в секции FROM.
resolveScalarSubqueriesImpl(*it);
}
}
2011-08-12 18:27:39 +00:00
}