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>
|
|
|
|
|
#include <DB/Parsers/ASTExpressionList.h>
|
|
|
|
|
|
|
|
|
|
#include <DB/Interpreters/Expression.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
void Expression::addSemantic(ASTPtr ast)
|
|
|
|
|
{
|
|
|
|
|
if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
{
|
2011-08-19 18:31:14 +00:00
|
|
|
|
Functions::const_iterator it = context.functions->find(node->name);
|
|
|
|
|
if (it == context.functions->end())
|
2011-08-12 18:27:39 +00:00
|
|
|
|
throw Exception("Unknown function " + node->name, ErrorCodes::UNKNOWN_FUNCTION);
|
|
|
|
|
|
|
|
|
|
node->function = it->second;
|
|
|
|
|
}
|
|
|
|
|
else if (ASTIdentifier * node = dynamic_cast<ASTIdentifier *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
NamesAndTypes::const_iterator it = context.columns.find(node->name);
|
|
|
|
|
if (it == context.columns.end())
|
|
|
|
|
throw Exception("Unknown identifier " + node->name, ErrorCodes::UNKNOWN_IDENTIFIER);
|
|
|
|
|
|
|
|
|
|
node->type = it->second;
|
|
|
|
|
}
|
|
|
|
|
else if (ASTLiteral * node = dynamic_cast<ASTLiteral *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
node->type = boost::apply_visitor(FieldToDataType(), node->value);
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-13 23:03:07 +00:00
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2011-08-12 18:27:39 +00:00
|
|
|
|
addSemantic(*it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Expression::checkTypes(ASTPtr ast)
|
|
|
|
|
{
|
|
|
|
|
/// Обход в глубину
|
|
|
|
|
|
2011-08-13 23:03:07 +00:00
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2011-08-12 18:27:39 +00:00
|
|
|
|
checkTypes(*it);
|
|
|
|
|
|
|
|
|
|
if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
/// Типы аргументов
|
|
|
|
|
DataTypes argument_types;
|
|
|
|
|
ASTs & arguments = dynamic_cast<ASTExpressionList &>(*node->arguments).children;
|
|
|
|
|
|
|
|
|
|
for (ASTs::iterator it = arguments.begin(); it != arguments.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
if (ASTFunction * arg = dynamic_cast<ASTFunction *>(&**it))
|
|
|
|
|
argument_types.insert(argument_types.end(), arg->return_types.begin(), arg->return_types.end());
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Получаем типы результата
|
|
|
|
|
node->return_types = node->function->getReturnTypes(argument_types);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Expression::glueTree(ASTPtr ast)
|
|
|
|
|
{
|
|
|
|
|
Subtrees subtrees;
|
|
|
|
|
glueTreeImpl(ast, subtrees);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Expression::glueTreeImpl(ASTPtr ast, Subtrees & subtrees)
|
|
|
|
|
{
|
|
|
|
|
/// Обход в глубину
|
|
|
|
|
|
2011-08-13 23:03:07 +00:00
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2011-08-12 18:27:39 +00:00
|
|
|
|
glueTreeImpl(*it, subtrees);
|
|
|
|
|
|
|
|
|
|
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];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Expression::setNotCalculated(ASTPtr ast)
|
|
|
|
|
{
|
|
|
|
|
ast->calculated = false;
|
2011-08-13 23:03:07 +00:00
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2011-08-12 20:39:42 +00:00
|
|
|
|
setNotCalculated(*it);
|
2011-08-12 18:27:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Expression::execute(Block & block)
|
|
|
|
|
{
|
|
|
|
|
setNotCalculated(ast);
|
|
|
|
|
executeImpl(ast, block);
|
2011-08-13 23:03:07 +00:00
|
|
|
|
block = projectResult(ast, block);
|
2011-08-12 18:27:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Expression::executeImpl(ASTPtr ast, Block & block)
|
|
|
|
|
{
|
|
|
|
|
/// Обход в глубину
|
|
|
|
|
|
2011-08-13 23:03:07 +00:00
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2011-08-12 18:27:39 +00:00
|
|
|
|
executeImpl(*it, block);
|
|
|
|
|
|
|
|
|
|
if (ast->calculated)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/** Столбцы из таблицы уже загружены в блок.
|
|
|
|
|
* Вычисление состоит в добавлении в блок новых столбцов - констант и результатов вычислений функций.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
{
|
2011-08-14 00:49:30 +00:00
|
|
|
|
//std::cerr << node->getTreeID() << std::endl;
|
2011-08-12 18:27:39 +00:00
|
|
|
|
|
2011-08-12 20:39:42 +00:00
|
|
|
|
/// Вставляем в блок столбцы - результаты вычисления функции
|
|
|
|
|
ColumnNumbers argument_numbers;
|
2011-08-13 21:14:02 +00:00
|
|
|
|
ColumnNumbers & result_numbers = node->return_column_numbers;
|
|
|
|
|
result_numbers.clear();
|
2011-08-12 20:39:42 +00:00
|
|
|
|
|
|
|
|
|
size_t res_num = 0;
|
|
|
|
|
for (DataTypes::const_iterator it = node->return_types.begin(); it != node->return_types.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
ColumnWithNameAndType column;
|
|
|
|
|
column.type = *it;
|
2011-08-13 21:14:02 +00:00
|
|
|
|
column.name = node->getTreeID() + "_" + Poco::NumberFormatter::format(res_num);
|
2011-08-12 20:39:42 +00:00
|
|
|
|
|
|
|
|
|
result_numbers.push_back(block.columns());
|
|
|
|
|
block.insert(column);
|
|
|
|
|
++res_num;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-13 21:05:18 +00:00
|
|
|
|
ASTs arguments = node->arguments->children;
|
2011-08-12 20:39:42 +00:00
|
|
|
|
for (ASTs::iterator it = arguments.begin(); it != arguments.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
if (ASTIdentifier * ident = dynamic_cast<ASTIdentifier *>(&**it))
|
|
|
|
|
argument_numbers.push_back(block.getPositionByName(ident->name));
|
2011-08-13 21:14:02 +00:00
|
|
|
|
else if (ASTFunction * func = dynamic_cast<ASTFunction *>(&**it))
|
|
|
|
|
argument_numbers.insert(argument_numbers.end(), func->return_column_numbers.begin(), func->return_column_numbers.end());
|
2011-08-12 20:39:42 +00:00
|
|
|
|
else
|
|
|
|
|
argument_numbers.push_back(block.getPositionByName((*it)->getTreeID()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
node->function->execute(block, argument_numbers, result_numbers);
|
2011-08-12 18:27:39 +00:00
|
|
|
|
}
|
|
|
|
|
else if (ASTLiteral * node = dynamic_cast<ASTLiteral *>(&*ast))
|
|
|
|
|
{
|
2011-08-14 00:49:30 +00:00
|
|
|
|
//std::cerr << node->getTreeID() << std::endl;
|
2011-08-12 20:39:42 +00:00
|
|
|
|
|
|
|
|
|
/// Вставляем в блок столбец - константу
|
2011-08-12 18:27:39 +00:00
|
|
|
|
|
2011-08-12 20:39:42 +00:00
|
|
|
|
ColumnWithNameAndType column;
|
|
|
|
|
column.column = node->type->createConstColumn(block.rows(), node->value);
|
|
|
|
|
column.type = node->type;
|
|
|
|
|
column.name = node->getTreeID();
|
|
|
|
|
|
|
|
|
|
block.insert(column);
|
2011-08-12 18:27:39 +00:00
|
|
|
|
}
|
2011-08-12 20:39:42 +00:00
|
|
|
|
|
|
|
|
|
ast->calculated = true;
|
2011-08-12 18:27:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-08-13 23:03:07 +00:00
|
|
|
|
|
|
|
|
|
Block Expression::projectResult(ASTPtr ast, Block & block)
|
|
|
|
|
{
|
|
|
|
|
Block res;
|
|
|
|
|
collectFinalColumns(ast, block, res);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Expression::collectFinalColumns(ASTPtr ast, Block & src, Block & dst)
|
|
|
|
|
{
|
|
|
|
|
if (ASTExpressionList * node = dynamic_cast<ASTExpressionList *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
for (ASTs::iterator it = node->children.begin(); it != node->children.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
if (ASTIdentifier * ident = dynamic_cast<ASTIdentifier *>(&**it))
|
|
|
|
|
dst.insert(src.getByName(ident->name));
|
|
|
|
|
else if (ASTFunction * func = dynamic_cast<ASTFunction *>(&**it))
|
|
|
|
|
for (ColumnNumbers::const_iterator jt = func->return_column_numbers.begin(); jt != func->return_column_numbers.end(); ++jt)
|
|
|
|
|
dst.insert(src.getByPosition(*jt));
|
|
|
|
|
else
|
|
|
|
|
dst.insert(src.getByName((*it)->getTreeID()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
|
|
|
|
collectFinalColumns(*it, src, dst);
|
|
|
|
|
}
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
if (ASTExpressionList * node = dynamic_cast<ASTExpressionList *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
for (ASTs::iterator it = node->children.begin(); it != node->children.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
if (ASTIdentifier * ident = dynamic_cast<ASTIdentifier *>(&**it))
|
|
|
|
|
res.push_back(ident->type);
|
|
|
|
|
else if (ASTFunction * func = dynamic_cast<ASTFunction *>(&**it))
|
|
|
|
|
res.insert(res.end(), func->return_types.begin(), func->return_types.end());
|
|
|
|
|
else if (ASTLiteral * lit = dynamic_cast<ASTLiteral *>(&**it))
|
|
|
|
|
res.push_back(lit->type);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
|
|
|
|
getReturnTypesImpl(*it, res);
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-12 18:27:39 +00:00
|
|
|
|
|
|
|
|
|
}
|