2013-05-24 10:49:19 +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/ASTAsterisk.h>
|
|
|
|
|
#include <DB/Parsers/ASTExpressionList.h>
|
|
|
|
|
#include <DB/Parsers/ASTSelectQuery.h>
|
|
|
|
|
#include <DB/Parsers/ASTSubquery.h>
|
|
|
|
|
#include <DB/Parsers/ASTSet.h>
|
2013-05-27 14:02:55 +00:00
|
|
|
|
#include <DB/Parsers/ASTOrderByElement.h>
|
2013-05-24 10:49:19 +00:00
|
|
|
|
|
|
|
|
|
#include <DB/DataTypes/DataTypeSet.h>
|
|
|
|
|
#include <DB/DataTypes/DataTypeTuple.h>
|
|
|
|
|
#include <DB/DataTypes/DataTypeExpression.h>
|
2013-07-26 13:46:52 +00:00
|
|
|
|
#include <DB/DataTypes/DataTypeNested.h>
|
2013-05-24 10:49:19 +00:00
|
|
|
|
#include <DB/Columns/ColumnSet.h>
|
|
|
|
|
#include <DB/Columns/ColumnExpression.h>
|
|
|
|
|
|
|
|
|
|
#include <DB/Interpreters/InterpreterSelectQuery.h>
|
|
|
|
|
#include <DB/Interpreters/ExpressionAnalyzer.h>
|
|
|
|
|
|
|
|
|
|
#include <DB/Storages/StorageMergeTree.h>
|
|
|
|
|
#include <DB/Storages/StorageDistributed.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
2013-06-15 04:45:59 +00:00
|
|
|
|
static std::string * getAlias(ASTPtr & ast)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
|
|
|
|
if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
return &node->alias;
|
|
|
|
|
}
|
|
|
|
|
else if (ASTIdentifier * node = dynamic_cast<ASTIdentifier *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
return &node->alias;
|
|
|
|
|
}
|
|
|
|
|
else if (ASTLiteral * node = dynamic_cast<ASTLiteral *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
return &node->alias;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-18 08:07:51 +00:00
|
|
|
|
static void setAlias(ASTPtr & ast, const std::string & alias)
|
|
|
|
|
{
|
|
|
|
|
if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
node->alias = alias;
|
|
|
|
|
}
|
|
|
|
|
else if (ASTIdentifier * node = dynamic_cast<ASTIdentifier *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
node->alias = alias;
|
|
|
|
|
}
|
|
|
|
|
else if (ASTLiteral * node = dynamic_cast<ASTLiteral *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
node->alias = alias;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
throw Exception("Can't set alias of " + ast->getColumnName(), ErrorCodes::UNKNOWN_TYPE_OF_AST_NODE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
|
|
|
|
|
void ExpressionAnalyzer::init()
|
|
|
|
|
{
|
|
|
|
|
select_query = dynamic_cast<ASTSelectQuery *>(&*ast);
|
|
|
|
|
has_aggregation = false;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
createAliasesDict(ast); /// Если есть агрегатные функции, присвоит has_aggregation=true.
|
|
|
|
|
normalizeTree();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-08-01 13:29:32 +00:00
|
|
|
|
getArrayJoinedColumns();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-10-21 11:33:25 +00:00
|
|
|
|
removeUnusedColumns();
|
|
|
|
|
|
2013-05-29 11:46:51 +00:00
|
|
|
|
/// Найдем агрегатные функции.
|
2013-05-24 10:49:19 +00:00
|
|
|
|
if (select_query && (select_query->group_expression_list || select_query->having_expression))
|
|
|
|
|
has_aggregation = true;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
ExpressionActions temp_actions(columns, settings);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
|
|
|
|
if (select_query && select_query->array_join_expression_list)
|
|
|
|
|
{
|
|
|
|
|
const ASTs & array_join_asts = select_query->array_join_expression_list->children;
|
|
|
|
|
for (size_t i = 0; i < array_join_asts.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
ASTPtr ast = array_join_asts[i];
|
|
|
|
|
getRootActionsImpl(ast, true, false, temp_actions);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addMultipleArrayJoinAction(temp_actions);
|
|
|
|
|
|
|
|
|
|
const Block & temp_sample = temp_actions.getSampleBlock();
|
2013-10-21 11:33:25 +00:00
|
|
|
|
for (NameToNameMap::iterator it = array_join_result_to_source.begin(); it != array_join_result_to_source.end(); ++it)
|
2013-10-17 13:32:32 +00:00
|
|
|
|
{
|
2013-10-21 11:33:25 +00:00
|
|
|
|
columns_after_array_join.push_back(NameAndTypePair(it->first, temp_sample.getByName(it->first).type));
|
2013-10-17 13:32:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-21 11:33:25 +00:00
|
|
|
|
for (NamesAndTypesList::iterator it = columns.begin(); it != columns.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
if (!array_join_result_to_source.count(it->first))
|
|
|
|
|
columns_after_array_join.push_back(*it);
|
|
|
|
|
}
|
2013-05-29 11:46:51 +00:00
|
|
|
|
getAggregatesImpl(ast, temp_actions);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
if (has_aggregation)
|
|
|
|
|
{
|
2013-05-29 11:46:51 +00:00
|
|
|
|
assertSelect();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
/// Найдем ключи агрегации.
|
|
|
|
|
if (select_query->group_expression_list)
|
|
|
|
|
{
|
2013-06-20 15:38:03 +00:00
|
|
|
|
NameSet unique_keys;
|
2013-05-24 10:49:19 +00:00
|
|
|
|
const ASTs & group_asts = select_query->group_expression_list->children;
|
|
|
|
|
for (size_t i = 0; i < group_asts.size(); ++i)
|
|
|
|
|
{
|
2013-06-11 16:21:25 +00:00
|
|
|
|
getRootActionsImpl(group_asts[i], true, false, temp_actions);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
NameAndTypePair key;
|
|
|
|
|
key.first = group_asts[i]->getColumnName();
|
2013-05-29 11:46:51 +00:00
|
|
|
|
key.second = temp_actions.getSampleBlock().getByName(key.first).type;
|
2013-05-24 10:49:19 +00:00
|
|
|
|
aggregation_keys.push_back(key);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-20 15:38:03 +00:00
|
|
|
|
if (!unique_keys.count(key.first))
|
|
|
|
|
{
|
|
|
|
|
aggregated_columns.push_back(key);
|
|
|
|
|
unique_keys.insert(key.first);
|
|
|
|
|
}
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
for (size_t i = 0; i < aggregate_descriptions.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
AggregateDescription & desc = aggregate_descriptions[i];
|
|
|
|
|
aggregated_columns.push_back(NameAndTypePair(desc.column_name, desc.function->getReturnType()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-10-17 13:32:32 +00:00
|
|
|
|
aggregated_columns = columns_after_array_join;
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-05-29 11:46:51 +00:00
|
|
|
|
NamesAndTypesList::iterator ExpressionAnalyzer::findColumn(const String & name, NamesAndTypesList & cols)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
|
|
|
|
NamesAndTypesList::iterator it;
|
2013-05-29 11:46:51 +00:00
|
|
|
|
for (it = cols.begin(); it != cols.end(); ++it)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
if (it->first == name)
|
|
|
|
|
break;
|
|
|
|
|
return it;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-10-21 11:33:25 +00:00
|
|
|
|
/// ignore_levels - алиасы в скольки верхних уровнях поддерева нужно игнорировать.
|
|
|
|
|
/// Например, при ignore_levels=1 ast не может быть занесен в словарь, но его дети могут.
|
2013-10-17 13:32:32 +00:00
|
|
|
|
void ExpressionAnalyzer::createAliasesDict(ASTPtr & ast, int ignore_levels)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
2013-10-17 13:32:32 +00:00
|
|
|
|
ASTSelectQuery * select = dynamic_cast<ASTSelectQuery *>(&*ast);
|
2013-08-01 14:43:04 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
/// Обход снизу-вверх. Не опускаемся в подзапросы.
|
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2013-10-17 13:32:32 +00:00
|
|
|
|
{
|
|
|
|
|
int new_ignore_levels = std::max(0, ignore_levels - 1);
|
2013-10-21 11:33:25 +00:00
|
|
|
|
/// Алиасы верхнего уровня в секции ARRAY JOIN имеют особый смысл, их добавлять не будем
|
|
|
|
|
/// (пропустим сам expression list и его детей).
|
2013-10-17 13:32:32 +00:00
|
|
|
|
if (select && *it == select->array_join_expression_list)
|
|
|
|
|
new_ignore_levels = 2;
|
2013-05-24 10:49:19 +00:00
|
|
|
|
if (!dynamic_cast<ASTSelectQuery *>(&**it))
|
2013-10-17 13:32:32 +00:00
|
|
|
|
createAliasesDict(*it, new_ignore_levels);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ignore_levels > 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2013-06-15 04:45:59 +00:00
|
|
|
|
std::string * alias = getAlias(ast);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
if (alias && !alias->empty())
|
|
|
|
|
{
|
|
|
|
|
if (aliases.count(*alias) && ast->getTreeID() != aliases[*alias]->getTreeID())
|
|
|
|
|
{
|
|
|
|
|
throw Exception("Different expressions with the same alias " + *alias, ErrorCodes::MULTIPLE_EXPRESSIONS_FOR_ALIAS);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
aliases[*alias] = ast;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StoragePtr ExpressionAnalyzer::getTable()
|
|
|
|
|
{
|
|
|
|
|
if (const ASTSelectQuery * select = dynamic_cast<const ASTSelectQuery *>(&*ast))
|
|
|
|
|
{
|
2014-01-28 16:45:10 +00:00
|
|
|
|
if (select->table && !dynamic_cast<const ASTSelectQuery *>(&*select->table) && !dynamic_cast<const ASTFunction *>(&*select->table))
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
2013-10-17 13:32:32 +00:00
|
|
|
|
String database = select->database ?
|
2013-05-24 10:49:19 +00:00
|
|
|
|
dynamic_cast<const ASTIdentifier &>(*select->database).name :
|
|
|
|
|
"";
|
|
|
|
|
const String & table = dynamic_cast<const ASTIdentifier &>(*select->table).name;
|
|
|
|
|
return context.tryGetTable(database, table);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return StoragePtr();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ExpressionAnalyzer::needSignRewrite()
|
|
|
|
|
{
|
|
|
|
|
if (settings.sign_rewrite && storage)
|
|
|
|
|
{
|
|
|
|
|
if (const StorageMergeTree * merge_tree = dynamic_cast<const StorageMergeTree *>(&*storage))
|
|
|
|
|
return merge_tree->getName() == "CollapsingMergeTree";
|
|
|
|
|
if (const StorageDistributed * distributed = dynamic_cast<const StorageDistributed *>(&*storage))
|
|
|
|
|
return !distributed->getSignColumnName().empty();
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String ExpressionAnalyzer::getSignColumnName()
|
|
|
|
|
{
|
|
|
|
|
if (const StorageMergeTree * merge_tree = dynamic_cast<const StorageMergeTree *>(&*storage))
|
|
|
|
|
return merge_tree->getSignColumnName();
|
|
|
|
|
if (const StorageDistributed * distributed = dynamic_cast<const StorageDistributed *>(&*storage))
|
|
|
|
|
return distributed->getSignColumnName();
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ASTPtr ExpressionAnalyzer::createSignColumn()
|
|
|
|
|
{
|
|
|
|
|
ASTIdentifier * p_sign_column = new ASTIdentifier(ast->range, sign_column_name);
|
|
|
|
|
ASTIdentifier & sign_column = *p_sign_column;
|
|
|
|
|
ASTPtr sign_column_node = p_sign_column;
|
|
|
|
|
sign_column.name = sign_column_name;
|
|
|
|
|
return sign_column_node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ASTPtr ExpressionAnalyzer::rewriteCount(const ASTFunction * node)
|
|
|
|
|
{
|
|
|
|
|
/// 'Sign'
|
|
|
|
|
ASTExpressionList * p_exp_list = new ASTExpressionList;
|
|
|
|
|
ASTExpressionList & exp_list = *p_exp_list;
|
|
|
|
|
ASTPtr exp_list_node = p_exp_list;
|
|
|
|
|
exp_list.children.push_back(createSignColumn());
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
/// sum(Sign)
|
|
|
|
|
ASTFunction * p_sum = new ASTFunction;
|
|
|
|
|
ASTFunction & sum = *p_sum;
|
|
|
|
|
ASTPtr sum_node = p_sum;
|
|
|
|
|
sum.name = "sum";
|
|
|
|
|
sum.alias = node->alias;
|
|
|
|
|
sum.arguments = exp_list_node;
|
|
|
|
|
sum.children.push_back(exp_list_node);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
return sum_node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ASTPtr ExpressionAnalyzer::rewriteSum(const ASTFunction * node)
|
2013-10-17 13:32:32 +00:00
|
|
|
|
{
|
2013-05-24 10:49:19 +00:00
|
|
|
|
/// 'x', 'Sign'
|
|
|
|
|
ASTExpressionList * p_mult_exp_list = new ASTExpressionList;
|
|
|
|
|
ASTExpressionList & mult_exp_list = *p_mult_exp_list;
|
|
|
|
|
ASTPtr mult_exp_list_node = p_mult_exp_list;
|
|
|
|
|
mult_exp_list.children.push_back(createSignColumn());
|
|
|
|
|
mult_exp_list.children.push_back(node->arguments->children[0]);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
/// x * Sign
|
|
|
|
|
ASTFunction * p_mult = new ASTFunction;
|
|
|
|
|
ASTFunction & mult = *p_mult;
|
|
|
|
|
ASTPtr mult_node = p_mult;
|
|
|
|
|
mult.name = "multiply";
|
|
|
|
|
mult.arguments = mult_exp_list_node;
|
|
|
|
|
mult.children.push_back(mult_exp_list_node);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
/// 'x * Sign'
|
|
|
|
|
ASTExpressionList * p_exp_list = new ASTExpressionList;
|
|
|
|
|
ASTExpressionList & exp_list = *p_exp_list;
|
|
|
|
|
ASTPtr exp_list_node = p_exp_list;
|
|
|
|
|
exp_list.children.push_back(mult_node);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
/// sum(x * Sign)
|
|
|
|
|
ASTFunction * p_sum = new ASTFunction;
|
|
|
|
|
ASTFunction & sum = *p_sum;
|
|
|
|
|
ASTPtr sum_node = p_sum;
|
|
|
|
|
sum.name = "sum";
|
|
|
|
|
sum.alias = node->alias;
|
|
|
|
|
sum.arguments = exp_list_node;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
sum.children.push_back(exp_list_node);
|
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
return sum_node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ASTPtr ExpressionAnalyzer::rewriteAvg(const ASTFunction * node)
|
|
|
|
|
{
|
|
|
|
|
/// node без alias для переписывания числителя и знаменателя
|
|
|
|
|
ASTPtr node_clone = node->clone();
|
|
|
|
|
ASTFunction * node_clone_func = dynamic_cast<ASTFunction *>(&*node_clone);
|
|
|
|
|
node_clone_func->alias = "";
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
/// 'sum(Sign * x)', 'sum(Sign)'
|
|
|
|
|
ASTExpressionList * p_div_exp_list = new ASTExpressionList;
|
|
|
|
|
ASTExpressionList & div_exp_list = *p_div_exp_list;
|
|
|
|
|
ASTPtr div_exp_list_node = p_div_exp_list;
|
|
|
|
|
div_exp_list.children.push_back(rewriteSum(node_clone_func));
|
|
|
|
|
div_exp_list.children.push_back(rewriteCount(node_clone_func));
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
/// sum(Sign * x) / sum(Sign)
|
|
|
|
|
ASTFunction * p_div = new ASTFunction;
|
|
|
|
|
ASTFunction & div = *p_div;
|
|
|
|
|
ASTPtr div_node = p_div;
|
|
|
|
|
div.name = "divide";
|
|
|
|
|
div.alias = node->alias;
|
|
|
|
|
div.arguments = div_exp_list_node;
|
|
|
|
|
div.children.push_back(div_exp_list_node);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
return div_node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-03 12:02:59 +00:00
|
|
|
|
bool ExpressionAnalyzer::considerSignRewrite(ASTPtr & ast)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
|
|
|
|
ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast);
|
2013-06-03 11:19:31 +00:00
|
|
|
|
if (!node)
|
2013-06-03 12:02:59 +00:00
|
|
|
|
return false;
|
2013-05-24 10:49:19 +00:00
|
|
|
|
const String & name = node->name;
|
|
|
|
|
if (name == "count")
|
|
|
|
|
ast = rewriteCount(node);
|
2013-06-03 12:02:59 +00:00
|
|
|
|
else if (name == "sum")
|
2013-05-24 10:49:19 +00:00
|
|
|
|
ast = rewriteSum(node);
|
2013-06-03 12:02:59 +00:00
|
|
|
|
else if (name == "avg")
|
2013-05-24 10:49:19 +00:00
|
|
|
|
ast = rewriteAvg(node);
|
2013-06-03 12:02:59 +00:00
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
return true;
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ExpressionAnalyzer::normalizeTree()
|
|
|
|
|
{
|
|
|
|
|
SetOfASTs tmp_set;
|
|
|
|
|
MapOfASTs tmp_map;
|
|
|
|
|
if (needSignRewrite())
|
|
|
|
|
sign_column_name = getSignColumnName();
|
2013-06-18 09:43:35 +00:00
|
|
|
|
normalizeTreeImpl(ast, tmp_map, tmp_set, "", false);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// finished_asts - уже обработанные вершины (и на что они заменены)
|
|
|
|
|
/// current_asts - вершины в текущем стеке вызовов этого метода
|
2013-10-18 08:07:51 +00:00
|
|
|
|
/// current_alias - алиас, повешенный на предка ast (самого глубокого из предков с алиасами)
|
2013-06-03 12:02:59 +00:00
|
|
|
|
/// in_sign_rewritten - находимся ли мы в поддереве, полученном в результате sign rewrite
|
2013-06-18 09:43:35 +00:00
|
|
|
|
void ExpressionAnalyzer::normalizeTreeImpl(ASTPtr & ast, MapOfASTs & finished_asts, SetOfASTs & current_asts, std::string current_alias, bool in_sign_rewritten)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
|
|
|
|
if (finished_asts.count(ast))
|
|
|
|
|
{
|
|
|
|
|
ast = finished_asts[ast];
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
ASTPtr initial_ast = ast;
|
|
|
|
|
current_asts.insert(initial_ast);
|
2013-06-15 07:10:06 +00:00
|
|
|
|
|
2013-06-18 09:43:35 +00:00
|
|
|
|
std::string * my_alias = getAlias(ast);
|
|
|
|
|
if (my_alias && !my_alias->empty())
|
2013-06-18 09:48:30 +00:00
|
|
|
|
current_alias = *my_alias;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-03 11:52:23 +00:00
|
|
|
|
/// rewrite правила, которые действуют при обходе сверху-вниз.
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-03 12:02:59 +00:00
|
|
|
|
if (!in_sign_rewritten && !sign_column_name.empty())
|
|
|
|
|
in_sign_rewritten = considerSignRewrite(ast);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-10-18 08:07:51 +00:00
|
|
|
|
bool replaced = false;
|
|
|
|
|
|
2013-06-03 11:52:23 +00:00
|
|
|
|
if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
/** Нет ли в таблице столбца, название которого полностью совпадает с записью функции?
|
|
|
|
|
* Например, в таблице есть столбец "domain(URL)", и мы запросили domain(URL).
|
|
|
|
|
*/
|
|
|
|
|
String function_string = node->getColumnName();
|
|
|
|
|
NamesAndTypesList::const_iterator it = findColumn(function_string);
|
|
|
|
|
if (columns.end() != it)
|
|
|
|
|
{
|
|
|
|
|
ASTIdentifier * ast_id = new ASTIdentifier(node->range, std::string(node->range.first, node->range.second));
|
|
|
|
|
ast = ast_id;
|
|
|
|
|
current_asts.insert(ast);
|
2013-10-18 08:07:51 +00:00
|
|
|
|
replaced = true;
|
2013-06-03 11:52:23 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ASTIdentifier * node = dynamic_cast<ASTIdentifier *>(&*ast))
|
2013-06-03 11:19:31 +00:00
|
|
|
|
{
|
2013-10-17 13:32:32 +00:00
|
|
|
|
if (node->kind == ASTIdentifier::Column)
|
2013-06-03 11:19:31 +00:00
|
|
|
|
{
|
2013-06-18 09:43:35 +00:00
|
|
|
|
/// Если это алиас, но не родительский алиас (чтобы работали конструкции вроде "SELECT column+1 AS column").
|
2013-06-03 11:19:31 +00:00
|
|
|
|
Aliases::const_iterator jt = aliases.find(node->name);
|
2013-06-18 09:43:35 +00:00
|
|
|
|
if (jt != aliases.end() && current_alias != node->name)
|
2013-06-03 11:19:31 +00:00
|
|
|
|
{
|
2013-10-18 08:07:51 +00:00
|
|
|
|
/// Заменим его на соответствующий узел дерева.
|
2013-06-15 07:10:06 +00:00
|
|
|
|
if (current_asts.count(jt->second))
|
|
|
|
|
throw Exception("Cyclic aliases", ErrorCodes::CYCLIC_ALIASES);
|
2013-10-18 08:07:51 +00:00
|
|
|
|
if (my_alias && !my_alias->empty() && *my_alias != jt->second->getAlias())
|
|
|
|
|
{
|
|
|
|
|
/// В конструкции вроде "a AS b", где a - алиас, нужно перевесить алиас b на результат подстановки алиаса a.
|
|
|
|
|
ast = jt->second->clone();
|
|
|
|
|
setAlias(ast, *my_alias);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ast = jt->second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
replaced = true;
|
2013-06-03 11:19:31 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/// Проверим имеет ли смысл sign-rewrite
|
2013-06-21 11:44:44 +00:00
|
|
|
|
if (!in_sign_rewritten && sign_column_name != "" && node->name == sign_column_name)
|
2013-06-03 11:19:31 +00:00
|
|
|
|
throw Exception("Requested Sign column while sign-rewrite is on.", ErrorCodes::QUERY_SECTION_DOESNT_MAKE_SENSE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ASTExpressionList * node = dynamic_cast<ASTExpressionList *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
/// Заменим * на список столбцов.
|
|
|
|
|
ASTs & asts = node->children;
|
|
|
|
|
for (int i = static_cast<int>(asts.size()) - 1; i >= 0; --i)
|
|
|
|
|
{
|
|
|
|
|
if (ASTAsterisk * asterisk = dynamic_cast<ASTAsterisk *>(&*asts[i]))
|
|
|
|
|
{
|
|
|
|
|
ASTs all_columns;
|
2014-01-10 13:24:50 +00:00
|
|
|
|
for (NamesAndTypesList::const_iterator it = columns.begin(); it != columns.end(); ++it)
|
2013-06-03 11:19:31 +00:00
|
|
|
|
all_columns.push_back(new ASTIdentifier(asterisk->range, it->first));
|
|
|
|
|
asts.erase(asts.begin() + i);
|
|
|
|
|
asts.insert(asts.begin() + i, all_columns.begin(), all_columns.end());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-10-18 08:07:51 +00:00
|
|
|
|
/// Если заменили корень поддерева вызовемся для нового корня снова - на случай, если алиас заменился на алиас.
|
|
|
|
|
if (replaced)
|
|
|
|
|
{
|
|
|
|
|
normalizeTreeImpl(ast, finished_asts, current_asts, current_alias, in_sign_rewritten);
|
|
|
|
|
current_asts.erase(initial_ast);
|
|
|
|
|
current_asts.erase(ast);
|
|
|
|
|
finished_asts[initial_ast] = ast;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-03 11:19:31 +00:00
|
|
|
|
/// Рекурсивные вызовы. Не опускаемся в подзапросы.
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
|
|
|
|
if (!dynamic_cast<ASTSelectQuery *>(&**it))
|
2013-06-18 09:48:30 +00:00
|
|
|
|
normalizeTreeImpl(*it, finished_asts, current_asts, current_alias, in_sign_rewritten);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
/// Если секция WHERE или HAVING состоит из одного алиаса, ссылку нужно заменить не только в children, но и в where_expression и having_expression.
|
|
|
|
|
if (ASTSelectQuery * select = dynamic_cast<ASTSelectQuery *>(&*ast))
|
|
|
|
|
{
|
2013-12-05 13:07:55 +00:00
|
|
|
|
if (select->prewhere_expression)
|
|
|
|
|
normalizeTreeImpl(select->prewhere_expression, finished_asts, current_asts, current_alias, in_sign_rewritten);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
if (select->where_expression)
|
2013-06-18 09:48:30 +00:00
|
|
|
|
normalizeTreeImpl(select->where_expression, finished_asts, current_asts, current_alias, in_sign_rewritten);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
if (select->having_expression)
|
2013-06-18 09:48:30 +00:00
|
|
|
|
normalizeTreeImpl(select->having_expression, finished_asts, current_asts, current_alias, in_sign_rewritten);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-18 09:43:35 +00:00
|
|
|
|
/// Действия, выполняемые снизу вверх.
|
|
|
|
|
|
2013-06-03 11:19:31 +00:00
|
|
|
|
if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
2014-02-28 13:09:43 +00:00
|
|
|
|
if (node->kind == ASTFunction::TABLE_FUNCTION)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
else if (node->name == "lambda")
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
2013-05-29 11:46:51 +00:00
|
|
|
|
node->kind = ASTFunction::LAMBDA_EXPRESSION;
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
else if (context.getAggregateFunctionFactory().isAggregateFunctionName(node->name))
|
|
|
|
|
{
|
2013-05-29 11:46:51 +00:00
|
|
|
|
node->kind = ASTFunction::AGGREGATE_FUNCTION;
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
2013-05-29 11:46:51 +00:00
|
|
|
|
else if (node->name == "arrayJoin")
|
|
|
|
|
{
|
|
|
|
|
node->kind = ASTFunction::ARRAY_JOIN;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
node->kind = ASTFunction::FUNCTION;
|
|
|
|
|
}
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
current_asts.erase(initial_ast);
|
|
|
|
|
current_asts.erase(ast);
|
|
|
|
|
finished_asts[initial_ast] = ast;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-11 16:21:25 +00:00
|
|
|
|
void ExpressionAnalyzer::makeSet(ASTFunction * node, const Block & sample_block)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
2013-05-29 11:46:51 +00:00
|
|
|
|
/** Нужно преобразовать правый аргумент в множество.
|
2013-06-26 16:31:49 +00:00
|
|
|
|
* Это может быть значение, перечисление значений или подзапрос.
|
2013-05-29 11:46:51 +00:00
|
|
|
|
* Перечисление значений парсится как функция tuple.
|
|
|
|
|
*/
|
|
|
|
|
IAST & args = *node->arguments;
|
|
|
|
|
ASTPtr & arg = args.children[1];
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-26 16:31:49 +00:00
|
|
|
|
if (dynamic_cast<ASTSet *>(&*arg))
|
|
|
|
|
return;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-29 11:46:51 +00:00
|
|
|
|
if (dynamic_cast<ASTSubquery *>(&*arg))
|
|
|
|
|
{
|
|
|
|
|
/// Исполняем подзапрос, превращаем результат в множество, и кладём это множество на место подзапроса.
|
|
|
|
|
ASTSet * ast_set = new ASTSet(arg->getColumnName());
|
2014-01-28 19:24:50 +00:00
|
|
|
|
|
|
|
|
|
/** Для подзапроса в секции IN не действуют ограничения на максимальный размер результата.
|
|
|
|
|
* Так как результат этого поздапроса - ещё не результат всего запроса.
|
|
|
|
|
* Вместо этого работают ограничения max_rows_in_set, max_bytes_in_set, set_overflow_mode.
|
|
|
|
|
*/
|
|
|
|
|
Context subquery_context = context;
|
|
|
|
|
Settings subquery_settings = context.getSettings();
|
|
|
|
|
subquery_settings.limits.max_result_rows = 0;
|
|
|
|
|
subquery_settings.limits.max_result_bytes = 0;
|
|
|
|
|
subquery_context.setSettings(subquery_settings);
|
|
|
|
|
|
|
|
|
|
InterpreterSelectQuery interpreter(arg->children[0], subquery_context, QueryProcessingStage::Complete, subquery_depth + 1);
|
2013-06-20 12:12:27 +00:00
|
|
|
|
ast_set->set = new Set(settings.limits);
|
2013-05-29 11:46:51 +00:00
|
|
|
|
ast_set->set->create(interpreter.execute());
|
|
|
|
|
arg = ast_set;
|
|
|
|
|
}
|
2013-06-26 16:31:49 +00:00
|
|
|
|
else
|
2013-05-29 11:46:51 +00:00
|
|
|
|
{
|
|
|
|
|
/// Случай явного перечисления значений.
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-29 11:46:51 +00:00
|
|
|
|
DataTypes set_element_types;
|
|
|
|
|
ASTPtr & left_arg = args.children[0];
|
|
|
|
|
|
|
|
|
|
ASTFunction * left_arg_tuple = dynamic_cast<ASTFunction *>(&*left_arg);
|
|
|
|
|
|
|
|
|
|
if (left_arg_tuple && left_arg_tuple->name == "tuple")
|
|
|
|
|
{
|
|
|
|
|
for (ASTs::const_iterator it = left_arg_tuple->arguments->children.begin();
|
|
|
|
|
it != left_arg_tuple->arguments->children.end();
|
|
|
|
|
++it)
|
2013-07-26 13:46:52 +00:00
|
|
|
|
set_element_types.push_back(sample_block.getByName((*it)->getColumnName()).type);
|
2013-05-29 11:46:51 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-06-11 16:21:25 +00:00
|
|
|
|
DataTypePtr left_type = sample_block.getByName(left_arg->getColumnName()).type;
|
2013-05-29 11:46:51 +00:00
|
|
|
|
if (DataTypeArray * array_type = dynamic_cast<DataTypeArray *>(&*left_type))
|
|
|
|
|
set_element_types.push_back(array_type->getNestedType());
|
|
|
|
|
else
|
|
|
|
|
set_element_types.push_back(left_type);
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-26 16:31:49 +00:00
|
|
|
|
/// Отличим случай x in (1, 2) от случая x in 1 (он же x in (1)).
|
|
|
|
|
bool single_value = false;
|
|
|
|
|
ASTPtr elements_ast = arg;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-26 16:31:49 +00:00
|
|
|
|
if (ASTFunction * set_func = dynamic_cast<ASTFunction *>(&*arg))
|
|
|
|
|
{
|
|
|
|
|
if (set_func->name != "tuple")
|
|
|
|
|
throw Exception("Incorrect type of 2nd argument for function " + node->name + ". Must be subquery or set of values.",
|
|
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-26 16:31:49 +00:00
|
|
|
|
/// Отличм случай (x, y) in ((1, 2), (3, 4)) от случая (x, y) in (1, 2).
|
|
|
|
|
ASTFunction * any_element = dynamic_cast<ASTFunction *>(&*set_func->arguments->children[0]);
|
|
|
|
|
if (set_element_types.size() >= 2 && (!any_element || any_element->name != "tuple"))
|
|
|
|
|
single_value = true;
|
|
|
|
|
else
|
|
|
|
|
elements_ast = set_func->arguments;
|
|
|
|
|
}
|
|
|
|
|
else if (dynamic_cast<ASTLiteral *>(&*arg))
|
|
|
|
|
{
|
|
|
|
|
single_value = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
throw Exception("Incorrect type of 2nd argument for function " + node->name + ". Must be subquery or set of values.",
|
|
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-26 16:31:49 +00:00
|
|
|
|
if (single_value)
|
|
|
|
|
{
|
|
|
|
|
ASTPtr exp_list = new ASTExpressionList;
|
|
|
|
|
exp_list->children.push_back(elements_ast);
|
|
|
|
|
elements_ast = exp_list;
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-29 11:46:51 +00:00
|
|
|
|
ASTSet * ast_set = new ASTSet(arg->getColumnName());
|
2013-06-20 12:12:27 +00:00
|
|
|
|
ast_set->set = new Set(settings.limits);
|
2013-06-26 16:31:49 +00:00
|
|
|
|
ast_set->set->create(set_element_types, elements_ast);
|
2013-05-29 11:46:51 +00:00
|
|
|
|
arg = ast_set;
|
|
|
|
|
}
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static std::string getUniqueName(const Block & block, const std::string & prefix)
|
|
|
|
|
{
|
|
|
|
|
int i = 1;
|
2013-06-21 20:34:19 +00:00
|
|
|
|
while (block.has(prefix + toString(i)))
|
2013-05-24 10:49:19 +00:00
|
|
|
|
++i;
|
2013-06-21 20:34:19 +00:00
|
|
|
|
return prefix + toString(i);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-11 16:21:25 +00:00
|
|
|
|
void ExpressionAnalyzer::getRootActionsImpl(ASTPtr ast, bool no_subqueries, bool only_consts, ExpressionActions & actions)
|
|
|
|
|
{
|
|
|
|
|
ScopeStack scopes(actions, settings);
|
2013-07-26 16:11:31 +00:00
|
|
|
|
getActionsImpl(ast, no_subqueries, only_consts, scopes);
|
2013-06-11 16:21:25 +00:00
|
|
|
|
actions = *scopes.popLevel();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-08-01 13:29:32 +00:00
|
|
|
|
void ExpressionAnalyzer::getArrayJoinedColumns()
|
|
|
|
|
{
|
2013-10-17 13:32:32 +00:00
|
|
|
|
if (select_query && select_query->array_join_expression_list)
|
|
|
|
|
{
|
2013-10-21 11:33:25 +00:00
|
|
|
|
ASTs & array_join_asts = select_query->array_join_expression_list->children;
|
|
|
|
|
for (size_t i = 0; i < array_join_asts .size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
ASTPtr ast = array_join_asts [i];
|
|
|
|
|
|
|
|
|
|
String nested_table_name = ast->getColumnName();
|
|
|
|
|
String nested_table_alias = ast->getAlias();
|
|
|
|
|
if (nested_table_alias == nested_table_name && !dynamic_cast<ASTIdentifier *>(&*ast))
|
|
|
|
|
throw Exception("No alias for non-trivial value in ARRAY JOIN: " + nested_table_name, ErrorCodes::ALIAS_REQUIRED);
|
|
|
|
|
|
|
|
|
|
if (array_join_alias_to_name.count(nested_table_alias) || aliases.count(nested_table_alias))
|
|
|
|
|
throw Exception("Duplicate alias " + nested_table_alias, ErrorCodes::MULTIPLE_EXPRESSIONS_FOR_ALIAS);
|
|
|
|
|
array_join_alias_to_name[nested_table_alias] = nested_table_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ASTs & query_asts = select_query->children;
|
|
|
|
|
for (size_t i = 0; i < query_asts.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
ASTPtr ast = query_asts[i];
|
|
|
|
|
if (select_query && ast == select_query->array_join_expression_list)
|
|
|
|
|
continue;
|
|
|
|
|
getArrayJoinedColumnsImpl(ast);
|
|
|
|
|
}
|
2013-10-18 08:40:14 +00:00
|
|
|
|
|
|
|
|
|
/// Если результат ARRAY JOIN не используется, придется все равно по-ARRAY-JOIN-ить какой-нибудь столбец,
|
|
|
|
|
/// чтобы получить правильное количество строк.
|
2013-10-21 11:33:25 +00:00
|
|
|
|
if (array_join_result_to_source.empty())
|
2013-10-18 08:40:14 +00:00
|
|
|
|
{
|
|
|
|
|
ASTPtr expr = select_query->array_join_expression_list->children[0];
|
|
|
|
|
String source_name = expr->getColumnName();
|
|
|
|
|
String result_name = expr->getAlias();
|
|
|
|
|
/// Это массив.
|
|
|
|
|
if (!dynamic_cast<ASTIdentifier *>(&*expr) || findColumn(source_name, columns) != columns.end())
|
|
|
|
|
{
|
2013-10-21 11:33:25 +00:00
|
|
|
|
array_join_result_to_source[result_name] = source_name;
|
2013-10-18 08:40:14 +00:00
|
|
|
|
}
|
|
|
|
|
else /// Это вложенная таблица.
|
|
|
|
|
{
|
|
|
|
|
bool found = false;
|
|
|
|
|
for (NamesAndTypesList::iterator it = columns.begin(); it != columns.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
String table_name = DataTypeNested::extractNestedTableName(it->first);
|
|
|
|
|
String column_name = DataTypeNested::extractNestedColumnName(it->first);
|
|
|
|
|
if (table_name == source_name)
|
|
|
|
|
{
|
2013-10-21 11:33:25 +00:00
|
|
|
|
array_join_result_to_source[DataTypeNested::concatenateNestedName(result_name, column_name)]
|
|
|
|
|
= it->first;
|
2013-10-18 08:40:14 +00:00
|
|
|
|
found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-21 11:33:25 +00:00
|
|
|
|
if (!found)
|
|
|
|
|
throw Exception("No columns in nested table " + source_name, ErrorCodes::EMPTY_NESTED_TABLE);
|
2013-10-18 08:40:14 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
}
|
2013-08-01 13:29:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ExpressionAnalyzer::getArrayJoinedColumnsImpl(ASTPtr ast)
|
2013-07-26 16:11:31 +00:00
|
|
|
|
{
|
|
|
|
|
if (ASTIdentifier * node = dynamic_cast<ASTIdentifier *>(&*ast))
|
|
|
|
|
{
|
2013-10-21 11:33:25 +00:00
|
|
|
|
if (node->kind == ASTIdentifier::Column)
|
|
|
|
|
{
|
|
|
|
|
String table_name = DataTypeNested::extractNestedTableName(node->name);
|
|
|
|
|
if (array_join_alias_to_name.count(node->name))
|
|
|
|
|
array_join_result_to_source[node->name] = array_join_alias_to_name[node->name];
|
|
|
|
|
else if (array_join_alias_to_name.count(table_name))
|
|
|
|
|
{
|
|
|
|
|
String nested_column = DataTypeNested::extractNestedColumnName(node->name);
|
|
|
|
|
array_join_result_to_source[node->name]
|
|
|
|
|
= DataTypeNested::concatenateNestedName(array_join_alias_to_name[table_name], nested_column);
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-07-26 16:11:31 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2013-07-26 17:21:01 +00:00
|
|
|
|
if (!dynamic_cast<ASTSelectQuery *>(&**it))
|
2013-08-01 13:29:32 +00:00
|
|
|
|
getArrayJoinedColumnsImpl(*it);
|
2013-07-26 16:11:31 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ExpressionAnalyzer::getActionsImpl(ASTPtr ast, bool no_subqueries, bool only_consts, ScopeStack & actions_stack)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
|
|
|
|
/// Если результат вычисления уже есть в блоке.
|
2013-06-26 16:31:49 +00:00
|
|
|
|
if ((dynamic_cast<ASTFunction *>(&*ast) || dynamic_cast<ASTLiteral *>(&*ast))
|
2013-06-11 16:21:25 +00:00
|
|
|
|
&& actions_stack.getSampleBlock().has(ast->getColumnName()))
|
2013-05-24 10:49:19 +00:00
|
|
|
|
return;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2014-01-13 11:29:24 +00:00
|
|
|
|
if (ASTIdentifier * node = dynamic_cast<ASTIdentifier *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
std::string name = node->getColumnName();
|
|
|
|
|
if (!only_consts && !actions_stack.getSampleBlock().has(name))
|
|
|
|
|
{
|
|
|
|
|
/// Запрошенного столбца нет в блоке.
|
|
|
|
|
/// Если такой столбец есть до агрегации, значит пользователь наверно забыл окружить его агрегатной функцией или добавить в GROUP BY.
|
|
|
|
|
|
|
|
|
|
bool found = false;
|
|
|
|
|
for (NamesAndTypesList::const_iterator it = columns_after_array_join.begin();
|
|
|
|
|
it != columns_after_array_join.end(); ++it)
|
|
|
|
|
if (it->first == name)
|
|
|
|
|
found = true;
|
|
|
|
|
|
|
|
|
|
if (found)
|
|
|
|
|
throw Exception("Column " + name + " is not under aggregate function and not in GROUP BY.",
|
2014-01-29 19:00:19 +00:00
|
|
|
|
ErrorCodes::NOT_AN_AGGREGATE);
|
2014-01-13 11:29:24 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
2013-05-29 11:46:51 +00:00
|
|
|
|
if (node->kind == ASTFunction::LAMBDA_EXPRESSION)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
throw Exception("Unexpected expression", ErrorCodes::UNEXPECTED_EXPRESSION);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
if (node->kind == ASTFunction::ARRAY_JOIN)
|
|
|
|
|
{
|
|
|
|
|
if (node->arguments->children.size() != 1)
|
|
|
|
|
throw Exception("arrayJoin requires exactly 1 argument", ErrorCodes::TYPE_MISMATCH);
|
|
|
|
|
ASTPtr arg = node->arguments->children[0];
|
2013-07-26 16:11:31 +00:00
|
|
|
|
getActionsImpl(arg, no_subqueries, only_consts, actions_stack);
|
2013-05-30 16:52:21 +00:00
|
|
|
|
if (!only_consts)
|
2013-08-01 16:00:38 +00:00
|
|
|
|
{
|
2013-10-17 13:32:32 +00:00
|
|
|
|
String result_name = node->getColumnName();
|
|
|
|
|
actions_stack.addAction(ExpressionActions::Action::copyColumn(arg->getColumnName(), result_name));
|
|
|
|
|
NameSet joined_columns;
|
|
|
|
|
joined_columns.insert(result_name);
|
|
|
|
|
actions_stack.addAction(ExpressionActions::Action::arrayJoin(joined_columns));
|
2013-08-01 16:00:38 +00:00
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-29 11:46:51 +00:00
|
|
|
|
if (node->kind == ASTFunction::FUNCTION)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
|
|
|
|
if (node->name == "in" || node->name == "notIn")
|
|
|
|
|
{
|
|
|
|
|
if (!no_subqueries)
|
|
|
|
|
{
|
2013-05-29 11:46:51 +00:00
|
|
|
|
/// Найдем тип первого аргумента (потом getActionsImpl вызовется для него снова и ни на что не повлияет).
|
2013-07-26 16:11:31 +00:00
|
|
|
|
getActionsImpl(node->arguments->children[0], no_subqueries, only_consts, actions_stack);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
/// Превратим tuple или подзапрос в множество.
|
2013-06-11 16:21:25 +00:00
|
|
|
|
makeSet(node, actions_stack.getSampleBlock());
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/// Мы в той части дерева, которую не собираемся вычислять. Нужно только определить типы.
|
|
|
|
|
/// Не будем выполнять подзапросы и составлять множества. Вставим произвольный столбец правильного типа.
|
|
|
|
|
ColumnWithNameAndType fake_column;
|
|
|
|
|
fake_column.name = node->getColumnName();
|
|
|
|
|
fake_column.type = new DataTypeUInt8;
|
|
|
|
|
fake_column.column = new ColumnConstUInt8(1, 0);
|
2013-06-11 16:21:25 +00:00
|
|
|
|
actions_stack.addAction(ExpressionActions::Action::addColumn(fake_column));
|
2013-07-26 16:11:31 +00:00
|
|
|
|
getActionsImpl(node->arguments, no_subqueries, only_consts, actions_stack);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
FunctionPtr function = context.getFunctionFactory().get(node->name, context);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
Names argument_names;
|
|
|
|
|
DataTypes argument_types;
|
2013-06-03 14:33:14 +00:00
|
|
|
|
bool arguments_present = true;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
/// Если у функции есть аргумент-лямбда-выражение, нужно определить его тип до рекурсивного вызова.
|
|
|
|
|
bool has_lambda_arguments = false;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
for (size_t i = 0; i < node->arguments->children.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
ASTPtr child = node->arguments->children[i];
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
ASTFunction * lambda = dynamic_cast<ASTFunction *>(&*child);
|
2013-06-26 16:31:49 +00:00
|
|
|
|
ASTSet * set = dynamic_cast<ASTSet *>(&*child);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
if (lambda && lambda->name == "lambda")
|
|
|
|
|
{
|
2013-06-03 14:33:14 +00:00
|
|
|
|
/// Если аргумент - лямбда-выражение, только запомним его примерный тип.
|
2013-05-24 10:49:19 +00:00
|
|
|
|
if (lambda->arguments->children.size() != 2)
|
|
|
|
|
throw Exception("lambda requires two arguments", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
ASTFunction * lambda_args_tuple = dynamic_cast<ASTFunction *>(&*lambda->arguments->children[0]);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
if (!lambda_args_tuple || lambda_args_tuple->name != "tuple")
|
|
|
|
|
throw Exception("First argument of lambda must be a tuple", ErrorCodes::TYPE_MISMATCH);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
has_lambda_arguments = true;
|
|
|
|
|
argument_types.push_back(new DataTypeExpression(DataTypes(lambda_args_tuple->arguments->children.size())));
|
2013-06-05 13:15:52 +00:00
|
|
|
|
/// Выберем название в следующем цикле.
|
|
|
|
|
argument_names.push_back("");
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
2013-06-26 16:31:49 +00:00
|
|
|
|
else if (set)
|
|
|
|
|
{
|
|
|
|
|
/// Если аргумент - множество, дадим ему уникальное имя,
|
|
|
|
|
/// чтобы множества с одинаковой записью не склеивались (у них может быть разный тип).
|
|
|
|
|
ColumnWithNameAndType column;
|
|
|
|
|
column.column = new ColumnSet(1, set->set);
|
|
|
|
|
column.type = new DataTypeSet;
|
|
|
|
|
column.name = getUniqueName(actions_stack.getSampleBlock(), "__set");
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-26 16:31:49 +00:00
|
|
|
|
actions_stack.addAction(ExpressionActions::Action::addColumn(column));
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-26 16:31:49 +00:00
|
|
|
|
argument_types.push_back(column.type);
|
|
|
|
|
argument_names.push_back(column.name);
|
|
|
|
|
}
|
2013-05-24 10:49:19 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2013-06-03 14:33:14 +00:00
|
|
|
|
/// Если аргумент не лямбда-выражение, вызовемся рекурсивно и узнаем его тип.
|
2013-07-26 16:11:31 +00:00
|
|
|
|
getActionsImpl(child, no_subqueries, only_consts, actions_stack);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
std::string name = child->getColumnName();
|
2013-06-11 16:21:25 +00:00
|
|
|
|
if (actions_stack.getSampleBlock().has(name))
|
2013-06-03 14:33:14 +00:00
|
|
|
|
{
|
2013-06-11 16:21:25 +00:00
|
|
|
|
argument_types.push_back(actions_stack.getSampleBlock().getByName(name).type);
|
2013-06-03 14:33:14 +00:00
|
|
|
|
argument_names.push_back(name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (only_consts)
|
|
|
|
|
{
|
|
|
|
|
arguments_present = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
throw Exception("Unknown identifier: " + name, ErrorCodes::UNKNOWN_IDENTIFIER);
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-03 14:33:14 +00:00
|
|
|
|
if (only_consts && !arguments_present)
|
|
|
|
|
return;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-11 16:21:25 +00:00
|
|
|
|
Names additional_requirements;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
if (has_lambda_arguments && !only_consts)
|
|
|
|
|
{
|
|
|
|
|
function->getLambdaArgumentTypes(argument_types);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
/// Вызовемся рекурсивно для лямбда-выражений.
|
|
|
|
|
for (size_t i = 0; i < node->arguments->children.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
ASTPtr child = node->arguments->children[i];
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
ASTFunction * lambda = dynamic_cast<ASTFunction *>(&*child);
|
|
|
|
|
if (lambda && lambda->name == "lambda")
|
|
|
|
|
{
|
|
|
|
|
DataTypeExpression * lambda_type = dynamic_cast<DataTypeExpression *>(&*argument_types[i]);
|
|
|
|
|
ASTFunction * lambda_args_tuple = dynamic_cast<ASTFunction *>(&*lambda->arguments->children[0]);
|
|
|
|
|
ASTs lambda_arg_asts = lambda_args_tuple->arguments->children;
|
2013-06-11 16:21:25 +00:00
|
|
|
|
NamesAndTypesList lambda_arguments;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
for (size_t j = 0; j < lambda_arg_asts.size(); ++j)
|
|
|
|
|
{
|
|
|
|
|
ASTIdentifier * identifier = dynamic_cast<ASTIdentifier *>(&*lambda_arg_asts[j]);
|
|
|
|
|
if (!identifier)
|
|
|
|
|
throw Exception("lambda argument declarations must be identifiers", ErrorCodes::TYPE_MISMATCH);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
String arg_name = identifier->name;
|
|
|
|
|
NameAndTypePair arg(arg_name, lambda_type->getArgumentTypes()[j]);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-11 16:21:25 +00:00
|
|
|
|
lambda_arguments.push_back(arg);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-11 16:21:25 +00:00
|
|
|
|
actions_stack.pushLevel(lambda_arguments);
|
2013-07-26 16:11:31 +00:00
|
|
|
|
getActionsImpl(lambda->arguments->children[1], no_subqueries, only_consts, actions_stack);
|
2013-06-11 16:21:25 +00:00
|
|
|
|
ExpressionActionsPtr lambda_actions = actions_stack.popLevel();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
String result_name = lambda->arguments->children[1]->getColumnName();
|
2013-05-28 11:54:37 +00:00
|
|
|
|
lambda_actions->finalize(Names(1, result_name));
|
2013-05-24 10:49:19 +00:00
|
|
|
|
DataTypePtr result_type = lambda_actions->getSampleBlock().getByName(result_name).type;
|
2013-06-03 14:08:08 +00:00
|
|
|
|
argument_types[i] = new DataTypeExpression(lambda_type->getArgumentTypes(), result_type);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-11 16:21:25 +00:00
|
|
|
|
Names captured = lambda_actions->getRequiredColumns();
|
|
|
|
|
for (size_t j = 0; j < captured.size(); ++j)
|
|
|
|
|
{
|
|
|
|
|
if (findColumn(captured[j], lambda_arguments) == lambda_arguments.end())
|
|
|
|
|
additional_requirements.push_back(captured[j]);
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-05 13:15:52 +00:00
|
|
|
|
/// Не можем дать название getColumnName(),
|
|
|
|
|
/// потому что оно не однозначно определяет выражение (типы аргументов могут быть разными).
|
2013-06-11 16:21:25 +00:00
|
|
|
|
argument_names[i] = getUniqueName(actions_stack.getSampleBlock(), "__lambda");
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
ColumnWithNameAndType lambda_column;
|
2013-06-11 16:21:25 +00:00
|
|
|
|
lambda_column.column = new ColumnExpression(1, lambda_actions, lambda_arguments, result_type, result_name);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
lambda_column.type = argument_types[i];
|
|
|
|
|
lambda_column.name = argument_names[i];
|
2013-06-11 16:21:25 +00:00
|
|
|
|
actions_stack.addAction(ExpressionActions::Action::addColumn(lambda_column));
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
if (only_consts)
|
|
|
|
|
{
|
|
|
|
|
for (size_t i = 0; i < argument_names.size(); ++i)
|
|
|
|
|
{
|
2013-06-11 16:21:25 +00:00
|
|
|
|
if (!actions_stack.getSampleBlock().has(argument_names[i]))
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
2013-06-03 14:33:14 +00:00
|
|
|
|
arguments_present = false;
|
2013-05-24 10:49:19 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-03 14:33:14 +00:00
|
|
|
|
if (arguments_present)
|
2013-06-11 16:21:25 +00:00
|
|
|
|
actions_stack.addAction(ExpressionActions::Action::applyFunction(function, argument_names, node->getColumnName()),
|
|
|
|
|
additional_requirements);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ASTLiteral * node = dynamic_cast<ASTLiteral *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
DataTypePtr type = apply_visitor(FieldToDataType(), node->value);
|
|
|
|
|
ColumnWithNameAndType column;
|
|
|
|
|
column.column = type->createConstColumn(1, node->value);
|
|
|
|
|
column.type = type;
|
|
|
|
|
column.name = node->getColumnName();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-11 16:21:25 +00:00
|
|
|
|
actions_stack.addAction(ExpressionActions::Action::addColumn(column));
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (ASTs::iterator it = ast->children.begin(); it != ast->children.end(); ++it)
|
2013-07-26 16:11:31 +00:00
|
|
|
|
getActionsImpl(*it, no_subqueries, only_consts, actions_stack);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ExpressionAnalyzer::getAggregatesImpl(ASTPtr ast, ExpressionActions & actions)
|
|
|
|
|
{
|
|
|
|
|
ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast);
|
2013-05-29 11:46:51 +00:00
|
|
|
|
if (node && node->kind == ASTFunction::AGGREGATE_FUNCTION)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
2013-05-29 11:46:51 +00:00
|
|
|
|
has_aggregation = true;
|
2013-05-24 10:49:19 +00:00
|
|
|
|
AggregateDescription aggregate;
|
|
|
|
|
aggregate.column_name = node->getColumnName();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
for (size_t i = 0; i < aggregate_descriptions.size(); ++i)
|
|
|
|
|
if (aggregate_descriptions[i].column_name == aggregate.column_name)
|
|
|
|
|
return;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
ASTs & arguments = node->arguments->children;
|
|
|
|
|
aggregate.argument_names.resize(arguments.size());
|
|
|
|
|
DataTypes types(arguments.size());
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
for (size_t i = 0; i < arguments.size(); ++i)
|
|
|
|
|
{
|
2013-06-11 16:21:25 +00:00
|
|
|
|
getRootActionsImpl(arguments[i], true, false, actions);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
const std::string & name = arguments[i]->getColumnName();
|
|
|
|
|
types[i] = actions.getSampleBlock().getByName(name).type;
|
|
|
|
|
aggregate.argument_names[i] = name;
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-27 14:02:55 +00:00
|
|
|
|
aggregate.function = context.getAggregateFunctionFactory().get(node->name, types);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-27 14:02:55 +00:00
|
|
|
|
if (node->parameters)
|
|
|
|
|
{
|
|
|
|
|
ASTs & parameters = dynamic_cast<ASTExpressionList &>(*node->parameters).children;
|
|
|
|
|
Row params_row(parameters.size());
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-27 14:02:55 +00:00
|
|
|
|
for (size_t i = 0; i < parameters.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
ASTLiteral * lit = dynamic_cast<ASTLiteral *>(&*parameters[i]);
|
|
|
|
|
if (!lit)
|
|
|
|
|
throw Exception("Parameters to aggregate functions must be literals", ErrorCodes::PARAMETERS_TO_AGGREGATE_FUNCTIONS_MUST_BE_LITERALS);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-27 14:02:55 +00:00
|
|
|
|
params_row[i] = lit->value;
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-27 14:02:55 +00:00
|
|
|
|
aggregate.function->setParameters(params_row);
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-27 14:02:55 +00:00
|
|
|
|
aggregate.function->setArguments(types);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
aggregate_descriptions.push_back(aggregate);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (size_t i = 0; i < ast->children.size(); ++i)
|
|
|
|
|
{
|
2013-06-21 11:32:27 +00:00
|
|
|
|
ASTPtr child = ast->children[i];
|
|
|
|
|
if (!dynamic_cast<ASTSubquery *>(&*child) && !dynamic_cast<ASTSelectQuery *>(&*child))
|
|
|
|
|
getAggregatesImpl(child, actions);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
void ExpressionAnalyzer::assertSelect()
|
|
|
|
|
{
|
|
|
|
|
if (!select_query)
|
|
|
|
|
throw Exception("Not a select query", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
}
|
2013-06-14 16:38:54 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
void ExpressionAnalyzer::assertAggregation()
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
|
|
|
|
if (!has_aggregation)
|
|
|
|
|
throw Exception("No aggregation", ErrorCodes::LOGICAL_ERROR);
|
2013-05-28 11:54:37 +00:00
|
|
|
|
}
|
2013-06-14 16:38:54 +00:00
|
|
|
|
|
2013-05-28 14:24:20 +00:00
|
|
|
|
void ExpressionAnalyzer::initChain(ExpressionActionsChain & chain, NamesAndTypesList & columns)
|
|
|
|
|
{
|
|
|
|
|
if (chain.steps.empty())
|
|
|
|
|
{
|
|
|
|
|
chain.settings = settings;
|
|
|
|
|
chain.steps.push_back(ExpressionActionsChain::Step(new ExpressionActions(columns, settings)));
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-05-28 11:54:37 +00:00
|
|
|
|
|
2013-10-17 13:32:32 +00:00
|
|
|
|
void ExpressionAnalyzer::addMultipleArrayJoinAction(ExpressionActions & actions)
|
|
|
|
|
{
|
2013-10-21 11:33:25 +00:00
|
|
|
|
NameSet result_columns;
|
|
|
|
|
for (NameToNameMap::iterator it = array_join_result_to_source.begin(); it != array_join_result_to_source.end(); ++it)
|
2013-10-17 13:32:32 +00:00
|
|
|
|
{
|
2013-10-21 11:33:25 +00:00
|
|
|
|
if (it->first != it->second)
|
|
|
|
|
actions.add(ExpressionActions::Action::copyColumn(it->second, it->first));
|
|
|
|
|
result_columns.insert(it->first);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-10-21 11:33:25 +00:00
|
|
|
|
actions.add(ExpressionActions::Action::arrayJoin(result_columns));
|
2013-10-17 13:32:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-07-26 16:33:05 +00:00
|
|
|
|
bool ExpressionAnalyzer::appendArrayJoin(ExpressionActionsChain & chain)
|
|
|
|
|
{
|
|
|
|
|
assertSelect();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
|
|
|
|
if (!select_query->array_join_expression_list)
|
2013-07-26 16:33:05 +00:00
|
|
|
|
return false;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-07-26 16:33:05 +00:00
|
|
|
|
initChain(chain, columns);
|
|
|
|
|
ExpressionActionsChain::Step & step = chain.steps.back();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
|
|
|
|
getRootActionsImpl(select_query->array_join_expression_list, false, false, *step.actions);
|
|
|
|
|
|
|
|
|
|
addMultipleArrayJoinAction(*step.actions);
|
2013-10-21 11:33:25 +00:00
|
|
|
|
|
|
|
|
|
for (NameToNameMap::iterator it = array_join_result_to_source.begin(); it != array_join_result_to_source.end(); ++it)
|
|
|
|
|
step.required_output.push_back(it->first);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-07-26 16:33:05 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
bool ExpressionAnalyzer::appendWhere(ExpressionActionsChain & chain)
|
|
|
|
|
{
|
|
|
|
|
assertSelect();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
if (!select_query->where_expression)
|
|
|
|
|
return false;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
|
|
|
|
initChain(chain, columns_after_array_join);
|
2013-05-28 14:24:20 +00:00
|
|
|
|
ExpressionActionsChain::Step & step = chain.steps.back();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 14:24:20 +00:00
|
|
|
|
step.required_output.push_back(select_query->where_expression->getColumnName());
|
2013-06-11 16:21:25 +00:00
|
|
|
|
getRootActionsImpl(select_query->where_expression, false, false, *step.actions);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ExpressionAnalyzer::appendGroupBy(ExpressionActionsChain & chain)
|
|
|
|
|
{
|
|
|
|
|
assertAggregation();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
if (!select_query->group_expression_list)
|
|
|
|
|
return false;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
initChain(chain, columns);
|
2013-05-28 14:24:20 +00:00
|
|
|
|
ExpressionActionsChain::Step & step = chain.steps.back();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
ASTs asts = select_query->group_expression_list->children;
|
2013-05-24 10:49:19 +00:00
|
|
|
|
for (size_t i = 0; i < asts.size(); ++i)
|
|
|
|
|
{
|
2013-05-28 14:24:20 +00:00
|
|
|
|
step.required_output.push_back(asts[i]->getColumnName());
|
2013-06-11 16:21:25 +00:00
|
|
|
|
getRootActionsImpl(asts[i], false, false, *step.actions);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExpressionAnalyzer::appendAggregateFunctionsArguments(ExpressionActionsChain & chain)
|
|
|
|
|
{
|
|
|
|
|
assertAggregation();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
|
|
|
|
initChain(chain, columns_after_array_join);
|
2013-05-28 14:24:20 +00:00
|
|
|
|
ExpressionActionsChain::Step & step = chain.steps.back();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-29 11:46:51 +00:00
|
|
|
|
for (size_t i = 0; i < aggregate_descriptions.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
for (size_t j = 0; j < aggregate_descriptions[i].argument_names.size(); ++j)
|
|
|
|
|
{
|
|
|
|
|
step.required_output.push_back(aggregate_descriptions[i].argument_names[j]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-29 11:46:51 +00:00
|
|
|
|
getActionsBeforeAggregationImpl(select_query->select_expression_list, *step.actions);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
if (select_query->having_expression)
|
2013-05-29 11:46:51 +00:00
|
|
|
|
getActionsBeforeAggregationImpl(select_query->having_expression, *step.actions);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
if (select_query->order_expression_list)
|
2013-05-29 11:46:51 +00:00
|
|
|
|
getActionsBeforeAggregationImpl(select_query->order_expression_list, *step.actions);
|
2013-05-28 11:54:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ExpressionAnalyzer::appendHaving(ExpressionActionsChain & chain)
|
|
|
|
|
{
|
|
|
|
|
assertAggregation();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
if (!select_query->having_expression)
|
|
|
|
|
return false;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 14:24:20 +00:00
|
|
|
|
initChain(chain, aggregated_columns);
|
|
|
|
|
ExpressionActionsChain::Step & step = chain.steps.back();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 14:24:20 +00:00
|
|
|
|
step.required_output.push_back(select_query->having_expression->getColumnName());
|
2013-06-11 16:21:25 +00:00
|
|
|
|
getRootActionsImpl(select_query->having_expression, false, false, *step.actions);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
return true;
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
void ExpressionAnalyzer::appendSelect(ExpressionActionsChain & chain)
|
|
|
|
|
{
|
|
|
|
|
assertSelect();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 14:24:20 +00:00
|
|
|
|
initChain(chain, aggregated_columns);
|
|
|
|
|
ExpressionActionsChain::Step & step = chain.steps.back();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-11 16:21:25 +00:00
|
|
|
|
getRootActionsImpl(select_query->select_expression_list, false, false, *step.actions);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 14:24:20 +00:00
|
|
|
|
ASTs asts = select_query->select_expression_list->children;
|
|
|
|
|
for (size_t i = 0; i < asts.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
step.required_output.push_back(asts[i]->getColumnName());
|
|
|
|
|
}
|
2013-05-28 11:54:37 +00:00
|
|
|
|
}
|
2013-05-24 10:49:19 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
bool ExpressionAnalyzer::appendOrderBy(ExpressionActionsChain & chain)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
2013-05-28 11:54:37 +00:00
|
|
|
|
assertSelect();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
if (!select_query->order_expression_list)
|
|
|
|
|
return false;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 14:24:20 +00:00
|
|
|
|
initChain(chain, aggregated_columns);
|
|
|
|
|
ExpressionActionsChain::Step & step = chain.steps.back();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-11 16:21:25 +00:00
|
|
|
|
getRootActionsImpl(select_query->order_expression_list, false, false, *step.actions);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 14:24:20 +00:00
|
|
|
|
ASTs asts = select_query->order_expression_list->children;
|
|
|
|
|
for (size_t i = 0; i < asts.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
ASTOrderByElement * ast = dynamic_cast<ASTOrderByElement *>(&*asts[i]);
|
|
|
|
|
if (!ast || ast->children.size() != 1)
|
|
|
|
|
throw Exception("Bad order expression AST", ErrorCodes::UNKNOWN_TYPE_OF_AST_NODE);
|
|
|
|
|
ASTPtr order_expression = ast->children[0];
|
|
|
|
|
step.required_output.push_back(order_expression->getColumnName());
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-28 14:24:20 +00:00
|
|
|
|
void ExpressionAnalyzer::appendProjectResult(DB::ExpressionActionsChain & chain)
|
2013-05-28 11:54:37 +00:00
|
|
|
|
{
|
|
|
|
|
assertSelect();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 14:24:20 +00:00
|
|
|
|
initChain(chain, aggregated_columns);
|
|
|
|
|
ExpressionActionsChain::Step & step = chain.steps.back();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
NamesWithAliases result_columns;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 14:24:20 +00:00
|
|
|
|
ASTs asts = select_query->select_expression_list->children;
|
|
|
|
|
for (size_t i = 0; i < asts.size(); ++i)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
2013-05-28 14:24:20 +00:00
|
|
|
|
result_columns.push_back(NameWithAlias(asts[i]->getColumnName(), asts[i]->getAlias()));
|
|
|
|
|
step.required_output.push_back(result_columns.back().second);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
step.actions->add(ExpressionActions::Action::project(result_columns));
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
Block ExpressionAnalyzer::getSelectSampleBlock()
|
|
|
|
|
{
|
|
|
|
|
assertSelect();
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:59:16 +00:00
|
|
|
|
ExpressionActions temp_actions(aggregated_columns, settings);
|
2013-05-30 16:52:21 +00:00
|
|
|
|
NamesWithAliases result_columns;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
ASTs asts = select_query->select_expression_list->children;
|
|
|
|
|
for (size_t i = 0; i < asts.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
result_columns.push_back(NameWithAlias(asts[i]->getColumnName(), asts[i]->getAlias()));
|
2013-06-11 16:21:25 +00:00
|
|
|
|
getRootActionsImpl(asts[i], true, false, temp_actions);
|
2013-05-30 16:52:21 +00:00
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
temp_actions.add(ExpressionActions::Action::project(result_columns));
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
return temp_actions.getSampleBlock();
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-29 11:46:51 +00:00
|
|
|
|
void ExpressionAnalyzer::getActionsBeforeAggregationImpl(ASTPtr ast, ExpressionActions & actions)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
|
|
|
|
ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast);
|
2013-05-29 11:46:51 +00:00
|
|
|
|
if (node && node->kind == ASTFunction::AGGREGATE_FUNCTION)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
|
|
|
|
ASTs & arguments = node->arguments->children;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
for (size_t i = 0; i < arguments.size(); ++i)
|
|
|
|
|
{
|
2013-06-11 16:21:25 +00:00
|
|
|
|
getRootActionsImpl(arguments[i], false, false, actions);
|
2013-05-29 11:46:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (size_t i = 0; i < ast->children.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
getActionsBeforeAggregationImpl(ast->children[i], actions);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2013-05-29 11:46:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-03 13:17:17 +00:00
|
|
|
|
ExpressionActionsPtr ExpressionAnalyzer::getActions(bool project_result)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
2013-05-28 12:19:25 +00:00
|
|
|
|
ExpressionActionsPtr actions = new ExpressionActions(columns, settings);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
NamesWithAliases result_columns;
|
2013-05-28 11:54:37 +00:00
|
|
|
|
Names result_names;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-17 13:29:50 +00:00
|
|
|
|
ASTs asts;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
if (ASTExpressionList * node = dynamic_cast<ASTExpressionList *>(&*ast))
|
2013-06-17 13:29:50 +00:00
|
|
|
|
asts = node->children;
|
2013-05-24 10:49:19 +00:00
|
|
|
|
else
|
2013-06-17 13:29:50 +00:00
|
|
|
|
asts = ASTs(1, ast);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-17 13:29:50 +00:00
|
|
|
|
for (size_t i = 0; i < asts.size(); ++i)
|
2013-05-24 10:49:19 +00:00
|
|
|
|
{
|
2013-06-17 13:29:50 +00:00
|
|
|
|
std::string name = asts[i]->getColumnName();
|
|
|
|
|
std::string alias;
|
|
|
|
|
if (project_result)
|
|
|
|
|
alias = asts[i]->getAlias();
|
|
|
|
|
else
|
|
|
|
|
alias = name;
|
|
|
|
|
result_columns.push_back(NameWithAlias(name, alias));
|
|
|
|
|
result_names.push_back(alias);
|
|
|
|
|
getRootActionsImpl(asts[i], false, false, *actions);
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-03 13:17:17 +00:00
|
|
|
|
if (project_result)
|
|
|
|
|
{
|
|
|
|
|
actions->add(ExpressionActions::Action::project(result_columns));
|
|
|
|
|
}
|
2013-06-18 09:43:35 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/// Не будем удалять исходные столбцы.
|
|
|
|
|
for (NamesAndTypesList::const_iterator it = columns.begin(); it != columns.end(); ++it)
|
|
|
|
|
result_names.push_back(it->first);
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-28 11:54:37 +00:00
|
|
|
|
actions->finalize(result_names);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
return actions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ExpressionActionsPtr ExpressionAnalyzer::getConstActions()
|
|
|
|
|
{
|
2013-06-03 14:33:14 +00:00
|
|
|
|
ExpressionActionsPtr actions = new ExpressionActions(NamesAndTypesList(), settings);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-11 16:21:25 +00:00
|
|
|
|
getRootActionsImpl(ast, true, true, *actions);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
return actions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExpressionAnalyzer::getAggregateInfo(Names & key_names, AggregateDescriptions & aggregates)
|
|
|
|
|
{
|
|
|
|
|
for (NamesAndTypesList::iterator it = aggregation_keys.begin(); it != aggregation_keys.end(); ++it)
|
|
|
|
|
key_names.push_back(it->first);
|
|
|
|
|
aggregates = aggregate_descriptions;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-20 13:50:55 +00:00
|
|
|
|
void ExpressionAnalyzer::removeUnusedColumns()
|
2013-05-30 16:52:21 +00:00
|
|
|
|
{
|
|
|
|
|
NamesSet required;
|
|
|
|
|
NamesSet ignored;
|
2013-10-21 11:33:25 +00:00
|
|
|
|
|
2013-10-17 13:32:32 +00:00
|
|
|
|
if (select_query && select_query->array_join_expression_list)
|
|
|
|
|
{
|
|
|
|
|
ASTs & expressions = select_query->array_join_expression_list->children;
|
|
|
|
|
for (size_t i = 0; i < expressions.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
/// Игнорируем идентификаторы верхнего уровня из секции ARRAY JOIN.
|
2013-10-21 11:33:25 +00:00
|
|
|
|
/// Их потом добавим отдельно.
|
2013-10-17 13:32:32 +00:00
|
|
|
|
if (dynamic_cast<ASTIdentifier *>(&*expressions[i]))
|
2013-12-06 10:41:54 +00:00
|
|
|
|
{
|
2013-10-17 13:32:32 +00:00
|
|
|
|
ignored.insert(expressions[i]->getColumnName());
|
2013-12-06 10:41:54 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/// Для выражений в ARRAY JOIN ничего игнорировать не нужно.
|
|
|
|
|
NamesSet empty;
|
|
|
|
|
getRequiredColumnsImpl(expressions[i], required, empty);
|
|
|
|
|
}
|
2013-10-21 11:33:25 +00:00
|
|
|
|
|
|
|
|
|
ignored.insert(expressions[i]->getAlias());
|
2013-10-17 13:32:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-21 11:33:25 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
getRequiredColumnsImpl(ast, required, ignored);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-10-21 11:33:25 +00:00
|
|
|
|
NameSet array_join_sources;
|
|
|
|
|
for (NameToNameMap::iterator it = array_join_result_to_source.begin(); it != array_join_result_to_source.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
array_join_sources.insert(it->second);
|
|
|
|
|
}
|
|
|
|
|
for (NamesAndTypesList::iterator it = columns.begin(); it != columns.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
if (array_join_sources.count(it->first))
|
|
|
|
|
required.insert(it->first);
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-20 13:50:55 +00:00
|
|
|
|
/// Нужно прочитать хоть один столбец, чтобы узнать количество строк.
|
|
|
|
|
if (required.empty())
|
|
|
|
|
required.insert(ExpressionActions::getSmallestColumn(columns));
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-21 10:36:01 +00:00
|
|
|
|
unknown_required_columns = required;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-20 13:50:55 +00:00
|
|
|
|
for (NamesAndTypesList::iterator it = columns.begin(); it != columns.end();)
|
|
|
|
|
{
|
|
|
|
|
NamesAndTypesList::iterator it0 = it;
|
|
|
|
|
++it;
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-21 10:36:01 +00:00
|
|
|
|
unknown_required_columns.erase(it0->first);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-20 13:50:55 +00:00
|
|
|
|
if (!required.count(it0->first))
|
2013-06-21 10:09:02 +00:00
|
|
|
|
{
|
|
|
|
|
required.erase(it0->first);
|
2013-06-20 13:50:55 +00:00
|
|
|
|
columns.erase(it0);
|
2013-06-21 10:09:02 +00:00
|
|
|
|
}
|
2013-06-20 13:50:55 +00:00
|
|
|
|
}
|
2014-01-16 14:52:13 +00:00
|
|
|
|
|
|
|
|
|
/// Возможно, среди неизвестных столбцов есть виртуальные. Удаляем их из списка неизвестных и добавляем
|
|
|
|
|
/// в columns list, чтобы при дальнейшей обработке запроса они воспринимались как настоящие.
|
|
|
|
|
for (NameSet::iterator it = unknown_required_columns.begin(); it != unknown_required_columns.end();)
|
|
|
|
|
{
|
2014-01-17 15:19:20 +00:00
|
|
|
|
if (storage && storage->hasColumn(*it))
|
2014-01-16 14:52:13 +00:00
|
|
|
|
{
|
2014-01-17 15:19:20 +00:00
|
|
|
|
columns.push_back(storage->getColumn(*it));
|
|
|
|
|
unknown_required_columns.erase(it++);
|
|
|
|
|
} else
|
|
|
|
|
++it;
|
2014-01-16 14:52:13 +00:00
|
|
|
|
}
|
2013-06-20 13:50:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Names ExpressionAnalyzer::getRequiredColumns()
|
|
|
|
|
{
|
2013-06-21 10:31:31 +00:00
|
|
|
|
if (!unknown_required_columns.empty())
|
|
|
|
|
throw Exception("Unknown identifier: " + *unknown_required_columns.begin(), ErrorCodes::UNKNOWN_IDENTIFIER);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-06-20 13:50:55 +00:00
|
|
|
|
Names res;
|
|
|
|
|
for (NamesAndTypesList::iterator it = columns.begin(); it != columns.end(); ++it)
|
|
|
|
|
res.push_back(it->first);
|
2013-05-30 16:52:21 +00:00
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-30 16:59:16 +00:00
|
|
|
|
void ExpressionAnalyzer::getRequiredColumnsImpl(ASTPtr ast, NamesSet & required_columns, NamesSet & ignored_names)
|
2013-05-30 16:52:21 +00:00
|
|
|
|
{
|
|
|
|
|
if (ASTIdentifier * node = dynamic_cast<ASTIdentifier *>(&*ast))
|
|
|
|
|
{
|
2013-10-21 11:33:25 +00:00
|
|
|
|
if (node->kind == ASTIdentifier::Column
|
|
|
|
|
&& !ignored_names.count(node->name)
|
|
|
|
|
&& !ignored_names.count(DataTypeNested::extractNestedTableName(node->name)))
|
2013-08-01 14:43:04 +00:00
|
|
|
|
{
|
2013-10-21 11:33:25 +00:00
|
|
|
|
required_columns.insert(node->name);
|
2013-08-01 14:43:04 +00:00
|
|
|
|
}
|
2013-05-30 16:52:21 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
if (ASTFunction * node = dynamic_cast<ASTFunction *>(&*ast))
|
|
|
|
|
{
|
|
|
|
|
if (node->kind == ASTFunction::LAMBDA_EXPRESSION)
|
|
|
|
|
{
|
|
|
|
|
if (node->arguments->children.size() != 2)
|
|
|
|
|
throw Exception("lambda requires two arguments", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
ASTFunction * lambda_args_tuple = dynamic_cast<ASTFunction *>(&*node->arguments->children[0]);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
if (!lambda_args_tuple || lambda_args_tuple->name != "tuple")
|
|
|
|
|
throw Exception("First argument of lambda must be a tuple", ErrorCodes::TYPE_MISMATCH);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
/// Не нужно добавлять параметры лямбда-выражения в required_columns.
|
|
|
|
|
Names added_ignored;
|
2013-06-03 12:26:06 +00:00
|
|
|
|
for (size_t i = 0 ; i < lambda_args_tuple->arguments->children.size(); ++i)
|
2013-05-30 16:52:21 +00:00
|
|
|
|
{
|
2013-06-03 12:26:06 +00:00
|
|
|
|
ASTIdentifier * identifier = dynamic_cast<ASTIdentifier *>(&*lambda_args_tuple->arguments->children[i]);
|
2013-05-30 16:52:21 +00:00
|
|
|
|
if (!identifier)
|
|
|
|
|
throw Exception("lambda argument declarations must be identifiers", ErrorCodes::TYPE_MISMATCH);
|
|
|
|
|
std::string name = identifier->name;
|
|
|
|
|
if (!ignored_names.count(name))
|
|
|
|
|
{
|
|
|
|
|
ignored_names.insert(name);
|
|
|
|
|
added_ignored.push_back(name);
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
getRequiredColumnsImpl(node->arguments->children[1], required_columns, ignored_names);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
for (size_t i = 0; i < added_ignored.size(); ++i)
|
|
|
|
|
ignored_names.erase(added_ignored[i]);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-17 13:32:32 +00:00
|
|
|
|
|
2013-12-06 10:41:54 +00:00
|
|
|
|
ASTSelectQuery * select = dynamic_cast<ASTSelectQuery *>(&*ast);
|
|
|
|
|
|
2013-05-30 16:52:21 +00:00
|
|
|
|
for (size_t i = 0; i < ast->children.size(); ++i)
|
2013-06-21 11:32:27 +00:00
|
|
|
|
{
|
|
|
|
|
ASTPtr child = ast->children[i];
|
2013-12-06 10:41:54 +00:00
|
|
|
|
/// Не пойдем в секцию ARRAY JOIN, потому что там нужно смотреть на имена не-ARRAY-JOIN-енных столбцов.
|
|
|
|
|
/// Туда removeUnusedColumns отправит нас отдельно.
|
|
|
|
|
if (!dynamic_cast<ASTSubquery *>(&*child) && !dynamic_cast<ASTSelectQuery *>(&*child) &&
|
|
|
|
|
!(select && child == select->array_join_expression_list))
|
2013-06-21 11:32:27 +00:00
|
|
|
|
getRequiredColumnsImpl(child, required_columns, ignored_names);
|
2013-10-17 13:32:32 +00:00
|
|
|
|
}
|
2013-05-30 16:52:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-05-24 10:49:19 +00:00
|
|
|
|
}
|